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

на главную

Жанры

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

Большинство ошибок возникает в конце циклов.

• Правильно ли проинициализированы переменные в начале цикла?

• Правильно ли заканчивается цикл (часто на последнем элементе)?

Приведем пример, который содержит ошибку.

int do_loop(const vector<int>& v) // плохая функция

// неправильный цикл

{

int i;

int sum;

while(i<=vec.size) sum+=v[i];

return sum;

}

Здесь

содержатся три очевидные ошибки. (Какие именно?) Кроме того, хороший тестировщик немедленно выявит возможности для переполнения при добавлении чисел к переменной
sum
.

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

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

char buf[MAX]; // буфер фиксированного объема

char* read_line // опасная функция

{

int i = 0;

char ch;

while(cin.get(ch) && ch!='\n') buf[i++] = ch;

buf[i+1] = 0;

return buf;

}

Разумеется, вы не написали бы ничего подобного! (А почему нет? Что плохого в функции

read_line
?) Однако эта ошибка, к сожалению, является довольно распространенной и имеет разные варианты.

// опасный фрагмент

gets(buf); // считываем строку в переменную buf

scanf("%s",buf); // считываем строку в переменную buf

Поищите описание функций
gets
и
scanf
в своей документации и избегайте их как чумы. Под словом “опасная” мы понимаем, что переполнение буфера является инструментом для взлома компьютеров. В настоящее время реализации выдают предупреждение об опасности использования функции
gets
и ее аналогов.

26.3.3.4. Ветвление

Очевидно, что, делая выбор, мы можем принять неправильное решение. Из-за этого инструкции
if
и
switch
являются одними из основных целей для тестировщиков. Существуют две проблемы, которые необходимо исследовать.

• Все ли возможные варианты предусмотрены?

• Правильные ли действия связаны с правильными вариантами выбора?

Рассмотрим следующую бессмысленную функцию:

void do_branch1(int x, int y) // плохая функция

//
неправильное использование инструкции if

{

if (x<0) {

if (y<0)

cout << "Большое отрицательное число \n";

else

cout << "Отрицательное число \n";

}

else if (x>0) {

if (y<0)

cout << "Большое положительное число \n";

else

cout << "Положительное число \n";

}

}

Наиболее очевидная ошибка в этом фрагменте заключается в том, что мы забыли о варианте, в котором переменная

x
равна нулю. Сравнивая числа (положительные или отрицательные) с нулем, программисты часто забывают о нем или приписывают неправильной ветви (например, относят его к отрицательным числам). Кроме того, существует более тонкая (хотя и распространенная) ошибка, скрытая в этом фрагменте: действия при условиях (
x>0 && y<0
) и (
x>0 && y>=0
) каким-то образом поменялись местами. Это часто случается, когда программисты пользуются командами “копировать и вставить”.

Чем более сложными являются варианты использования инструкций

if
, тем вероятнее становятся ошибки. Тестировщики анализируют такие коды и стараются не пропустить ни одной ветви. Для функции
do_branch1
набор тестов очевиден.

do_branch1(–1,–1);

do_branch1(–1, 1);

do_branch1(1,–1);

do_branch1(1,1);

do_branch1(–1,0);

do_branch1(0,–1);

do_branch1(1,0);

do_branch1(0,1);

do_branch1(0,0);

По существу, это наивный подход “перебора всех альтернатив”, которой мы применили, заметив, что функция

do_branch1
сравнивает значения с нулем с помощью операторов
<
и
>
. Для того чтобы выявить неправильные действия при положительных значениях переменной
x
, мы должны объединить вызовы функции с желаемыми результатами.

Обработка инструкций

switch
аналогична обработке инструкций
if
.

void do_branch1(int x, int y) // плохая функция

// неправильное использование инструкции switch

{

if (y<0 && y<=3)

switch (x) {

case 1:

cout << "Один\n";

break;

case 2:

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

Толян и его команда

Иванов Дмитрий
6. Девяностые
Фантастика:
попаданцы
альтернативная история
7.17
рейтинг книги
Толян и его команда

Кодекс Крови. Книга IХ

Борзых М.
9. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга IХ

Кодекс Охотника. Книга XV

Винокуров Юрий
15. Кодекс Охотника
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XV

Мастер Разума II

Кронос Александр
2. Мастер Разума
Фантастика:
героическая фантастика
попаданцы
аниме
5.75
рейтинг книги
Мастер Разума II

Идеальный мир для Социопата 4

Сапфир Олег
4. Социопат
Фантастика:
боевая фантастика
6.82
рейтинг книги
Идеальный мир для Социопата 4

Проклятый Лекарь V

Скабер Артемий
5. Каратель
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Проклятый Лекарь V

Live-rpg. эволюция-5

Кронос Александр
5. Эволюция. Live-RPG
Фантастика:
боевая фантастика
5.69
рейтинг книги
Live-rpg. эволюция-5

Сонный лекарь 6

Голд Джон
6. Сонный лекарь
Фантастика:
альтернативная история
аниме
5.00
рейтинг книги
Сонный лекарь 6

Сумеречный стрелок

Карелин Сергей Витальевич
1. Сумеречный стрелок
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Сумеречный стрелок

Мимик нового Мира 8

Северный Лис
7. Мимик!
Фантастика:
юмористическая фантастика
постапокалипсис
рпг
5.00
рейтинг книги
Мимик нового Мира 8

Титан империи 4

Артемов Александр Александрович
4. Титан Империи
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Титан империи 4

Бездомыш. Предземье

Рымин Андрей Олегович
3. К Вершине
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Бездомыш. Предземье

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

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

Генерал Скала и сиротка

Суббота Светлана
1. Генерал Скала и Лидия
Любовные романы:
любовно-фантастические романы
6.40
рейтинг книги
Генерал Скала и сиротка