Почему следует избегать оператора goto

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

На смену оператору goto пришли конструкции с несколько более сложной структурой, но и с более широкими возможностями: for, while и do...while. Несмотря на то что после полного искоренения оператора goto структура программ значительно прояснилась, негативные высказывания в его адрес следует признать преувеличенными. Как любой инструмент программирования, при правильном использовании оператор goto может оказаться достаточно полезным. В силу этого комитет ANS1 принял решение оставить этот оператор в языке. Правда, вместе с этим родилась шутка: "Дети! Использование этого оператора в домашних условиях небезопасно!"

Организация циклов с помощью оператора while

В циклах, организованных с помощью оператора while, выполнение последовательности операций продолжается до тех пор, пока условие продолжения цикла истинно. В примере программы в листинге 7.1 значение переменной counter увеличивалось до тех пор, пока не стало равным пяти. Листинг 7.2 демонстрирует тот же алгоритм, реализованный с помощью оператора while.

Листинг 7.2. Организация цикла с помощью оператора while

1: // Листинг 7.2.

2: // Организация цикла с помощью оператора while

3:

4: #include <iostream.h>

5:

6: int main()

7: {

8: int counter = 0; // присвоение начального значения

9:

10: while(counter < 5) // проверка условия продолжения цикла

11: {

12: counter++; // тело цикла

13: cout << " counter: " << counter << "\;n";

14: }

15:

16: cout << " Complete. Counter: " << counter << ".\n";

17: return 0;

18: }

Результат:

counter: 1

counter: 2

counter: 3

counter: 4

counter: 5

Complete. Counter: 5.

Анализ: Эта несложная программа показывает пример организации цикла с помощью оператора while. В начале каждой итерации проверяется условие, и, если оно выполняется, управление передается на первый оператор цикла. В нашем примере условию продолжения цикла удовлетворяют все значения переменной counter, меньшие пяти (строка 10). Если условие выполняется, запускается следующая итерация цикла. В строке 12 значение счетчика увеличивается на единицу, а в строке 13 выводится на экран. Как только значение счетчика достигает пяти, тело цикла (строки 11 — 14) пропускается и управление передается в строку 15.

Сложные конструкции с оператором while

Сложность логического выражения, являющегося условием в операторе while, не ограничена. Это позволяет использовать в конструкции while любые логические выражения C++. При построении выражений допускается использование логических операций: && (логическое И), 11 (логическое ИЛИ), а также ! (логическое отрицание). В листинге 7.3 показан пример использования более сложных условий в конструкциях с оператором while.

Листинг 7.3. Сложные условия в конструкциях while

1: // Листинг 7.3.

2: // Сложные условия в конструкциях while

3:

4: include <iostream.h>

5:

6: int main()

7: {

8: unsigned short small;

9: unsigned long large;

10: const unsigned short MAXSMALL=65535;

11:

12: cout << "Enter a small number: ";

13: cin >> small;

14: cout << "Enter a large number: ";

15: cin >> large;

16:

17: cout << "small: " << small << "...";

18:

19: // на каждой итерации проверяются три условия

20: while (small < large && large > 0 && small < MAXSMALL)

21: {

22: if (small % 5000 == 0) // после каждых 5000 строк выводится точка

23: cout << ".";

24:

25: small++;

26:

27: large-=2;

28: }

39:

30: cout << "\nSmall: " << small << " Large: " << large << endl;

31: return 0;

32: }

Результат:

Enter а small number: 2

Enter а large number: 100000

small: 2

Small: 33335 Large: 33334

Анализ: Программа представляет собой простую логическую игру. Вначале предлагается ввести два числа — small и large. После этого меньшее значение увеличивается на единицу, а большее уменьшается на два до тех пор, пока они не "встретятся". Цель игры: угадать число, на котором значения "встретятся".

В строках 12—15 осуществляется ввод значений. В строке 20 проверяется три условия продолжения цикла.

1. Значение переменной small не превышает значения large.

2. Значение переменной large неотрицательное и не равно нулю.

3. Значение переменной small не превышает значения константы MAXSMALL.

Далее, в строке 23, вычисляется остаток от деления числа small на 5000, причем значение переменной small не изменяется. Если small делится на 5000 без остатка, результатом выполнения этой операции будет 0. В этом случае для визуального представления процесса вычислений на экран выводится точка. Затем в строке 26 значение переменной small увеличивается на 1, а в строке 28 значение large уменьшается на 2.

Цикл завершается, если хотя бы одно из условий перестает выполняться. После этого управление передается в строку 29, следующую за телом цикла.

Операторы break и continue

Часто бывает необходимо перейти на следующую итерацию цикла еще до завершения выполнения всех операторов тела цикла. Для этого используется оператор continue.

Кроме того, в ряде случаев требуется выйти за пределы цикла, даже если условия продолжения цикла выполняются. В этом случае используется оператор break.

Пример использования этих операторов приведен в листинге 7.4. Это несколько усложненный вариант уже знакомой игры. В этом случае, кроме меньшего и большего значений, предлагается ввести шаг и целевое значение. Как и в предыдущем примере, на каждой итерации цикла значение переменной small увеличивается на единицу. Значение large уменьшается на два, если меньшее число не кратно значению переменной шага (skip). Игра заканчивается, когда значение переменой small становится больше, чем значение large. Если значение переменной large совпадает с целевым значением (target), выводится сообщение и игра прерывается.

Цель игры состоит в том, чтобы угадать число, в которое "попадет" значение target.

Листинг 7.4. Использование break и continue

1: // Листинг 7.4.

2: // Пример использования операторов break и continue

3:

4: #include <iostream.h>

5:

6: int main()

7: {

8: unsigned short small;

9: unsigned long large;

10: unsigned long skip;

11: unsigned long target;

12: const unsigned short MAXSMALL=65535;

13:

14: cout << "Enter a smail number: ";

15: cin >> small;

16: cout << "Enter a large number: ";

17: cin >> large;

18: cout << "Enter a skip number: ";

19: cin >> skip;

20: cout << "Enter a target number; ";

21: cin >> target;

22:

23: cout << "\n"

24:

25: // установка условий продолжения цикла

26: while (small < large && large > 0 && small < MAXSMALL)

27:

28: {

29:

30: small++;

31:

32: if (small % skip == 0) // уменьшить значение large?

33: {

34: cout << "skipping on:" << small << endl;

35: continue;

36: }

37:

38: if (large == target) // проверка попадания в цель

39: {

40: cout << " Target reached!";

41: break;

42: }

43:

44: large-=2;

45: } // конец цикла

46:

47: cout << "\nSmall: " << small << " Large: " << large << endl;

48: return 0;

49: }

Результат:

Enter a small number: 2

Enter a large number: 20

Enter a skip number: 4

Enter a target number: 6

skipping on 4

skipping on 8

Small: 10 Large: 8

Анализ: Как видим, игра закончилась поражением пользователя, поскольку меньшее значение превысило большее, а цель так и не была достигнута.

В строке проверяются условия продолжения цикла. Если значение переменной small меньше значения large, а также если large больше нуля и small не превышает значение константы SMALLINT, управление передается первому оператору тела цикла.

В строке 32 вычисляется остаток от деления значения переменной small на значение skip. Если значение small кратно skip, оператор continue запускает следующую итерацию цикла (срока 26). В результате такого перехода пропускается проверка целевого значения и операция уменьшения значения переменной large.

Сравнение значений target и large выполняется в строке 38. Если эти значения равны, игра заканчивается победой пользователя. В этом случае программа выводит сообщение о победе, работа цикла прерывается оператором break и управление передается в строку 46.

Наши рекомендации