проверка доступности данных перед называнием станд.:: getline

Я хотел бы считать некоторые данные с потока, у меня есть использование std::getline. Ниже образца с помощью std::cin.

std::string line;
std::getline( std::cin, line );

Это - блокирующаяся функция т.е. при отсутствии данных или строки для чтения, она блокирует выполнение.

Вы знаете, существует ли функция для проверки доступности данных перед вызовом std::getline? Я не хочу блокироваться.

Как я могу проверить, полон ли потоковый буфер данных, допустимых для успешного вызова к std::getline?

Независимо от того, что похоже на код ниже

if( dataAvailableInStream() )
{
     std::string line;
     std::getline( std::cin, line );
}
26
задан meagar 19 March 2013 в 18:55
поделиться

5 ответов

Библиотека iostream не поддерживает концепцию неблокирующего ввода/вывода. Я не думаю, что в стандарте C++ есть что-то, что поддерживает. Любое хорошее решение, скорее всего, будет специфичным для конкретной платформы. Если вы можете использовать библиотеки POSIX, вы можете посмотреть на select. Обычно он используется для сетевых задач, но он будет работать, если вы передадите ему дескриптор файла для stdin.

8
ответ дан 28 November 2019 в 07:53
поделиться

Не существует стандартного способа проверить, блокируется ли getline . Вы можете использовать:

std::cin.rdbuf()->in_avail()

, чтобы узнать, сколько символов определенно доступно до того, как операция чтения может быть заблокирована, но вам придется читать символы один за другим перед повторной проверкой in_avail , поскольку нет возможности заранее узнайте, является ли какой-либо из ожидающих символов новой строкой или фактическим концом потока. В противном случае вызов getline может заблокироваться.

Обратите внимание, что хотя если in_avail () возвращает положительное число, гарантируется, что до конца потока доступно по крайней мере такое количество символов, обратное неверно. Если in_avail () возвращает ноль, символы все еще могут быть доступны, и поток может не блокироваться немедленно.

17
ответ дан 28 November 2019 в 07:53
поделиться

std :: iostream предоставляет функцию просмотра, которая возвращает следующий символ в потоке, не удаляя его. Таким образом, вы можете сделать что-то вроде следующего (полностью не проверено).

bool dataAvailableInStream( std::iostream &stream )
{
  return stream.peek() != std::iostream::traits_type::eof();
}

Править

Как указывает rubenvb, std :: cin блокируется по замыслу. Таким образом, приведенный выше код поможет вам обойти блокировку getline , но не cin .

Править Править

Как Чарльз указывает ниже, просматривает блоки, если данные недоступны. Следовательно, это не дает полного решения. Это убережет вас от блокировки на getline , но не от блокировки в целом.

-3
ответ дан 28 November 2019 в 07:53
поделиться

Хотя ответ nathan peek () покажет, есть ли данные, нет никакой гарантии, что std :: getline () будет успешным в чтение «строчки».

Всегда намного проще, хотя и немного назад, попробовать getline и проверить результат самого вызова функции:

std::string line;
while( !std::getline(std::cin, line) )
{
    cout << "Enter something please" << endl;
}

Этот код будет работать до тех пор, пока cin не получит то, что ему нравится (т.е. сможет извлечь и разместить в строке ). Я не считаю, что peek () здесь необходим или полезен.

РЕДАКТИРОВАТЬ: Дело в том, что cin (== стандартный ввод с клавиатуры) должен будет заблокировать программу, пока она ожидает ввода, как еще она может получить какой-либо ввод, если она не будет ждать?

0
ответ дан 28 November 2019 в 07:53
поделиться

Какую проблему вы пытаетесь решить, избегая блокировки чтения здесь?

Непереносимость Я полагаю, вы могли бы использовать poll или select чтобы узнать, есть ли данные для чтения на stdin (часто fd 0 в системах unix).

В качестве альтернативы вы можете создать второй поток для выполнения операций ввода-вывода и просто позволить ему блокироваться, чтобы вы могли продолжить нормальную обработку в основном потоке.

0
ответ дан 28 November 2019 в 07:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: