|
Управление потоком
3.8. Оператор CONTINUE
Оператор continue родственен оператору break, но используется реже; он приводит к началу следующей итерации охватывающего цикла ( for, while, do ). В циклах while и do это означает непосредственный переход к выполнению проверочной части; в цикле for управление передается на шаг реинициализации. (оператор continue применяется только в циклах, но не в переключателях. оператор continue внутри переключателя внутри цикла вызывает выполнение следующей итерации цикла).
В качестве примера приведем фрагмент, который обрабатывает только положительные элементы массива а; отрицательные значения пропускаются.
for (i = 0; i < n; i++) { if (a[i] < 0) /* skip negative elements */ continue; ... /* do positive elements */ }
оператор continue часто используется, когда последующая часть цикла оказывается слишком сложной, так что рассмотрение условия, обратного проверяемому, приводит к слишком глубокому уровню вложенности программы.
Упражнение 3-6
Напишите программу копирования ввода на вывод, с тем исключением, что из каждой группы последовательных одинаковых строк выводится только одна. (Это простой вариант утилиты uniq систем UNIX).
Оператор GOTO и метки
В языке "C" предусмотрен и оператор goto, которым бесконечно злоупотребляют, и метки для ветвления. С формальной точки зрения оператор goto никогда не является необходимым, и на практике почти всегда можно обойтись без него. Мы не использовали goto в этом курсе.
Тем не менее, мы укажем несколько ситуаций, где оператор goto может найти свое место. Наиболее характерным является его использование тогда, когда нужно прервать выполнение в некоторой глубоко вложенной структуре, например, выйти сразу из двух циклов. Здесь нельзя непосредственно использовать оператор break, так как он прерывает только самый внутренний цикл. Поэтому:
for ( ... ) for ( ... ) { ... if (disaster) goto error; } ... error: clean up the mess
Если программа обработки ошибок нетривиальна и ошибки могут возникать в нескольких местах, то такая организация оказывается удобной. Метка имеет такую же форму, что и имя переменной, и за ней всегда следует двоеточие. Метка может быть приписана к любому оператору той же функции, в которой находится оператор goto.
В качестве другого примера рассмотрим задачу нахождения первого отрицательного элемента в двумерном массиве. (Многомерные массивы рассматриваются в лекции "лекции 5" ). Вот одна из возможностей:
for (i = 0; i < n; i++) for (j = 0; j < m; j++) if (v[i][j] < 0) goto found; /* didn't find */ ... found: /* found one at position i, j */ ...
Программа, использующая оператор goto, всегда может быть написана без него, хотя, возможно, за счет повторения некоторых проверок и введения дополнительных переменных. Например, программа поиска в массиве примет вид:
found = 0; for (i = 0; i < n && !found; i++) for (j = 0; j < m && !found; j++) found = v[i][j] < 0; if (found) /* it was at i-1, j-1 */ ... else /* not found */ ...
Хотя мы не являемся в этом вопросе догматиками, нам все же кажется, что если и нужно использовать оператор goto, то весьма умеренно.