简体   繁体   中英

unexpected behavior when read a character from istringstream

I have a question on the stream behavior, see the following example. What I was expecting is the ss_char and ss_int will be eof state, but just the ss_int will be eof state.

My question is, why isn't ss_char eof state? Can't I use the operator>>, only the istringstream::get() function, but then why read the value successfully?

Output:
char value: a
int value: 42

ss_char eof: false // why false?
ss_int eof: true

Sorry for my poor English. I'm working on improving my English.

#include <iostream>
#include <sstream>

int main(int /*argc*/, char const * /*argv*/[])
{
    char c;
    int num;
    std::istringstream ss_int("42");
    std::istringstream ss_char("a");

    if (ss_char >> c)
    {
        std::cout << "char value: " << c << std::endl;
    }
    else
    {
        std::cout << "cannot read char" << std::endl;
    }

    if (ss_int >> num)
    {
        std::cout << "int  value: " << num << std::endl;
    }
    else
    {
        std::cout << "cannot read int" << std::endl;
    }

    std::cout << std::endl;

    std::cout << "ss_char eof: " << std::boolalpha << ss_char.eof() << std::endl; // why false
    std::cout << "ss_int  eof: " << std::boolalpha << ss_int.eof() << std::endl;

    return 0;
}

CppReference says: "This function only reports the stream state as set by the most recent I/O operation, it does not examine the associated data source. For example, if the most recent I/O was a get(), which returned the last byte of a file, eof() returns false. The next get() fails to read anything and sets the eofbit. Only then eof() returns true."

oefbit will turn true when a read operation attempts to read beyond end of file, but not when it reads exactly to the end of file without trying to go further. When you read the char, it knows it should read a single byte, so this read operation is ok, the read position advance 1 byte, goes to the end, but let say the the stream still haven't noticed that it is indeed the end, it will if you try to read something else. When you read an integer, it tries to read beyond 42 because the length of the integer is not clear, it could have been 42901, so it has to read until it sees an space, and end of line, or eventually the end of the file/stream if there's nothing else to read.

And the result of the operator >> is the stream itself. When it is converted to void* (or bool, depends on c++11 or previous) it works as !fail(), so it tells you if the read or write operation was ok, regardless of whether it reached the end of file (next read operation will fail if it is now at the end).

The EOF condition doesn't actually occur until you try to read past the end of the stream.

In the char case you read exactly one character, the only one available. You don't try to read past the end because there is no need to.

Extracting an int on the other hand attempts to consume as many digits as possible. It reads the 4 and the 2, and then it tries to read again to see if there is another digit to consume, it does attempt to read past the end in this case. It notices that the input came to an end and so finishes the conversion of 42.

when extracting chars, it will pull a single character at a time and skip white spaces on consecutive calls.

when extracting int, the parser attempts to pull as many characters out to form the number. this causes the integer extraction to hit the eof in your test case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM