6.3.1. Первое приближение
На этом этапе мы действительно еще не готовы написать программу, имитирующую функции калькулятора. Мы просто мало думали об этом, но размышления — трудная работа, а, как большинство программистов, мы стремимся сразу писать какой-то код. Итак, попробуем написать простую программу-калькулятор и посмотрим, к чему это приведет. Первое приближение может выглядеть примерно так:
#include "std_lib_facilities.h"
int main()
{
cout << "Пожалуйста, введите выражение (допускаются + и –): ";
int lval = 0;
int rval;
char op;
int res;
cin>>lval>>op>>rval; // считываем что-то вроде 1 + 3
if (op=='+')
res = lval + rval; // сложение
else if (op=='–')
res = lval – rval; // вычитание
cout << "Результат: " << res << '\n';
keep_window_open();
return 0;
}
Иначе говоря, программа считывает пару значений, разделенных оператором, например 2+2, вычисляет результат (в данном случае 4) и выводит его на печать. Здесь переменная, стоящая слева от оператора, обозначена как lval, а переменная, стоящая справа от оператора, — как rval.
Эта программа работает! Ну и что, если программа довольно простая? Очень хорошо получить что-то работающее! Возможно, программирование и компьютерные науки проще, чем о них говорят. Может быть, но не стоит слишком увлекаться ранним успехом. Давайте сделаем кое-что.
1. Несколько упростим код.
2. Добавим операции умножения и деления (например, 2*3).
3. Добавим возможность выполнять несколько операторов (например, 1+2+3).
В частности, известно, что корректность входной информации следует проверять (в нашем варианте мы “забыли” это сделать) и что сравнивать значения с несколькими константами лучше всего с помощью инструкции switch, а не if.
Цепочку операций, например 1+2+3+4, будем выполнять по мере считывания значений; иначе говоря, начнем с 1, потом увидим +2 и добавим 2 к 1 (получим промежуточный результат, равный 3), увидим +3 и добавим 3 к промежуточному результату, равному 3, и т.д.
После нескольких неудачных попыток и исправления синтаксических и логических ошибок получим следующий код:
#include "std_lib_facilities.h"
int main()
{
cout <<
<< "Пожалуйста, введите выражение (допускаются +, –, * и /): ";
int lval = 0;
int rval;
char op;
cin>>lval; // считываем самый левый операнд
if (!cin) error("нет первого операнда");
while (cin>>op) { // считываем оператор и правый операнд в цикле
cin>>rval;
if (!cin) error("нет второго операнда ");
switch(op) {
case '+':
lval += rval; // сложение: lval = lval + rval
break;
case '–':
lval –= rval; // вычитание: lval = lval – rval
break;
case '*':
lval *= rval; // умножение: lval = lval * rval
break;
case '/':
lval /= rval; // деление: lval = lval / rval
break;
default: // нет другого оператора: выводим результат
cout << "Результат: " << lval << '\n';
keep_window_open();
return 0;
}
}
error("неверное выражение");
}
Это неплохо, но попытайтесь вычислить выражение 1+2*3, и вы увидите, что результат равен 9, а не 7, как утверждают учителя математики. Аналогично, 1–2*3 равно –3, а не –5, как мы думали. Мы выполняем операции в неправильном порядке: 1+2*3 вычисляется как (1+2)*3, а не 1+(2*3), как обычно. Аналогично, 1–2*3 вычисляется как (1–2)*3, а не 1–(2*3), как обычно. Лентяи! Мы можем считать правило, согласно которому умножение выполняется раньше, чем сложение, устаревшим, но не стоит отменять многовековые правила просто для того, чтобы упростить себе программирование.