cin.eof() functionality

心已入冬 提交于 2019-12-29 08:33:11

问题


I understand that cin.eof() tests the stream format. And while giving input, end of character is not reached when there is wrong in the input. I tested this on my MSV C++ 2010 and am not understanding the strange results. No matter what I give the input, I am getting Format Error message that is present in the program.

#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;
}

Results I expected:

Values for i =

  1. 10 => Correct Input but the output is Format Error
  2. 12a => Format Error

Could someone explain where I am going wrong. Thanks.


回答1:


std::cin.eof() tests for end-of-file (hence eof), not for errors. For error checking use !std::cin.good(), the built-in conversion operator (if(std::cin)) or the boolean negation operator (if(!std::cin)).




回答2:


Use a direct test of the status of the stream with:

while (cin >> i)
{
    ...
}



回答3:


For an input stream to enter the EOF state you have to actually make an attempt to read past the end of stream. I.e. it is not enough to reach the end-of-stream location in the stream, it is necessary to actually try to read a character past the end. This attempt will result in EOF state being activated, which in turn will make cin.eof() return true.

However, in your case you are not only not doing that, you (most likely) are not even reaching the end of stream. If you input your 10 from the keyboard, you probably finished the input by pressing the [Enter] key. This resulted in a new-line character being added to the input stream. So, what you are actually parsing with >> operator in this case is actually a 10\n sequence. Since you requested an int value from the stream, it only reads the numerical characters from the stream, i.e. it reads 1 and 0, but it stops at \n. That \n remains in the stream. You never read it. So, obviously, your code never reaches the end-of-file position in the stream. You have to reason to expect cin.eof() to become true in such case.




回答4:


#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;
}

Also see Testing stream.good() or !stream.eof() reads last line twice.

Sample session with the above program, note that input lines are marked with comments not present in the actual output:

$ 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.



回答5:


Assuming your input is line based, I suggest that you read the whole line using std::getline(). Once you have the line, you can analyse it and decide whether it contains correct or wrong input. Put the line into std::istringstream and do something like the following:

Edit: Changed !! iss to static_cast<bool>(iss) for compatibility with 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);



回答6:


Adding to the previous answer: After reading your input (like 10), you are not at end-of-file, as you can easily type some more. How is the system to know that you will not?

When reading your second input (12a), it correctly reads all the digits that can be part of an integer. The letter 'a' cannot, so it is left for some possible later input. For example, you can read all parts of 12a with this code

int i; char c;

cin >> i >> c;




回答7:


cin.eof() test if the stream has reached end of file which happens if you type something like Ctrl+C (on Windows), or if input has been redirected to a file etc.

To test if the input contains an integer and nothing but an integer, you can get input first into a string and then convert that with a stringstream. A stringstream indeed reaches eof if there's no more to be extracted from it.

#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;
}



回答8:


EOF stands for e nd o f f ile. std::cin is the standard input. The standard input, under normal circumstances, never reaches the end: you can always just type some more.

Further, .eof() only returns true if an input operation has already failed because of trying to read past the end of the file. The program actually can't tell that it's "at the end of file"; that is, the only way it can find out that the next attempt to read data will fail is by actually making the attempt.



来源:https://stackoverflow.com/questions/4939251/cin-eof-functionality

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!