Simple try catch looping solution for c++ - c++

I can't see why this fails. Why does it loop forever after throwing the error?
bool undone;
do
{
undone = false;
try
{
o.spr(); // function throwing error E object
}
catch(E &r)
{
undone = true;
cout << r.reason << endl;
}
}
while(undone);
Here is the function:
void spr()
{
E r;
int n;
cout << " put n : "<<endl;
cin >> n;
if (cin.fail())
{
r.reason="fail !!";
throw r;
}
cout << " your n is : "<< n;
}

Your problem is recovering after the error.
First you have to clear the error flag from cin using cin.clear(). Then you have to read the bad input so it doesn't cause an error next time:
void spr()
{
E r;
int n;
cout << " put n : "<<endl;
cin >> n;
if (cin.fail())
{
cin.clear(); // clear the error flag
std::string bad_input;
cin >> bad_input; // skip over bad input
// now it is safe to re-use cin
r.reason="fail !!";
throw r;
}
cout << " your n is : "<< n;
}
Probably a better way to skip the bad input:
void spr()
{
E r;
int n;
cout << " put n : "<<endl;
cin >> n;
if (cin.fail())
{
cin.clear(); // clear the error flag
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // skip over bad input
r.reason="fail !!";
throw r;
}
cout << " your n is : "<< n;
}
The cin.ignore() function skips over the maximum possible number of input characters until it gets to an end of line '\n' character.

In case o.spr() throws, you set undone to true. Then condition in while() is checked, and it's true, so it loops, tries to call o.spr() again, and so on... Reconsider your undone flag and its value.

Related

Why is my nested while-loop looping infinitely?

I am having trouble getting this nested while-loop to function how I want it to.
#include <iostream>
#include <math.h>
double time_to_ground(double);
int main() {
std::cout.precision(4);
bool go = 1;
double height{};
while (go) {
std::cout << "Please enter the height of the building in meters.\n";
std::cin >> height;
while (height < 0) {
std::cout << "\nPlease enter a positive number.\n";
std::cin >> height;
}
double time = time_to_ground(height);
std::cout << "It will take " << time << " seconds for the ball to reach the ground to reach the ground.\n";
std::cout << "Go again?\n0) no\n1) yes\n";
std::cin >> go;
//This loop breaks the code
while (!((go == 0) || (go == 1))) {
std::cout << "Enter either:\n0) no\n1) yes\n";
std::cin >> go;
}
}
return 0;
}
double time_to_ground(double height) {
return sqrt(2 * height / 9.81);
}
The idea is simply just to make sure the user only inputs a 0 or 1. It works fine if I put a 0 or 1, However when I run the code and input say, a 6, I get stuck in an infinite loop!
Thanks in advance!
You have declared go as a bool but you are trying to read it as an integer.
Just change bool go = 1; to int go = 1;
Trying to read an integer input that is not 0 or 1 into a boolean variable fails and once cin has failed all input using cin will fail until you clear the error. That's why you get an infinite loop.
An alternative way of writing the loop is to check for the input error directly. You can keep the go variable as bool and write this
while (!(std::cin >> go))
{
std::cin.clear(); // clear the cin error
std::cout << "Enter either:\n0) no\n1) yes\n";
}
This works because std::cin >> go will return false if the input fails. Notice that I clear the error once it has occurred.
An alternate solution to this would be to keep bool go = 1; and then replace:
while (!((go == 0) || (go == 1))) {
std::cout << "Enter either:\n0) no\n1) yes\n";
std::cin >> go;
}
with:
while (std::cin.fail())
{
std::cin.clear();
std::cout << "Enter either:\n0) no\n1) yes\n";
std::cin >> go;
}
std::cin.fail() returns true if the last std::cin input failed. But will return false otherwise.
std::cin.clear() clears the error flag on std::cin.
use int data type in your main function
int go = 1;
instead of bool
bool go = 1;
bool can not handle values other than 0,1
it will work.

C++ can't call same function twice with different parameters

