Задание
1. Скомпилируйте файл
calculator08buggy.cpp
.
2. Пройдитесь по всей программе и добавьте необходимые комментарии.
3. В ходе комментирования вы обнаружите ошибки (специально вставленные в код, чтобы вы их нашли). Исправьте их; в тексте книги их нет.
4. Тестирование: подготовьте набор тестовых вводных данных и используйте их для тестирования калькулятора. Насколько полон ваш список? Что вы ищете? Включите в список отрицательные числа, нуль, очень маленькие числа и “странный” ввод.
5. Проведите тестирование и исправьте все ошибки, которые пропустили при комментировании.
6. Добавьте предопределенное имя
k
со значением
1000
.
7. Предусмотрите возможность вычисления функции
sqrt()
, например
sqrt(2+6.7)
. Естественно, значение
sqrt(x)
— это квадратный корень из числа
x;
например
sqrt(9)
равно
3
.
8. Используйте стандартную функцию
sqrt()
, описанную в заголовочном файле
std_lib_facilities.h
. Не забудьте обновить комментарии и грамматику.
9. Предусмотрите перехват попыток извлечь квадратный корень из отрицательного числа и выведите на экран соответствующее сообщение об ошибке.
10. Предусмотрите возможность использовать функцию
pow(x,i)
, означающую “умножить
x
на себя
i
раз”; например
pow(2.5,3)
равно
2.5*2.5*2.5
. Аргумент
i
должен быть целым числом. Проверьте это с помощью оператора
%
.
11. Измените “ключевое слово объявления” с
let
на
#
.
12. Измените “ключевое слово выхода” с
q
на
exit
. Для этого понадобится строка для кодирования инструкции “выход”, как мы уже делали для инструкции “let” в разделе 7.8.2.
Контрольные вопросы
1. Зачем работать над программой, когда ее первая версия уже доказала свою работоспособность? Перечислите причины.
2. Почему выражение “
1+2; q
”, введенное в программу, не приводит к выходу из нее после обнаружения ошибки?
3. Зачем нам понадобилась символьная константа с именем
number
?
4. Мы разбили функцию
main()
на две разные функции. Что делает новая функция и зачем мы разделили функцию
main()
?
5. Зачем вообще разделять код на несколько функций? Сформулируйте принципы.
6. Зачем нужны комментарии и как они должны быть организованы?
7. Что делает оператор
narrow_cast
?
8. Как используются символические константы?
9. Почему важна организация кода?
10. Как мы реализовали оператор
%
(остаток) применительно к числам с плавающей точкой?
11. Что и как делает функция
is_declared()
?
12. Реализация “ключевого слова”
let
использует несколько символов. Как обеспечен ввод этой лексемы как единого целого в модифицированном коде?
13. Сформулируйте правило, определяющее, что является именем в калькуляторе и что нет?
14. Чем хороша идея о постепенной разработке программ?
15. Когда следует начинать тестирование?
16. Когда следует проводить повторное тестирование?
17. Как вы принимаете решение о том, какие функции следует сделать отдельными?
18. Как вы выбираете имена для переменных и функций? Обоснуйте свой выбор.
19. Зачем нужны комментарии?
20. Что следует писать в комментариях, а что нет?
21. Когда следует считать программу законченной?
Термины
Упражнения
1. Предусмотрите использование символа подчеркивания в именах внутри программы–калькулятора.
2. Реализуйте оператор присваивания
=
, чтобы можно было изменять значение переменной после ее объявления с помощью инструкции
let
.
3. Реализуйте именованные константы, которые действительно не могут изменять свои значения. Подсказка: в класс
Variable
необходимо добавить функцию-член, различающую константы и переменные и проверяющую это при выполнении функции
set_value()
. Если хотите дать пользователю возможность объявлять собственные именованные константы (а не только
pi
и
e
), то необходимо добавить соответствующее обозначение, например
const pi = 3.14;
.
4. Функции
get_value()
,
set_value()
,
is_declared()
и
define_name()
оперируют переменной
var_table
. Определите класс
Symbol_table
с членом
var_table
типа
vector<Variable>
и функциями-членами
get()
,
set()
,
is_declared()
и
define()
. Перепишите программу так, чтобы использовать переменную типа
Symbol_table
.
5. Модифицируйте функцию
Token_stream::get()
так, чтобы, обнаружив символ перехода на следующую строку, она возвращала лексему
Token(print)
. Для этого требуется обеспечить поиск разделителей и обработку символа
'\n'
. Для этого можно использовать стандартную библиотечную функцию
isspace(ch)
, возвращающую значение
true
, если символ
ch
является разделителем.
6. Каждая программа должна содержать подсказки для пользователя. Пусть при нажатии клавиши
<Н>
калькулятор выводит на экран инструкции по эксплуатации.
7. Измените команды
q
и
h
на
quit
и
help
соответственно.
8. Грамматика в разделе 7.6.4 является неполной (мы уже предостерегали вас от чрезмерного увлечения комментариями); в ней не определена последовательность инструкций, например
4+4;
5–6;
, и не учтены усовершенствования, описанные в разделе 7.8. Исправьте грамматику. Кроме того, добавьте в первый и все остальные комментарии программы все, что считаете нужным.