Функциональность cin.eof () - PullRequest
       61

Функциональность cin.eof ()

8 голосов
/ 09 февраля 2011

Я понимаю, что cin.eof() проверяет формат потока. И при подаче ввода, конец символа не достигается, если во вводе есть ошибки. Я проверил это на своем MSV C ++ 2010 и не понимаю странных результатов. Независимо от того, что я даю, я получаю сообщение Ошибка формата , присутствующее в программе.

#include <iostream>
using namespace std;

int main()
{
    int i;
    cin>> i;

    if(!cin.eof())
    {
        cout<< "\n Format Error \n";
    }
    else
    {
        cout<< "\n Correct Input \n";
    }

    getchar();
    return 0;
}

Результаты, которые я ожидал:

Значения для i =

  1. 10 => Правильный ввод , но вывод Ошибка форматирования
  2. 12a => Ошибка формата

Может кто-нибудь объяснить, где я иду не так. Спасибо.

Ответы [ 8 ]

18 голосов
/ 09 февраля 2011

std::cin.eof() проверяет конец файла (следовательно, eof), а не на ошибки.Для проверки ошибок используйте !std::cin.good(), встроенный оператор преобразования (if(std::cin)) или логический оператор отрицания (if(!std::cin)).

10 голосов
/ 27 октября 2012

Используйте прямую проверку статуса потока с:

while (cin >> i)
{
    ...
}
3 голосов
/ 09 февраля 2011

Для того, чтобы входной поток вошел в состояние EOF, вы должны попытаться прочитать после конца потока . То есть этого недостаточно, чтобы достичь местоположения конца потока в потоке, необходимо фактически попытаться прочитать символ после конца. Эта попытка приведет к активации состояния EOF, что в свою очередь заставит cin.eof() вернуть true.

Однако в вашем случае вы не только не делаете этого, вы (скорее всего) даже не достигаете конца потока. Если вы вводите 10 с клавиатуры, вы, вероятно, завершили ввод, нажав клавишу [Ввод]. Это привело к добавлению символа новой строки во входной поток. Таким образом, то, что вы на самом деле анализируете с помощью оператора >>, в данном случае на самом деле представляет собой последовательность 10\n. Поскольку вы запросили значение int из потока, он читает только числовые символы из потока, то есть читает 1 и 0, но останавливается на \n. Это \n остается в потоке. Вы никогда не читаете это. Таким образом, очевидно, что ваш код никогда не достигает позиции конца файла в потоке. В таком случае вы должны ожидать, что cin.eof() станет true.

2 голосов
/ 09 февраля 2011

Предполагая, что ваши входные данные основаны на строках, я предлагаю вам прочитать всю строку, используя std::getline(). Если у вас есть строка, вы можете проанализировать ее и решить, содержит ли она правильные или неправильные данные. Поместите строку в std::istringstream и сделайте что-то вроде следующего:

Редактировать: Изменено !! iss на static_cast<bool>(iss) для совместимости с C ++ 0x.

std::istringstream iss (line);
char ch;
long lval;
// read the input
iss >> lval;
// result variable will contain true if the input was correct and false otherwise
result
    // check that we have read a number of at least one digit length
    = static_cast<bool>(iss)
    // check that we cannot read anything beyond the value read above
    && ! (iss >> ch);
2 голосов
/ 09 февраля 2011
#include <iostream>

int main() {
  using namespace std;
  int i;
  if (cin >> i) {
    cout << "Extracted an int, but it is unknown if more input exists.\n";
    char c;
    if (cin.get(c)) {  // Or: cin >> c, depending on how you want to handle whitespace.
      cin.putback(c);
      cout << "More input exists.\n";
      if (c == '\n') {  // Doesn't work if you use cin >> c above.
        cout << "But this was at the end of this line.\n";
      }
    }
    else {
      cout << "No more input exists.\n";
    }
  }
  else {
    cout << "Format error.\n";
  }
  return 0;
}

Также см. Тестирование stream.good () или! Stream.eof () дважды читает последнюю строку .

Пример сеанса с вышеуказанной программой, обратите внимание, что строки вводапомечены комментариями, которых нет в фактическом выводе:

$ your-program
12  # input
Extracted an int, but it is unknown if more input exists.
More input exists.
But this was at the end of this line.

$ your-program
12a  # input
Extracted an int, but it is unknown if more input exists.
More input exists.

$ echo -n 12 | your-program
Extracted an int, but it is unknown if more input exists.
No more input exists.

$ your-program
a  # input
Format error.
1 голос
/ 09 февраля 2011

cin.eof() проверить, достиг ли поток конца файла, что происходит, если вы наберете что-то вроде Ctrl + C (в Windows) или если ввод был перенаправлен в файл и т. Д.вход содержит целое число и ничего, кроме целого числа, вы можете сначала получить входные данные в строку, а затем преобразовать их с помощью потока строк.Струнный поток действительно достигает eof, если из него больше нечего извлечь.

#include <iostream>
#include <sstream>
#include <string>

int main() {
    using namespace std;
    int i;
    string input;
    cin >> input; //or getline(cin, input)
    stringstream ss(input);
    if (ss >> i && ss.eof()) {  //if conversion succeeds and there's no more to get
        cout<< "\n Correct Input \n";
    }
    else {
        cout<< "\n Format Error \n";
    }

  return 0;
}
1 голос
/ 09 февраля 2011

Добавление к предыдущему ответу: После прочтения ввода (например, 10), вы не в конце файла, так как вы можете легко набрать еще немного. Как система узнает, что не узнаешь?

При чтении вашего второго ввода (12а) он правильно читает все цифры, которые могут быть частью целого числа. Буква «а» не может, поэтому она оставлена ​​для возможного последующего ввода. Например, вы можете прочитать все части 12а с помощью этого кода

int i; символ с;

cin >> i >> c;

0 голосов
/ 09 февраля 2011

EOF означает e и o f f ile.std :: cin - это стандартный ввод.Стандартный ввод при нормальных обстоятельствах никогда не достигает конца: вы всегда можете просто набрать еще немного.

Кроме того, .eof () возвращает true, только если операция ввода уже завершилась неудачей из-за попыткиПрочитать за концом файла .Программа на самом деле не может сказать , что она "в конце файла";то есть единственный способ узнать, что следующая попытка чтения данных потерпит неудачу, - это сделать эту попытку.

...