Thread: goodbit and failbit of cin

  1. #16
    Registered User
    Join Date
    Sep 2003
    Posts
    133
    this sounds like a logical method too. Thanks for the information.

  2. #17
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    I also have a question regarding this isssue.
    I recently had problem that I wasn't able to solve:
    consider this:

    Code:
    #include <limits>
    #include <iostream>
    using namespace std;
    
    int main()
    {
    	int x;
    	
    	cin>>x;
    	while(!cin.good())
    	{
    		cout<<"something is bad";
    		cin.clear();
            	cin.ignore(numeric_limits<int>::max(), '\n');
            	cout << "\nInput Invalid. Please Try Again: " << flush;
    			cin>>x;
    	}
    
    	
    	return 0;
    	
    }
    And this works fine if you expect user to enter integer and user enters "fsdfsdfs"
    but what if user enters 4.56 as value, then everything goes silently and rest of number stays in
    stream so next calling ( for example cin>>x) whil pick up the rest from stream. How can I test
    to see it it was integer that userentered or not (then I need to take appropriate action like
    ignore() etc)?

  3. #18
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    I can't believe that nobody tried to answer this!

  4. #19
    Registered User
    Join Date
    Mar 2002
    Posts
    1,595
    OK, here's a shot without a compiler to assist.

    expected input: int like 3

    actual input: decimal value like 3.14

    input type: extraction operator, >>

    outcome: the >> operator will extract the 3 from the input buffer and place it in some temporary storage to see if there is another digit next in line, to make 33 for example, as opposed to just 3, or whether there is something else there. It will then extract then extract the decimal point. Since the decimal point isn't valid in an int the fail bit for cin will be flipped and the decimal point will probably remain in the input buffer together with the 14. The success/failure of the action can be assessed, the failbit can be reset if needed, and the input buffer could then be cleared of any remaining material the same way as before.

    Another alternative would be to accept user input only as a string, not as a numerical value. Then you can parse the string to see if erroneous material is present. If input is appropriate for the type you eventually want to use, then you can convert the string input into a numerical value using atoi() or atol() as appropriate. In fact, this may be how cin evaluates input and decides that inappropriate material is present and therefore resets the fail bit of the state variable in the first place, but I can't say that for sure.

  5. #20
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    That's ok, but if you can give me some code example

  6. #21
    Registered User
    Join Date
    Mar 2002
    Posts
    1,595
    //version trying to use built in methods of cin
    Code:
    int num;
    bool acceptInput = true;
    while(acceptInput)
    {
      cout << "enter an integer" << endl;
      
      cin >> num;
      if(cin.fail())
      {
         //not sure if why failed so don't accept input
         cin.clear();
         cin.ignore(50000, '/n');
         cout << "inappropriate input, try again" << endl;
      }
      else
        acceptInput = false;
    }
    version using input as string and manually parsing string for validation

    Code:
    char input[100];
    int i;
    int num;
    bool acceptInput = true;
    bool accpeptable = true;
    while(acceptInput)
    {
      //reset flag each time through loop
      acceptable = true;
      
      //request input
      cout << "enter an integer" << endl;
    
      //store input as string
      cin >> input;
      
      //look at every char of string
      for(i = 0; i < strlen(input); ++i)
     {
        if(isdigit(input[i]))
        {
           //do nothing
        }
         else
         {
           //there can be nothing but digits in ints
           acceptable = false;
    
           //stop for loop
           i = strlen(input);
    
          //notify user
           cout << "inappropriate input. try again." << endl;
         }
      }
    
       //if all char in input were digits
       if(acceptable)
       {
          //stop while loop
          acceptInput = false;
    
          //convert string to int
          num = atoi(input);
        }
    }
    NOTE: none of the above code has been compiled or tested.

    Possible bug with second version:
    what if user input 123456789. This input would pass the manual validation process but be too big for a valid int. Suspect that output would be same as if user input same value and code accepted input directly into int variable, but I won't swear to it. The second version might be more robust if input were converted to type double first, the value of the double is evaluated, if the value of the double is above the upper limit of an int, then the user is notified of inappropriate input and the process continues; but I'll leave that up to you to do.

  7. #22
    Registered User
    Join Date
    Sep 2003
    Posts
    135
    Originally posted by elad
    expected input: int like 3

    actual input: decimal value like 3.14

    input type: extraction operator, >>

    outcome: the >> operator will extract the 3 from the input buffer and place it in some temporary storage to see if there is another digit next in line, to make 33 for example, as opposed to just 3, or whether there is something else there. It will then extract then extract the decimal point. Since the decimal point isn't valid in an int the fail bit for cin will be flipped and the decimal point will probably remain in the input buffer together with the 14.
    I don't think the fail bit will be set in this case. I believe the stream will still be in a good state; it will just stop extracting from cin when it encounters the first non-digit character, i.e. the decimal point.
    Gambling. The new yoga, with cash prizes!

Popular pages Recent additions subscribe to a feed