goncalotomas
goncalotomas

Reputation: 1000

Why does this program require 3 lines of input?

I'm trying to make a program that mimics a code example in Bjarne Stroustrup's C++ book. This is an initial approach to make a calculator that can parse longer expressions that need to be evaluated. I don't care for operator precedence just yet, and I'm trying to understand an issue I'm having with my current code. Here it is:

#include <iostream>
using namespace std;

int main() {
  cout << "Expression: ";
  int lval = 0; //left-hand value
  int rval; // right-hand value
  char op;
  cin >> lval; //read leftmost operand
  while (cin>>op) { //read operator and righ-hand operand repeatedly
    cin >> rval;
    switch (op) {
    case '+':
      lval += rval; //add: lval = lval+rval
      break;
    case '-':
      lval -= rval; //subtract: lval = lval-rval
      break;
    case '*':
      lval *= rval; //multiply: lval =lval*rval
      break;
    case '/':
      lval /= rval; // divide: lval = lval/rval
      break;
    default:  // not another operator: print result
      cout << "Result: " << lval << '\n';
      return 0;
    }
  }
return 0;
}

When I compile and run the program, I always need to add two extra lines of input, for instance:

$ ./calculator
>Expression: 1+2+3
>
>
[I can keep pressing enter as many times as I wish until I type in 2 more lines]
>l
>l
>Results: 6

Why does the program behave this way? Why doesn't cin>>op return false when a \n character is read?

It confuses me because I copied the while(cin>>op) part from the book.

Upvotes: 0

Views: 69

Answers (2)

Biruk Abebe
Biruk Abebe

Reputation: 2233

Because you are reading cin>>op and cin>>rval for each iteration and this read operations will block until the user enters some value. The >> operator will not read new line character('\n') so unless you enter some other value and press enter both of this lines will block,which explains why,after writing the expression, no matter how many time you press enter it will wait for you to enter two other values(the first value begin non-operator values so that the default switch statement is executed) to get to the result.

You could use cin.get() to get the operator because it also reads a new line and read the rval within the switch statement for each operator to avoid this.

cout << "Expression: ";
  int lval = 0; //left-hand value
  int rval; // right-hand value
  char op;
  cin >> lval; //read leftmost operand
  while (cin.get(op)) { //read operator and righ-hand operand repeatedly
    switch (op) {
    case '+':
      cin >> rval;
      lval += rval; //add: lval = lval+rval
      break;
    case '-':
      cin >> rval;
      lval -= rval; //subtract: lval = lval-rval
      break;
    case '*':
      cin >> rval;
      lval *= rval; //multiply: lval =lval*rval
      break;
    case '/':
      cin >> rval;
      lval /= rval; // divide: lval = lval/rval
      break;
    default:  // not another operator: print result
      cout << "Result: " << lval << '\n';
      return 0;
    }
  }

Upvotes: 2

Frank Puffer
Frank Puffer

Reputation: 8215

For each iteration of the while loop, you need two inputs (cin >> op and cin >> rval), this includes the last one that switches to the defaultcase. That's why you have to enter the two additional lines.

Upvotes: 4

Related Questions