Infinite loop on EOF in C++ - c++

This code works as desired for the most part, which is to prompt the user for a single character, perform the associated action, prompt the user to press return, and repeat. However, when I enter ^D (EOF) at the prompt, an infinite loop occurs. I am clearing the error state via std::cin.clear() and calling std::cin.ignore(...) to clear the buffer. What could be causing the infinite loop?
#include <iostream>
#include <limits>
void wait()
{
std::cout << std::endl << "press enter to continue.";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin.clear();
std::cin.get();
}
int main()
{
char response;
while (true)
{
std::cout << "enter a character at the prompt." << std::endl << "> ";
std::cin >> response;
switch (response)
{
case 'q':
exit(0);
break;
}
wait();
}
}
I am running this in the Mac OS X terminal, if it matters.
UPDATE: What I am really asking here is, when the user enters EOF (^D) at the prompt, how do I (a) detect it and (b) reset the stream so that the user can continue to enter data.
The following example is different from the code above, but illustrates the same principle of clearing the stream after a ^D has been detected and continuing to read from that stream.
> a
you entered: a
> b
you entered: b
> ^D
you entered EOF
> c
you entered: c
...

You should always check whether any of a stream's failure flags are set after calling formatted extraction operation, in your example you are checking response without checking whether response was correctly extracted.
Also, you are using std::endl in your prompt output where it doesn't make sense. std::endl prints \n and then flushes the buffer, but you then immediately print more characters so the flush is redundant. As cin and cout are (usually) tied, calling an input function for std::cin will cause std::cout to be flushed in any case so you may as well put a \n into your prompt string and save on the verbose extra << operators.
Why not make a prompting function that prints the prompt, retrieves the input an returns a reference to the stream so that you can test it for success using the usual stream to boolean type conversion.
This way you can get rid of the while true and explicit break.
std::istream& prompt_for_input( std::istream& in, std::ostream& out, char& response )
{
out << "enter a character at the prompt.\n> ";
in >> response;
return in;
}
int main()
{
char response;
while ( prompt_for_input( std::cin, std::cout, response ) && response != 'q' )
{
wait();
}
}

The question does not really make sense for standard input. It will be hard to read something from standard input after that stream has ended -- you'll have to re-open it somehow, but there is no way to re-open standard input. It might be connected to a pipe, or to a file, or to a terminal -- and there's no behaviour suitable for all of these.
So you're going to be reading explicitly from the terminal, I assume. On UN*X systems, that means reading /dev/tty, and re-opening it when needed. Here's a simple example that does it; most error-checking omitted.
// Warning: UN*X-specific
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
for(unsigned i=0; ; i++) {
ifstream tty("/dev/tty");
if (! tty) {
cerr << "Failed to open TTY" << endl;
return 2;
}
string s;
while (getline(tty,s))
cout << i << ": " << s << endl;
}
return 0; // (unreached)
}

You'll need to clear the flags to get the stream to do much of anything after it encounters EOF.

Err, I may be missing something, but I don't ever see you break out of the while (true) loop.
// ...
while (true) {
if (std::cin.eof()) {
break;
}
// ...
}

Upon reading an EOF, you just ignore it and loop back, without exiting the loop, so you'll continually read the EOF and continually loop. If you want to do something on seeing an EOF, you need to handle it either in your switch or before.
Perhaps you want to read input from somewhere after the user has closed your stdin with ^D? In that case, you'll have to close cin and reopen it to read from the other place you want to read input from.

As mentioned, you need to make sure the stream is not in a bad state. I would change while condition to use good(). Don't just check EOF as there are several ways a stream can become "bad" other than EOF.
while (std::cin.good()) {...

while ((std::cout << "Enter a character at the prompt ")
&& (!(std::cin >> response) || response =='q')) {
std::cout << "Not a valid input";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

Related

c++ stop asking for input on ctrl-d

I am trying to read user input until ctrl-d is hit. If I am correct, ctrl+d emits an EOF signal so I have tried checking if cin.eof() is true with no success.
Here is my code:
string input;
cout << "Which word starting which year? ";
while (getline(cin, input) && !cin.eof()) {
cout << endl;
...
cout << "Which word starting which year? ";
}
So you want to read until EOF, this is easily achieved by simply using a while loop and getline:
std::string line;
while (std::getline(std::cin, line))
{
std::cout << line << std::endl;
}
Here using getline(getline returns the input stream) you get the input, if you press Ctrl+D, you break out of the while loop.
It's inportant to note that EOF is triggered different on Windows and on Linux. You can simulate EOF with CTRL+D (for *nix) or CTRL+Z (for Windows) from command line.
Keep in mind that you might exit the loop in other conditions too - std::getline() could return a bad stream for some failures and you might want to consider handling those cases too.

Reading in \n and EOF from the user, if user enters a string?

I want to check if the user enters \n and EOF in the string that they enter. So far, I've tried
getline(cin, temp);
if(cin.EOF())//tried and did not work
cout << "failed EOF";
if(temp[temp.size()] == '\n')
cout << "\n";
Determining a valid extraction is more straightforward than you might think. If the extraction fails, it will be reflected in the program through the stream state of the input stream used for the extraction. Moreoever, std::getline() returns the stream, which (when implicitly converted to boolean), will check its stream state for the appropriate bits. You can take advantage of this functionality and encase the extraction in an if statement, which will implicitly convert its parameter to boolean:
if (std::getline(std::cin, temp))
If the extraction performed successfully, the if statement will execute. If you want to response to the user through the stream state, you can set the exceptions mask in stream and check for any thrown exceptions:
if (std::getline(std::cin, temp))
{
std::cout << "Extraction produced: " << temp << std::endl;
}
try {
std::cin.exceptions(std::ios_base::failbit | std::ios_base::eofbit);
}
catch (std::ios_base::failure&)
{
std::ios_base::iostate exceptions = std::cin.exceptions();
if ((exceptions & std::ios_base::eofbit) && std::cin.eof())
{
std::cout << "You've reached the end of the stream.";
}
}
The above is just an example. I haven't tried to compile it. :)

Why does the program end when I enter a number?

I began programming on C++ some days ago and something is really getting me troubles:
whenever I enter the number, the program ends.
Code:
using namespace std;
int main()
{
int entry;
cout << "Write a number: ";
cin >> entry;
cout << entry;
cin.get();
return 0;
}
I need some help here so my programs could run right.
By right I mean to output the number after ending... but it just ends after I enter the number and press enter It does not print it.
UPDATE:
For the sake of the ones who didn't understood what I was meaning (sorry for my english)
Ok let me explain.
-So the program is suposed to get the values from the keyboard right.
-I enter a number let´s say is 6, ok now I press enter.
-Alright now the number is supposed to be output on the screen, but this doesn´t happen because the program closes too fast.
But this was solved actually, by adding a second cin.get(); or by adding a cin.ignore(); after each data input petition.
Here's a slightly improved version that might be closer to what you wanted:
#include <string>
#include <sstream>
#include <iostream>
int main()
{
int n;
std::string line;
while (true)
{
std::cout << "Please enter an integer: ";
if (!(std::getline(std::cin, line))) { return 1; /* error! */ }
std::istringstream iss(line);
if (iss >> n) { break; }
}
std::cout << "Thank you. You said: " << n
<< "\n\nPlease press Enter to quit.";
std::getline(std::cin, line);
}
The error condition in the getline is triggered when the input stream is closed or otherwise terminated before another line could be read (e.g. if you hit Ctrl-D on the console). The token extraction into n fails until you enter a valid integer, and the loop will continue looping until this happens.
All you need to do is consume the newline that is left over after reading the integer.
This happens in java as well.
using namespace std;
int main()
{
int entry;
cout << "Write a number: ";
cin >> entry;
cout << entry;
cin.get(); //Consume newline
cin.get();
return 0;
}
get() reads one and only one character from the stream, so it's perfectly normal that the program ends after you enter your number.
Have a look either at the std::basic_istream<>::getline() method or, easier, std::getline() which doesn't require a dynamic buffer.
If you need more information about basic IO in C++, you can read the following documentation : Basic Input/Output - C++
Update
Like stated in the comments, I missunderstood the question, I was initially thinking that only one digit was read into the variable.
After reading carefully again, I'm unable to understand what the problem is.
The reason for this is youre using
cin.get();
return 0;
at the end of the program , the cin.get() reads the number you entered then goes straight to return 0; thus ending the program.
to stop this you can add an extra cin.get(); before return 0;
or use
system("Pause");
before return 0; instead

c++ validate number and stop infinity loop

I'm doing a console app, I'm passing an integer to the app and it works ok, but if I pass a letter, it goes crazy,
int opt=0;
std::cout<<"Pick lang:"<<'\n';
std::cout<<"1.[es-ES]:"<<'\n';
std::cout<<"2.[en-US]:"<<'\n';
std::cin >> opt;
while(opt<1 || opt>2)
{
std::cout<<"\nERROR!"<<'\n';
std::cout<<"Pick lang again:"<<'\n';
std::cout<<"1.[es-ES]:"<<'\n';
std::cout<<"2.[en-US]:"<<'\n';
std::cin >> opt;
}
I tried to use isdigit() but I get the same result. Thanks
After performing cin >> extraction, you want to check if the cin stream is still good or not. If you expect cin to extract a number but it gets something else instead, eg. like a letter, then the stream will be set to a bad state and that's why you see it 'going crazy'.
What you have to do is after input, check if cin is still good. If it's in a bad state, you need to clear its flags and then remove out any of the junk data in the stream. If you don't, then subsequent uses of cin will simply fail to function.
Taking your code snippet for example, you can change it to something like this:
int opt = 0;
bool inputGood = false;
do
{
std::cout << "Pick lang again:" << '\n';
std::cout << "1.[es-ES]:" << '\n';
std::cout << "2.[en-US]:" << '\n';
inputGood = std::cin >> opt;
if(!inputGood)
{
std::cout << "\nERROR! Invalid choice." << '\n';
cin.clear();
while( cin.get() != '\n' );
}
}while(!inputGood || opt < 1 || opt > 2);
Edit: whoops minor error in the cin error handling. Corrected and should be working now. :)
The problem is that the call std::cin >> opt is failing to parse the character and returns immediatly (without consuming the buffer), then it finds the same contents and fail....
You should check the result of the operation and react to it. One possibility would be checking the fail bit (std::cin.fail()) and failing the whole operation or consuming parts of the buffer (maybe a a single character, maybe more, depending on how you want the application to behave).
The simplest thing would probably be not reading into a number, but rather a character, and then comparing with the expected character:
char opt = 0;
do {
// prompt user for input
if (! (std::cin >> opt) ) {
// io error, report and bail out
break;
}
} while ( opt != '0' && opt != '1' );
Reading in numbers directly is
problematic
If std::cin is presented with input it
cannot process, std::cin goes into a
"fail" state The input it cannot
process is left on the input stream.
All input will be ignored by std::cin
until the "fail" state is cleared:
std::cin.clear()
A routine that reads
a number directly should:
Read in the
number
Check to see that the input
stream is still valid
If the input
stream is not good (!std::cin)
Call
std::cin.clear() to take the stream
out of the "fail" state.
Remove from
the stream the input that caused the
problem: std::cin.ignore(...)
Get the
input again if appropriate or
otherwise handle the error
more info here: http://www.augustcouncil.com/~tgibson/tutorial/iotips.html
When you insert a letter this happens:
operator>> extracts characters from the stream and try to convert them to a number;
it fails in the conversion, so it sets the stream state to ios::failbit and returns; opt probably is untouched (the standard delegates this stuff to the locale library, which is a zone of C++ that I never really understood - for the brave enough, it's at §22.2.2.1.2);
since it returned and (probably) opt is left as it is, the loop continues;
when the execution returns to std::cin >> opt;, operator>> sees that the state is still ios::failbit, so it doesn't even try to extract anything;
goto 3.
To fix the problem, you should clean the error state and remove the "wrong" characters from the input buffer. Since you probably don't want to add all that code to every cin>>, it's useful to create a function to deal with this common problem; personally, I created this little header (AcquireInput.hpp) that has proven useful many times:
#ifndef ACQUIREINPUT_HPP_INCLUDED
#define ACQUIREINPUT_HPP_INCLUDED
#include <iosfwd>
#include <limits>
#include <string>
template<typename InType> void AcquireInput(std::ostream & Os, std::istream & Is, const std::string & Prompt, const std::string & FailString, InType & Result)
{
do
{
Os<<Prompt.c_str();
if(Is.fail())
{
Is.clear();
Is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
Is>>Result;
if(Is.fail())
Os<<FailString.c_str();
} while(Is.fail());
}
template<typename InType> InType AcquireInput(std::ostream & Os, std::istream & Is, const std::string & Prompt, const std::string & FailString)
{
InType temp;
AcquireInput(Os,Is,Prompt,FailString,temp);
return temp;
}
/* Usage example:
//1st overload
int AnInteger;
AcquireInput(cout,cin,"Please insert an integer: ","Invalid value.\n",AnInteger);
//2nd overload (more convenient, in this case)
int AnInteger=AcquireInput(cout,cin, "Please insert an integer: ","Invalid value.\n");
*/
#endif

How to validate numeric input in C++

I'd like to know how to limit an input value to signed decimals using std::cin.
double i;
//Reading the value
cin >> i;
//Numeric input validation
if(!cin.eof())
{
peeked = cin.peek();
if(peeked == 10 && cin.good())
{
//Good!
count << "i is a decimal";
}
else
{
count << "i is not a decimal";
cin.clear();
cin >> discard;
}
}
This also gives an error message with the input -1a2.0 avoiding the assignation of just -1 to i.
If the backing variable of the cin is a number, and the string provided is not a number, the return value is false, so you need a loop:
int someVal;
while(!(cin >> someVal)) {
cin.reset();
cout << "Invalid value, try again.";
}
Combining the techniques from the top answer here and this website, I get
input.h
#include <ios> // Provides ios_base::failure
#include <iostream> // Provides cin
template <typename T>
T getValidatedInput()
{
// Get input of type T
T result;
cin >> result;
// Check if the failbit has been set, meaning the beginning of the input
// was not type T. Also make sure the result is the only thing in the input
// stream, otherwise things like 2b would be a valid int.
if (cin.fail() || cin.get() != '\n')
{
// Set the error state flag back to goodbit. If you need to get the input
// again (e.g. this is in a while loop), this is essential. Otherwise, the
// failbit will stay set.
cin.clear();
// Clear the input stream using and empty while loop.
while (cin.get() != '\n')
;
// Throw an exception. Allows the caller to handle it any way you see fit
// (exit, ask for input again, etc.)
throw ios_base::failure("Invalid input.");
}
return result;
}
Usage
inputtest.cpp
#include <cstdlib> // Provides EXIT_SUCCESS
#include <iostream> // Provides cout, cerr, endl
#include "input.h" // Provides getValidatedInput<T>()
int main()
{
using namespace std;
int input;
while (true)
{
cout << "Enter an integer: ";
try
{
input = getValidatedInput<int>();
}
catch (exception e)
{
cerr << e.what() << endl;
continue;
}
break;
}
cout << "You entered: " << input << endl;
return EXIT_SUCCESS;
}
Sample run
Enter an integer: a
Invalid input.
Enter an integer: 2b
Invalid input.
Enter an integer: 3
You entered: 3.
cin's >> operator works by reading one character at a time until it hits whitespace. That will slurp the whole string -1a2.0, which is obviously not a number so the operation fails. It looks like you actually have three fields there, -1, a, and 2.0. If you separate the data by whitespace, cin will be able to read each one without problem. Just remember to read a char for the second field.
I tried many techniques for reading integer input from the user using the >> operator, but in a way or another all my experiments have failed.
Now I think that getline() function (not the method with the same name on std::istream) and the strtol() function from the include cstdlib is the only predictable consistent solution for this problem. I would appreciate if someone proved me wrong. Here is something like the one I use:
#include <iostream>
#include <cstdlib>
// #arg prompt The question to ask. Will be used again on failure.
int GetInt(const char* prompt = "? ")
{
using namespace std; // *1
while(true)
{
cout << prompt;
string s;
getline(cin,s);
char *endp = 0;
int ret = strtol(s.c_str(),&endp,10);
if(endp!=s.c_str() && !*endp)
return ret;
}
}
*1: Placing using namespace whatever; to the global scope may lead to broken "unity builds" (google!) on larger projects, so should be avoided. Practice to not use that way, even on smaller projects!
Reading integers from files is a very different matter. Raúl Roa's approach can be good for that if properly worked out. I also suggest that wrong input files should not be tolerated, but it really depends on the application.
Be warned that using >> and getline() in the same program on cin will lead to some problems. Use one of them only, or google to know how to handle the issue (not too hard).
Something like:
double a;
cin >> a;
Should read your signed "decimal" fine.
You'll need a loop and some code to make sure it handles invalid input in a sensible way.
Good luck!