Is there a way to have exceptions work indefinitely? - c++

I have been trying to take an input from the user. I want to ensure that the input meets my requirements for the rest of the code for which I have used a try and catch block.
However, after only one time catching, it aborts the code. I want to ensure that after catching error it actually goes back to the input function for as many times until the user gives the program a valid input. Is there a way to do that except not using try catch blocks altogether?
Here's the code:
#include <iostream>
#include <string>
#include <typeinfo>
using namespace std;
long num; // I need num as global
long get_input()
{
string input;
long number;
cout << "Enter a positive natural number: ";
cin >> input;
if ( !(stol(input)) ) // function for string to long conversion
throw 'R';
number = stol(input);
if (number <= 0)
throw 'I';
return number;
}
int main()
{
try
{
num = get_input();
}
catch (char)
{
cout << "Enter a POSTIVE NATURAL NUMBER!\n";
}
// I want that after catch block is executed, the user gets chances to input the correct number
// until they give the right input.
return 0;
}

You need explicitly write such a handling, e.g. via loop:
int main()
{
while (1) {
try
{
num = get_input();
return 0; // this one finishes the program
}
catch (char)
{
cout << "Enter a POSTIVE NATURAL NUMBER!\n";
}
}
}

Related

C++ advice on exception handling

As I am very new to exceptions, I am having some trouble with the below memory exception code. Basically, I would need to calculate and show sum of 10 positive inputs. During the input, my program should use exception mechanism to display a message that it doesn't allow negative numbers / not-a-numbers (NaN) if so is the input and then exit the program. I am told to use std::cin.fail() to detect whether the value entered fits the variable type(but I am not sure how to implement it). Would appreciate your help thanks!
#include <iostream>
int main() {
int number;
int a=-2;
try {
for(int i=0; i<10;i++) {
std::cin>>number;
}
}
catch (...) {
number==-number?
std::cout << "Its negative"<<std::endl;
number==a?
std::cout << "Its NaN"<<std::endl;
}
}
You say "10 positive inputs", but you have int number;. If your number is going to be an integer, then it can't take fractions like 33.44 for instance, and it also can't be NaN (so you wouldn't need to check for that). If you want to allow fractions, do double number instead. That aside, the check could look like this:
for (int i = 0; i < 10; i++) {
std::cin >> number;
if (std::cin.fail()) {
std::cin.clear();
std::string input;
std::cin >> input;
std::cout << "input failed! Invalid input: " << input << std::endl;
return -1;
}
After every inputted number, you do the std::cin.fail() check. If it failed, you can just return. In this example, I also made it print the invalid input. For that you need to call std::cin.clear(); to reset that error flag, and then you can put that invalid input into an std::string (which should work, unlike with the number). You need to include <string> for that. If you don't need to print anything, you can just return and forget about the clearing, the string and the output. Also, in this example, since the mess made by the invalid input is neatly cleaned up, you could take more (valid) inputs again if you don't return instead.
Next, checking for negative numbers:
if (number < 0) {
std::cout << "Error: Negative number!" << std::endl;
return -1;
}
Finally, the NaN check (for double):
if (isnan(number)) {
std::cout << "Error: number is NaN!" << std::endl;
return -1;
}
You need to include <math.h> for the isnan.
Putting it all together, it could look like this:
#include <iostream>
#include <string> // std::istream >> std::string
#include <math.h> // isnan
int main() {
double number;
for (int i = 0; i < 10; i++) {
std::cin >> number;
if (std::cin.fail()) {
std::cin.clear();
std::string input;
std::cin >> input;
std::cout << "input failed! Invalid input: " << input << std::endl;
return -1;
}
if (number < 0) {
std::cout << "Error: Negative number!" << std::endl;
return -1;
}
if (isnan(number)) {
std::cout << "Error: number is NaN!" << std::endl;
return -1;
}
}
return 0;
}

Program does nothing when run

This program is a very simple one, a guessing game, however the issue is that when I compile it, it displays no errors. When I run it, it does nothing. I have tried fixing it, in that I moved the code within the guess() function back into main, and that works, printing "Enter a number between 0 & 100: ". Then when you do enter a number, it freezes, and this is probably caused by the lack of stop condition for the recursion. As I am not returning integers, as main has to, I reverted back to using the guess() function, and I have no idea why it doesn't work.
#include <iostream>
#include <cstdlib>
#include <string>
int computer = rand() % 101;
int user = 0;
int counter = 0;
std::string guess();
int main(void) {
std::string guess();
return 0;
}
std::string guess() {
std::cout << "Enter a number between 0 & 100: ";
std::cin >> user;
if(!(std::cin >> user)) {
return "You entered a non-numeric. Try again. Tries will not be added.";
std::cin.clear();
std::cin.ignore(10000, '\n');
std::string guess();
}
else {
if(user == computer) {
std::cout << "You guessed the right number of " << computer << " in " << counter << " tries.\n";
}
else {
if(user < computer) {
return "The answer is higher. Try again.";
}
else if(user > computer) {
return "The answer is lower. Try again.\n";
}
counter++;
std::string guess();
}
}
}
Note that I am very much a novice programmer, and the issue is probably quite simple and obvious, but I just can't see it. Thanks.
The problem is, that your often write std::string guess(); in order to call your guess() method (e.g. in main. But that doesn't call the method. What it actually does is to declare a new function guess, which is never called (see also Most vexing parse). To only call the method simply write guess();, or auto result = guess(); if you actually want to use the return value.
Also there is an error in this part of your code (see comment):
if(!(std::cin >> user)) {
return "You entered a non-numeric. Try again. Tries will not be added.";
// the following lines are never executed, since you already returned.
std::cin.clear();
std::cin.ignore(10000, '\n');
std::string guess();
}
Issue
The issue is indeed simple and obvious:
std::string guess();
It's obvious that you would like to call your "guess" function, but instead you've just declared it inside "main" and inside "guess".
These declarations are similar to the declaration that you made on the next line after int counter = 0;. It tells compiler that if it encounters call to the function named "guess" it should know that it is a function that takes no arguments and returns std::string.
So, the issue is that instead of calling a function, you declared it several times;
Solution
When you want to call your function you should do it like this:
std::string result = guess();
But since you return some message from guess() I think you should add output after that:
std::cout << result << std::endl;
Actually, I think it would be better to remove return value altogether. In order to do that you should modify "guess" function in a following way:
change return type from std::string to void
replace return with std::cout <<.
Many mistakes.
Firstly you don't need string return type.
So change std::string guess() to void guess()
Then use cin.fail() instead of !(cin>>user)
Also use else if rather than
else{
if{
To generate random number, firstly intialize seed and that can't be done globally, so generate random number in main and pass it in guess function.
To summarize here is the code
#include <iostream>
#include <cstdlib>
#include <string>
#include<ctime>
int user = 0;
int counter = 0;
void guess(int computer);
int main(void) {
srand(time(NULL));
int computer = rand() % 101;
guess(computer);
return 0;
}
void guess(int computer) {
std::cout << "Enter a number between 0 & 100: ";
std::cin >> user;
//std::cout<<computer<<std::endl;
if(std::cin.fail()) {
std::cout<< "You entered a non-numeric. Try again. Tries will not be added.";
std::cin.clear();
std::cin.ignore(10000, '\n');
guess(computer);
}
else if(user == computer) {
std::cout << "You guessed the right number of " << computer << " in " << counter << " tries.\n";
return;
}
if(user < computer) {
std::cout<< "The answer is higher. Try again.\n";
}
else if(user > computer) {
std::cout<< "The answer is lower. Try again.\n";
}
counter++;
guess(computer);
}

How to throw an std::iostream failure in C++?

How do I manually throw an std::iostream::failure?
I have a try-catch loop that catches an exception when the user tries to input a non-integer string, however it does not throw an exception if the user tries to input a float since it will try to read everything before the decimal point in a float value. My solution is to manually throw the exception if there is still data remaining in the stream, how do I do that?
/*
Sample Implementation Code in C++
Handling Inputs from User in C++
This code only stops running when the user
inputs the appropriate values. Otherwise, the program
will continue asking the user for input.
*/
#include <iostream>
#include <limits> //numeric_limits
#include <stdexcept>
int main() {
std::cin.exceptions(std::ios::failbit); // set exceptions to be thrown when a failbit is set
int num = 0;
int den = 0;
while (true) {
try {
std::cout << "Enter numerator: ";
std::cin >> num;
if(std::cin.peek() != '\n') {
//HOW TO DO THIS PART?
std::iostream::failure e;
throw e;
}
std::cout << "Enter denominator: ";
std::cin >> den;
std::cout << "The quotient is " << num/den << std::endl;
} catch (std::iostream::failure& e){
std::cout << "Input should be an integer." << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
return 0;
}
Apparently it's as simple as:
throw std::iostream::failure("");
the important thing I forgot is the empty string ("") since it has a constructor that takes a string argument but not a void argument.

C++ input validation

I am beginning C++ programming, and have to do a lot of input validation. I have found this function that seems universally applicable, but am having trouble with one aspect; If I were to type -90, the program doesn't give an error. my question(s) are:
1. How can I add the circumstance that input cannot be <= 0?
2. Is there a better way to limit users input? Maybe a library within C++?
Thank you for any help, or advice.
#include <ios> // Provides ios_base::failure
#include <iostream> // Provides cin
template <typename T>
T getValidatedInput()
{
// Get input of type T
T result;
cin >> result;
// Check if the failbit has been set, meaning the beginning of the input
// was not type T. Also make sure the result is the only thing in the input
// stream, otherwise things like 2b would be a valid int.
if (cin.fail() || cin.get() != '\n')
{
// Set the error state flag back to goodbit. If you need to get the input
// again (e.g. this is in a while loop), this is essential. Otherwise, the
// failbit will stay set.
cin.clear();
// Clear the input stream using and empty while loop.
while (cin.get() != '\n')
;
// Throw an exception. Allows the caller to handle it any way you see fit
// (exit, ask for input again, etc.)
throw ios_base::failure("Invalid input.");
}
return result;
}
Usage
inputtest.cpp
#include <cstdlib> // Provides EXIT_SUCCESS
#include <iostream> // Provides cout, cerr, endl
#include "input.h" // Provides getValidatedInput<T>()
int main()
{
using namespace std;
int input;
while (true)
{
cout << "Enter an integer: ";
try
{
input = getValidatedInput<int>();
}
catch (exception e)
{
cerr << e.what() << endl;
continue;
}
break;
}
cout << "You entered: " << input << endl;
return EXIT_SUCCESS;
}
You can use functions to validate
template <typename T>
T getValidatedInput(function <bool(T)> validator) {
T tmp;
cin >> tmp;
if (!validator(tmp)) {
throw ios_base::failure("Invalid input.");
}
return tmp;
}
Usage
int input = getValidatedInput<int>([] (int arg) -> bool {
return arg >= 0;
});
std::istream::operator >> is defined in terms of strtol, strtoul, and cousins*, which unfortunately all invariably accept a minus sign even for unsigned types.
Essentially all you can do is accept signed int input and compare the result to zero. std::cin.setf( std::ios::failbit ) artificially raises a conversion exception, so you can sort-of emulate how the conversion function should behave on error, but that might not really be much help.
* operator >> is defined in terms of std::num_get, which is defined in terms of scanf, which is defined in terms of strto*. Everyone just passed the buck, but strtoul is pretty surely defective.
Use unsigned int as a template parameter.
Only you can setup a rules about what input is valid and what is not.
I hope this is what you're after, it exit's upon entering zero, but will display negative numbers. It throws an exception error due to the input catch method.
#include "stdafx.h"
#include <iostream>
using namespace std;
void inputcatch()
{
cin.clear();
cin.ignore(cin.rdbuf()->in_avail());
}
int main()
{
int input;
bool quit = false;
while (!quit)
{
cout << "Enter number" << endl;
cin >> input;
if (cin.fail())
{
inputcatch();
cout << "incorrect input" << endl;
}
else if (input == 0)
{
quit = true;
}
else
{
cout << "your number: " << input << endl;
}
}
return 0;
}

How do I sanitise cin?

Say I have a program that takes in integers. How do I stop the program from falling apart if the user enters an out of range number, or a letter or something?
The cin's base class is std::basic_istream. The input stream indicates a recoverable error in case it cannot extract the requested data from the stream. In order to check for that error bit, std::basic_istream::fail() method must be used — it returns true if there was a failure or false if everything is alright. It is important to remember that if there is an error, the data is left in the stream and, of course, the error bit(s) must also be cleared using std::basic_istream::clear(). Also, a programmer must ignore incorrect data, or otherwise an attempt to read something else will fail again. For that purpose, std::basic_istream::ignore() method can be used. As for the valid range of values, it must be checked manually. Okay, enough theory, here is a simple example:
#include <limits>
#include <iostream>
int main()
{
int n = 0;
for (;;) {
std::cout << "Please enter a number from 1 to 10: " << std::flush;
std::cin >> n;
if (std::cin.fail()) {
std::cerr << "Sorry, I cannot read that. Please try again." << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
continue;
}
if (n < 1 || n > 10) {
std::cerr << "Sorry, the number is out of range." << std::endl;
continue;
}
std::cout << "You have entered " << n << ". Thank you!" << std::endl;
break;
}
}
Hope it helps. Good Luck!
I prefer reading the input as strings, and then sanitizing them with boost::lexical_cast<>:
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
int main () {
std::string s;
while( std::cin >> s) {
try {
int i = boost::lexical_cast<int>(s);
std::cout << "You entered: " << i << "\n";
} catch(const std::bad_cast&) {
std::cout << "Ignoring non-number: " << s << "\n";
}
}
}
Postscript: If you are allergic to Boost, you can use this implementation of lexical_cast:
template <class T, class U>
T lexical_cast(const U& u) {
T t;
std::stringstream s;
s << u;
s >> t;
if( !s )
throw std::bad_cast();
if( s.get() != std::stringstream::traits_type::eof() )
throw std::bad_cast();
return t;
}
something like this should do you need to clear the buffer after checking aswell if i remember right
if (cin.fail())
{
cout<<"need to put a number"<<endl;
cin.clear();
cin.ignore();
}
If You dont want to add libraries to your code you could also use do..while() statements.
in your do while you will ask for user input and then receive it to your variable then in the while part you will be able to check that this is the data you are expecting if not continue to ask for the data.
just another option ....even though the answer already mentioned should work more than adequately
You can use the following code for simplest and fast checking of valid input in int :
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int intb;
while( !( cin>>intb ) ){
cin.clear ();
cin.ignore (1000, '\n');
cout<<"Invalid input enter again: "<<endl;
}
cout<<"The value of integer entered is "<<b<<endl;
return 0;
}
The while loop keeps on iterating until it gets the right input.
cin.clear() changes the error control state.
cin.ignore() removes clear the input stream so that new input can be taken again. If not done thw while loop will be in infinite state.