Getline stuck on infinite loop - c++

I run the following snippet of code expecting that when i hit the new line (Enter key), the program will halt, but it does not do that, any idea what's the problem ? Thanks.
#include <bits/stdc++.h>
using namespace std;
int main() {
string s ;
while(getline(cin ,s)){
cout << s << endl ;
}
}

Hitting the Enter key ends a line. If there’s no other text on the line it’s an empty line, but a line nonetheless.
There are a couple of ways you can handle this.
First, depending on your OS, either ctrl-D or ctrl-Z will act like end-of-file, and the call to getline will fail, ending the loop.
Second, if you want an empty line to end the loop, just check for it:
while (getline(cin, s) && s.length() != 0)
std::cout << s << '\n';

Pressing enter is like entering an empty line, you didn't put any condition for your program to exit. It will stay in infinity unless you forcefully exit it. Implement an exit condition in the while(), so that when it is not met, the loop will exit, and obviously put the getline() inside to keep asking prompting for input.

Related

Keep asking for input and reopen stdin

I have a task to create a program that does some calculation on a vector of numbers. The vector must contain at least 1 number in it and if it doesn't I have to throw an exception and try again. There is a video example how the code should work here: https://asciinema.org/a/283343
I'm guessing that EOF is being signaled using CTRL+D and that's what causes the exception to be thrown.
If they were using Enter (new line), it would leave a blank line behind.
But in my case, after I press CTRL+D, my program just runs in an infinite loop because the stdin stays in a failed state despite me using cin.clear().
Is there another shortcut similar to CTRL+D that they might be using for this, or is there a way to reopen the stream, or restart the whole application.
The program runs fine on Windows when I use CTRL+Z, but on Linux I just can't get it to work the same.
Example code below:
#include<iostream>
#include<vector>
void enter_elements(std::vector<double>& input_list){
double x;
std::cout << "Enter numbers: " << std::endl;
while(std::cin >> x){
input_list.push_back(x);
}
if(input_list.empty()){
throw std::string("You must enter at least 1 number!");
}
}
int main(){
std::vector<double> input_list;
try {
enter_elements(input_list);
} catch (const std::string& e) {
std::cout << "Error: " << e << std::endl;
std::cin.clear();
enter_elements(input_list);
}
return 0;
}
Can anyone help me with this problem or suggest where could I maybe read more about it?
No.
Once the stream is closed, the stream is closed. That's it.
What I'd do is accept a set of numbers on one line. Your input iteration would end at the end of the line. Then you validate those numbers, and ask for another line if necessary.
You can do that by looping over std::getline instead of using formatted extraction. Then you'd need to parse the line you get.
That's not what the video shows, but I don't know how they achieved that. Maybe you should ask them!
Are you asking how to stop the program?
If so, on linux, you should try CTRL+C instead of CTRL+D or CTRL+Z while your program is running
This is the sort of reason why I hate using cin >> anInt. I much prefer to getLine and parse it myself. Then you can make it do anything and decide how you're going to determine end of list, etc.
Yes, it's more code. But you don't run into these weird problems like this.

While loop with getline doesn't end for user input

I thought getline stops at a newline character, but the while loop does not end? it returns the correct data but it just sits in the terminal window. For example:
Enter an expression: #5+4#5+4
(blinking cursor)
(can enter data forever and press enter forever and it wont exit)
my code, (main.cpp):
int main()
{
string exp;
cout << "Enter an Infix Expression:";
while (getline(cin, exp, '#'))
{
string token = exp;
string post;
cout << token << endl;
IntoPost *infix = new IntoPost(token.length());
post = infix->inToPost(token);
cout << post << endl;
}
cin.get();
}
The Solution Using EOF
Your current program is looping endlessly because getline returns std::basic_istream, so while(getline()) will never equate to 'false'.
As #0x499602D2 has stated, your program is working as intended, but the extraction from getline can only end in two ways, as indicated by the reference here:
Extracts characters from is and stores them into str until the delimitation character delim is found (or the newline character, '\n', for when no delimiter is specified).
The extraction also stops if the end of file is reached in is or if some other error occurs during the input operation.
The first condition is difficult to pull off, as inputs on console are triggered by the \n character.
As for the second condition, as per #DavidC.Rankin:
You can also generate a manual EOF on Linux with [Ctrl+d] or windows with [Ctrl+z] (generally twice is required)
This means the solution is to use [Ctrl+d] or [Ctrl+z] to trigger the second condition to end your while loop at any time.
Alternative Using a Break Statement
One alternative way you can try to end the loop instead is breaking on input of an 'exit' string:
(1)
#include <algorithm>
//...
while (getline(cin, exp, '#'))
{
// removes meaningless endline chars from input
exp.erase(std::remove(exp.begin(), exp.end(), '\n'), exp.end());
if (exp == "exit"){
break;
}
//... Your While Block Code Here!
}
To break out of your while loop, you can simply use:
exit#
# Note, the endls from your couts in the loop will bleed into your inputs on your next while (getline(cin, exp, '#')), giving us unwanted newlines. To prevent this, we can get rid of the endlines from the inputs by using std::erase(). If you wish to keep those endlines in your input, simply set string token = exp; in front of the erase() line.
That's right, getline blocks the execution of the loop until a line separator is received and returns while that all is well, in the next step everything is repeated. If you want the loop not to be infinite - then put the Boolean variable key in the loop condition, and from the input check if the last character is an exit symbol and if so switch the variable key

