3

When cin>>(int) and cin>>(string) are called, when the first input is not correct for integer, it seems that cin>>(string) will fail to retrieve the second input even if it is correct string.

The source code is simple as:

cout<<"Please enter count and name"<<endl;;
int count;
cin>>count;     // >> reads an integer into count
string name;
cin>>name;      // >> reades a string into name

cout<<"count: "<<count<<endl;
cout<<"name: "<<name<<endl;

The test cases are:

Case 1: Type characters(which not fit for int) and characters

Please enter count and name

ad st

count: 0

name:

Case 2: Type numbers and characters

Please enter count and name

30 ad

count: 30

name: ad

Case 3: Type numbers and numbers (which could be taken as strings)

Please enter count and name

20 33

count: 20

name: 33

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
lst
  • 65
  • 5
  • 2
    `std::cin` has a state that you can inspect eg via `std::cin.good()`. Input can fail, and often it does, so you need to do something about it – 463035818_is_not_an_ai Dec 13 '18 at 12:58
  • how can state/result from first use of cin affect second use of cin? Or does it mean that before every use of cin, need to check or clear state of cin? I have never seen any pre-handling of cin state in code. Thanks. – lst Dec 13 '18 at 13:07
  • @lst 1) "_how can state/result from first use of cin affect second use of cin?_" If `cin` is in an invalid state, any further operations are meaningless. 2) "_Or does it mean that before every use of cin, need to check or clear state of cin?_" Yes, one needs to get into habit of checking that operations succeeded, instead of assuming that they did. 3) "_I have never seen any pre-handling of cin state in code_" `if (cin>>count) {/* operation succeeded */ }` – Algirdas Preidžius Dec 13 '18 at 14:35

2 Answers2

6

A stream has an internal error flag that, once set, remains set until you explicitly clear it. When a read fails, e.g. because the input could not be converted to the required type, the error flag is set, and any subsequent reading operation will not even be tried as long as you do not clear this flag:

int main() {

    stringstream ss("john 123");

    int testInt;
    string testString;

    ss >> testInt;
    if (ss) {
        cout << "good!" << testInt << endl;
    } else {
        cout << "bad!" << endl;
    }

    ss >> testString;
    if (ss) {
        cout << "good!" << testString << endl;
    } else {
        cout << "bad!" << endl;
    }

    ss.clear();
    ss >> testString;
    if (ss) {
        cout << "good:" << testString << endl;
    } else {
        cout << "bad!";
    }
}

Output:

bad!
bad!
good:john
Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58
  • Just find another thread similar to this question: https://stackoverflow.com/a/39282970/8641405 – lst Dec 15 '18 at 16:16
  • It mentions both cin.clear() and cin.ignore(). Does it mean that in certain cases, for example if there are multiple error inputs in the stream, we have to call cin.ignore(streamsize, delim) to clear the cin buffer? – lst Dec 15 '18 at 16:24
  • I have tried cin.clear() and cin.ignore() and also find another link talking about how to handle maximum number of characters to extract and provide the delimiting character. [link] https://stackoverflow.com/questions/257091/how-do-i-flush-the-cin-buffer and below codes seems to work:int id; cout<<"Please enter an integer for your ID\n"; if (!(cin>>id)) { cin.clear(); cin.ignore(numeric_limits::max(), '\n'); } – lst Dec 16 '18 at 04:08
0

You can check for the input statement if it is succeeded or not with the

cin.good() method

If the input statement fails it returns false else true. Here is a small example:

#include <iostream>
#include <cstdlib>

using namespace std;

int main()
{
  int x; 

  // prompt the user for input 
  cout << "Enter an integer: " << "\n"; 
  cout << "cin.good() value: " << cin.good() << "\n";
  // get input 
  cin >> x; 
  cout << "cin.good() value: " << cin.good() << "\n";
  // check and see if the input statement succeeded 
  if (!cin) { 
    cout << "That was not an integer." << endl; 
    return EXIT_FAILURE; 
  } 

  // print the value we got from the user 
  cout << x << endl; 
  return EXIT_SUCCESS; 
}

Output:

Enter an integer: 
cin.good() value: 1
asd
cin.good() value: 0
That was not an integer.
Tibor Fekete
  • 199
  • 14
  • @PeteBecker Thanks for the explanation. Since cin status can be good or bad, will it be more safe to always check cin status before and after use of cin? It seems that people usually just call cin>> directly without any checking. Is it because that is just in toy programs? Is it true that in real industrial grade software/systems, input stream is always being checked and reset to good when malfunctioning? – lst Dec 15 '18 at 16:31
  • @lst — that depends on what your program does. The bad state is sticky, so if you’re doing a bunch of input you can check it at the end to see if something failed. On the other hand, repetitive input is usually done in a loop: `while (std::cin >> i) { /* do something with i */ }`. – Pete Becker Dec 15 '18 at 18:28
  • 2
    @TiborFekete I guess to solve the cin bad state and also to flush the data wrongly read into, the code cin.clear(); and cin.ignore(numeric_limits::max(), '\n'); seems to work. I refer to the [link] https://stackoverflow.com/questions/257091/how-do-i-flush-the-cin-buffer – lst Dec 16 '18 at 04:13