C++ Notes: String stream example

This example reads lines with an integer, an operator, and another integer. For example,

   25 * 3
   4 / 2

It's simple to read each of these three elements, but what happens if something is wrong with the input. For example, errors in the input like

   25 * 3 + 1 or
   25 *

will cause the whole program to fail. The solution is to read each line into a string, then read from the string. This will isolate the errors to one line, which is something that isn't possible with normal stream I/O, which will simply ignore whitespace, including line breaks. The example below shows how to do this.

  1 
  2 
  3 
  4 
  5 
  6 
  7 
  8 
  9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
// sstream-line-input.cpp - Example of input string stream.
//          This accepts only lines with an int, a char, and an int.
// Fred Swartz 11 Aug 2003

#include <iostream>
#include <sstream>
#include <string>
using namespace std;
//================================================================ main
int main() {
    string s;                 // Where to store each line.
    int    a, b;              // Somewhere to put the ints.
    char   op;                // Where to save the char (an operator)
    istringstream instream;   // Declare an input string stream
    
    while (getline(cin, s)) { // Reads line into s
        instream.clear();     // Reset from possible previous errors.
        instream.str(s);      // Use s as source of input.
        if (instream >> a >> op >> b) {
            instream >> ws;        // Skip white space, if any.
            if (instream.eof()) {  // true if we're at end of string.
                cout << "OK." << endl;
            } else {
                cout << "BAD. Too much on the line." << endl;
            }
        } else {
            cout << "BAD: Didn't find the three items." << endl;
        }
    }
    return 0;
}

Note that ws is an input manipulator that skips whitespace. The flow could be simplified somewhat by making the if more complicated. Here is the central part rewritten, adding some calculator code.

if ((instream >> a >> op >> b >> ws) && instream.eof()) {
   switch (op) {
       case '+': result = a + b; break;
       case '-': result = a - b; break;
       case '*': result = a * b; break;
       case '/': result = a / b; break;
       default : cout << "Bad operator '" << op << endl;
                 continue;  // next loop iteration
   }
   cout << result << endl << endl;
} else {
   cout << "BAD INPUT." << endl;
}