Игнорирование EOF на std :: cin в C ++ - PullRequest
2 голосов
/ 23 марта 2009

У меня есть приложение, которое реализует интерактивную оболочку, аналогично тому, как работает консоль Python / irb. Теперь проблема в том, что если пользователь случайно нажал ^D EOF, и мой вызов getline() возвращает пустую строку, которую я рассматриваю как «нет ввода», и снова отображает приглашение.

Это приводит к бесконечному циклу, который печатает подсказку.

Теперь в Python я решил бы эту проблему, поймав EOFError, но в C ++ не возникает никаких исключений, которые я мог бы поймать, и, похоже, в cin нет настройки игнорирования EOF.

Есть намеки?

Ответы [ 5 ]

7 голосов
/ 23 марта 2009

Если он не может ничего прочитать, он устанавливает failbit. Просто протестируйте поток в условии if и очистите бит:

if(!getline(std::cin, myline)) {
    std::cin.clear();
    std::cout << "you should enter something" << std::endl;
}

Внутренне, последовательность в вашем случае такова:

  • Подождите на терминале строку. Терминал будет блокироваться, пока пользователь не издаст новую строку. Возможны два вероятных случая ошибки
    1. Пользователь сразу нажимает EOF. Это заставит getline вообще ничего не читать, и установит failbit и eofbit.
    2. Пользователь вводит что-то и затем нажимает EOF. Это заставит getline потреблять что-то, а затем ударит EOF при попытке получить следующего персонажа. Это приводит к установке eofbit.
  • Вы попробуете что-то прочитать снова. Функция извлечения создаст объект типа istream::sentry, который проверяет, в каком состоянии находится поток. Если какой-либо из битов ошибок установлен, это приведет к немедленному возврату функции извлечения. Это вызвало бесконечный цикл раньше.

Вызов clear() очищает все биты ошибок, и вы можете снова читать ваши вещи.

3 голосов
/ 23 марта 2009

Правильное решение благодаря litb:

if (!getline(std::cin, str)) {
    std::cin.clear();
    std::cout << std::endl;
}
1 голос
/ 23 марта 2009

Функция getline() сигнализирует об ошибках, используя следующие биты:

  • eofbit
  • failbit
  • badbit

Попробуйте проверить это, прежде чем продолжить.

0 голосов
/ 23 марта 2009

Хорошо, в других ответах использование cin.clear () было описано как возможное решение.

Другая хитрость заключается в том, что для обработки ввода с консоли используются другие средства, отличные от стандартного, в котором для терминала установлен другой режим, позволяющий обрабатывать Ctrl + D напрямую. В режиме RAW или в других режимах вы получаете более прямой доступ к последовательностям ввода и управления со стороны пользователя (например, Ctrl + D или Ctrl + C), которые больше не обрабатываются.

В некоторых библиотеках вы можете попытаться собрать больше информации (или даже сэкономить время кодирования):

½ Информацию о вашей проблеме вы можете найти в документации здесь .

0 голосов
/ 23 марта 2009

См. http://www.horstmann.com/cpp/pitfalls.html

Вы можете использовать код как:

while (cin)
{  int x;
   cin >> x;
   if (cin) a.push_back(x);
}
...