简体   繁体   中英

breaking out of while loop using cin.fail

I am having difficulty figuring out how to get my loop to end, when an incorrect input is given. Every combination I could think of, to end the loop hasn't worked. What could be the next step to figure this out. The code is attached below. The next step, when the correct input is given, is to increment the number.

int main(){

int startingNumber;
int endingNumber;
int incriment;

cout<<"Enter a starting number\n";
cout<<"**";
while(!(cin>>startingNumber))
{
cout<<"Error: invalid entry\n";
cin.clear();
cin.ignore (500 ,'\n');  
break;
return 0;
}

cout<<"Enter a ending number\n";
cout<<"**";
while(!(cin>>endingNumber))
{
cout<<"Error: invalid entry\n";
cin.clear();
cin.ignore (500 ,'\n');  
}



}

First, good job on looking to validate the stream-state after input and before making use of the variable filled. Far too many questions simply ignore validation.

It looks like what you are trying to do is to require valid input from the user, and if a non-integer value is entered resulting in failbit being set, you want to clear the error bit, ignore the offending character and require the user to try again. That is a proper approach.

Where your logic breaks down is thinking you need to break if failbit is set. Just the opposite. To handle and recover from an invalid input, you want to loop-continually and break only when valid input is received. That way you validate the input, and if you have what you need, you break the read-loop, otherwise you handle the error and require the user to try again.

Ignoring increment for now, it looks like you wanted to:

#include <iostream>
#include <limits>       /* for numeric limits */

int main(){

    int startingNumber;
    int endingNumber;
    
    while (true) {  /* loop continually until valid input received */
        std::cout << "Enter a starting number\n** ";    /* prompt */
        if (std::cin >> startingNumber) {               /* validate */
            break;                                      /* break on good */
        }
        /* handle error */
        std::cerr << "  Error: invalid entry\n";
        std::cin.clear();
        std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
    }
    
    while (true) {  /* ditto */
        std::cout << "Enter a ending number\n** ";
        if (std::cin >> endingNumber) {
            /* add any additional needed criteria */
            if (endingNumber == startingNumber) {
                std::cerr << "  Error: must not be startingNumber.\n";
            }
            else {
                break;
            }
        }
        else {  /* condition cin.fail error since == check added */
            std::cerr << "  Error: invalid entry\n";
            std::cin.clear();
            std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
        }
    }
    
    std::cout << "startingNumber : " << startingNumber <<
                "\nendingNumber   : " << endingNumber << '\n';
}

( note: you would also want to check for eofbit and exit gracefully if the user enter a manual EOF with Ctrl + d ( Ctrl + z on windows). Canceling input is a valid act by the user. Consider also checking for badbit in the off-chance there was a terminal error that was unrecoverable -- not likely -- up to you)

Note also the additional condition in the second input routine that checks if startingNumber == endingNumber . This is by way of example, presuming you don't want a zero increment later. The point being you can tailor your input routine to handle as many contingent cases as your code needs. You would much rather over-validate than let a corner-case that tanks your code slip through.

One additional consideration is calling std::cin.ignore() after the good input is received to deal with any trailing characters. (eg "20 more fleas" would be valid input but leave " more fleas" in the input buffer. In the event there is nothing to ignore, std::ignore() will return eofbit that you will need to .clear() . See: std::basic_istream::ignore This would be another simple addition that would strengthen your input routine.

Example Use/Output

Exercising the code you could do:

$ ./bin/startendno
Enter a starting number
** my dog has 10 fleas
  Error: invalid entry
Enter a starting number
** 10
Enter a ending number
** 10
  Error: must not be startingNumber.
Enter a ending number
** foo
  Error: invalid entry
Enter a ending number
** 20
startingNumber : 10
endingNumber   : 20

Look things over and let me know if you have further questions.

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