0

I'm writing a program that acts as a calculator; based on the character input by the user it performs a certain operation. The structure of the program seems to work fine, but I'd like to be able to check for erroneous input. After receiving the float variable, is there any way to check if it does not contain any characters other than digits and decimals? I've tried isdigit, and this:

if (!(cin >> x)) {
    cout << "You did not enter a correct number!" << endl; 
    return;
}

But nothing seems to be working.

Here is a sample of one of the simple operation functions I'm using:

void Add(){
    float x = 0, y = 0, z = 0;
    cout << "Please enter two numbers you wish "
         << "to add separated by a white space:" << endl; 
    cin >> x >> y;
    z = x+y;
    cout << x << " + " << y << " = " << z << "." << endl;
    return;
}
mskfisher
  • 3,291
  • 4
  • 35
  • 48
ghudner
  • 15
  • 1
  • 1
  • 4
  • possible duplicate of [C++ IsFloat function](http://stackoverflow.com/questions/447206/c-isfloat-function) – Jack Nov 24 '10 at 20:41
  • check the link to the duplicate, maybe it can help you – Jack Nov 24 '10 at 20:42
  • Could you provide a little sample of the input that isn't working for you, and what you want it to do? – David Thornley Nov 24 '10 at 20:46
  • @Jack: I don't see that it's a duplicate. The other question is about telling if a string converts to a valid floating-point number, and this is about reading input. There are significant differences, because the `cin >> x >> y;` doesn't yield a string. – David Thornley Nov 24 '10 at 20:48
  • Infact I would read a string, then check, then convert it to a float if it's correct. – Jack Nov 24 '10 at 21:23
  • @Jack and David Thornley: You're both right here. My question isn't quite a duplicate, but the solution to that other one works for me perfectly. I used the code given to me by Shawn Yarbrough below and was successful. Thanks a bunch everyone! – ghudner Nov 25 '10 at 00:30
  • See also: http://stackoverflow.com/questions/3273993/how-do-i-validate-user-input-as-a-double-in-c – Marc Gravell Nov 25 '10 at 06:30

4 Answers4

2

You test the state of the stream:

float x, y;
if (std::cin >> x >> y) {
    // input extraction succeeded
}
else {
    // input extraction failed
}

If this isn't working for you, then you need to post the exact code that isn't working.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
1

To detect erroneous string input where you expected a number, C++ doesn't automatically know what you want, so one solution is to first accept your input as strings, validate those strings, then if valid, only then convert the strings to float numbers using the atof() function.

The standard string class has a function called find_first_not_of() to help you tell C++ which characters you consider valid. If the function finds a character not in your list, it will return the position of the bad character, otherwise string::npos is returned.

// add.cpp

#include <iostream>
#include <string>
#include <cstdlib>    // for atof()

using namespace std;


void Add()
{
    cout << "Please enter two numbers you wish "
         << "to add, separated by a white space:"
         << endl;

    string num1, num2;

    cin >> num1;
    if( num1.find_first_not_of("1234567890.-") != string::npos )
    {
        cout << "invalid number: " << num1 << endl;
        return;
    }

    cin >> num2;
    if( num2.find_first_not_of("1234567890.-") != string::npos )
    {
        cout << "invalid number: " << num2 << endl;
        return;
    }

    float x = 0, y = 0, z = 0;
    x = atof( num1.c_str() );
    y = atof( num2.c_str() );
    z = x+y;

    cout << x << " + " << y << " = " << z << "." << endl;
}

int main(void)
{
    Add();
    return 0;
}
corecursion
  • 826
  • 7
  • 10
  • Thanks Shawn! This solution works for me perfectly. I just coded it as a function, and can now use to get the input for all my operation functions. Thanks a lot everyone for your help; i'll probably have a bunch more questions in the future and this site will be a great help! Cheers. – ghudner Nov 25 '10 at 00:28
0

One possibility would be to read the input as a string, then use boost lexical_cast to convert to floating point. lexical_cast only considers the conversion successful if the entire input converts to the target -- otherwise, it'll throw a bad_lexical_cast exception.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
-1

Another idea would be to test the input against a regex. An example regex for a float could be

-?[0-9]+([.][0-9]+)?

This method would also make it easier to refine the matching mechanism by only modifying the regex, and you could map multiple regular expressions against different types of input, for example an integer could then be expressed as

-?[0-9]+

and so on. Keep in mind however, that this only tests if the input is a valid format, it still requires a numerical conversion afterwards (I prefer boost::lexical_cast).

(You can also try it out with http://gskinner.com/RegExr/)

Mephane
  • 1,984
  • 11
  • 18