c++ try and catch not ending program - c++

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.

Related

Exception Handling: stuck in infinite loop if a char is entered

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;
}

String error when expanding a dynamic array

I'm having a problem with trying to append an extra element to a dynamic array. I know I can use vectors, but for academic purposes, I have to use arrays.
#include <iostream>
using namespace std;
template <class T>
class MyList
{
protected:
T* elems;
int itsSize;
public:
MyList(int itsSize):itsSize(itsSize)
{
elems = new T[itsSize];
}
~MyList()
{
delete [] elems;
}
int getSize()
{
return itsSize;
}
virtual void addElem(){}
virtual void getElem(){}
};
template <class T>
class MyStack : public MyList<T>
{
int counter;
public:
MyStack(int size):MyList<T>::MyList(size){counter=0;}
void addElem()
{
T* tmp = new T[counter+1];
for (int i = 0; i<counter+1; i++)
tmp[i] = MyList<T>::elems[i];
counter++;
delete [] MyList<T>::elems;
MyList<T>::elems = tmp;
cin >> MyList<T>::elems[counter-1];
if(cin.fail())
{
cin.clear();
string line;
getline(cin, line);
throw "Wrong String Input--> will enter 0";
}
}
void getElem()
{
for(int i=counter-1; i>=0; i--)
{
cout << "Element-->" << MyList<T>::elems[i] << endl;
}
}
};
int main()
{
int storeChoice;
cout << "Would you like to store integers, strings or rectangles (1,2, or 3)?" << endl;
cin >> storeChoice;
if(storeChoice==1)
{
MyStack<int> numList(1);
cout << "Enter num:";
numList.addElem();
bool choiceAddLoop = true;
while(choiceAddLoop == true)
{
try
{
char choiceAdd;
cout << "Would you like to enter another elem?(y/n)" << endl;
cin >> choiceAdd;
if(choiceAdd=='y')
{
try
{
cout << "Enter num:";
numList.addElem();
}
catch(const char* wrongInput)
{
cout << wrongInput << endl;
}
}
else if(choiceAdd=='n')
{
choiceAddLoop=false;
break;
}
else
throw "Invalid Input.";
}
catch(const char* invalidChoice)
{
cout << invalidChoice;
}
}
cout << endl << "All Elements" << endl;
numList.getElem();
}
else if(storeChoice==2)
{
MyStack<string> stringList(1);
cout << "Enter string:";
stringList.addElem();
bool choiceAddLoop = true;
while(choiceAddLoop == true)
{
try
{
char choiceAdd;
cout << "Would you like to enter another elem?(y/n)" << endl;
cin >> choiceAdd;
if(choiceAdd=='y')
{
cout << "Enter string:";
stringList.addElem();
}
else if(choiceAdd=='n')
{
choiceAddLoop=false;
break;
}
else
throw "Invalid Input.";
}
catch(const char* invalidChoice)
{
cout << invalidChoice;
}
}
cout << endl << "All Elements" << endl;
stringList.getElem();
}
}
When I select the first choice ( integer ) the code will work:
Would you like to store integers, strings or rectangles (1,2, or 3)?
1
Enter num:22
Would you like to enter another elem?(y/n)
y
Enter num:3
Would you like to enter another elem?(y/n)
n
All Elements
Element-->3
Element-->22
Process returned 0 (0x0) execution time : 5.162 s
Press any key to continue.
A problem occurs in the second choice (string):
Would you like to store integers, strings or rectangles (1,2, or 3)?
2
Enter string:hello
Would you like to enter another elem?(y/n)
y
Enter string:terminate called after throwing an instance of 'std::length_error'
what(): basic_string::_M_create
Process returned 3 (0x3) execution time : 6.761 s
Press any key to continue.
It's the same code for both, why does it work only with integers?
The error happens when you call MyStack<T>::addElem(). When you copy the elements from the old array to the new array your loop should stop at counter, not counter+1. Correct version:
for (int i = 0; i<counter; i++)
tmp[i] = MyList<T>::elems[i];
Accessing MyList<T>::elems[counter], which is out of bounds, results in undefined behavior. For the int-case you were just lucky that the data currently stored there could be correctly interpreted as integer, with std::string you had less luck. So the random data which you wanted to interpret as std::string caused the error you got.
Live demo

If in the input I give any character data why this will not going to throw section

#include <iostream>
using namespace std;
int main()
{
int x;
cin>>x;
cout << "Before try \n";
try {
cout << "Inside try \n";
if (x <0)
{
throw x;
//cout << "After throw (Never executed) \n";
}
}
catch (int x ) {
cout << "Exception Caught \n";
}
catch (char x ) {
cout << "Exception hjCaught \n";
}
return 0;
}
If in the input I give any character data why this will not going to throw section. Is my code is wrong because it works fine with the integer datatype.
I don't understand why you added the last catch (char x) clause.
When the program looks like this:
#include <iostream>
using namespace std;
int main()
{
int x;
cin>>x;
cout << "Before try \n";
try {
cout << "Inside try \n";
if (x <0)
{
throw x;
//cout << "After throw (Never executed) \n";
}
}
catch (int x ) {
cout << "Exception Caught \n";
}
}
It seems to work:
positive numbers won't throw exception
negative numbers throw an exception
As per according to this program, it will throw the exception when positive numbers.
But when you will enter the char input in the int variable then there will be an input failure and there will be 0 in the x.
You can check it by using this.
#include <iostream>
using namespace std;
int main()
{
int x;
cin >> x;
if (cin.fail())
{
cout << "x is " << x << endl;
}
cout << "Before try \n";
try
{
cout << "Inside try \n";
if (x < 0)
{
throw x;
//cout << "After throw (Never executed) \n";
}
}
catch (int x)
{
cout << "Exception Caught \n";
}
return 0;
}
The program output on the char input will be
a
x is 0
Before try
Inside try
As the x will have 0 so it will not throw exception as the condition is x<0

