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;
}
Related
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.
I'm working through a text book for self study. I can do the while loop no problem, but I have no idea how to do the terminating character.
Here is what I have now:
#include "../../std_lib_facilities.h" // Supplied by book author
int main()
{
int ii = 0;
int yy = 0;
bool test = true;
cout << "Enter two ints" << endl;
while (test)
{
cin>>ii, cin>>yy;
// this if statement doesn't work
if (ii == '|' || yy == '|')
{
test = false;
}
// this if statement catches all bad input, even the terminating '|'
if (cin.fail())
{
cout << "bad input";
cin.clear();
cin.ignore();
continue;
}
else
cout << ii << yy << endl;
}
return 0;
}
Streams can be a little confusing if you're unfamiliar with them. It's a large topic that's just going to require more research. Here's an example that should work, to hopefully get you started.
int main(int argc, char* argv[])
{
bool test = true;
while ( test ) {
std::cout << "Enter two integers> ";
int x, y;
// if this fails, stream is bad.
// #note this will fail for any input which cannot be interpreted
// as an integer value.
if (std::cin >> x >> y) {
std::cout << x << " " << y << std::endl;
}
else {
// clear stream error state so we can read from it again.
std::cin.clear();
// check for terminating character; else unknown.
if (std::cin.get() == '|')
std::cout << "Terminator found, exiting." << std::endl;
else
std::cerr << "Error: bad input, exiting." << std::endl;
// in either case the loop terminates.
test = false;
}
}
return 0;
}
Hope this helps. Good luck.
Use the cin.peek() function as follows, before you input the two numbers:
c=(cin >> ws).peek();
if(c=='|')
{
cout<<"exiting";return 1;
}
Note: (cin>>ws) is to get rid of leading whitespaces. Also, c is of type char.
The complete code now looks like this:
int main()
{
int ii = 0;
int yy = 0;
bool test = true;
cout << "Enter two ints" << endl;
while (test)
{
char c;
c=(cin >> ws).peek();
if(c=='|')
{
cout<<"exiting";return 1;
}
cin>>ii, cin>>yy;
if (cin.fail())
{
cout << "bad input";
cin.clear();
cin.ignore();
continue;
}
else
cout << ii << yy << endl;
}
return 0;
}
Okay, I am very new to try-except. I do-not know if what i'm trying to do is possible, but thought i'd ask for input anyway.
My program is supposed to average x amount of user inputs until he/she enters q.
Here is the function that is giving me the most problems.
vector user_input()
{
vector<double> scores;
string user_command;
do{
double user_input;
cout << "Enter the scores to be averaged (range 0-100) or enter q to quit: " << endl;
cin >> user_command;
if (is_number(user_command))
{
user_input = atof(user_command.c_str());
if (user_input < 0 || user_input > 100)
cout << "This is not within range!" << endl;
else{
scores.push_back(user_input);}
}
}
while (user_command != "q" && user_command != "Q");
return scores;
}
I need some insight on why this program won't compile. Any help would be appreciated
You haven't clearly specified your requirements which makes it difficult to know how to answer the question. I'm assuming you want something like this:
#include <string>
#include <vector>
#include <iostream>
#include <sstream>
typedef double score_type; //so we don't need to write 'double' everywhere, makes it easy to change the type
void user_input(std::vector<score_type>& scores)
{
std::string command;
for (;;)
{
score_type score;
std::cout << "Enter the scores to be averaged (range 0-100) or enter q to quit: " << std::endl;
std::cin >> command;
if (command == "q" || command == "Q")
{
//works better than a do-while in this case
break;
}
try
{
//stod to throw std::invalid_argument and std::out_of_range, check documentation (http://en.cppreference.com/w/cpp/string/basic_string/stof)
score = std::stod(command.c_str());
}
catch (std::exception e)
{
//build exception string
std::ostringstream oss;
oss << "bad input: " << command;
//throw new exception to be handled elsewhere
throw std::exception(oss.str().c_str());
}
if (score < 0 || score > 100)
{
std::cerr << "Input is not within range (0-100)!" << std::endl;
}
scores.push_back(score);
}
}
int main()
{
for (;;)
{
std::vector<score_type> scores;
try
{
user_input(scores);
}
catch (std::exception e)
{
std::cout << "input exception: " << e.what() << std::endl;
}
score_type score_sum = 0;
for (auto score : scores)
{
score_sum += score;
}
score_type average_score = 0;
if (!scores.empty())
{
average_score = score_sum / scores.size();
}
std::cout << "average score: " << average_score << std::endl;
std::cout << "go again? (y/n): " << std::endl;
std::string command;
std::cin >> command;
if (command == "y")
{
continue;
}
else if (command == "n")
{
break;
}
}
}
In future, make sure all the code you post in future questions can be compiled and ran by anyone, especially for simple stuff like this. You can use http://ideone.com/ to test your code samples before posting.
I have a question that might be very simple to many of you however, I have not found an answer to my question.
I have the program below that is working properly. This code turns a number into a floating number and integer.
Let's say you entered 5.4, the program will give you 5.4 for double and 5 for integer.
Now I need to add a throw catch statement to my program in case the user enters a text instead of a number ("If the conversion fails, throw an exception and allow the user to re-enter the value.").
This is the pseudocode of what I need to do.
try {
if(num ==character)
throw;
cout << "\n The number entered " << num << "invalid, please enter again";
}
catch
{
}
and I implemented something like this, however it did not work. I set the 'a' variable character thinking the user has to enter a text in order to get that message. However it did not work and gave some errors.
try
{
char a;
if (num == a)
throw num;
}
catch(int e)
{
cout << "A number of " << a << " is invalid." << endl;
cout << "Please re-enter a number: ";
cin << num
}
I am very new with this "try,throw,catch" terms. I would be happy if you help me through this, thanks.
#include <C:\\CSIS1600\MyCppUtils.cpp>
#include <iostream>
#include <string>
using namespace myNameSpace;
int main()
{
runner("is running");
cout << "Enter a number : ";
string num;
getline(cin, num);
cout<< "double " << getValidDouble(num) << endl;
cout<< "integer " << getValidInt(num) << endl;
system("pause");
return 0;
}
#include<iostream>
#include<string>
using namespace std;
namespace myNameSpace
{
string num;
void runner(string str)
{
cout <<"runner-3() is running.."<<endl;
}
int getValidInt(string n)
{
int valueint;
valueint=atoi(n.c_str());
return valueint;
}
double getValidDouble(string n )
{
double valuedouble;
valuedouble = atof(n.c_str());
return valuedouble;
}
}
You can use Boost to do a lexical cast. If you have valid input (e.g. 2.54), no exception will be thrown, but with invalid input (e.g. 2???54) the bad_lexical cast is thrown:
#include <boost/lexical_cast.hpp>
try
{
double x1 = boost::lexical_cast<double> ("2.54");
double x2 = boost::lexical_cast<double> ("2???54");
cout << x1 << x2 << endl;
}
catch(boost::bad_lexical_cast& e)
{
cout << "Exception caught - " << e.what() << endl;
}
try
{
int selection;
if(selection > 4 || selection < 1)
throw selection;
}
catch(int selection)
{
cout << "Menu selection out of range." << endl;
}
The above code works fine for int values that are out of range, but I cannot get it to work if a char value is entered at (cin >> selection).
I have tried to post a catch block with an ellipsis [catch(...)] to account for char entries but that does not work.
I have also tried a catch block with [catch(char selection)] but that does not work either.
I would like to use an exception to handle this error as it would help in my overall project in other menu type areas.
You should try something with that snippet :
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
while (true) {
cout << "Please enter a valid number: ";
getline(cin, input);
// This code converts from string to number safely.
stringstream myStream(input);
if (myStream >> myNumber)
break;
cout << "Invalid number, please try again" << endl;
}
You can make cin capture input using a string, and throw an exception if you can't parse it as an int. One way of doing it would be to use the str2int function from Dan Moulding's answer in the following manner:
std::string str;
cin >> str;
int selection;
STR2INT_ERROR err = str2int(selection, str.c_str());
try
{
if(err != SUCCESS || selection > 4 || selection < 1)
throw str;
}
catch(std::string &selection)
{
cout << "Menu selection [" << selection << "] invalid" << endl;
}
{
int a;
try
{
cout << "Enter:";
cin >> a;
if (!a)
{
throw 1;
}
cout<<"Int";
}
catch (...)
{
cout << " no. Should be int" << '\n';
}
}
be careful
this code only work if input is char not if input is float