How do you write a foolproof error response?

My little brother, to whom I show my little programs regularly, always laughs at the fact that all he needs to do to crash them is type letters into the variable inputs. Can I stop him doing this with an error message?

(At the moment, I'm not concerned with how to reset the program or anything. All I want is an error message.)

My current code is this:

1
2
3
4
5
    cout   << "Input a variable."; double x_h; cin >> x_h;

        if (!(x_h<1e100 && x_h>-1e100))
            {cout << "Error: your number is too big or small. Try again next time.";
            exit(1);}


This works if the number is obscenely big or small. Is there any way to modify this so I can test to see if the variable a letter?

Thanks,
Tom
Last edited on
When I need to idiot-proof my inputs in C++, I usually have the data read into a stringstream, check the string for anything that isn't allowed to be there (stray characters, invalid syntaxes), and then output it into the variable(s) of choice from the stringstream.

-Albatross
It's not a bad idea to also provide a minimal example or at least a reference link along with your explanation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <sstream>
#include <string>

using namespace std;

int main()
{
    string input;
    double number;

    while (true)
    {
        cout << "enter a number: ";
        getline(cin, input);

        if (input == "") break;

        stringstream buffer(input);

        buffer >> number;

        if ( !(buffer && buffer.eof()) )
            cout << "dude... wtf? -.-" << endl;
        else
            cout << "you entered: " << number << endl;
    }

    return 0;
}

Useful link -> http://cplusplus.com/reference/iostream/stringstream/
Another useful link -> http://cplusplus.com/articles/D9j2Nwbp/

The same can be done with cin, for that matter, avoiding the getline/stringstream altogether.

(Albeit slightly differently... you won't check for eof, and you will need to reset the stream state and clear the input stream on error (2 lines of code).
If you're only dealing with numbers, I agree. However, if you're dealing with strings too, you'll
probably want to use getline. And if you're going to use getline, it's better to use it for numbers too.

Thanks everyone, but I'm very new to programming in general. As a result, m4aster r0shi's links kind of went over my head a bit. Is there a simple way to explain what a stringstream (or a string, for that matter) is?

Does "break" mean just come out of the endless "while" loop?

Is <sstream> only used to include the stringstream function?
And what is the purpose of the <string> header?

What does the getline function do?

And what does .eof mean, and why does it relate to what's trying to be done?

Thanks a lot guys :S
TentPegSlayer wrote:
Does "break" mean just come out of the endless "while" loop?

Yes.

TentPegSlayer wrote:
what is the purpose of the <string> header?

It allows us to use string objects.

TentPegSlayer wrote:
What does the getline function do?

Exactly what its name says. There are two variations, one
that works with strings and one that works with char arrays:

http://cplusplus.com/reference/string/getline/
http://cplusplus.com/reference/iostream/istream/getline/

TentPegSlayer wrote:
Is <sstream> only used to include the stringstream function?

Yes, it allows us to use stringstream objects.

This line -> stringstream buffer(input); creates a stringstream
object named buffer and initializes its internal string to input.

http://cplusplus.com/reference/iostream/stringstream/ says:
stringstream provides an interface to manipulate strings as if they were input/output streams

You can think of stringstreams as cin/cout objects, except the
data got/put from/to keyboard/screen is got/put from/to strings.

TentPegSlayer wrote:
And what does .eof mean, and why does it relate to what's trying to be done?

Treating buffer as a bool is a shortcut to writing buffer.good(). If an input operation fails for any reason, buffer.good() returns false.
EOF stands for End Of File. If buffer's internal string is consumed, buffer.eof() returns true. I'll try to answer this using examples.

enter a number: abc123
dude... wtf? -.- // number is untouched,  bool(buffer) is false, buffer internal string is "abc123", buffer.eof() is false
enter a number: 123abc
dude... wtf? -.- // number is set to 123, bool(buffer) is true,  buffer internal string is "abc",    buffer.eof() is false
enter a number: 123
you entered: 123 // number is set to 123, bool(buffer) is true,  buffer internal string is "",       buffer.eof() is true

You may also find this useful -> http://cplusplus.com/forum/beginner/40285/#msg217380

EDIT:

m4ster r0shi wrote:
Treating buffer as a bool is a shortcut to writing buffer.good(). If an input operation fails for any reason, buffer.good() returns false.

This is not right. Treating buffer as a bool is a shortcut to writing !buffer.fail().

http://cplusplus.com/reference/iostream/ios/operator_voidpt/
http://cplusplus.com/reference/iostream/ios/good/
http://cplusplus.com/reference/iostream/ios/fail/
Last edited on
Okay, I'm starting to understand it. Though I'm starting to think my base knowledge of C++ just isn't good enough to try strings yet.

I'll do a bit of background reading, and come back to attack this again in a few months.

Thanks for your help, m4ster r0shi!
Using stringstreams is the preferred method (and is easier then the one below, once you fully understand them.) However, here is an example using just strings to help you understand why reading input from cin into a string will allow you to validate your data.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <string>

using namespace std;

int main() {
	string str; //create a string (the C++ version of char[])
	getline(cin, str); //read a line of text from cin, unlike "cin >> str" which only reads to the first whitespace character
	//WARNING: Using "getline(cin, __)" and "cin >> __" in the same program will cause unintuitive behavior
	for( int i = 0; i < str.length(); i++ ) //loop through each charecter of str
		if( str[i] < '0' || str[i] > '9' ) { //if str[i] is not one of the characters between '0' and '9', i.e. str[i] is not a digit
			cerr << "ERROR: Why do you do this?" << endl; //print an error message to cerr (the standard error stream)
			return 1; //finish (quit/exit) our program, and return an error code to the environment signifying that the program did not run correctly
		}
	//if we make it here then all the characters in str must be digits
	double num = aotf( str.c_str() ); //one way to parse (convert, interpret) the string str as a double
	//NOTE: str.c_str() will return the equivalent char[] (char*, null-terminated, C string)
	... //do stuff with num
	return 0;
}
Topic archived. No new replies allowed.