I'm having a problem with my exception handling. It seems to work with negative input, but whenever I try to enter a character, it gets stuck in an infinite loop in the first try/catch block.
I try clear() and ignore() for cin, but it still didn't work. I tried a different if statement for input, such as (if ((ft >100)) || (in >100)), and the exception is thrown just fine.
Am I missing something?
#include <iostream>
using namespace std;
class convert
{
private:
int feet;
int inch;
public:
convert() = default;
double calculation(int ft, int in)
{
double cm = 0;
cm = ((ft * 30.48) + (in * 2.54));
return cm;
}
};
class negativeNumber
{};
class invalidInput
{};
int main()
{
int ft;
int in;
double cm = 0;
convert h;
while (true)
{
try
{
cout << "Please enter your height in (ft, in) format" << endl;
cin >> ft;
cin >> in;
if ((ft < 0) || (in < 0))
{
throw negativeNumber();
}
if (cin.fail())
{
throw invalidInput();
}
cm = h.calculation(ft, in);
cout << "Your height in cm is: " << cm << endl;
break;
}
catch (negativeNumber)
{
cout << "You entered negative numbers. Try again" << endl;
system("pause");
}
catch (invalidInput)
{
cout << "You entered a character. Try again" << endl;
system("pause");
}
}
return 0;
}
You absolutely need to call cin.clear() and cin.ignore() when input fails to read. You need to clear cin's error state in order to continue reading input, and you need to remove the failed data from cin's input buffer so you don't keep reading the same data over and over.
Also, you should check for input failure before checking for negatives. ft and in will not have valid values if they fail to read.
Also, you should always catch exceptions by (const) reference, not by value.
Try this instead:
#include <iostream>
#include <limits>
using namespace std;
class convert
{
public:
static double calculation(int ft, int in)
{
double cm = 0;
cm = ((ft * 30.48) + (in * 2.54));
return cm;
}
};
class negativeNumber
{};
class invalidInput
{};
int main()
{
int ft;
int in;
double cm;
while (true)
{
try
{
cout << "Please enter your height in (ft, in) format" << endl;
if (!(cin >> ft >> in))
{
throw invalidInput();
}
if ((ft < 0) || (in < 0))
{
throw negativeNumber();
}
cm = convert::calculation(ft, in);
cout << "Your height in cm is: " << cm << endl;
break;
}
catch (const negativeNumber &)
{
cout << "You entered a negative number. Try again" << endl;
system("pause");
}
catch (const invalidInput &)
{
cout << "You entered bad input. Try again" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
system("pause");
}
}
return 0;
}
Related
I am trying to get the addition done on the following method defined in my code, but after submitting the user input the program just return an exception instead of addition.
Exception:
terminate called after throwing an instance of 'std::invalid_argument'
what(): stoi
This application has requested the Runtime to terminate it in an
unusual way. Please contact the application's support team for more
information.
Code:
#include <iostream>
#include <string>
using namespace std;
bool inputValidation_F(string userInput_VSTR1, string userInput_VSTR2)
{
for (int inputChecker_V = 0; inputChecker_V < userInput_VSTR1.length() || userInput_VSTR1.length() && inputValidation_F; inputChecker_V ++)
if (!(userInput_VSTR1[inputChecker_V] || userInput_VSTR2[inputChecker_V] >= 48 && userInput_VSTR1[inputChecker_V] || userInput_VSTR2[inputChecker_V] <= 57))
return false;
return true;
}
void mainMenu_F();
void userChoice_F();
void calCulations_F(double, double);
void resultAddition_F(double, double);
int main()
{
mainMenu_F();
}
void mainMenu_F()
{
cout << "Main Menu:" << '\n';
cout << "-------------------------------" << '\n';
cout << "Enter + for Addition" << '\n';
cout << "-------------------------------" << '\n';
cout << "Choose any Option from the List" << '\n';
cout << "-------------------------------" << '\n';
userChoice_F();
}
void userChoice_F()
{
double addition_V_1;
double addition_V_2;
char uChoice_V;
cin >> uChoice_V;
switch (uChoice_V)
{
case '+':
cout << "Addition: Enter the first value: "; cin >> addition_V_1;
cout << "Addition: Enter the second value: "; cin >> addition_V_2;
calCulations_F(addition_V_1, addition_V_2);
}
}
void calCulations_F(double addition_V_1, double addition_V_2)
{
string addition_V_1STR;
string addition_V_2STR;
addition_V_1 = stod (addition_V_1STR);
addition_V_2 = stod (addition_V_2STR);
bool additionChecker_F;
additionChecker_F = inputValidation_F (addition_V_1STR, addition_V_2STR);
if (!additionChecker_F)
additionChecker_F = false;
else resultAddition_F (addition_V_1, addition_V_2);
}
void resultAddition_F(double addition_V_1, double addition_V_2)
{
double resultAddition_V = (addition_V_1 + addition_V_2);
cout << "The result for the addition of the Entered values is: [" << resultAddition_V << "]" << '\n';
}
terminate called after throwing an instance of 'std::invalid_argument' what(): stoi
The reason's here:
void userChoice_F() {
.
.
// passing two 'double' parameters
calCulations_F(addition_V_1, addition_V_2);
}
void calCulations_F(double addition_V_1, double addition_V_2)
{
double resultAddition_V; // redundant
string addition_V_1STR; // created, uninitialized
string addition_V_2STR; // created, uninitialized
// you're overriding the parameters here
addition_V_1 = stoi (addition_V_1STR); // convert ? to double
addition_V_2 = stoi (addition_V_2STR); // again here
// better put stod() with a valid string here
.
.
}
Firstly, you're trying to convert the string into an integer and store it in a double, that's not a very useful idea, try std::stod() instead. But still that'll fail because addition_V_1STR and addition_V_2STR are empty (never assigned before), they're useless here.
Other problems:
In the 6th line, you're comparing an integer to a long unsigned int, that's a bad practice.
In the same line, userInput_VSTR1.length() && inputValidation_F will never be NULL.
resultAddition_V is redundant here.
I think this solution will solve your Issues and Misunderstandings, Your code is edited and if you have any question, ask in comment or chat section, I will be happy to help you.
#include <iostream>
#include <string>
#include <limits>
using namespace std;
bool isvalid_(string);
bool inputValidation_F(string userInput_VSTR1, string userInput_VSTR2)
{
for (int inputChecker_V = 0; inputChecker_V < userInput_VSTR1.length() || userInput_VSTR1.length() && inputValidation_F; inputChecker_V ++)
if (!(userInput_VSTR1[inputChecker_V] || userInput_VSTR2[inputChecker_V] >= 48 && userInput_VSTR1[inputChecker_V] || userInput_VSTR2[inputChecker_V] <= 57))
return false;
return true;
}
void mainMenu_F();
void userChoice_F();
void calCulations_F(double, double);
void resultAddition_F(double, double);
int main()
{
mainMenu_F();
}
void mainMenu_F()
{
cout << "Main Menu:" << '\n';
cout << "Enter + for Addition" << '\n';
userChoice_F();
}
void userChoice_F()
{
double addition_V_1, addition_V_2;
char uChoice_V;
cin >> uChoice_V;
switch (uChoice_V)
{
case '+':
cout << "Addition: Enter the first value: "; cin >> addition_V_1;
cout << "Addition: Enter the second value: "; cin >> addition_V_2;
while(!isvalid_("Ops! Entered invalid value, Try again."));
calCulations_F(addition_V_1, addition_V_2);
break;
default:
cout << "Invalid Choice," << '\n';
}
}
void calCulations_F(double addition_V_1, double addition_V_2)
{
if (!inputValidation_F)
bool isvalid_ = 0;
else resultAddition_F (addition_V_1, addition_V_2);
}
void resultAddition_F(double addition_V_1, double addition_V_2)
{
double resultAddition_V = (addition_V_1 + addition_V_2);
cout << "The result for the addition of the Entered values is: [" << resultAddition_V << "]" << '\n';
}
bool isvalid_(string err_msg)
{
if(cin.rdstate())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>:: max(), '\n');
system("cls");
cout << "Invalid number entry! Try again from the Beginning." << '\n';
mainMenu_F();
return false;
}
return true;
}
I know this is a lot of code but it's just a program that prompts for speed, altitude, fuel, and direction and catches any errors. If an error is thrown then the program should stop and if there is no error than the program should just display all the values. My problem is that whenever the last try-catch statement(InvalidDirection) catches an error the program still runs the showAll function.
#pragma once
#include <iostream>
using namespace std;
class FlightInfo
{
private:
int absoluteAltitude = 0;
int speed = 0;
int fuelLevel = 0;
int direction = 0;
public:
class InvalidSpeed
{};
class InvalidDirection
{};
class InvalidFuelLevel
{};
class InvalidAltitude
{};
// setters
//valid 0-10000
void setAbsoluteAltitude(int alt) {
if (alt >= 0 && alt <= 10000) {
absoluteAltitude = alt;
}
else {
throw InvalidAltitude();
}
}
//valid 0 - 650
void setSpeed(int currentSpeed) {
if (currentSpeed >= 0 && currentSpeed <= 650) {
speed = currentSpeed;
}
else {
throw InvalidSpeed();
}
}
// Valid 0 - 100
void setFuelLevel(int level) {
if (level >= 0 && level <= 100) {
fuelLevel = level;
}
else {
throw InvalidFuelLevel();
}
}
// valid 0-359
void setDirection(int heading) {
if (heading >= 0 && heading <= 359) {
direction = heading;
}
else {
throw InvalidDirection();
}
}
// getters
int getAbsoluteAltitude() {
return absoluteAltitude;
}
int getSpeed() {
return speed;
}
int getFuelLevel() {
return fuelLevel;
}
int getDirection() {
return direction;
}
void showAll() {
cout <<"Altitude = " << getAbsoluteAltitude() << endl;
cout <<"Speed = " << getSpeed() << endl;
cout <<"FuelLevel = " << getFuelLevel() << endl;
cout <<"Direction = " << getDirection() << endl;
}
};
Here is my driver/cpp file
#include "FlightInfo.h"
#include <iostream>
using namespace std;
int main() {
FlightInfo flight;
int getTheSpeed;
int getTheAltitude;
int getTheFuel;
int getTheDirection;
cout << "Enter Speed ";
cin >> getTheSpeed;
try {
flight.setSpeed(getTheSpeed);
}
catch (FlightInfo::InvalidSpeed)
{
cout << "ERROR: speed less than 0 or greater than 650" << endl;
}
cout << "Enter altitude ";
cin >> getTheAltitude;
try {
flight.setAbsoluteAltitude(getTheAltitude);
}
catch (FlightInfo::InvalidAltitude)
{
cout << "ERROR: Altitude less than 0 or greater than 10000" << endl;
}
cout << "Enter Fuel Level ";
cin >> getTheFuel;
try {
flight.setFuelLevel(getTheFuel);
}
catch (FlightInfo::InvalidFuelLevel)
{
cout << "ERROR: Fuel level less than 0 or greater than 100" << endl;
}
cout << "Enter direction ";
cin >> getTheDirection;
try {
flight.setDirection(getTheDirection);
}
catch (FlightInfo::InvalidDirection)
{
cout << "ERROR: Direction is less than 0 or greater than 359" << endl;
}
flight.showAll();
system("pause");
return 0;
}
The Problem:
Even when the last try-catch statements catch an error the program still runs the showAll function.
The Reason:
None of the catch clauses exits the program.
Possible Solutions:
In every catch clause, put a return <any number other than zero>.
Do not catch the Exceptions.
In every catch clause, put an exit clause.
I am not sure that I see the issue with what you described. Are you expecting when invalid direction is thrown the program does not get to showall()?:
cout << "Enter direction ";
cin >> getTheDirection;
try {
flight.setDirection(getTheDirection);
}
catch (FlightInfo::InvalidDirection)
{
cout << "ERROR: Direction is less than 0 or greater than 359" << endl;
}
flight.showAll();
But here you are "catch"ing the exception and handling it. Therefore the program continues. If you want it to end you will need to re-throw or not catch the exception:
cout << "Enter direction ";
cin >> getTheDirection;
//try {
flight.setDirection(getTheDirection);
//}
//catch (FlightInfo::InvalidDirection)
//{
// cout << "ERROR: Direction is less than 0 or greater than 359" << endl;
//}
flight.showAll();
Now your inner "throw" will not be caught and your program will end.
//Benjamin McKinney
//CSCI 2010-10
//Spring 2015
//PASS 3
//Programmed on Windows 8.1 using Visual C++ 2010 Express
//This program plays the game MasterMind
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
using namespace std;
struct Player
{
string Name;
int HighScores[6];
bool CheatOn;
};
struct Board
{
int NumHoles;
int Holes[6];
};
struct Guess
{
int Count;
int NumHoles;
int Holes;
};
void printHighScores(string);
void readHighScore(string);
void updateHighScore(string, int);
string getPlayer();
int getBoard();
void playGame(string);
void menu(string);
int main()
{
Player p;
srand((unsigned int)time(0));
cout << "!!! Benjamin McKinney's Master-MasterMind!!!\n";
cout << "--------------------------------------------\n";
getPlayer();
menu(p.Name);
cout << "Goodbye, " << p.Name << endl;
printHighScores(p.Name);
cout << "----------------------------------------------\n";
cout << "!!! Benjamin McKinney's Master-MasterMind!!!\n";
system("PAUSE");
return 0;
}
void printHighScores(string name)
{
return;
}
void readHighScore(string)
{
return;
}
void updateHighScore(string, int)
{
return;
}
string getPlayer()
{
Player p;
cout << "What is your name?\n";
cin >> p.Name;
cout << "Welcome, " << p.Name << endl;
p.CheatOn = false;
readHighScore(p.Name);
return p.Name;
}
int getBoard()
{
Board b;
cout << "Enter the number of holes you would like: ";
cin >> b.NumHoles;
if(b.NumHoles > 6 || b.NumHoles < 1)
{
cout << "Error! You must pick a number between 1 and 6! Try again!\n";
}
for(int i=0;i<b.NumHoles;i++)
{
b.Holes[i] = rand() % 2 + 1;
}
return b.NumHoles;
}
void playGame(string)
{
Player p;
Board b;
Guess g;
getBoard();
g.Count=0;
for(int i=0;i<b.NumHoles;i++)
{
cout << "Enter your guess for the row\n";
if(p.CheatOn == true)
{
for(int a=0;a<(sizeof(b.Holes)-1);a++)
{
cout << b.Holes[a];
}
}
cout << "Enter your guess for hole " << i << ": ";
cin >> g.Holes;
g.Count++;
}
return;
}
void menu(string)
{
Player p;
char choice;
cout << "Please choose an option below:\n";
cout << "\t P)lay\n\t Q)uit\n\tChoice: ";
cin >> choice;
if(choice == 'P')
playGame(p.Name);
else
if(choice == 'Q')
return;
else`enter code here`
if(choice == 'C')
{
p.CheatOn = true;
playGame(p.Name);
}
}
Ignore the three HighScore functions, but otherwise I can't get this to work... "Run-Time Check Failure #3 - The variable 'b' is being used without being initialized." is the main issue that I'm having. If anyone can help me I would really appreciate it. Thanks!
In the playGame function:
void playGame(string)
{
Player p;
Board b; // <----- uninitialized
// ...
for(int i=0;i<b.NumHoles;i++)
// ^^^^^^^^^^
you use b.NumHoles when you have never initialized b.
I guess you intended that getBoard() would magically have some effect on b but it doesn't. The getBoard function updates a local board but never does anything with it.
To fix this you could change getBoard to return the whole board:
Board getBoard()
{
Board b;
// set up b...
return b;
}
and then inside playGame:
Board b = getBoard();
There's another error just below:
for(int a=0;a<(sizeof(b.Holes)-1);a++)
The sizeof operator gives the size in bytes. You actually want the size in elements, so you need to divide by the element size:
a < (sizeof b.Holes / sizeof b.Holes[0])
I'm not sure what the -1 was meant to be doing either, this would just cause you to not output the last hole.
How would I check if the input is really a double?
double x;
while (1) {
cout << '>';
if (cin >> x) {
// valid number
break;
} else {
// not a valid number
cout << "Invalid Input! Please input a numerical value." << endl;
}
}
//do other stuff...
The above code infinitely outputs the Invalid Input! statement, so its not prompting for another input. I want to prompt for the input, check if it is legitimate... if its a double, go on... if it is NOT a double, prompt again.
Any ideas?
Try this:
while (1) {
if (cin >> x) {
// valid number
break;
} else {
// not a valid number
cout << "Invalid Input! Please input a numerical value." << endl;
cin.clear();
while (cin.get() != '\n') ; // empty loop
}
}
This basically clears the error state, then reads and discards everything that was entered on the previous line.
failbit will be set after using an extraction operator if there was a parse error, there are a couple simple test functions good and fail you can check. They are exactly the opposite of each other because they handle eofbit differently, but that's not an issue in this example.
Then, you have to clear failbit before trying again.
As casablanca says, you also have to discard the non-numeric data still left in the input buffer.
So:
double x;
while (1) {
cout << '>';
cin >> x;
if (cin.good())
// valid number
break;
} else {
// not a valid number
cout << "Invalid Input! Please input a numerical value." << endl;
cin.clear();
cin.ignore(100000, '\n');
}
}
//do other stuff...
I would use:
double x;
while (!(std::cin >> x)) {
std::cin.clear();
std::cin.ignore(2147483647, '\n');
std::cout << "Error.\n";
}
or
double x;
while ((std::cout << "> ") && !(std::cin >> x)) {
std::cin.clear();
std::cin.ignore(2147483647, '\n');
std::cout << "Error.\n";
}
#include <iostream>
#include <string>
bool askForDouble(char const *question, double &ret)
{
using namespace std;
while(true)
{
cout << question << flush;
cin >> ret;
if(cin.good())
{
return true;
}
if(cin.eof())
{
return false;
}
// (cin.fail() || cin.bad()) is true here
cin.clear(); // clear state flags
string dummy;
cin >> dummy; // discard a word
}
}
int main()
{
double x;
if(askForDouble("Give me a floating point number! ",x))
{
std::cout << "The double of it is: " << (x*2) << std::endl;
} else
{
std::cerr << "END OF INPUT" << std::endl;
}
return 0;
}
bool is_double(double val)
{
bool answer;
double chk;
int double_equl = 0;
double strdouble = 0.0;
strdouble = val;
double_equl = (int)val;
chk = double_equl / strdouble;
if (chk == 1.00)
{
answer = false; // val is integer
return answer;
} else {
answer = true; // val is double
return answer;
}
}
One way is to check for floating number equality.
double x;
while (1) {
cout << '>';
cin >> x;
if (x != int(x)) {
// valid number
break;
} else {
// not a valid number
cout << "Invalid Input! Please input a numerical value." << endl;
}
}
When running the following code and enter a number, it works fine.
But when entering a letter, the program enters an infinite loop, displaying "Enter a number (0 to exit): cin failed."
My intent was to handle the cin fail case and prompt the user again.
int number;
do{
cout << "Enter a number (0 to exit): ";
cin >> number;
if(cin.fail()){
cout << "cin failed." << endl;
cin.clear();
}else{
cout << "cin succeeded, " << number << " entered." << endl;
}
}while(number != 0);
You need to clear the line from cin, using cin.ignore, in addition to clearing the stream state (which is what cin.clear does).
I have several utility functions to make this easier (you'll be interested in clearline in particular, which clears the stream state and the current line) and almost an exact example of what you want.
Your code, more or less, using my clearline:
#include "clinput.hpp" // move my file to a location it can be used from
int main() {
using namespace std;
while (true) {
cout << "Enter a number (0 to exit): ";
int number;
if (cin >> number) {
cout << "Read " << number << '\n';
if (number == 0) {
break;
}
}
else {
if (cin.eof()) { // tested only *after* failed state
cerr << "Input failed due to EOF, exiting.\n";
return 1;
}
cerr << "Input failed, try again.\n";
clearline(cin); // "cin >> clearline" is identical
}
}
return 0;
}
There is still a potential issue here (fixed in my clinput_loop.cpp with blankline), with leaving input in the buffer that will screw up later IO (see "42 abc" in the sample session). Extracting the above code into a separate and self-contained function is left as an exercise for the reader, but here's a skeleton:
template<class Type, class Ch, class ChTr>
Type read(std::basic_istream<Ch,ChTr>& stream, Ch const* prompt) {
Type value;
// *try input here*
if (could_not_get_input or more_of_line_left) {
throw std::runtime_error("...");
}
return value;
}
template<class Type, class Ch, class ChTr>
void read_into(
Type& value,
std::basic_istream<Ch,ChTr>& stream,
Ch const* prompt
) {
value = read<Type>(stream, prompt);
}
Example use:
int n;
try {
read_into(n, std::cin, "Enter a number: ");
}
catch (std::runtime_error& e) {
//...
raise;
}
cout << "Read " << n << '\n';
clearline function extracted for posterity, in case above links ever break (and slightly changed to make self-contained):
#include <istream>
#include <limits>
template<class C, class T>
std::basic_istream<C,T>& clearline(std::basic_istream<C,T>& s) {
s.clear();
s.ignore(std::numeric_limits<std::streamsize>::max(), s.widen('\n'))
return s;
}
The template stuff is a bit confusing if you're not used to it, but it's not hard:
std::istream is a typedef of std::basic_istream<char, std::char_traits<char> >
std::wistream is a typedef of std::basic_istream<wchar_t, std::char_traits<wchar_t> >
widen allows '\n' to become L'\n' as appropriate
this code works for both of the common char and wchar_t cases, but also any compatible instantiation of basic_istream
it's written to be called as clearline(stream) or stream >> clearline, compare to other manipulators like std::endl, std::ws, or std::boolalpha
This is probably what you intended to do:
#include <iostream>
using namespace std;
int main ()
{
int i;
do {
if (cin.fail())
{
cin.ignore(255);
cin.clear();
}
cout << "Please enter an integer value: ";
cin >> i;
} while ( cin.fail() );
cout << "The value you entered is " << i;
return 0;
}
This is simple example of cin.fail()
It will process input until a valid integer value is provided
#include <iostream>
using namespace std;
int main()
{
int j;
int i;
i = 0;
while (1) {
i++;
cin >> j;
if (cin.fail()) return 0;
cout << "Integer " << i << ": " << j << endl;
}
}
Input:
42 51 85 hello 85
Output:
Integer 1: 42
Integer 2: 51
Integer 3: 85