I have a C++ program that calls the same function tempGauge() twice. It hits the first call then skips the second call and goes to userData() and gives me the error "finished with exit code 6". when I comment out the first call the second call works as expected and ends with the exit code 0.
int tempGuage(int &array, int &actDay);
void userData();
int main() {
const int totalTemp(10);
int firstDay[totalTemp];
int secondDay[totalTemp];
int dayOne = 1;
int dayTwo = 2;
tempGauge(firstDay[totalTemp], dayOne);
tempGauge(secondDay[totalTemp], dayTwo);
userData();
return 0;
}
int tempGauge(int &array,int &actDay)
{
int i;
int maxTemps;
for(i=1;i < maxTemps;++i)
{
cout << "Enter # of temps on DAY " << actDay <<":";
cin >> maxTemps;
if(maxTemps <=0||maxTemps>=11)
{
cout << "Enter at least 1 but no more than 10. Try again.";
}
else
{
cout << "Enter the " << maxTemps << " temps(s):";
cin >>array;
i++;
}
}
return array;
}
Your code has undefined behavior.
Both of your calls to tempGuage() are passing in invalid int& references in the 1st parameter, as the [totalTemp] index is accessing an int that is beyond the bounds of each array. So, even if tempGauge() worked properly (which it doesn't), it would be filling in invalid memory. Since you clearly want to fill the arrays, you need to change [totalTemp] to [0] instead so you start filling at the beginning of each array rather than at the end.
Inside of tempGauge(), maxTemps is uninitialized when entering the loop, so the number of iteration is indeterminate. But, even if it weren't, the statement cin >>array; does not read in an entire array, like you are expecting. Even if it could, it would not know how many ints to read, since array is declared as a reference to a single int and you can't pass maxTemps to operator>>. You would need a loop to read each int individually, which you are trying to do, but you are not looping correctly. And also, cin >> array would need to be changed to cin >> array[i];, which won't work unless int &array is changed to either int (&array)[10] or int *array. In which case, main() would then have to be updated accordingly, by dropping the [0] when passing in each array.
With that said, try this instead:
#include <limits>
const int totalTemp = 10;
int tempGuage(int (&array)[totalTemp], int actDay);
void userData();
int main()
{
int firstDay[totalTemp] = {};
int secondDay[totalTemp] = {};
tempGuage(firstDay, 1);
tempGuage(secondDay, 2);
userData();
return 0;
}
int tempGuage(int (&array)[totalTemp], int actDay)
{
int maxTemps;
cout << "Enter # of temps on DAY " << actDay << ":";
do
{
if (!(cin >> maxTemps))
{
cout << "Invalid input. Try again.";
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
else if ((maxTemps <= 0) || (maxTemps > totalTemp))
{
cout << "Enter at least 1 but no more than " << totalTemp << ". Try again.";
}
else
{
cout << "Enter the " << maxTemps << " temps(s):";
for(int i = 0; i < maxTemps; ++i)
{
while (!(cin >> array[i]))
{
cout << "Invalid input for temp " << i+1 << ". Try again.";
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
break;
}
}
while (true);
return maxTemps;
}
void userData()
{
//...
}
Live Demo

Something strange inside while when try to validate data

I'm trying to make do while loop what will validate data! When wrong data got should ask again. BUT when wrong data got program do loop again with skipping cin >> a;
Here two validation codes what I already tried:
1st one [Pic of console]
int a;
do
{
a = NULL;
cout << "Press some number: ";
cin >> a;
} while (a>=0 || a<=0);
2nd one: [Pic of console]
int a;
do
{
cin.clear(); cin.sync();
cout << "give me number: "; cin >> a;
} while (cin.fail());
This way you can check input is number or not:
int a;
bool flag=false;
while (true)
{
flag=false;
std::string input;
std::cout << "Press some number: ";
std::getline(std::cin,input);
try
{
a = stoi(input);
}
catch(const std::exception& e)
{
std::cout <<"Invalid number" << std::endl;
flag=true;
}
if (!flag)
break;
There are other ways to do this but i didn't mess your head with vectors or other things.

Integer validation for input

I tried to prompt user for input and do the validation. For example, my program must take in 3 user inputs. Once it hits non-integer, it will print error message and prompt for input again. Here is how my program going to be look like when running :
Enter number: a
Wrong input
Enter number: 1
Enter number: b
Wrong input
Enter number: 2
Enter number: 3
Numbers entered are 1,2,3
And here is my code:
double read_input()
{
double input;
bool valid = true;
cout << "Enter number: " ;
while(valid){
cin >> input;
if(cin.fail())
{
valid = false;
}
}
return input;
}
My main method:
int main()
{
double x = read_input();
double y = read_input();
double z = read_input();
}
When my first input is non-integer, the program just exits by itself. It does not ask for prompting again. How could I fixed it? Or am I supposed to use a do while loop since I asking for user input.
Thanks in advance.
When the reading fails, you set valid to false, so the condition in the while loop is false and the program returns input (which is not initialized, by the way).
You also have to empty the buffer before using it again, something like:
#include <iostream>
#include <limits>
using namespace std;
double read_input()
{
double input = -1;
bool valid= false;
do
{
cout << "Enter a number: " << flush;
cin >> input;
if (cin.good())
{
//everything went well, we'll get out of the loop and return the value
valid = true;
}
else
{
//something went wrong, we reset the buffer's state to good
cin.clear();
//and empty it
cin.ignore(numeric_limits<streamsize>::max(),'\n');
cout << "Invalid input; please re-enter." << endl;
}
} while (!valid);
return (input);
}
Your question did get myself into other issues like clearing the cin on fail() --
double read_input()
{
double input;
int count = 0;
bool valid = true;
while(count != 3) {
cout << "Enter number: " ;
//cin.ignore();
cin >> input;
if(cin.fail())
{
cout << "Wrong Input" <<endl;
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
else
count++;
}
return input;
}
The problem is in the while condition
bool valid = true;
while(valid){
You loop until you get a non valid input, this absolutly not what you want! loop condition should be like this
bool valid = false;
while(! valid){ // repeat as long as the input is not valid
Here is a modified version of your read_double
double read_input()
{
double input;
bool valid = false;
while(! valid){ // repeat as long as the input is not valid
cout << "Enter number: " ;
cin >> input;
if(cin.fail())
{
cout << "Wrong input" << endl;
// clear error flags
cin.clear();
// Wrong input remains on the stream, so you need to get rid of it
cin.ignore(INT_MAX, '\n');
}
else
{
valid = true;
}
}
return input;
}
And in your main you need to ask for as may doubles as you want, for example
int main()
{
double d1 = read_input();
double d2 = read_input();
double d3 = read_input();
cout << "Numbers entered are: " << d1 << ", " << d2 << ", " << d3 << endl;
return 0;
}
You may also want to have a loop where you call read_double() and save the returned values in an array.

How to catch this exception C++

I'd like to catch exception which occurs when somebody gives not a number value on the cin so the program will read next value.
#include <iostream>
using namespace std;
int main()
{
int x = 0;
while(true){
cin >> x;
cout << "x = " << x << endl;
}
return 0;
}
If you really want to use exception handling, you could do something like this:
cin.exceptions(ios_base::failbit); // throw on rejected input
try {
// some code
int choice;
cin >> choice;
// some more code
} catch(const ios_base::failure& e) {
cout << "What was that?\n";
break;
}
Reference: http://www.cplusplus.com/forum/beginner/71540/
There is no exception being thrown at all. Instead, cin sets a "bad input" flag of sorts. What you want is this:
while ((std::cout << "Enter input: ") && !(std::cin >> x)) {
std::cin.clear(); //clear the flag
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n'); //discard the bad input
std::cout << "Invalid input; please re-enter.\n";
}
This series of questions explains it really well.
Links:
clear()
ignore()
Add something like:
if(cin.fail())
{
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(),' ');
cout << "Please enter valid input";
}
int main()
{
int x = 0;
cin.exceptions(ios::failbit);
while(true){
try
{
cin>>x;
}
catch(ios_base::failure& e)
{
//..
}
cout<<"x = "<<x<<endl;
}
return 0;
}
This should work.