Страница 22 из 69
Выберите Run/Step Over, выполните WORDCNT до оператора
вызова wordlen. Затем выберите Run/Trace Into (или F7), чтобы
войти в функцию wordlen раньше чем выполнится оператор ее вызова.
Run/Trace Into пошагово выполнит программу, подобно Run/Step
Over, но вместо вызова функций осуществляет вход в них. В нашем
случае, шкала выполнения переместится в wordlen.
Сейчас важно понять логику работы wordlen. Функции передает-
ся один параметр (указатель), который указывает на слово в буфере
строки и называется wordptr. Значение wordptr присваивается ло-
кальной переменной wordlimit. Затем начинается цикл while до тех
пор, пока не встретится пробел (конец слова) или null-символ (ко-
нец строки). И наконец происходит возврат разницы между wordlimit
и wordptr, как длины слова.
Выполните две строки wordlen, описанные через оператор прис-
воения. Для этого вы можете воспользоваться Run/Trace Into или
Run/Step Over. Поскольку wordlen не вызывает никаких функций, то
эти две команды будут работать одинаково.
Оцените строку, содержащую wordlimit и присваивающую указа-
- 177,178 -
тель. Выполните оператор while. Маркер выполнения должен перемес-
титься на следующую строку, в которой происходит увеличение
wordlimit. Вместо этого он перемещается на строку дальше, на опе-
ратор return. Это может быть ошибка, которую мы ищем.
Замечание: вы вероятно захотите дважды нажать Esc, для того,
чтобы вернуться в редактор Турбо Си. Вместо этого можно
воспользоваться F10.
Обсудим, что происходит дальше. Поскольку wordlimit не уве-
личивается, то разница между wordptr и wordlimit равна 0, и
wordlen тоже возвратит 0. Это именно та ошибка, которую мы иска-
ли. Мы сузили область ошибки с "ошибка в wordlen" до "ошибка в
операторе while функции wordlen". Раз так, то нужно внимательно
посмотреть на текст программы и сделать вывод, что же неверно.
Мы можем вычислить выражение, стоящее в операторе while по
частям и посмотреть, как они работают вместе. Величина *wordlimit
равна Т кода ASCII. Мы не можем вычислить *wordlimit != SPACE,
так как SPACE символ определенный с помощью #define; но мы можем
вычмслить *wordlimit != ' ' (SPACE это ' '), и его величина равна
1 (истина). Значением выражения в целом должна быть истина, но
оно ложно. Значит все дело в операторе &.
В данном случае оператор & применен неверно. В Си он
определен как оператор поразрядного И, то есть операция И
применяется к каждому биту одного операнда с соответствующим ему
битом другого операнда. Так как *wordlimit != SPACE всегда равен
0 или 1 , *wordlimit & *wordlimit != SPACE равно 0 всякий раз. И
здесь необходимо применить оператор &&, результатом которого
является 1, если оба операнда ненулевые. (Попробуйте вычислить
все выражение сначала с одним & и затем с && и сравните
результат).
Путаница, возникающая & с && и ! с !!, является одной из
самых общих ошибок, которые допускают новички программирующие на
Си. После того, как вы нашли ошибку в вашей программе, и в
дальнейшем подобные ошибки вы легко узнаете.
- 179,180 -
Устранение ошибки
-----------------------------------------------------------------
Для того, чтобы исправить ошибку, вам нужно всего лишь
изменить & на &&. Сохраните исправленную программу в файле (наж-
мите F2), для защиты выполненных изменений, в случае случайного
разрушения программы во время последующего сеанса отладки. Затем
выполните Run /Run снова. Так, как вы модифицировали исходный
текст, вам будет сделан запрос на пересоздание программы. Нажмите
Y и программа будет перекомпилирована и перекомпонована. Теперь
возможна дальнейшая отладка откорректированной программы.
Прежде чем приступить к дальшему поиску ошибок дадим корот-
кое резюме нашим действиям, закрывая взгляд на встретившиеся воз-
можности отладчика.
Что вы достигли
-----------------------------------------------------------------
Вы завершили первый сеанс отладки с помощью Run/Program
Reset (или Ctrl-F2). Затем вы выполнили WORDCNT до вызова функции
wordlen с помощью установленной контрольной точки.
Потом вы провели трассировку wordlen, войдя в нее с помощью
Run/Trace INFO (или F7), начали ее пошаговое выполнение и нашли
ошибку. Вы исправили ошибку, сохранили исходный текст, и подгото-
вили программу к дальнейшей отладке.
- 181,182 -
Немного о контрольных точках
-----------------------------------------------------------------
Если вы не выходили из Турбо Си после первого урока, то
контрольная точка, установленная вами в строке содержащей опера-
тор while( fgets(... , остается, когда мы стартуем и во второй
раз. Вот почему WORDCNT выполнится до котрольной точки, а не до
конца программы. Как вы видите контрольные точки сохраняются от
одного сеанса к другому. Даже если между ними вы проводили редак-
тирование или преобразование программы. Турбо Си перемещает каж-
дую контрольную точку выше или ниже, держа ее справа оператора.
Контрольные точки сохраняются если вы установили их в прог-
раммном файле и сохранили его. Контрольные точки будут потеряны
только в том случае, когда вы:
# вышли из интегрированной среды;
# уничтожили строку исходного файла, в которой была установ-
лена контрольная точка;
# убрали все контрольные точки с помощью Break/Watch/Clear
All Breakpoints.
Однако Турбо Си может потерять контрольные точки в двух
случаях:
# если вы редактируете файл, содержащий контрольные точки, а
затем потеряли (не сохранили) отредактированную версию
файла. Турбо Си не помнит положение контрольных точек в
оригинальной версии файла и может поместить их в неверные
строки.
Если вы потеряли отредактированную версию исходного файла,
то вам необходимо убрать все контрольные точки
(выберите Break/Watch/Clear All Breakpoints), а затем соз-
дать их вновь. Заметьте, что Break /Watch/Clear All
Breakpoints уничтожает все контрольные точки вашей прог-
раммы, а не только те, которые вы редактировали в исходном
файле.
# если вы редактируете файл и продолжаете сеанс, не выполнив
перередактирование и компиляцию. Контрольные точки стоят
на своих местах, но так как исходный файл не соответствует
- 183,184 -
выполняемой программе, то индикаторы контрольных точек
указывают не на те строки. (Маркер выполнения также нахо-
дится на неверной строке).
Вы не можете попасть в такую ситуацию случайно потому, что
Турбо Си выдает запрос "Source modified, rebuild (Исходный
текст модифицирован, перестроить)?", когда вы пытаетесь
продолжить или начать сеанс вновь.
Перед компиляцией вы можете установить контрольные точки в
строках, содержащих невыполняемые операторы, таких как коммента-
рии или пустые строки. В этом случае Турбо Си сообщит вам, что
контрольные точки установлены в строках, содержащих невыполняемый
код. После компиляции файла Турбо Си становятся известны строки,
содержащие выполняемые операторы и вы будете об этом предупрежде-
ны, если попытаетесь установить контрольную точку в этих строках.
Переместить курсор к следующей контрольной точке можно с по-
мощью выбора Break/View Next Breakpoints. Заметьте, что по этой
команде курсор перемещается к следующей контрольной точке в текс-
те программы, а не к той, которая бы выполнилась, если бы прог-
рамма работала. Для просмотра контрольных точек программы можно
испоьзовать Break/Watch/Next Breakpoints, это полезно, когда вы
хотите уничтожить только часть контрольных точек.