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