Программирование. Принципы и практика использования C++ Исправленное издание, стр. 86
2342Введем выражение
5+6523425+65Несмотря на свой опыт, скорее всего, вы будете сильно озадачены. Даже опытный программист будет озадачен таким поведением программы. Что происходит? В этот момент попробуйте выйти из программы. Как это сделать? Мы “забыли” указать в программе команду выхода, но прекращение работы может спровоцировать ошибка, поэтому введите символ
хОднако мы забыли провести различие между вводом и выводом на экран. Прежде чем перейти к решению основной задачи, давайте исправим вывод, чтобы экран лучше отражал то, что мы делаем. Добавим символ =, чтобы отметить результат.
while (cin) cout << "= " << expression() << '\n'; // версия 1Теперь введем ту же самую последовательность символов, что и раньше. На экране появится следующее:
2 3 4 = 2 5+6 = 5 x Неправильная лексемаСтранно! Попробуйте понять, почему программа делает это. Мы попробовали еще несколько примеров. Только посмотрите на эту головоломку!
• Почему программа реагирует после ввода символов
23• Почему после ввода числа
424• Почему при вычислении выражения
5+6511Существует множество способов получить такие загадочные результаты. Некоторые из них мы проверим в следующей главе, а пока просто подумаем. Может ли программа руководствоваться неверной арифметикой? Это крайне маловероятно: значение
425+61151 2 3 4+5 6+7 8+9 10 11 121 2 3 4+5 6+7 8+9 10 11 12= 1= 4= 6= 8= 10Что? Ни
23494+56136+7Хорошенько подумайте: программа выводит каждую третью лексему! Может быть, программа “съедает” часть входной информации без вычислений? Похоже на это. Проанализируем функцию
expression()double expression(){ double left = term(); // считываем и вычисляем Терм Token t = get_token(); // получаем следующую лексему while(true) { switch(t.kind) { case '+': left += term(); // вычисляем и добавляем Term t = get_token(); break; case '–': left –= term(); // вычисляем и вычитаем Терм t = get_token(); break; default: return left; // финал: символов + и – нет; // возвращаем ответ } }}Если объект класса
Tokenget_token()'+''–'returnterm()Модифицируем функцию
expression()tПредположим, в нашем распоряжении есть поток лексем — “
Token_streamtsToken_streamget()putback(t)t