Std::Getline on Std::Cin

std::getline on std::cin

Most likely you are trying to read a string after reading some other data, say an int.

consider the input:

11
is a prime

if you use the following code:

std::cin>>number;
std::getline(std::cin,input)

the getline will only read the newline after 11 and hence you will get the impression that it's not waiting for user input.

The way to resolve this is to use a dummy getline to consume the new line after the number.

std::cin.getline( ) vs. std::cin

In case with char*, std::cin.getline getting line, instead of std::cin getting first word.

Why do cin and getline exhibit different reading behavior?

reading behavior of cin and getline.

cin does not "read" anything. cin is an input stream. cin is getting read from. getline reads from an input stream. The formatted extraction operator, >>, reads from an input stream. What's doing the reading is >> and std::getline. std::cin does no reading of its own. It's what's being read from.

first cin read up until the "\n". once it hit that "\n", it increments the
cursor to the next position

No it doesn't. The first >> operator reads up until the \n, but does not read it. \n remains unread.

The second >> operator starts reading with the newline character. The >> operator skips all whitespace in the input stream before it extracts the expected value.

The detail that you're missing is that >> skips whitespace (if there is any) before it extracts the value from the input stream, and not after.

Now, it is certainly possible that >> finds no whitespace in the input stream before extracting the formatted value. If >> is tasked with extracting an int, and the input stream has just been opened and it's at the beginning of the file, and the first character in the file is a 1, well, the >> just doesn't skip any whitespace at all.

Finally, std::getline does not skip any whitespace, it just reads from the input stream until it reads a \n (or reaching the end of the input stream).

Stuck in loop during std::getline and std::cin during while loop

cin controls input from a stream buffer, which put your input characters in a stream buffer, then it was passed to getline.
cin ends input when you signaled EOF with Ctrl+D, Ctrl+Z, or Enter.
See this link
detecting end of input with cin.

getline extracts characters from input and appends them to str until it meet one of the end conditions,
in your situaton the end condition is the endline character '\n', because the default delimeter is the endline character.
You may define your own delimeter getline(intput, str, $your_delemeter) , and do a little experiment.

How to break std::cin(std::cin.getline) executuion from other thread

std::cin is a blocking call that can not be interrupted.

This thread here seems to have some non-blocking alternatives:
https://stackoverflow.com/a/40812107/2562287

If you used a non blocking alternative for std::cin along with an boolean (threadsafe from either a mutex or being atomic, preferably the latter), you could set the boolean on the other thread and read the boolean on the input thread, if the boolean is either true or false then exit the input function.

Ways std::getline(std::cin, string) can fail from keyboard input

std::getline could fail if you've used stdin previously without clearing the failbit and if the input exceeds std::string::max_size (see comment of Davis Herring).
Otherwise, I know of no way to let std::getline fail except by EOF (^Z/^D).

But, here is your code with some small improvements:

template<typename T>
T get_type(std::string prompt)
{
T output;
std::string input;
while(true)
{
std::cout << prompt;
std::getline(std::cin, input);
std::istringstream iss(input);
if(!std::cin)
{
std::cin.clear();
// std::clearerr(stdin);
}
else if(iss >> output && iss.eof())
return output;

std::cout << "Invalid input type. Please try again:\n";
}
}

As mentioned in the comments, it is necessary to use clearerr on stdin on some systems. If your system requires that, just uncomment std::clearerr(stdin);.

Because of your 2x <Enter> problem: the ignore statement is unnecessary. You just ignore the next input (that's why you have to hit <Enter> twice).

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

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;


Related Topics



Leave a reply



Submit