Чтение онлайн

на главную - закладки

Жанры

Программирование. Принципы и практика использования C++ Исправленное издание
Шрифт:

} // Ой!

• Совпадает ли количество открывающих и закрывающих скобок?

if (a<=0 // Ой!

x = f(y);

Компилятор обычно сообщает об этих ошибках “поздно”; он просто не знает, что вы имели в виду, когда забыли поставить закрывающую скобку после нуля.

• Каждое ли имя объявлено?

• Включены ли все необходимые заголовочные файлы (например,

#include "std_lib_facilities.h"
)?

• Объявлено ли каждое имя до его использования?

Правильно ли набраны все имена?

int count; /* ... */ ++Count; // Ой!

char ch; /* ... */ Cin>>c; // Ой-ой!

• Поставлена ли точка с запятой после каждой инструкции?

x = sqrt(y)+2 // Ой!

z = x+3;

В упражнениях мы привели еще больше примеров таких ошибок. Кроме того, помните о классификации ошибок, указанной в разделе 5.2.

После того как программа скомпилирована, а ее связи отредактированы, наступает самый трудный этап, на котором необходимо понять, почему программа работает не так, как вы предполагали. Вы смотрите на результаты и пытаетесь понять, как ваша программа могла их вычислить. На самом деле чаще программисты смотрят на пустой экран и гадают, почему их программа ничего не вывела. Обычная проблема с консолью Windows заключается в том, что она исчезает, не дав вам шанса увидеть, что было выведено на экран (если что-то все-таки было выведено). Одно из решений этой проблемы — вызвать функцию

keep_window_open
из заголовочного файла
std_lib_facilities.h
в конце функции
main
. В таком случае программа попросит вас ввести что-нибудь перед выходом, и вы сможете просмотреть результаты ее работы до того, как окно закроется. В поисках ошибок тщательно проверьте инструкцию за инструкцией, начиная с того места, до которого, по вашему мнению, программа работала правильно. Встаньте на место компьютера, выполняющего вашу программу. Соответствует ли вывод вашим ожиданиям? Разумеется, нет, иначе вы не занимались бы отладкой.

Часто, когда программист не видит проблемы, причина заключается в том, что вы видите не действительное, а желаемое. Рассмотрим пример.

for (int i = 0; i<=max; ++j) { // Ой! (Дважды)

for (int i=0; 0<max; ++i); // Выводим элементы вектора v

cout << "v[" << i << "]==" << v[i] << '\n';

Последний пример позаимствован из реальной программы, написанной опытным программистом (я подозреваю, что он писал этот фрагмент глубокой ночью).

• Часто, когда вы не видите проблемы, причина заключается в том, что между точкой, где программа еще работала правильно, и следующей точкой, где программа выдала неверный ответ, содержится слишком много инструкций (или выводится слишком мало информации). Большинство интегрированных сред программирования допускают пошаговую отладку программ. В конце концов, вы научитесь пользоваться этими возможностями, но при отладке простых программ достаточно расставить в нескольких местах дополнительные инструкции вывода (с помощью потока cerr). Рассмотрим пример.

int my_fct(int a, double d)

{

int res = 0;

cerr << "my_fct(" << a << "," << d << ")\n";

// ...какой-то
код...

cerr << "my_fct возвращает " << res << '\n';

return res;

}

• Вставьте инструкции для проверки инвариантов (т.е. условий, которые всегда должны выполняться; см. раздел 9.4.3) в подозрительные разделы.

Рассмотрим пример.

int my_complicated_function(int a, int b, int c)

// Аргументы являются положительными и a < b < c

{

if (!(0<a && a<b && b<c)) // ! значит НЕ, а && значит И

error("Неверные аргументы функции mcf");

// ...

}

Если все сказанное не привело к успеху, вставьте инварианты в разделы программы, которые вы считаете правильными. Весьма вероятно, что вы найдете ошибку. Инструкция для проверки инвариантов называется

assert
.

Интересно, что существует несколько эффективных способов программирования. Разные люди совершенно по-разному программируют. Многие различия между методами отладки объясняются разнообразием программ, а другие проистекают из разных образов мышления. Следует знать, что наилучшего способа отладки не существует. Просто надо помнить, что запутанный код чаще содержит ошибки. Старайтесь писать программы просто и логично, форматируйте их, и вы сэкономите время за счет отладки.

5.10. Пред- и постусловия

Теперь вернемся к вопросу, как поступать к неправильными аргументами функции. Вызов функции — это наилучшая отправная точка, для того чтобы подумать о правильном коде и обработке ошибок: именно здесь происходит разделение вычислений на логические блоки. Рассмотрим следующий пример, уже показанный выше:

int my_complicated_function(int a, int b, int c)

// Аргументы являются положительными и a < b < c

{

if (!(0<a && a<b && b<c)) // ! значит НЕ, а && значит И

error("Неверные аргументы функции mcf");

// ...

}

Во-первых, в комментарии утверждается, какие аргументы ожидает функция, а затем происходит проверка этого условия (и генерирование исключения, если это условие нарушается). Это правильная стратегия. Требования, которые функция предъявляет к своим аргументам, часто называют предусловиями (pre-condition): они должны выполняться, чтобы функция работала правильно. Вопрос заключается в том, что делать, если предусловия нарушаются. У нас есть две возможности.

Поделиться:
Популярные книги

Звезда сомнительного счастья

Шах Ольга
Фантастика:
фэнтези
6.00
рейтинг книги
Звезда сомнительного счастья

Магия чистых душ

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.40
рейтинг книги
Магия чистых душ

Возвышение Меркурия. Книга 7

Кронос Александр
7. Меркурий
Фантастика:
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 7

На границе империй. Том 2

INDIGO
2. Фортуна дама переменчивая
Фантастика:
космическая фантастика
7.35
рейтинг книги
На границе империй. Том 2

Легат

Прокофьев Роман Юрьевич
6. Стеллар
Фантастика:
боевая фантастика
рпг
6.73
рейтинг книги
Легат

Младший сын князя

Ткачев Андрей Сергеевич
1. Аналитик
Фантастика:
фэнтези
городское фэнтези
аниме
5.00
рейтинг книги
Младший сын князя

Восьмое правило дворянина

Герда Александр
8. Истинный дворянин
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Восьмое правило дворянина

Энфис 4

Кронос Александр
4. Эрра
Фантастика:
городское фэнтези
рпг
аниме
5.00
рейтинг книги
Энфис 4

Серые сутки

Сай Ярослав
4. Медорфенов
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Серые сутки

Комбинация

Ланцов Михаил Алексеевич
2. Сын Петра
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Комбинация

Чехов книга 3

Гоблин (MeXXanik)
3. Адвокат Чехов
Фантастика:
попаданцы
альтернативная история
аниме
6.00
рейтинг книги
Чехов книга 3

Двойня для босса. Стерильные чувства

Лесневская Вероника
Любовные романы:
современные любовные романы
6.90
рейтинг книги
Двойня для босса. Стерильные чувства

Эволюция мага

Лисина Александра
2. Гибрид
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Эволюция мага

Инцел на службе демоницы 1 и 2: Секса будет много

Блум М.
Инцел на службе демоницы
Фантастика:
фэнтези
5.25
рейтинг книги
Инцел на службе демоницы 1 и 2: Секса будет много