Exceptional Handling in C++ when user inputs string instead of int

I have a program that requires a user to input a integer number which then has to go to several conditions. When I run the program, if i input a int number it works but if i input a character, the programs just spams the error messages.
I think exception handling might work here but i m not sure how to do.Help out guys!
Here is a part of my prog:
#include <iostream.h>
#include <conio.h>
int i, j, data;
void main()
{
int tempdata;
retry:
cout<<"\n\n Enter the row and coloumn where you want to enter data" <<endl;
cin>>i>>j;
if (i>=1 && i<=9 && j>=1 && j<=9)
{
cout<<"\n Enter your desired value to put in that place"<<endl;
cin>>tempdata;
if(tempdata>=1 && tempdata<=9)
{
data=tempdata;
}
else
{
cout<<"\n Soduku contains numbers from 1 to 9 only.Please try again"<<endl;
goto retry;
}
}
else
{
cout<<"\nEntered row or coloumn is not valid"<<endl;
cout<<"Please try again"<<endl;
goto retry;
}
getch();
}
Instead of a cout, you should indeed use exception handling.
if(tempdata>=1 && tempdata<=9)
{
data=tempdata;
}
else
{
throw std::runtime_error("Soduku contains numbers from 1 to 9 only.Please try again");
}
By putting all this into a function, and not your main, you can then call this function within a try/catch block, and deal properly with the exception: display a pop-up message if you have a GUI, ignore the input, etc. The important part is that, if you ignore it, it is not actually ignored. It is dealt with. Which makes your code a LOT cleaner and maintainable. Example:
try
{
input();
}
catch(std::runtime_error& e)
{
// deal with your invalid input here
}
Also, goto statements are considered bad practice. They can be easily replaced by if/else or while statements, or with return codes in functions. And using them tend to make the code unreadable, difficult to follow.
You need to validate that cin >> is successful before you can then use the value entered. If the user enters data that does not match the expected type, you have to clear the error before you can read new input again.
Try this:
#include <iostream>
#include <limits>
int i, j, data;
bool isNumValid(int data) {
return ((data >= 1) && (data <= 9));
}
void clearInput() {
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
int main() {
int tempdata;
do {
std::cout << "\n\n Enter the row and column where you want to enter data" << std::endl;
if (!(std::cin >> i >> j)) {
std::cout << "\n Please enter numbers only!" << std::endl;
clearInput();
continue;
}
if (!isNumValid(i) || !isNumValid(j)) {
std::cout << "\nEntered row or column is not valid" << std::endl;
std::cout << "Please try again" << std::endl;
continue;
}
std::cout << "\n Enter your desired value to put in that place" << std::endl;
if (!(std::cin >> tempdata)) {
std::cout << "\n Please enter a number only!" << std::endl;
clearInput();
continue;
}
if (!isNumValid(tempdata) {
std::cout << "\n Soduku contains numbers from 1 to 9 only" << std::endl;
std::cout << "Please try again" << std::endl;
continue;
}
data = tempdata;
}
while (true);
std::cin.get();
return 0;
}
Alternatively:
#include <iostream>
#include <limits>
#include <stdexcept>
int i, j, data;
bool isNumValid(int data) {
return ((data >= 1) && (data <= 9));
}
void checkRowColValid(int row, not col) {
if (!isNumValid(row) || !isNumValid(col))
throw std::out_of_range("Entered row or column is not valid");
}
void checkDataValid(int data) {
if (!isNumValid(data))
throw std::out_of_range("Soduku contains numbers from 1 to 9 only");
}
int main() {
int tempdata;
std::cin.exceptions(std::ios_base::failbit);
do {
try {
std::cout << "\n\n Enter the row and column where you want to enter data" << std::endl;
std::cin >> i >> j;
checkRowColValid(i, j);
std::cout << "\n Enter your desired value to put in that place" << std::endl;
std::cin >> tempdata;
checkDataValid(tempdata);
data = tempdata;
}
catch (const std::out_of_range &e) {
std::cout << "\n " << e.what() << std::endl;
std::cout << "Please try again" << std::endl;
}
catch (const std::ios_base::failure &) {
std::cout << "\n Please enter numbers only!" << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
while (true);
std::cin.get();
return 0;
}

I keep getting the error "The variable 'b' is being used without being initialized, and I'm not sure how to fix it

//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.