Reputation: 185
I'm trying to repeatedly read integers, and for tokens that are not integers, to read and handle them as strings. I thought the following would work:
string s;
int x;
while(1) {
if (cin >> x) // try reading as int
cout << "read int: " << x << endl;
else { // try reading as string
cin.clear();
if (cin >> s)
cout << "read string: " << s << endl;
else
break; // eof
}
}
However, for input (with newline at end)
1 2 a
it gives output
read int: 1
read int: 2
It seems that after clearing the state of the stream is not exactly the same as before, and in fact cin >> s
fails. Why is this, and how can I achieve my desired behaviour?
To clarify, I can't parse the string as an int because I have not "learned" that yet.
Upvotes: 2
Views: 247
Reputation: 867
Why not read it as a string, then try a conversion, so if the conversion fails you can treat it as a string.
In C++11 there is std::stoi
. Which will throw an exception if a conversion cannot be found.
Another way would be read it in as a string, and then parse using a stringstream.
If you cannot use an existing string parsing method, why not write your own?
// Returns false if not an int, otherwise true and outint will hold the correct value.
bool strtoint(const std::string str, int *outint) {
int val = 0;
for (int x = str.length() - 1; x >= 0; x--) {
if (!(str[x] <= '9' && str[x] >= '0') || !(str[x] == '-')) {
return false;
} else if (str[x] == '-') {
val *= -1;
} else {
val += (int)((str[x] - '0') * pow(10, (str.length() - 1) - x));
}
}
*outint = val;
return true;
}
Or something kinda like that, I'm not sure if the logic is completely correct, but I think it's on the right track.
Upvotes: 2
Reputation: 280500
clear
does not rewind the stream; it only clears the error flags, as the name suggests. To solve your problem, read the input as a string, then try to parse it as an int. The link explains the details of the string-int conversion better than I could.
Upvotes: 5