简体   繁体   中英

Trying to validate input in C++

The idea behind this code in c++ is to calculate the sum of all the entered numbers. When the user enters 0, the program should stop. This part of the code is working as I intended, but I'd like to include a variant which recognizes that a character different than a float number has been entered, ignore it in the calculation and allow the user to continue entering float numbers. At the moment, entering anything else but a float number stops the program.

I know there's a "if (!(cin >> numb))" condition, I've tried parsing it in different places in the code, but I can't figure out how to force the program to ignore these invalid inputs. I would be very grateful for any help.

#include <iostream>
#include <stdlib.h>

using namespace std;

float numb; float sum=0;

int main()
{
    cout << "This app calculates the sum of all entered numbers." << endl;
    cout << "To stop the program, enter 0." << endl << endl;
    cout << "Enter the first number: ";
    cin >> numb;

    while(true)
    {
        sum += numb;

        if (numb!=0)
        {
            cout << "Sum equals: " << sum << endl << endl;
            cout << "Enter another number: ";
            cin >> numb;
        }
        else
        {
            cout << "Sum equals: " << sum << endl << endl;
            cout << "Entered 0." << endl;
            cout << "Press Enter to terminate the app." << endl;
            exit(0);
        }
    }
    return 0;
}

You have three options:

  • trial and error: try to read a float, and in case of error clear the error flag, ignore the bad input and read again. The problem is that you don't know really how many of the input is to be ignored.
  • read strings: read space delimited strings, try to convert the string using stringstream , and just ignore the full string in case of error. The problem is that if the input starts with a valid float but then contains invalid characters (eg 12X4), the invalid part will be ignored (eg X4)
  • control parsing: read space delimited strings, try to convert the string using std::stof() , and check that all characters of the string where successfully read

Here the second approach, with a slightly restructured loop, so that a 0 entry will lead to exiting the loop and not the full program:

string input;  
while(cin >> input)
{
    stringstream sst(input); 
    if (sst>>numb) {
        sum += numb;
        cout << "Sum equals: " << sum << endl << endl;
        if (numb==0)
        {
            cout << "Entered 0." << endl;
            break;  // exits the while loop 
        }
        cout << "Enter another number: ";
    }
    else 
    {
        cout << "Ignored entry "<<input<<endl; 
    }
}
cout << "Press Enter to terminate the app." << endl;

Online demo

If you prefer a more accurate parsing, consider something like:

size_t pos=0; 
float xx = stof(input, &pos );
if (pos!=input.size()) {
    cout << "error: invalid trailing characters" <<endl; 
}

You have to clear the failbit after a failed read. After that, you can read in the invalid stuff into a string (that you just ignore). This function will read in values and add them up until it encounters a 0 or the end of the input stream.

int calc_sum_from_input(std::istream& stream) {
    int sum = 0; 
    // If it couldn't read a value, we just read the thing into here
    std::string _ignored;
    while(stream) // Checks if the stream has more stuff to read
    {
        int value;
        if(stream >> value) 
        {
            if(value == 0) // Exit if it read the value 0
                break;
            else 
                sum += value; // Otherwise update the sum
        }
        else {
            // Clear the failbit
            stream.clear(); 
            // Read ignored thing
            stream >> _ignored;
        }
    }
    return sum; 
}

The logic is basically:

  • set the initial sum to 0
  • check if there's stuff to read
    • if there is, try reading in a value
    • if successful, check if the value is 0
      • if it's 0, exit and return the sum
      • otherwise, add the value to the sum
    • otherwise, clear the failbit (so that you can read stuff in again) and read the bad value into a string (which gets ignored)
  • otherwise, return the value

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