Catch cin exception - c++

I want to ask the user for input, which I get with cin like this
void AskForGroundstate() {
cout << "Please enter an groundstate potential value in Volt:" << endl;
if (!(cin >> _VGroundstate)) {
cin.clear();
cin.ignore();
cout << "Groundstate potential not valid." << endl;
AskForGroundstate();
}
}
_VGroundstate is a double, so if the user enters an String with not numbers, it should ask him again for a better input. But the problem is, that when the input is for example "AA", than the program executes AskForGroundstate two times, with "AAA" three times etc. Did I use the clear wrong?

The problem is that cin.ignore() drops one character; you want to drop all characters to end of line:
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
This ensures that all invalid input is dropped before end-users are prompted for input again.

Related

Avoid bad user input (string when what's asked is an integer)

I have an infinite while loop, where the user is asked for a number.
My problem is very simple: If the input is a string, I want to re-ask user for input, outputting the message "Enter a valid choice: ".
I searched, and looks like I should check for cin.fail(), then call cin.clear() and cin.ignore().
Here's my code:
int main() {
int choice;
bool failed = false;
while (true) {
if (failed) cout << "Enter a valid choice: ";
else cout << "Enter a number: ";
cin >> choice;
if (cin.fail()) {
cin.clear();
cin.ignore();
failed = true;
}
}
return 0;
}
However, this doesn't really fix my problem. Of course, it isn't printing infinitely, but for each letter extra letter , it prints another "Enter a valid choice:"
Seems like I need to call cin.ignore() for each extra letter.
Any other way of doing this?
You have an infinite loop because you are not breaking the loop even when valid input is enter. Is that what you really want? If so, at the least, you are not resetting the failed flag in valid input.
More importantly, when invalid input is entered, you are not ignoring everything that was enteted, you are only ignoring 1 char at a time. That is why you see extra prompts.
Try this instead :
int main() {
int choice;
while (true) {
cout << "Enter a number: ";
while (!(cin >> choice)) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Enter a valid choice: ";
}
}
return 0;
}
The reason it is printing so many times is because you are only clearing the state of cin, but aren't clearing the input buffer. You can do so in multiple ways:-
Use fflush(stdin) to clear the input buffer.This is the C method and can be done by including cstdio header.
Use the cin.ignore to ignore all characters in the current input stream. You can do this by replacing the line cin.ignore() which ignores a single character by this code cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n') which ignores the entire line. For this you need the limits header.
Finally you can do the same with a simple loop like while (cin.get() != '\n'){continue;} which ignores all characters till new line.
Also another approach to the same problem is to take the input in form of a string and use the strtol() or the isdigit() functions to check if the input is valid.
By the way the infinite loop is because you have not used the break statement to terminate the loop. So you can avoid this by adding
if(!failed)
break;
Also you need to change the state of Failed at the entry of each loop by adding
failed=false;
at the start of the loop body.

How to skip 'enter' in cin.ignore()

I write a code to check char 'exit' in int cin. But I find that I need to set delimiters in cin.ignore such as '\n' and input it when running command and I think that is not friendly.
How can I change the code to skip the extracting step , maybe using other code instead of cin.ignore?
Sorry for everyone who try to read my English and answer as I not a native English user.
I mean cin.ignore is to extracts and discards characters until the given character is found, is it have a way to clear the cin buffer in C++ with discarding characters without extracting?
void checkcin(int &y)
{
string input = "", ans;
cin.clear();
cin.ignore(INT_MAX, '\n');
getline(cin, input);
while (input == "exit")
{
cout << "Are you sure to exit: ";
cin >> ans;
if (ans == "yes")
{
cout << "Bye." << endl;
exit(0);
}
else if (ans == "no")
{
cout << "Then welcome back!";
cout << "Input again: ";
cin >> input;
}
}
y = std::stoi(input);
}
The first parameter in the "std::cin.ignore()" that you are using just comes down to a very large number. This should be the maximum number of characters that the input buffer can hold. This number may be different on different systems or even header files for different compilers.
You need to press enter twice because there is nothing in the buffer to ignore. It is waiting for something to be entered to ignore. some people will use this to pause the program before the "return 0;".

Clear entire line from cin instead of one character at a time when the user enters bad input

I have a question on some commands for cin. I'm still very new to c++ so bear with me.
I'm doing a simple calculation program where the user inputs a value and the program does a calculation with the input. I'm attempting to create a loop that checks the input to ensure the user inputted and number. After some research I found that using cin.clear and cin.ignore will clear the previous input so the user can input a new value after the loop checks to see if its not a number. It works well, except when the user inputs a word larger then 1 letter. It then loops and removes each letter one at a time until the previous cin is cleared. Is there a way to remove the entire word rather then one character at a time? I feel I have incorrectly interpreted what the cin commands actually do.
Here is the code in question:
//Ask the user to input the base
cout << "Please enter the Base of the triangle" << endl;
cin >> base;
//A loop to ensure the user is entering a numarical value
while(!cin){
//Clear the previous cin input to prevent a looping error
cin.clear();
cin.ignore();
//Display command if input isn't a number
cout << "Not a number. Please enter the Base of the triangle" << endl;
cin >> base;
}
I think you could get the answer in many ways on the net. Still this works for me:
#include <iostream>
#include <limits>
using namespace std;
int main() {
double a;
while (!(cin >> a)) {
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cout << "Wrong input, retry!" << endl;
}
cout << a;
}
This example is simpler than the one linked in the comments since you are expecting input from the user, one input per line.

