4

Consider the following code which takes an integer input and then prints the cin stream state:

#include <iostream>  
using namespace std;

int main()
{
    int number;
    cout<<"Enter a number \n";
    cin>>number;
    cout<<cin.rdstate()<<endl;
    return 0;
}

If the number entered is "zzzz" then the rdstate returns a value of 4.
If the number entered is "10zzzz" then the rdstate returns a value of 0, number has a value of 10, and the input stream has "zzzz" in it.

My question is:
1. Why isn't a input of "10zzzz" treated as an invalid input (atleast one of the failure bits should have been set.)
2. What is an elegant solution to detect and handle this situation.

Thanks!!!

Achint Mehta
  • 349
  • 1
  • 5
  • 14

2 Answers2

2

First of all I would like to ask what you are trying to do with:

cout<<cin.rdstate()<<endl;

Read this page for the proper use of rdstate() http://www.cplusplus.com/reference/iostream/ios/rdstate/

second: to check wetether the input is either stringtype or integer type you might want to add something extra wich will convert the input string to integer data and will respond with an error message when feeded an invalid input.

therefor this will help you out:

int main() {

 string input = "";

 // How to get a string/sentence with spaces
 cout << "Please enter a valid sentence (with spaces):\n>";
 getline(cin, input);
 cout << "You entered: " << input << endl << endl;

 // How to get a number.
 int myNumber = 0;

 while (true) {
   cout << "Please enter a valid number: ";
   getline(cin, input);

   // This code converts from string to number safely.
   stringstream myStream(input);
   if (myStream >> myNumber)
     break;
   cout << "Invalid number, please try again" << endl;
 }
 cout << "You entered: " << myNumber << endl << endl;

 // How to get a single char.
 char myChar  = {0};

 while (true) {
   cout << "Please enter 1 char: ";
   getline(cin, input);

   if (input.length() == 1) {
     myChar = input[0];
     break;
   }

   cout << "Invalid character, please try again" << endl;
 }
 cout << "You entered: " << myChar << endl << endl;

 cout << "All done. And without using the >> operator" << endl;

 return 0;
}
dennis
  • 2,000
  • 18
  • 26
  • Thanks for the response. When I executed your program I get the same result. If 10z is entered as the integer, no error is detected. Following is the output that I got $ ./err_stream Please enter a valid sentence (with spaces): >Hello World You entered: Hello World Please enter a valid number: 10z You entered: 10 Please enter 1 char: 2 You entered: 2 All done. And without using the >> operator – Achint Mehta May 09 '12 at 09:33
  • Also, I had put "cout< – Achint Mehta May 09 '12 at 09:38
0

If the number entered is "zzzz" then the rdstate returns a value of 4. If the number entered is "10zzzz" then the rdstate returns a value of 0, number has a value of 10, and the input stream has "zzzz" in it.

To understand why these happen, we need to understand how the extraction operator (operator>>) works. Here are a few good links to start with:

std::cin and handling invalid input

std::istream::operator>>

One could dig deeper in the following places:

operator>>(std::basic_istream)

std::basic_istream<CharT,Traits>::operator>>

std::num_get<CharT,InputIt>::get, std::num_get<CharT,InputIt>::do_get

In simple terms, when writing to an arithmetic type, the input is parsed character by character as long as the sequence of characters can be exactly interpreted as a value of that type. When it is no longer possible to do so, the parsing stops and the valid value that has been obtained till that point is used.

"zzzz" presents no valid value, while "10zzzz" allows 10 to be parsed.

As far as a solution is concerned, the string stream based answer by dennis could be improved to handle trailing characters as shown here. !myStream.eof() will evaluate to true if there are trailing characters.

Also, there are other options apart from using a string stream. For e.g., strtol, std::stoi.

Also, using an input string stream instead of a string stream in this context will be better. See here.

Hari
  • 1,561
  • 4
  • 17
  • 26