- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Шрифт:
Интервал:
Закладка:
double expression()
{
double left = term(); // считываем и вычисляем Терм
Token t = get_token(); // получаем следующую лексему
while(true) {
switch(t.kind) {
case '+':
left += term(); // вычисляем Терм и добавляем его
t = get_token();
break;
case '–':
left –= term(); // вычисляем Терм и вычитаем его
t = get_token();
break;
default:
return left; // финал: символов + и – нет;
// возвращаем ответ
}
}
}
Обратите внимание на то, что — за исключением цикла — этот вариант напоминает первый (см. раздел 6.5.2.1). Мы просто удалили вызов функции expression() в функции expression() и заменили его циклом. Другими словами, перевели Выражение в грамматическом правиле в цикл поиска Терма, за которым следует символ + или –.
6.5.3. Термы
Грамматическое правило для Терма очень похоже на правило для Выражения.
Терм:
Первичное выражение
Терм '*' Первичное выражение
Терм '/' Первичное выражение
Терм '%' Первичное выражение
Следовательно, программный код также должен быть похож на код для Выражения. Вот как выглядит его первый вариант:
double term()
{
double left = primary();
Token t = get_token();
while(true) {
switch (t.kind) {
case '*':
left *= primary();
t = get_token();
break;
case '/':
left /= primary();
t = get_token();
break;
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. Запустите его и испытайте.
Нет ничего удивительного в том, что эта первая версия калькулятора работает не совсем так, как мы ожидали. Мы пожимаем плечами и спрашиваем себя: “Почему?”, или “Почему программа работает так,

