开发者

cin.eof() functionality

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 =

    开发者_如何学Python
  1. 10 => Correct Input but the output is Format Error
  2. 12a => Format Error

Could someone explain where I am going wrong. Thanks.


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


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

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


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.


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


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);


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;


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