Kira Chow
Kira Chow

Reputation: 185

How to try reading as int, then if it fails read as string?

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

Answers (2)

scaryrawr
scaryrawr

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

user2357112
user2357112

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

Related Questions