Invalid input for std::cin

The following code is intended to concatenate words entered by the user.
#include <iostream>
#include <string>
int main() {
// insert code here...
std::string s;
std::string concString;
while (std::cin >> s)
{
concString = concString + s;
}
std::cout << concString << std::endl;
return 0;
}
I am stuck in this while loop during execution because of which I am not able to print the concatenated string. How do I exit this loop? What is an invalid input for std::cin?
Typically, a loop like that is stopped by end of file, rather than invalid input.
In a *nix environment, you can usually send an end of file to the terminal with CTRL+d, and at a windows console, CTRL+z.
See https://stackoverflow.com/a/16136924/1084944
You could, however, implement your own additional way to signify end of input. For example, having your users enter a blank line when done, or the word quit or such. Once you've chosen one, you should communicate that to the user, and you will have to structure your loop to be able to detect these conditions and exit.

Getting more lines from input in C++

I need to read lines from standard input, but I dont really know, how many it will be.
I tried to do it with getline() and cin combined with a while loop, but it led to an infinite loop:
string line;
while( getline(cin, string) ){...}
or
string word;
while( cin >> word ){...}
it doesnt stops at the end of the input( the lines are coming at one time, so the user is hitting just one time the Enter key ).
Thanks for your help.
Reading your comments you have a misunderstanding of "end of input".
When you start your program it waits for input from console, and if input is available it reads it. Initially your copy some strings to your console so your program takes this as input. But your program still keeps reading from the console because there was no "end of input". The program is still connected to the console.
You need to signal "end of input" to your program. On Windows you do this by pressing Ctrl+Z. On Linux you need to press Ctrl+D.
Your problem is reading from the console.
As your console does not put an EOF(end of file) when you enter an empty line.
You should try pipeing the input from a file to your program. This should end, when there is no more input.
Otherwise, just check if the string is empty, and break out of the loop, if it is empty.
The way you run your program, your input doesn't end, since the console can always provide more input. Your program behaves correctly, though perhaps not in the way you desire. That's because you have misunderstood your own desires.
What you are looking for is perhaps (but I can't be sure) for the program to end when either the input ends or when the input contains a blank line. This can be coded as follows:
int main()
{
for (std::string line; std::getline(std::cin, line); )
{
if (line.empty())
{
std::cout << "Got blank line, quitting.\n";
return 0;
}
// process line
}
std::cout << "End of input, quitting.\n";
return 0;
}

getline causes infinite loop when redirecting file to standard input

The following code simply echoes the standard input to the standard output. If I run the program like so ./a.out, I can type anything and the program works fine. However, if I run it like this ./a.out < input.txt I get an infinite loop, regardless of the content of input.txt.
#include <iostream>
using namespace std;
int main() {
string input;
while (true) {
cout << "Type your input: ";
getline(cin, input);
cout << input << endl;
}
return 0;
}
What am I doing wrong?
EDIT: To clarify, I expect that after the input from the input file is finished, getline waits for more input from stdin. Instead, it continues to read when nothing is there.
You don't have a terminating condition for your loop: while (true) is an infinite loop in any case - that is, without a break/exit/etc. in the loop body.
I'm guessing that when using your program to echo stdin you end it by pressing Ctrl-C. Run your program using ./a.out, and type Ctrl-D (EOF): you'll also get an infinite loop.
Look over the docs for getline: use the return value to end your loop:
while (getline(cin, input))
Your loop has no terminating condition, be it a break, or right inside the while part. Instead, you probably want this:
while (getline(cin, input))
That will end when the input fails, most likely resulting from having reached EOF.
What you're doing wrong is that you ignore the result of an input operation, in this case getline.
You must never ignore the result of an input operation. It is always a programming error to do so. You cannot know or make assumptions about the state of external data, so you must always check whether an input operation succeeded. If it does not, then it is generally an error to access the purported input variable for reading, so you really need to check every time, and before accessing the result.
In the present case, std::getline returns a reference to the stream object, and you can evaluate the stream as a boolean. It evaluates as true if and only if the extraction succeeded; otherwise, you must not use the result (and presumably stop reading).
All in all, the code should go like this:
for (std::string line; std::getline(std::cin, line); )
{
// use "line"
}