Отладка и выполнение программы
После того, как программа набрана в виде текста в окне редактирования, ее необходимо откомпилировать, устранить синтаксические и семантические ошибки и выполнить, то есть получить конечный результат.
После набора программы ее рекомендуется сохранить на диске. Более того, если текст программы достаточно объемен, лучше всего делать и промежуточные записи во избежание потери набранного текста при ошибочных действиях или сбоях компьютера.
Рис. 3. Сохранение текста программы
Если программа набирается заново, то есть активное окно имеет имя NONAME00.PAS, то при сохранении программы, – нажатии клавиши F2, выполнится команда File/ Save as... При этом появится диалоговое окно со списком файлов, – программ из текущего раздела, аналогично примеру, приведенному на рис. 3. В области Save file as набирается имя файла, с которым он будет сохранен на диске. Если не ставить точку и расширение, то имя автоматически будет дополнено расширением .PAS. После записи на диск имя в текущем окне редактирования сменится на заданное. После дальнейшего набора программы или ее корректировки при нажатии клавиши F2 будет выполняться команда File/ Save (сохранение файла с тем же именем), и никаких дополнительных запросов происходить не будет.
При переходе к новой программе окно с текстом старой программы закрывают (<Alt+F3> или Window/ Close, хотя это и не обязательно) и открывают новое окно редактирования (File/ New). При необходимости загрузки (чтения с диска) другой, ранее набранной программы, выполняется команда File/ Open... (F3), в появляющемся диалоговом окне, представленном на рис. 4, в области Files перемещением маркера выбирается нужный файл и нажимается клавиша Enter, эквивалентная кнопке диалогового окна Open. Здесь так же можно открывать вложенные папки, их список находится в конце, или переходить к папкам более высокого уровня, выбрав строку «..\».
Рис. 4. Загрузка текста программы
После ввода всей программы (или ее загрузки) ее можно либо откомпилировать с целью устранения синтаксических ошибок (<Alt+F9>), либо сразу выполнить (<Ctrl+F9>). В последнем случае все равно произойдет предварительная компиляция, и если присутствуют синтаксические ошибки, программа выполняться не будет.
Все ошибки программ делятся на два больших класса: ошибки компиляции и ошибки выполнения. О первом типе ошибок сообщает компилятор до запуска программы на выполнение с указанием типа ошибки и предполагаемого ее места. К сожалению, ошибка может быть совсем не там, где стоит курсор; его положение – это фактически то место, где компилятор «осознает» ошибку. Например, если имеется лишнее слово BEGIN в программе, то компилятор не поймет этого до тех пор, пока не дойдет до последней строки программы (пары служебных слов BEGIN... END должны быть сбалансированы).
На начальном этапе программирования большинство синтаксических ошибок происходит из-за невнимательности набора программы. Даже в первой строке часто делаются ошибки, как представлено на рис. 5. После компиляции курсор установлен в самой первой позиции (на рисунке буква Р подчеркнута).
Рис. 5. Пример 1 синтаксической ошибки
В данном примере пояснение причины ошибки, а это красная строка с текстом «Error 36: BEGIN expected» (ожидается служебное слово Begin), не имеет особого смысла. Здесь служебное слово Program пишется с одним m, поэтому первая строка не воспринята как начало текста программы. В Турбо Паскале заголовок программы (первая строка) может отсутствовать, так же как и все разделы описаний. Но раздел операторов, начинающихся со слова Begin, должен быть обязательно.
Более осмысленное толкование причины ошибки происходит в случае, представленном на рис. 6 во фрагменте окна.
Рис. 6. Пример 2 синтаксической ошибки
Здесь сообщение причины ошибки, «Error 85: “;” expected»: перед единицей (где установлен курсор) ожидается точка с запятой. Причина ошибки заключается в том, что имя программы, как и имена переменных, не должно включать пробелы, поэтому за разделителем, – пробелом, – должна идти следующая конструкция языка, отделяемая от заголовка точкой с запятой.
Довольно часто курсор устанавливается в строке, следующей за ошибочной, пример которой представлен на рис. 7 во фрагменте окна.
Рис. 7. Пример 3 синтаксической ошибки
Точка с запятой должна стоять перед F (на этой букве установлен курсор), то есть в конце предыдущей строки.
В любом случае при непонимании ошибки следует обратиться к синтаксису отмеченной курсором конструкции языка Турбо Паскаль (оператору, описанию, структуре), либо к предыдущей.
Ошибки выполнения появляются после компиляции программы и запуска ее на выполнение, и на экране с текстом программы выдается сообщение вида
Run-time error < nnn > at < xxxx:yyyy >
где nnn номер ошибки выполнения, xxxx:yyyy адрес ошибки выполнения.
Ошибки выполнения искать труднее, чем синтаксические. Это и ошибки на уровне операционной системы DOS, и ошибки ввода-вывода, и ошибки алгоритма, и другие. Но, хотя ошибок данного класса довольно много, в данном курсе контрольных работ чаще всего появляются только две фатальные ошибки (приводящие к аварийному завершению программы):
200 Division by zero (Деление на нуль)
205 Floating point overflow (Переполнение при операции с плавающей точкой)
Вообще говоря, комментарии к этим ошибкам не требуют дополнительных пояснений, хотя они могут случаться не только при недопустимых делениях и вышедших из под контроля циклах операций умножения, но и при недопустимых аргументах математических функций: отрицательных значениях для логарифмов и квадратных корней, и других.
Все же наибольшую трудность вызывают ситуации, когда никаких сообщений не появляется, а компьютер просто «зависает», или выдает результат, но неверный. При этом начинающий пользователь склонен обвинять компьютер, хотя практически всегда виноват он сам. Эти ошибки возникают либо при неверно составленном алгоритме, а соответственно, и программе, либо при выходе за границы неконтролируемых величин.
Для обнаружения выходов за допустимые границы и переполнений можно использовать две директивы компилятора. По умолчанию они выключены, так как замедляют работу программы и увеличивают ее размер, а используются только при отладке.
Проверка границ. {$R+}, эквивалент меню Options / Compiler, опция Runtime errors / Range checking.
Данная директива приводит в действие генерацию кода проверки границ. Все выражения с индексированными строками и массивы проверяются на предмет нахождения их внутри указанных границ, а все операторы присваивания значений скалярным величинам и переменным поддиапазонов также проверяются на нахождение в заданных границах. Если обнаруживается нарушение диапазона, программа завершает свою работу, выводя сообщение об ошибке выполнения при проверке границ:
201 Range check error
Проверка переполнения при математических операциях. {Q+}, эквивалент меню Options / Compiler, опция Runtime errors / Overflow checking.
Проверяется результат операций над целочисленными данными. Программа завершает работу аналогично:
215 Arithmetic overflow error
ИИО Турбо Паскаля может работать с несколькими окнами, просмотреть список открытых окон можно командой Window/ List... В окне редактирования набираются, просматриваются и редактируются программы, отдаются команды ИИО, устанавливаются параметры работы и так далее. Но при запуске программы появляется другое окно, – окно пользователя, «User screen». Сюда помещаются результаты работы по программе, и оно видно до тех пор, пока программа не перестанет выполняться. Так как в данном курсе контрольных работ программы весьма просты, то они выполняются практически мгновенно, и снова появляется окно редактирования ИИО. Для просмотра экрана пользователя (в данных работах это результат вычислений по программе) нажимается комбинация клавиш <Alt+F5>.Для возврата к основному окну можно нажать любую клавишу.
Если после запуска возникнет необходимость прервать выполнение программы, например в случае ее «зацикливания», используют комбинацию клавиш <Ctrl+Break>.
В окне пользователя мы увидим либо сообщение об ошибке выполнения, либо результат (если отсутствует оператор вывода, естественно, результата не будет). Результат может быть и неверным как из-за неправильно составленного алгоритма, так и из-за ошибок в программе, которые формально, с точки зрения компилятора, ошибками не являются. Например, при вычислении суммы по фрагменту программы, представленному на рис. 8.
Рис. 8. Пример логической ошибки в программе
Для этой программы результат вычислений будет равен 0.10000. Здесь после служебного слова do стоит пустой оператор (точка с запятой), поэтому именно он, то есть «ничто», будет выполняться десять раз. Затем к нулю прибавится одна десятая. Формально программа составлена правильно, но фактически десять раз должен выполняться оператор из строки S:=S+1/I.
Конкретные рекомендации в таких случаях являются индивидуальными для каждой программы, существуют только общие методы тестирования. Рассмотрим два самых простейших.
Первый метод самый универсальный и может использоваться с любыми языками программирования, компиляторами и ассемблерами. Заключается он в выводе промежуточных результатов. Внутрь цикла, или в «подозрительные» места программы временно вставляются операторы вывода изменяемых переменных. Например, программа (приведен фрагмент)
For i:=1 to 15 do
Begin
S:=S+1/i;
i:=i+1
end;
просто «зацикливается» (если не используются директивы контроля). Но если перед i:=i+1 поставить оператор
Writeln (S:8:5,i:8);
то после запуска программы появятся два столбика бегущих чисел. Если приостановить вывод информации на экран монитора клавишей Pause, то сразу будет видно, что i изменяется не с шагом 1, а 2. То есть параметр цикла изменяется и в операторе For, и в операторе присваивания.
Второй метод привлекает средства отладки ИИО. Предварительно установив программный счетчик на начало программы (<Ctrl+F2>), открывается специальное окно наблюдаемых переменных (Watch-окно, клавиши <Ctrl+F7>). В нем набирается имя первой контролируемой переменной, нажимается Enter. После этого появляется окно с именем Watches и значением этой переменной, в которое можно добавить и другие переменные для контроля их значений. Для пооператорного выполнения программы предназначена «горячая» клавиша F7. После каждого нажатия клавиши F7 выполняется один оператор. Если он производит изменение значения переменной, то это сразу отразится в окне наблюдения.
Таким образом, анализируя изменение значений переменных при пооператорном выполнении программы, легко найти ошибку в алгоритме, и соответственно в программе.
По завершении работы с ИИО, из нее можно выйти по комбинации клавиш <Alt+X>.