2009-03-23 4 views
2

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

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

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

Любые подсказки?

ответ

3

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

if (!getline(std::cin, str)) { 
    std::cin.clear(); 
    std::cout << std::endl; 
} 
+0

Пока этого не сделать. По причинам, неизвестным мне, я только что получил новую учетную запись, хотя я вошел в систему с моим существующим: -/ –

+0

@mitsuhiko Возможно, вы вошли в систему, используя другую учетную запись openid. –

+0

Получил мой счет. Кажется, что stackoverflows поддержка делегата OpenID немного глючит –

1

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

  • eofbit
  • failbit
  • badbit

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

+0

я могу проверить их, но я не могу игнорировать ВФ таким образом. Поэтому я не могу продолжать использовать входной поток. Я мог только закрыть приложение, которое не то, что я хочу. –

+0

Дарнит, ты избил меня на 1 мин :) +1 –

+0

Вы пробовали cin.clear(); ? – dirkgently

7

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

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() устраняет все ошибки, и вы можете продолжить чтение своих материалов.

0

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

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

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

Я не вижу, как это решит описанную проблему. – ypnos

+0

@ypnos код должен был быть примером, а не решением. Во всяком случае, теперь у нас есть решение, благодаря Litb –

0

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

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

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

½ Вы можете найти некоторую информацию о своей проблеме в документах here.