С помощью функции
Инструкция continue в чем-то похожа на break, но применяется гораздо реже. Она вынуждает ближайший объемлющий ее цикл (for, while или do-while) начать следующий шаг итерации. Для while и do-while это означает немедленный переход к проверке условия, а для for - к приращению шага. Инструкцию continue можно применять только к циклам, но не к switch. Внутри переключателя switch, расположенного в цикле, она вызовет переход к следующей итерации этого цикла.
Вот фрагмент программы, обрабатывающий только неотрицательные элементы массива a (отрицательные пропускаются).
for (i = 0; i ‹ n; i++) {
if (a[i] ‹ 0) /* пропуск отрицательных элементов */
continue;
… /* обработка положительных элементов */
}
К инструкции continue часто прибегают тогда, когда оставшаяся часть цикла сложна, а замена условия в нем на противоположное и введение еще одного уровня приводят к слишком большому числу уровней вложенности.
3.8 Инструкция goto и метки
В Си имеются порицаемая многими инструкция goto и метки для перехода на них. Строго говоря, в этой инструкции нет никакой необходимости, и на практике почти всегда легко без нее обойтись. До сих пор в нашей книге мы не использовали goto.
Однако существуют случаи, в которых goto может пригодиться. Наиболее типична ситуация, когда нужно прервать обработку в некоторой глубоко вложенной структуре и выйти сразу из двух или большего числа вложенных циклов. Инструкция break здесь не поможет, так как она обеспечит выход только из самого внутреннего цикла. В качестве примера рассмотрим следующую конструкцию:
for (…)
for (…) {
…
if (disaster) /* если бедствие */
goto error; /* уйти на ошибку */
error: /* обработка ошибки */
ликвидировать беспорядок
Такая организация программы удобна, если подпрограмма обработки ошибочной ситуации не тривиальна и ошибка может встретиться в нескольких местах.
Метка имеет вид обычного имени переменной, за которым следует двоеточие. На метку можно перейти с помощью goto из любого места данной функции, т. е. метка видима на протяжении всей функции.
В качестве еще одного примера рассмотрим такую задачу: определить, есть ли в массивах a и b совпадающие элементы. Один из возможных вариантов ее реализации имеет следующий вид:
for (i = 0; i ‹ n; i++)
for (j = 0; j ‹ m; j++)
if (a[i] == b[i])
goto found;
/* нет одинаковых элементов */
…
found:
/* обнаружено совпадение: a[i] - b[i] */
Программу нахождения совпадающих элементов можно написать и без goto, правда, заплатив за это дополнительными проверками и еще одной переменной:
found = 0;
for (i = 0; i ‹ n && !found; i++)
for (j = 0; j ‹ m && !found; j++)
if (a[i] == b[j])
found = 1;
if (found) /* обнаружено совпадение: a[i-1] - b[j-1] */
…
else
/* нет одинаковых элементов */
…
За исключением редких случаев, подобных только что приведенным, программы с применением goto, как правило, труднее для понимания и сопровождения, чем программы, решающие те же задачи без goto. Хотя мы и не догматики в данном вопросе, все же думается, что к goto следует прибегать крайне редко, если использовать эту инструкцию вообще.
Глава 4. Функции и структура программы
Функции разбивают большие вычислительные задачи на более мелкие и позволяют воспользоваться тем, что уже сделано другими разработчиками, а не начинать создание программы каждый раз "с нуля". В выбранных должным образом функциях "упрятаны" несущественные для других частей программы детали их функционирования, что делает программу в целом более ясной и облегчает внесение в нее изменений.