Это занятие мы отведем такой замечательной особенности программирования, чисто прикладной, как отладка. О, сколько этому понятию посвящено легенд! :) В каждой программе есть хотя бы одна ошибка, слышали, наверное? Вот-вот, борьба с ошибками и назыается отладкой. Когда вроде бы код набран верно, и программа запускается, а выдает совсем не то, что создатель от нее хочет. Или вообще ничего не делает. И начинаются часы вылавливания багов так называемых, и бессонные ночи.
В каждом втором письме с ответами на задание вы просите ваши программы проверить, правильно или нет. Увы, это вряд ли возможно в прниципе. Особенность исходных текстов в том, что понять их может только автор, и если в более-менее простых алгоритмах постороннему еще можно разобраться (но не быстро), то уже в мало-мальски большой программе рыться практически бесполезно.
Я ошибся, что сразу не объяснил способы - критерии правильности созданной программы. Они двоякие :)
Во-первых, оценивать программу будет заказчик. Как она устроена внутри, какой там код, его не интересует. Ему надо, чтобы она выполняла алгоритм правильно. Для этого он введет различные варианты исходных данных и проверит, совпадает ли ответ программы с заранее известным и рассчитанным. Такой процесс называется тестирование.
Программа проверяется на наборах тестов до тех пор, пока либо не ошибется (в таких случаях говорят, вы наверное слышали, "упала", "вылетела", "сбойнула", "глюкнула"), либо не пройдет проверку успешно. Блат, очевидно, тут не поможет :)
Подготовка тестовых примеров - тоже искусство. В нормальных компаниях есть такие должности инженеров-тестировщиков. Вот принципы тестирования, которыми я лично пользуюсь много лет (часть первая):
1. Число контрольных примеров должно быть минимальным. Это достигается тщательным подбором исходных данных.
2. Испытывать программу надо разумно :)
3. Начинать тестирование надо как можно раньше - то есть не тогда, когда уже весь код написан, а так - написали некоторую часть, протестировали. Написали - протестировали.
4. Лучше проверять программу вручную, причем не код, а алгоритм. Проверили его сами, по шагам, получили во всех случаях правильный результат - просто переносите его в виде кода в среду разработки.
5. Для первых проверок использовать простые тесты.
6. В тестах использовать различные типы данных. Так, ожидается ввод числа, а мы вводим строку :)
7. Тестирование должно охватывать все логические ветви (например, при расчете дискримининта тесты должны включать варианты, когда корень один и ни одного, и по разным причинам).
Допустим, тест выявил ошибку. Вот реальный пример прислала Лена (я его чуть-чуть сократил):
program Project2;
{$APPTYPE CONSOLE}
uses math, SysUtils;
var a,b,c:integer;
var d,kd,x,x1,x2:real;
begin
readln(a);
readln(b);
readln(c);
d:=(power(b,2)-4*a*c);
kd:=sqrt(d);
IF ( D<0) OR (A=0) THEN
begin
writeln( ' reshenii net ' );
end;
if (d=0) and (a<>0) then
begin
x:=-b/2*a;
write( ' x= ' );
write(x);
end;
if (d>0) and (a<>0) then
begin
x1:=(-b-kd)/2*a;
x2:=(-b+kd)/2*a;
write( ' x1= ' );
write(x1);
write( ' ; x2= ' );
write(x2);
end;
readln;
end.
В процессе тестирования :) Лена выяснила, что если дискриминант D меньше нуля, то сообщение, которое должно выдаваться (в первом условном операторе), не показывается, и программа завершается с ошибкой. Это, кстати, нормально. Профессиональные программисты со стажем 10 и более лет на 1000 строк исходного кода допускают в среднем 131,3 ошибки. ОДна ошибка на 8 операторов :)
Но что делать-то? Как найти, в чем ошибка?
Способов как минимум три. Все они основаны на том, что программисту надо взять на себя ответственность за свой собственный программный код.
1) Классический метод пристального взгляда подразумевает рассматривание исходных текстов :) Очень эффективно, кстати, как ни удивительно - я когда-то на эту тему даже статью написал:
Ну, кто первый в этом коде найдет ошибку, просто его рассматривая? :)
2) Выдача промежуточных результатов (на экран, в файл). Некоторые среды даже способны собирать информацию о внутренней работе программы в процессе ее выполнения. В нашем случае после каждого важного оператора можно ставить что-то вроде
writeln(важная-переменная); readln;
и смотреть на экране, как происходит расчет.
3) Самый популярный способ - выполнение программы по шагам. Рассмотрим его более подробно.
Вот программу вышеприведенную мы запустили, нажав F9, ввели например 1 enter 1 enter 10 enter, и тут сработала она как-то не так. Просто закрылась и все. Хорошо бы посмотреть, что же у нее внутри происходит, правда?
В Дельфи имеется такая магическая клавиша F8. Для нее и кнопочка на панели есть, рядом с Run, крайнаяя справа, называется Step Over (Шаг поверх). Почему поверх, пока неважно (а в принципе означает выполнение за один шаг текущей команды без погружения в нее саму).
Нажмите! Смелее!
В результате сиреневой (в зависимости от настроек) линией подсветилась строчка редактора:
Да еще стрелочка слева видна. Это означает, что умница Дельфи начала выполнять нашу программу по шагам. Сейчас будет выполнена самая первая команда программы begin. Так как она ничего не делает, то ничего и не произойдет.
Снова нажмите - снова полоска подсветки переместится на следующий выполняемый оператор. Где мы вводим a. Что теперь будет, если снова нажать F8?
Важно! ПОдсвечивается та строка, которая только будет выполняться после нажатия, а не та, которая уже была выполнена.
Так как сейчас выполняется ввод с консоли, то после нажатия F8 полоска исчезнет. Переключитесь в окно программы-консоли (оно должно быть видно внизу на панели задач), введите число, нажмите Enter - управление снова вернется в Дельфи!
Не помню, как ранние версии, а Дельфи 7 способна показывать значения любых переменных, если на них навести курсор! Наведите курсор на любое место, где переменная a записана, и вам покажется всплывающее сообщение "a = 1".
Таким образом доходим до расчета Д. Он у нас будет равен -39, проверьте. А вот при попытке выполнить следующий оператор расчета переменной kd, где корень из Д вычисляется, программа и завершится (с ошибкой). Почему? Догадайтесь сами :)
Удобно? Не то слово. Это основной инструмент программиста, пошаговый отладчик.
Нередко выполнять всю программу по шагам неудобно - слишком долго. Можно воспользоваться так называемыми
точкам прерывания. Поставьте курсор на строку с расчетом kd, и нажмите F5. Эта строчка выделится красной полосой. Теперь запустите программу на выполнение обычным способом - клавишей F9. Как только программа дойдет в ходе работы до строчки,
помеченной красной линией, работа ее прервется, и управление будет передано Дельфи (стрелочка в редакторе слева появится). Дальше программу снова можно по шагам выполнять, смотреть значения переменных и так далее.
Если ошибка найдена, а программа находится в решиме отладки (Debug), то программу надо предварительно завершить (прекратить работу). Для этого используется комбинация клавиш Ctrl + F2 или команда главного меню Run - Program Reset.
В Borland C++Builder также все будет.
Коварный Microsoft, конкурент Borland по средствам разработки, в Visual Studio (Visual Basic, Visual C++) использует прямо противоположные клавиши. Для запуска - F5, для установки точки прерывания - F9. Я их все время путаю :)
Шаг (Step Over) - F10, сброс програмы - Shift + F5. В остальном все так же подсвечивается, значения переменных показываются при наведении курсора.
Задание - придумайте для всех своих программ подходящие тесты, и повыполняйте их по шагам. Освойтесь с этим очень полезным и очень важным режимом.
А также на развитие творческих способностей. Давно что-то мы их не развивали. Все логика, логика :)
У вас наверняка в ходе создания своих программок встречались уже ошибки. Так вот. По какой-нибудь ошибке
придумайте СКАЗКУ.
Присылайте мне, а я их обязательно опубликую.
Ну например на тему ошибки в этом выпуске - "Поставил царь у склада стражников, да только не снаружи ворот, а внутри у дальней стенки..." :)