C++ if(!cin) causes loop

I tried to use if(!cin) to validate if the user input really is an integer. However my programm then just goes into an infinite loop never asking vor new input
do{
cin >> temp->data;
if(!cin){
cout << "Please enter a Number!" << '\n';
correct=false;
}
}while(correct==false);
Would be great if someone could help me :)
When std::cin fails to read the input, the appropriate error flags are set. Therefore you want to reset the flags using std::cin.clear() so that the next input operation will work correctly and then skip everything until the new line using std::cin.ignore(..) in order to avoid similarly formatted input.
while (!(std::cin >> temp->data))
{
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "\nPlease enter a number!" << std::endl;
}
std::numeric_limits<std::streamsize>::max() returns the max amount of characters a stream can hold so that the whole line is guaranteed to be ignored.
If you want to do that kind of check, read the data from cin to a string and convert the string to a number:
string str;
do{
cin >> str;
if(!cin){
cout << "Please enter a Number!" << '\n';
correct=false;
}
else{
istringstream stream(str);
stream >> temp->data;
if(!stream){
cout << "Please enter a Number!" << '\n';
correct=false;
}
}
}while(correct==false);
Use cin.fail() to check whether the user entered correct input. cin.fail() returns true if the last cin command failed, and false otherwise. Moreover, your loop is likely to be infinite, so you must also state an else where you will set the check flag correct to true. Thus, to invalidate the loop's condition and exit the loop in the case user entered correct input (see code below):
do{
cin >> temp->data;
if(cin.fail()){
cin.clear();
cin.ignore(10000, '\n');
cout << "Please enter a Number!" << '\n';
correct=false;
} else {
correct=true;
}
}while(correct==false);
Your 'correct' variable actually doesn't do anything the way you are using it. It's not possible to exit the loop without correct being true; so you could do away with it, and just use a loop-exiting command when you have read the number.
Also, none of the answers posted so far handle the input being closed. They would go into an infinite loop in that scenario.
// A loop; we will break out when we successfully read a number.
while ( 1 )
{
// Prompt for a number and read it
cout << "Please enter a Number!" << endl;
cin >> temp->data;
// Exit loop if we successfully read
if ( cin )
break;
// Check to see if we failed due to the input being closed
if ( cin.eof() )
{
cerr << "End of input reached.\n";
return 0; // depends what your function returns of course
}
// reset the error condition that was caused by trying to read an integer and failing
cin.clear();
// discard anything they previously typed
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
Moving on from this, a good design would be to actually have this code be an entire function in itself. Then you can call the function whenever you need to get a number safely, without needing to duplicate code. The function declaration might be:
void input_number(int &the_number, std::istream &in, std::string prompt);
which would output the_number, and it would handle end-of-file either by throwing an exception, or by relying on the caller to check for !cin, or even by returning a bool; whatever fits in best with your error handling overall.
For one, if you put a "!" before a condition in an if statement. That's supposed to be a "not" operator.

Catch ios::failure keeps looping

The code below should check every input once and display "Not a number" whenever the input is not a number.
int input;
while (1 == 1){
cout << "Enter a number: ";
try{
cin.exceptions(istream::failbit);
cin >> input;
}catch(ios::failure){
cout << "Not a number\n";
input = 0;
}
}
The problem is that when the catch is called (when it is not a number) it displays "Invalid number" endlessly like if the while() loop was executed several times but without asking for any new input.
while(true) or while(1) [or for(;;)] are customary ways to make a "forever loop".
You need to "clean up" the input that isn't acceptable within the cin stream.
The typical approach is to call cin.ignore(1000, '\n'); which will ignore all input until the next newline [up to 1000 characters - you can choose a bigger number, but usually a 1000 is "enough to get to a newline].
You will almost certainly also (thanks Potatoswatter) need to call cin.clear(); on the input, to remove the failed state, so that next input can succeed. [And cin.ignore() is further input, so it needs to go before that - just to be clear].
Though you failed to extract characters from the stream into an int, those characters remain in the stream so that you can attempt to extract them as something else, instead.
To skip them entirely, run std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); inside your catch block.
Then, whatever the user enters next will be the first thing in the stream. And perhaps that'll be a number, so your next attempt to extract into an int succeeds.
Well yeah. Your try-catch statement is inside the loop. So you try something, it fails and throws an exception, then you catch the exception, and you never exit or return from the loop so you do the same thing all over again.
But since your input wasn't processed the first time (throwing an exception instead), it's not going to be processed the second time, or the third time, or any time.
To advance, handle the exception by ignoring the input until the next space:
int input;
while (1 == 1){
cout << "Enter a number: ";
try{
cin.exceptions(istream::failbit);
cin >> input;
}catch(ios::failure){
cout << "Not a number\n";
input = 0;
//the line below ignores all characters in cin until the space (' ')
//(up to 256 characters are ignored, make this number as large as necessary
cin.ignore(256, ' ');
}
}
By the way, as a general rule: exceptions should be for something that is truly exceptional, particularly since there is overhead for handling the exception. There is debate about whether invalid user input is exceptional.
As an alternative, you can make a much more compact, equally correct loop without exceptions like the following:
int input;
while (true){ //outer while loop that repeats forever. Same as "while(1 == 1)"
cout << "Enter a number: ";
//The following loop just keeps repeating until a valid value is entered.
//The condition (cin >> input) is false if e.g. the value is a character,
//or it is too long to fit inside an int.
while(!(cin >> input)) {
cout << "Not a number" << endl;
input = 0;
}
}