简体   繁体   中英

C++ test if input is an double/char

I am trying to get input from the user and need to know a way to have the program recognize that the input was or was not a double/char this is what i have right now... but when you type an incorrect type of input

1) the double test one just loops infinatly

2) the char one won't stop looping even with the correct imput

int main () {
    double _double = 0;
    bool done = true;
while ( done ) {
    cout << "Please enter a DOUBLE:\n" << endl;
    cin >> _double;
    if ( _double > 0 ) { done = false; }
    if ( _double < 0 ) { cout << "\nthe number you entered was less than zero\nplease enter a valad number..." << endl; } 
    if(cin.fail()) { cin.clear(); }
}

done = false;
char _char = ' ';
while ( !done ) {
    cout << "Please enter a CHAR" << "\n";
    cout << "\t'y' = yes\n\t'n' = no" << endl;
    cin >> _char;
    if ( _char == 'y' || _char == 'n' ) { done = true; }
    if ( ! (_char == 'y' || _char == 'n') ) { cout << "\nyou have entered an invald symbol... \n" << endl; }
    if(cin.fail()) { cin.clear(); }
}

The best bet is always to read your input as strings. You can then use functions like std::strtod() to test and convert to doubles. Checking if streams have failed and then resetting them is error prone at best, and doesn't give you the possibility of producing good error messages.

For example:

string s;
cin >> s;
char * p;
double d = strtod( s.c_str(), & p );
if ( * p == 0 ) {
   cout << "Read double: " << d << endl;
}
else {
   cout << "Read string: " << s << endl;
}

The pointer 'p' will point to the first character that cannot be converted to a double. How exactly you handle that really depends on your app's logic.

The problem is that when you read something and cin sees the input can never be a double, it stops reading, leaving the stuff in the buffer that it didn't consume. It will signal failure, which you clear but you won't eat the remaining input that cin didn't eat up. So, the next time the same wrong input is tried to read again, and again...

The problem with the char one is that you have to press the return key to make it process any characters on most terminals (this does not happen if you make your program read from a file, for instance). So if you press y then it won't go out of the read call, until you hit the return key. However, then it will normally proceed and exit the loop.

As others mentioned you are better off with reading a whole line, and then decide what to do. You can also check the number with C++ streams instead of C functions:

bool checkForDouble(std::string const& s) {
  std::istringstream ss(s);
  double d;
  return (ss >> d) && (ss >> std::ws).eof();
}

This reads any initial double number and then any remaining whitespace. If it then hit eof (end of the file/stream), it means the string contained only a double.

std::string line;
while(!getline(std::cin, line) || !checkForDouble(line)) 
  std::cout << "Please enter a double instead" << std::endl;

For the char, you can just test for length 1

std::string line;
while(!getline(std::cin, line) || line.size() != 1) 
  std::cout << "Please enter a double instead" << std::endl;

If you want to read only 1 char and continue as soon as that char was typed, then you will have to use platform dependent functions (C++ won't provide them as standard functions). Look out for the conio.h file for windows for instance, which has the _getch function for this. On unix systems, ncurses provides such functionality.

cin >> _double will always get you a double, whether they typed in "42", "0" or "mary had a little lamb". You need to read the user input as a string, then test that string to see if it is a double. sscanf will return 0 if it can't convert the input string to the desired type:

cout << "Please enter a DOUBLE:\n" << endl;
    string s;
cin >> s;
    if( !sscanf(s.c_str(), "%lf", &_double) )
    {
        done = false;
        cout << "Not a number, sparky. Try again." << endl;
        continue;
    }

Also, identifiers with leading underscores like you have are reserved by the language. Don't get in the habit of naming things like _double -- someday, they may not work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM