exer240
exer240

Reputation: 37

It seems to me as if std::getline doesn't handle new lines correctly?

With the code below, I want the user to write a text in the terminal, and then print out the last sentence of the text. Maybe I should mention that I'm running on a Linux desktop.

#include <string>
#include <iostream> 

int main()
{
    std::string user_text{};

    while(std::getline(std::cin, user_text))
    {

    }

    std::cout << "Text: " << user_text << std::endl;

    return 0;
}

Anyways if I, after running the program, write for example:

Hi my name is

And then press 'ctrl+d', the output will indeed be "Text: Hi my name is"

However if I instead do this:

Hi my name is 'press enter'

Name my is hi 'press enter'

And then press 'ctrl+d'. The output will be "Text: ". Why is this? Shouldn't getline stop when I have pressed 'ctrl+d'?

Thanks in advance!

Upvotes: 1

Views: 617

Answers (3)

fjardon
fjardon

Reputation: 7996

Ctrl+D causes the process's read from the terminal to return immediately. If you press Ctrl+D after typing: Hi my name is, the process will read: Hi my name is. getline will not find a \n and will restart reading. Then you press Ctrl+D a second time (you didn't say it but I am sure you did). And this will interrupt the read, causing it to return 0, which is as-if the terminal was closed. getline will then return the current value: Hi my name is.

In the second case, you haven't typed anything since the last \n, so when you press Ctrl+D, read directly returns 0 and getline returns with an empty string.

Upvotes: 0

Remy Lebeau
Remy Lebeau

Reputation: 596833

std::getline() erases the output std::string before attempting to read from the stream.

In your second case, the first 2 calls to std::getline() have already read everything you have typed in, there is nothing left when you press CTRL-D during the 3rd call, so there is nothing for std::getline() to output into the std::string.

Save the last successful line read to a separate variable, eg:

std::string user_text, line;

while(std::getline(std::cin, line))
{
    user_text = line;
}

std::cout << "Text: " << user_text << std::endl;

Upvotes: 4

Nick Reed
Nick Reed

Reputation: 5059

std::getline is working as intended: it's getting a line. If you press enter, it creates a new, empty line; if you then press ctrl+d, you're terminating std::getline, which returns that (empty) line's contents.

From the docs:

getline reads characters from an input stream and places them into a string:

  1. Behaves as UnformattedInputFunction, except that input.gcount() is not affected. After constructing and checking the sentry object, performs the following:
    1. Calls str.erase()
    2. 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.
    3. If no characters were extracted for whatever reason (not even the discarded delimiter), getline sets failbit and returns.
  2. Same as getline(input, str, input.widen('\n')), that is, the default delimiter is the endline character.

Upvotes: 1

Related Questions