Сообщения об ошибках. Ошибки в программах делятся на те, которые Паскаль замечает, и на те, что не замечает и в принципе заметить не может. К первым относятся все синтаксические погрешности, например, BIGIN вместо BEGIN. Их Паскаль замечает еще на стадии компиляции. На стадии выполнения он замечает такие ошибки, как Sqrt(-25), то есть квадратный корень из ‑25. Но вот, если вы, желая возвести число a в куб, вместо a*a*a пишете a*a, то этого не заметит ни один язык в мире.
Обнаружив грамматическую ошибку, Паскаль выдает золотыми буквами на красном фоне краткое описание ошибки и ставит курсор в то место программы, где, по его мнению, она находится.
Обнаружив ошибку на стадии выполнения, Паскаль выдает белыми буквами на черном фоне окна пользователя сообщение Runtime error и иногда золотыми буквами на красном фоне краткое описание ошибки и ставит курсор в то место программы, где, по его мнению, она находится.
Вот наиболее типичные для начинающих сообщения об ошибках того и другого рода:
Сообщение |
Перевод |
Вероятная причина ошибки |
Unexpected end of file |
Неожиданный конец файла |
Вы забыли поставить точку после последнего END. Или не совпадает количество begin и количество end |
“;” expected |
Ждал точку с запятой |
Вы забыли поставить точку с запятой после предыдущего оператора |
“,” expected |
Ждал запятую |
Вы указали слишком мало параметров в обращении к подпрограмме |
“)” expected |
Ждал скобку “)” |
Вы указали слишком много параметров в обращении к подпрограмме |
Unknown identifier |
Неизвестное имя |
Вы забыли описать это имя в разделе описаний Неправильно записали стандартное имя, например, ReedLn вместо ReadLn |
Type mismatch |
Несовпадение типов |
В вашей программе встречаются примерно такие «сладкие парочки»: VAR c:String; … c:=1+2 или VAR h:Integer; … h:=9/7 |
Duplicate identifier |
Дубль имени |
Одно и то же имя описано два раза. Например, VAR a, c, a :String; |
Syntax error |
Синтаксическая ошибка |
Паскаль затрудняется назвать причину ошибки. Часто причина в том, что вы забыли взять строковую константу в кавычки |
BEGIN expected |
Ждал BEGIN |
Возможно, не совпадает количество begin и количество end |
END expected |
Ждал END |
Возможно, не совпадает количество begin и количество end |
String constant exeeds line |
Строковая константа превышает допустимую длину |
Вы забыли закрыть кавычки в строковой константе |
Line too long |
Строчка слишком длинна |
Слишком длинная строчка в программе (не путать со строковой константой, которую нужно брать в кавычки). Не рекомендую залезать программным текстом за правый край экрана |
Disk full |
Диск заполнен |
На вашем диске не осталось места. Надо что-то стереть |
Lower bound greater than upper bound |
Нижняя граница диапазона больше верхней |
Например, вы вместо array[2..5] написали array[5..2]. |
Invalid floating point operation |
Неправильная операция с вещественным результатом |
Sqrt(-25) или a/0 или что-нибудь в этом роде |
Ordinal expression expected |
Ждал выражение порядкового типа |
Например, вы вместо for i:=1 to 8 написали for i:=1 to 8.5 |
Error in expression |
Ошибка в выражении |
Например, вы вместо k:=а*8 написали k:=а**8 |
Range check error |
Ошибка проверки диапазона |
Переменная в процессе выполнения программы вышла за пределы допустимого диапазона, как например, в 12.9 |
Constant out of range |
Константа не в диапазоне |
Величина константы в программе превосходит допустимый диапазон |
Invalid numeric format |
Неправильный числовой формат |
Если, например, вы по оператору ReadLn(k) в программе VAR k:Integer; …. ReadLn(k) … пытаетесь ввести число 25.3 |
Более подробное описание некоторых ошибок вы найдете в 4.3.
Понять смысл многих других сообщений об ошибках вам поможет перевод некоторых часто встречающихся в сообщениях слов:
expected ждал
identifier имя
invalid неправильный
operation операция
error ошибка
variable переменная
Невозможно создать компилятор, который бы всегда точно находил место и причину ошибки. Поэтому приготовьтесь к тому, что некоторые сообщения вы будете долго разглядывать в недоумении. Считайте их не реальными ошибками, а намеками на реальные ошибки.
Пошаговый режим
Вы запускаете программу, Паскаль на ошибки не жалуется, но результаты вас не удовлетворяют. Предположим, что внимательно просмотрев программу, ошибку вы не обнаружили. Все. Вы в тупике.
На случай возникновения таких ситуаций Паскаль предлагает ряд отладочных средств. Я начну с пошагового режима.
Идея пошагового режима вот в чем. Компьютер слишком быстро выполняет программу и человек не успевает проследить «за ходом его мыслей». Хорошо бы мы сами задавали темп выполнения программы. Тогда ошибку обнаружить было бы значительно легче.
Рассмотрим задачу из 5.1: В компьютер вводятся два произвольных положительных числа - длины сторон двух кубиков. Компьютер должен подсчитать объем одного кубика - большего по размеру . Обозначаем a1 - сторону одного кубика, a2 - сторону другого, V - объем кубика. Приведем второй вариант программы:
VAR a1,a2,V : Real;
BEGIN
ReadLn (a1,a2);
if a1>a2
then V:=a1*a1*a1
else V:=a2*a2*a2;
WriteLn (V : 15:5)
END.
Запускайте программу, но не обычным образом, а клавишей F7, которая является более быстрым способом вызова меню Run®Trace into. (Кстати, обратите внимание, что справа от многих опций меню обозначены «горячие» клавиши, которыми эти опции можно быстро вызывать.) Паскаль откомпилирует вашу программу и сделает паузу перед началом выполнения программы, подсветив горизонтальной полосой строку BEGIN.
Еще раз F7. Ничего не происходит, только полоса подсветки прыгает на следующую строку. В ней находится первый исполняемый оператор вашей программы – ReadLn (a1,a2).
Итак, правило простое – при нажатии на F7 Паскаль выполняет одну строку программы и подсвечивает ту строку, которой предстоит быть выполненной.
F7. Паскаль выполняет ReadLn (a1,a2), в результате чего у вас, как и при обычном выполнении программы, во весь экран распахивается черное окно пользователя. Оператор требует ввода двух чисел. Введите, например, 5 и 4, не забыв нажать на клавишу ввода. Окно пользователя пропадет, снова возникнет окно редактора и вы увидите, что серая полоса подсветки перескочила на строку if a1>a2.
F7. Паскаль выполняет if a1>a2, в результате чего полоса прыгает на then V:=a1*a1*a1, так как 5>4.
F7. Полоса перепрыгивает через else V:=a2*a2*a2 и попадает на WriteLn (V : 15:5).
F7. Паскаль выполняет WriteLn (V : 15:5), в результате чего печатается результат, а полоса перескакивает на строку END.
F7. Полоса пропадает. Программа выполнена. Посмотрим на результат при помощи Alt-F5.
Теперь еще раз выполните ту же программу в пошаговом режиме. Но когда ReadLn (a1,a2) потребует двух чисел, введите 2 и 3. Теперь уже после if a1>a2 полоса прыгает не на then V:=a1*a1*a1, а на else V:=a2*a2*a2.
В любой момент пошагового выполнения программы вы можете вместо F7 выбрать Run®Run (клавиши Ctrl-F9) и программа продолжит выполняться в обычном режиме. Чтобы прервать пошаговый режим, выберите Run®Program reset (клавиши Ctrl-F2).
Работа с окнами пользователя и отладчика
Предположим, у вас не получается задание из 6.1 - определить без компьютера, что будет печатать следующая программа:
LABEL m1,met5;
VAR n,k : Integer;
BEGIN
n:=10;
k:=0;
WriteLn('Считаем зайцев' );
met5: Write(n);
n:=n+k;
goto m1;
n:=n+1;
m1: Write(' зайцев ');
ReadLn;
k:=k+1;
goto met5;
WriteLn('Посчитали зайцев')
END.
Ответ: Эта программа должна печатать:
Считаем зайцев
10 зайцев
10 зайцев
11 зайцев
13 зайцев
16 зайцев
20 зайцев
………
С ответом у вас не сходится. Значит, вы чего-то не понимаете. Чего? Чтобы определить это, вы вводите программу в компьютер. Он печатает все, как в ответе. Почему? Вероятно, вы не понимаете, как изменяются в процессе выполнения программы значения переменных n и k. Хорошо бы можно было подсмотреть за их значениями в оперативной памяти. Хорошо бы также напечатанные результаты не пропадали с экрана, а были бы всегда перед глазами.
Проделайте следующее. (При дальнейшем объяснении я буду предполагать, что вы умеете обращаться с несколькими окнами на экране. Кто не умеет, читайте следующий параграф.)
Сузьте окно вашей программы так, чтобы оно освободило примерно половину ширины экрана. Далее - Debug®Output. Перед вами появляется черное окно пользователя, в котором вы привыкли наблюдать результаты, но в уменьшенном виде. Измените его размер и отбуксируйте на свободное место экрана.
Далее - Debug®Watch. Перед вами появляется окно отладчика, в котором вы будете наблюдать значения переменных величин в оперативной памяти. Измените его размер и отбуксируйте на оставшуюся часть экрана.
Вот как будет выглядеть ваш экран после всех манипуляций (и уже после нескольких выполнений цикла в пошаговом режиме, о чем дальше):
Вы сами должны сказать Паскалю, за какими переменными хотите следить. Очевидно, в вашем случае это n и k. Ваши действия: Debug®Add watch… ,запишите имя n в открывшемся диалоговом окне и – щелчок по кнопке OK. В окне отладчика появится сообщение n:7 или n:0 или какое-нибудь другое число или сообщение. Не обращайте на это внимания. Повторите всю процедуру с k.
Теперь можно запускать программу на выполнение в пошаговом режиме. Для этого нажмите на F7. Паскаль откомпилирует вашу программу, возможно, изменит значения в окне отладчика и сделает паузу перед началом выполнения программы, подсветив горизонтальной полосой строку BEGIN.
F7. Паскаль, возможно, обнулит значения в окне отладчика. Полоса подсветки прыгает на следующую строку. В ней находится первый исполняемый оператор вашей программы – n:=10.
Итак, правило простое – при нажатии на F7 Паскаль выполняет одну строку программы и подсвечивает ту строку, которой предстоит быть выполненной.
F7. Паскаль выполняет n:=10, в результате чего в окне отладчика значение n меняется на 10, а серая полоса прыгает на строку k:=0.
F7. Паскаль выполняет k:=0, в результате чего в окне отладчика значение k становится равным 0, а полоса прыгает на строку WriteLn('Считаем зайцев' ).
F7. Паскаль выполняет WriteLn('Считаем зайцев' ), в результате чего в окне пользователя появляется напечатанный текст Считаем зайцев, а полоса прыгает на строку met5: Write(n).
F7. Паскаль выполняет Write(n). В окне пользователя в новой строке появляется число 10, так как в оперативной памяти n равно 10 (об этом нам говорит окно отладчика). а полоса прыгает на строку n:=n+k.
F7. Паскаль выполняет n:=n+k, в результате чего в окне отладчика значение n остается равным 10, так как в оперативной памяти k равно 0. Полоса прыгает на строку goto m1.
F7. Паскаль выполняет goto m1. Полоса перепрыгивает на строку m1: Write(' зайцев ').
F7. Паскаль выполняет Write(' зайцев ' ), в результате чего в окне пользователя справа от числа 10 появляется текст зайцев, а полоса прыгает на строку ReadLn.
F7. Паскаль выполняет ReadLn, в результате чего окно пользователя распахивается на весь экран и ReadLn ждет, когда вы нажмете на клавишу ввода. Вы нажимаете – и полоса прыгает на строку k:=k+1.
F7. Паскаль выполняет k:=k+1, в результате чего в окне отладчика значение k меняется на 11. Полоса прыгает на строку goto met5.
F7. Паскаль выполняет goto met5. Полоса перепрыгивает вверх, на строку met5: Write(n).
И так далее.
Если ваша программа рисует что-то в графическом режиме, то, к сожалению, при описанном способе работы картинки видны не будут.
Если в вашей программе есть подпрограммы, то серая полоса проникнет и внутрь подпрограмм и будет скакать там, как ни в чем не бывало. Таким образом, вы сможете анализировать и работу подпрограмм. Если же вы не хотите утомлять себя прыжками внутри подпрограмм, нажимайте не F7, а F8. Тогда Паскаль будет выполнять подпрограмму мгновенно в автоматическом режиме и серая полоса будет путешествовать только внутри основной программы. Вы можете свободно чередовать нажатия F7 и F8. Клавиша F7 будет направлять вас «вглубь» подпрограмм, а F8 - «наружу».
Отладка больших программ
Точки прерывания - Breakpoints. Будем считать “большими” программы, превышающие пару размеров экрана. Для них изложенный только что пошаговый режим может быть очень утомительным, так как слишком часто приходится жать F7. Вы можете заставить Паскаль при выполнении программы задерживаться не на каждой строке, а только на некоторых - тех, что вам нужно.
Поставьте курсор на одну из этих строк и нажмите Ctrl-F8. Строка станет красной. Это знак того, что при выполнении программа на ней остановится. Будем называть эту строку точкой прерывания или контрольной точкой.
Поставьте курсор на другую строку и снова нажмите Ctrl-F8. Эта строка тоже станет точкой прерывания.
Так проделайте со всеми нужными вам строками. Затем можете обычным образом вывести на экран окна пользователя и отладчика.
А теперь обычным образом (Run®Run или Ctrl-F9) запускайте программу. Программа будет выполняться до тех пор, пока не наткнется на какую-нибудь точку прерывания. На ней она встанет и продолжит работу с того места, где остановилась, только при новом нажатии Ctrl-F9. И так далее.
Убирается точка прерывания точно так же, как ставится - Ctrl-F8.
“Иди до курсора” - Goto cursor. Это еще один способ остановки в нужной вам строке. Поставьте курсор в нужную строку и нажмите F4. Программа будет выполняться до тех пор, пока не наткнется на строку с курсором. А теперь поставьте курсор в другую строку и снова нажмите F4. Программа продолжит работу с того места, где остановилась, и будет выполняться до тех пор, пока не наткнется на строку с курсором. И так далее.
Кстати, в процессе выполнения программы вы можете достаточно свободно переключаться между разными способами ее выполнения – F7, F4 или Ctrl-F9.
Испольование Write и ReadLn. Если программа работает с графикой, то пользоваться вышеописанными средствами отладки или неудобно или нельзя. Не беда. Еще до существования всех и всяческих отладчиков программисты пользовались вспомогательной печатью значений переменных. Действительно, вместо использования окна отладчика для подсматривания за переменными n и k, вы просто можете в программу вставить дополнительный оператор Write(’ n=‘,n,’ k=‘,k). А вместо пошагового режима можете в нужных местах программы поставить ReadLn. Когда программа будет отлажена, вы уберете эти дополнительные операторы.
Только имейте в виду, что когда экран с вашими картинками донизу будет заполнен информацией, напечатанной оператором Write, он начнет прокручиваться вверх, а вместе с ним вверх уползут и ваши картинки. Чтобы избежать этого, нужно сделать так, чтобы не допечатав донизу, компьютер при помощи ReadLn сделал паузу (чтобы вы успели посмотреть результаты печати) и снова стал печатать бы сверху. А для печати сверху необходимо вставить в нужное место программы оператор GotoXY (см.15.7). А уж для этого вам нужно использовать модуль CRT (см. 9.1) и вставить в начало программы оператор DirectVideo:=false (см.10.3).
Скачано с www.znanio.ru
Материалы на данной страницы взяты из открытых источников либо размещены пользователем в соответствии с договором-офертой сайта. Вы можете сообщить о нарушении.