HansKlokkenspel
HansKlokkenspel

Reputation: 33

std::getline skipping input from std::cin after last occurrence of delimiter, but not with input from std::istringstream

I need to read some input that is delimited by a whitespace, the main construction I used for this is:

while(std::getline(std::cin, s, ' ')){
    std::cout << s << std::endl;
}

For the input: "this is some text"

The output for S will be: "this", "is", "some", thus skipping the last piece of input after the last whitespace.

I want to include the last piece of input in my program as well, so I went looking for a solution and found the following:

while (std::getline(std::cin, line)) {
    std::istringstream iss(line);

    while (std::getline(iss, s, ' ')) {
        std::cout << s << std::endl;
    }
}

For the input: "this is some text"

The output for S will be: "this", "is", "some", "text", which is exactly what I want.

My question is: why does reading from std::cin with a delimiter skip the input after the last occurrence of the delimiter, but reading from std::istringstream does not?

Upvotes: 3

Views: 797

Answers (1)

erip
erip

Reputation: 16945

My question is: why does reading from std::cin with a delimiter skip the input after the last occurrence of the delimiter, but reading from std::istringstream does not?

It doesn't.

In your first example:

while(std::getline(std::cin, s, ' ')){
    std::cout << s << std::endl;
}

You are specifically reading items from newline that are literally delimited by a single space. Because the line is (ostensibly) ended with a newline, it will never finish extracting from the input string as it is expecting either ' ' or an EOF.

In your second example:

while (std::getline(std::cin, line)) {
    std::istringstream iss(line);

    while (std::getline(iss, s, ' ')) {
        std::cout << s << std::endl;
    }
}

The std::getline in the first while will strip the newline from your example sentence. Then items are extracted according to some basic rules.

Here are the rules (from cppreference):

Extracts characters from input and appends them to str until one of the following occurs (checked in the order listed)
    a) end-of-file condition on input, in which case, getline sets eofbit.
    b) the next available input character is delim, as tested by Traits::eq(c, delim), in which case the delimiter character is extracted from input, but is not appended to str.
    c) str.max_size() characters have been stored, in which case getline sets failbit and returns.

Upvotes: 4

Related Questions