Avoid fail state of the input stream - inputting a char into an int!!

I am working on a Homework assignment and need this ASAP.  I can email my professor but will not get an answer until the morning, most likely.

What is the common procedure to avoid entering the fail state of the input stream?  I am writing a program, which is actually a simple game, and it depends on the user entering an integer value to be subtracted from an existing integer value.  This is contained in a while loop, which runs until the remaining integer is 1.

How can I catch a user's mistake when he enters a non-integer like "a"?  My professor mentioned something about validating using a char first, but then how would I even test to see if the char is an integer or not?

I know I can say if ( !istream ) then output an error.... or something like that... but of course now the input stream is in the fail state and the entire program must be restarted in order to restore that stream.  Do I have everything correct?  What should I do, besides just yelling at the user after he enters a character in place of an integer, and breaking the program, so that I can loop back and say hey you can't enter that, enter an integer now... without breaking that input stream.

Thanks in advance!  Hopefully I have worded this clearly...
LVL 4
jonnyz0109Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

grg99Commented:
The trick is to not read an integer, but read the input as a char.  Then validate the character as being a digit.  Then if and onyl if it's a digit, append that digit to some string variable you're keeping.    Then when they press <Enter> or whatever to signal they're done, convert the string to an integer with something like atoi().
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
jonnyz0109Author Commented:
1) How do I validate the character as being a digit?
2) Can I use a string variable that is not an array?
3) I don't think we have "learned" atoi() yet... anything else I can use?

Thanks
0
efnCommented:
> 1) How do I validate the character as being a digit?

There's an isdigit function in the standard library.

> 2) Can I use a string variable that is not an array?

Yes.

> 3) I don't think we have "learned" atoi() yet... anything else I can use?

You could use a stringstream or the library function strtol, but neither of these is likely to be significantly easier.

The approach grg99 gave you is pretty standard and is probably what your professor was suggesting, but there is another way.  Once an input stream goes into the failed state, it is not necessarily stuck in that state for the remaining life of the program.  The failed state is just a bit that you can clear with the istream::clear() function.  Then you can read from the stream again.  The tricky part is that the bad input will still be sitting in the stream, so you have to read past it and throw it away before you can read the next real input from the user.  The istream::ignore() function is handy for this.  Typically one tells this function to ignore everything up to the end of a line.

--efn
0
Exploring SQL Server 2016: Fundamentals

Learn the fundamentals of Microsoft SQL Server, a relational database management system that stores and retrieves data when requested by other software applications.

jonnyz0109Author Commented:
so here is what I have... not sure how nice it will look without a good courier-like font...

int n = 0, pileSize = [some random integer]
while ( pileSize > 1 )
{
      cout << "\nPile Size: " << pileSize << endl;
      cout << "Your Move: ";
      cin >> n;

                if ( !istream)
                {
                                istream::clear();
>>                            ..... AND DO WHAT HERE??                         <<

      if ( ( n == 0 ) || ( n > ( pileSize / 2 ) ) )
      {
            cout << "You have made an illegal move.\nYou must take at least 1 marble and no more than half the pile size." << endl;
      }
      else /* if ( ( n > 0 ) && ( n <= ( pileSize / 2 ) ) ) */
      {
            pileSize = pileSize - n;
      }
0
efnCommented:
Your input stream is named "cin", so that is the object to name when you want to do something to the stream.

if (!istream)

won't work.  It should be something like

if (!cin)

or

if (cin.fail())

Similarly, you want to code cin.clear().

After that, you need a call to cin.ignore to tell it to read past the bad input, probably up to the end of the input line.  You can read about this function here:

http://www.cplusplus.com/ref/iostream/istream/ignore.html

You can look for the newline character '\n' marking the end of an input line.

--efn
0
jonnyz0109Author Commented:
OK Well I'm still not sure how to do that... but I got an email from my professor.

I plan to go over this in class today:
 
1.  to test whether a char is numeric use isdigit(myChar)
2. to convert a char, after doing the above test, use noMarbles = int(myChar - '0') where noMarbles is an int and '0' is zero ... you will need to derive an algorithm to convert the stream of chars to a decimal number.

I'll see what that means later today in class.
0
jonnyz0109Author Commented:
BTW, finished the game for everything except for this one thing... I figured I could always go back and fix it.  Currently I'm just using an int and when I enter a character it goes crazy   :o)
0
havman56Commented:


when user enters a character u can detect

input stream

use sprintf to convert the anydata to the buffer and check the buffer whether the values
are in character range if it is integer then  then inform user u entered integer.

data what he enters

sprintf(buffer,"%d",data);

have ur logic wriiten absed on it

0
jonnyz0109Author Commented:
Cleaning up old questions and forgot I had this one.  My professor ended up giving me the solution... basically, input into a char MyChar and use the following in a loop.

MyInt = (MyInt * 10) + (MyChar - '0')

Where MyInt is initialized to 0.  The state to end the loop is when MyChar = '\n' .  What I wasn't realizing when I opened this question was that if you input an entire line, and you're inputting into a char, it only reads one character at a time and leaves the rest in the stream.  So there is no need to do anything fancy, just keep increasing the existing value by ten and add the next one on until the end line is reached.

Thanks all :o)
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.