2

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.

Kira Chow
  • 185
  • 1
  • 7
  • Is it true that you *can't* (meaning school project) or "don't want to"? Concerning parse that is. – ChiefTwoPencils Jul 06 '13 at 01:50
  • @BobbyDigital Yes, it's related to school, so I can't. – Kira Chow Jul 06 '13 at 01:51
  • @KiraChow: Either you're approaching the assignment wrong, or the assignment is stupid. Either way, the solution will depend on a more thorough understanding of the details of your course than is realistic to convey in a StackOverflow question. – user2357112 Jul 06 '13 at 01:53
  • Well then maybe you've learned ways of determining if a specific char is alpha and such? Then you could still read as string and determine if it's a number or not. Meaning your traverse the input string and deduce by it's contents if it could possibly be a number. – ChiefTwoPencils Jul 06 '13 at 01:53
  • 1
    wait, I'm a little confused. Is your problem that it's not printing out `read string: a` at the end or something else? A quick [test](http://ideone.com/9xpYnz) shows all 3 outputs printed as expected. – greatwolf Jul 06 '13 at 01:55
  • @greatwolf Yes, I've tested it on ideone and I know it works there. That's why I specified that there is a newline at the end and that it's from the file. Because in my environment, it doesn't work. – Kira Chow Jul 06 '13 at 01:57
  • Are you saying you're piping the file content from stdout to your program's stdin because `cin` is being used here, not `fstream`. – greatwolf Jul 06 '13 at 02:03
  • 1
    @greatwolf Yes, should've clarified that it's what I mean. – Kira Chow Jul 06 '13 at 02:04
  • Can you add what platform environment this is failing under + compiler toolchain version used if possible. – greatwolf Jul 06 '13 at 02:08
  • @greatwolf Thanks for trying so much to help, but I may go with one of the given answers (we did cover string streams). If you're interested, it's in Linux with g++ 4.4.5. – Kira Chow Jul 06 '13 at 02:14

2 Answers2

5

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.

Community
  • 1
  • 1
user2357112
  • 260,549
  • 28
  • 431
  • 505
2

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.

scaryrawr
  • 777
  • 4
  • 12
  • Thanks for the effort, I was hoping it would not come to this. :) I'll accept yours because you mentioned string streams, which we did cover (although did not learn of its particular use in parsing). – Kira Chow Jul 06 '13 at 02:23
  • It probably shouldn't, but sometimes it's just a fun rewrite existing things. – scaryrawr Jul 06 '13 at 02:25