Вход/Регистрация
Программирование. Принципы и практика использования C++ Исправленное издание
вернуться

Страуструп Бьерн

Шрифт:

case '%':

left %= primary;

t = get_token;

break;

default:

return left;

}

}

}

К сожалению, этот код не компилируется: операция вычисления остатка (
%
) для чисел с плавающей точкой не определена. Компилятор вежливо предупредит нас об этом. Когда мы утвердительно ответили на вопрос 5 из раздела 6.3.5 — “Следует ли позволить ввод чисел с плавающей точкой?”, — мы не думали о таких последствиях и просто поддались искушению добавить в программу дополнительные возможности. Вот так всегда! Что же делать? Можно во время выполнения программы проверить, являются ли оба операнда операции
%
целыми числами, и сообщить об ошибке, если это не так. А можно просто исключить операцию
%
из возможностей нашего калькулятора. Эту функцию всегда можно добавить позднее (см. раздел 7.5). Исключив операцию
%
, получим вполне работоспособную функцию: термы правильно распознаются и вычисляются. Однако опытный программист заметит нежелательную деталь, которая делает функцию
term
неприемлемой. Что произойдет, если ввести выражение
2/0
? На нуль делить нельзя. Если попытаться это сделать, то аппаратное обеспечение компьютера обнаружит это и прекратит выполнение программы, выдав сообщение об ошибке. Неопытный программист обязательно столкнется с этой проблемой. По этой причине лучше провести проверку и выдать подходящее сообщение.

double term

{

double left = primary;

Token t = get_token;

while(true) {

switch (t.kind) {

case '*':

left *= primary;

t = get_token;

break;

case '/':

{ double d = primary;

if (d == 0) error("деление на нуль");

left /= d;

t = get_token;

break;

}

default:

return left;

}

}

}

Почему мы поместили обработку операции

/
внутри блока? На этом настоял компилятор. Если мы хотим определить и инициализировать переменные в операторе
switch
, то должны поместить ее в блоке.

6.5.4. Первичные выражения

Грамматическое правило для первичных выражений также простое.

Первичное выражение:

Число

'('Выражение')'

Программный код, реализующий это правило, немного сложен, поэтому он открывает больше возможностей для синтаксических ошибок.

double primary

{

Token t = get_token;

switch (t.kind) {

case '(': // обработка варианта '('выражение')'

{ double d = expression;

t = get_token;

if (t.kind != ')') error("')' expected");

return d;

}

case '8': // используем '8' для представления числа

return t.value; // возвращаем значение числа

default:

error("ожидается первичное выражение");

}

}

По сравнению с функциями

expression
и
term
в этом программном коде нет ничего нового. В нем используются те же самые языковые конструкции и методы, и объекты класса
Token
обрабатываются точно так же.

6.6. Испытание первой версии

Для того чтобы выполнить эти функции калькулятора, необходимо реализовать функции

get_token
и
main
. Функция
main
тривиальна: мы просто вызываем функцию
expression
и выводим результат на печать.

int main

try {

while (cin)

cout << expression << '\n';

keep_window_open;

}

catch (exception& e) {

cerr << e.what << endl;

keep_window_open ;

return 1;

}

catch (...) {

cerr << "exception \n";

keep_window_open ;

return 2;

}

Обработка ошибок представляет собой обычный шаблон (см. раздел 5.6.3). Отложим реализацию функции

get_token
до раздела 6.8 и протестируем эту первую версию калькулятора.

ПОПРОБУЙТЕ

Первая версия программы, имитирующей работу калькулятора (включая функцию

get_token
), содержится в файле
calculator00.cpp
. Запустите его и испытайте.

  • Читать дальше
  • 1
  • ...
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: