Чтение онлайн

на главную - закладки

Жанры

Программирование. Принципы и практика использования C++ Исправленное издание
Шрифт:

return 1;

}

По существу, мы заменили функцию

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

Обнаружив эту проблему, мы написали вариант функции

keep_window_open
, аргументом которой была строка, закрывающая окно, как только пользователь вводил ее после приглашения. Таким образом, более простое решение выглядит так:

catch (runtime_error& e) {

cerr << e.what << endl;

keep_window_open("~~");

return 1;

}

Рассмотрим

еще один пример.

+1

!1~~

Эти данные вынуждают калькулятор выдавать соответствующие сообщения об ошибках, например

Чтобы выйти, введите ~~

и не прекращать работу, пока пользователь не введет строку

~~
.

Входные данные для калькулятора вводятся с клавиатуры. Это затрудняет тестирование: каждый раз, внося улучшение, мы должны напечатать множество контрольных примеров (каждый раз заново!), чтобы убедиться, что программа по-прежнему работает. Было бы лучше, если бы контрольные примеры где-то хранились и вызывать их одной командой. Некоторые операционные системы (в частности, Unix) упрощают эту задачу, позволяя потоку

cin
считывать данные из файла без модификации программы, а потоку
cout
— направлять данные в файл. В других случаях мы должны модифицировать программу так, чтобы она использовала файл (подробнее об этом — в главе 10).

Рассмотрим примеры.

1+2; q

1+2 q

Мы хотели бы вывести результат (

3
) и выйти из программы. Забавно, что строка

1+2 q

приводит к этому результату, а более очевидная строка

1+2; q

вызывает ошибку Ожидается первичное выражение. Где следует искать эту ошибку? Конечно, в функции

main
, где обрабатываются символы ; и q. Мы добавили инструкции “печать” и “выход” просто для того, чтобы поскорее получить работающий вариант калькулятора (см. раздел 6.6), а теперь расплачиваемся за эту поспешность. Рассмотрим еще раз следующий фрагмент:

double val = 0;

while (cin) {

cout << "> ";

Token t = ts.get;

if (t.kind == 'q') break;

if (t.kind == ';')

cout << "= " << val << '\n';

else

ts.putback(t);

val = expression;

}

Если обнаруживаем точку с запятой, то вызываем функцию

expression
, не проверяя символ
q
. Эта функция в первую очередь ищет вызов функции
term
, которая вызывает функцию
primary
, обнаруживающую символ q. Буква q не является первичным выражением, поэтому получаем сообщение об ошибке. Итак, после тестирования точки с запятой мы должны обработать символ q.
В этот момент мы почувствовали необходимость несколько упростить логику, поэтому окончательный вариант функции
main
выглядит так:

int main

try

{

while (cin) {

cout << "> ";

Token t = ts.get;

while (t.kind == ';') t=ts.get; // считываем ';'

if (t.kind == 'q') {

keep_window_open;

return 0;

}

ts.putback(t);

cout << "= " << expression << endl;

}

keep_window_open;

return 0;

}

catch (exception& e) {

cerr << e.what << endl;

keep_window_open("~~");

return 1;

}

catch (...) {

cerr << "exception \n";

keep_window_open("~~");

return 2;

}

Это повышает надежность обработки ошибок. Таким образом, теперь можно искать новые пути улучшения калькулятора.

7.4. Отрицательные числа

Проверив калькулятор, легко убедиться, что он не слишком элегантно обрабатывает отрицательные числа. Например, выражение

–1/2

является ошибочным.

Для того чтобы калькулятор работал корректно, мы должны были бы написать

(0–1)/2

Однако это неприемлемо.

Обычно такие проблемы выявляются на поздних этапах отладки и тестирования. Только тогда можно увидеть, что на самом деле делает программа, и получить информацию, позволяющую уточнить исходные идеи. Планируя проект, целесообразно сэкономить время и извлечь выгоду из наших уроков. Очень часто первая версия поставляется пользователям без необходимых уточнений из-за напряженного расписания и жесткой стратегии управления, которая не позволяет вносить исправления в спецификацию на поздних этапах разработки. Поздние добавления — это кошмар менеджера. На самом деле, когда программа уже достаточно работоспособна, но еще не готова к поставке, еще не поздно внести дополнения; это самый первый момент, когда можно учесть опыт ее использования. Реалистичное расписание должно учитывать это обстоятельство.

В данном случае необходимо внести исправления в грамматику, чтобы предусмотреть унарный минус. На первый взгляд легче всего внести исправления в пункт Первичное выражение. Сейчас он выглядит так:

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

Число

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

Нам требуется, чтобы этот пункт выглядел примерно таким образом:

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

Число

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

Курсант: назад в СССР

Дамиров Рафаэль
1. Курсант
Фантастика:
попаданцы
альтернативная история
7.33
рейтинг книги
Курсант: назад в СССР

Чужая семья генерала драконов

Лунёва Мария
6. Генералы драконов
Фантастика:
фэнтези
5.00
рейтинг книги
Чужая семья генерала драконов

Пышка и Герцог

Ордина Ирина
Фантастика:
юмористическое фэнтези
историческое фэнтези
фэнтези
5.00
рейтинг книги
Пышка и Герцог

Имперский Курьер. Том 5

Бо Вова
5. Запечатанный мир
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Имперский Курьер. Том 5

Имя нам Легион. Том 7

Дорничев Дмитрий
7. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 7

Возвышение Меркурия

Кронос Александр
1. Меркурий
Фантастика:
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия

Законы Рода. Том 11

Андрей Мельник
11. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Законы Рода. Том 11

Измена. (Не)любимая жена олигарха

Лаванда Марго
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. (Не)любимая жена олигарха

Вираж бытия

Ланцов Михаил Алексеевич
1. Фрунзе
Фантастика:
героическая фантастика
попаданцы
альтернативная история
6.86
рейтинг книги
Вираж бытия

Отмороженный 11.0

Гарцевич Евгений Александрович
11. Отмороженный
Фантастика:
боевая фантастика
рпг
попаданцы
фантастика: прочее
фэнтези
5.00
рейтинг книги
Отмороженный 11.0

История "не"мощной графини

Зимина Юлия
1. Истории неунывающих попаданок
Фантастика:
попаданцы
фэнтези
5.00
рейтинг книги
История немощной графини

Крестоносец

Ланцов Михаил Алексеевич
7. Помещик
Фантастика:
героическая фантастика
попаданцы
альтернативная история
5.00
рейтинг книги
Крестоносец

Газлайтер. Том 15

Володин Григорий Григорьевич
15. История Телепата
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
Газлайтер. Том 15

Призыватель нулевого ранга

Дубов Дмитрий
1. Эпоха Гардара
Фантастика:
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Призыватель нулевого ранга