Можно ли использовать break
Содержание статьи
Мысли вслух
В общении с коллегами — учителями информатики — я много раз сталкивался с твёрдым убеждением, что использование оператора
break
для досрочного выхода из цикла — это «неграмотно», «грязный хак», «не соответствует принципам структурного программирования» и вообще «я своим ученикам такое не зачту». В то же время общение с профессиональными программистами показывает, что такой прием на практике применяется очень часто, потому что это удобно и в большинстве случаев делает программу более понятной.
Такой «разброд» имеет совершенно объяснимые причины. Большинство преподавателей, с одной стороны, когда-то заучили, что структурное программирование — это хорошо, а любое отступление от него — это плохо. С другой стороны, сами они уже фактически отошли от промышленного программирования: я могу на пальцах одной руки пересчитать знакомых (в том числе и по Интернету) учителей информатики, которые сами написали что-то стóящее. Таким образом, наблюдаем закон Дж.Б. Шоу в действии.
Попробуем разобраться в сути вещей. Оператор
break
— это фактически оператор перехода, знаменитый
GOTO
, который в 1970-е годы был морально уничтожен, прежде всего, стараниями «отца структурного программирования» Эдсгера Дейкстры [1]. Однако сами «отцы» хорошо понимали, что программа без
GOTO
ещё не становится автоматически структурной программой. Поэтому появилось на свет эссе Дональда Кнута «Структурное программирование с операторами GOTO» [2]. Кнут писал (перевод мой):
«Другими словами, мы не должны просто удалять операторы GOTO из-за того, что сейчас модно это делать; присутствие или отсутствие операторов GOTO — это не главный вопрос. Истинная цель состоит в том, чтобы формулировать наши программы таким образом, чтобы их было легко понимать.»
Посмотрим, как обстоит дело с пониманием программ, содержащих циклы с операторами
break
и сравним их с программами, где операторов
break
умышленно избегают.
Пример 1. С клавиатуры вводятся числа, ввод заканчивается числом 999. Вычислить сумму введенных чисел.
Вот решение с использованием
break
:
s := 0; while True do begin Readln(x); if x = 999 then break; s := s + x; end;
На взгляд автора, этот алгоритм очень хорошо соответствует словесному описанию: «строим цикл, выход из которого происходит при получении числа 999».
Теперь посмотрим на «кошерные» альтернативы. Нужно как-то выполнить те же действия (то есть, выйти из цикла при получении числа 999), не используя оператор выхода из цикла.
Во-первых, можно поставить условие цикла
x 999
, но при этом нужно будет инициализировать переменную
x
до цикла каким-то «магическим числом», отличным от 999, например, 1 (или 998 :-). Программист, который будет разбираться в таком коде через некоторое время, спасибо вам не скажет. Кроме того, вторую часть тела цикла придется взять в условный оператор, а эта вторая часть может быть достаточно большой. Читабельность явно не повышается. Зато программа «структурная», можно «взять с полки пирожок». 🙂
s:=0; x := 1; while x 999 do begin Readln(x); if x 999 then s := s + x; end;
Заметим, что число 999 появляется в программе дважды: в заголовке цикла и в условии в теле цикла, что само по себе уже нехорошо.
Можно вынести оператор
Readln
за цикл, продублировав его в теле цикла:
s := 0; Readln(x); while x 999 do begin s := s + x; Readln(x); end;
На взгляд автора, при этом два оператора ввода, выполняющие одну и ту же функцию, «размывают» логику программы и не добавляют ей «прозрачности». Кроме того, вместо
Readln
в других ситуациях может стоять целая группа операторов, и тут уже дублирование будет выглядеть совсем некрасиво.
Кроме того, можно ввести логическую переменную (флаг), которой присваивается истинное значение при получении числа 999:
stop := False; while not stop do begin Readln(x); if x = 999 then stop := True else s := s + x; end;
Но тут нужно вспомнить о «бритве Оккама» — не плоди лишних сущностей. И ещё — любое усложнение системы, как правило, снижает её надежность.
Еще один вариант — перейти на цикл с постусловием:
s := 0; repeat Readln(x); if x 999 then s := s + x; until x = 999;
Во-первых, как и в одном из предыдущих вариантов, здесь два раза всплывает число 999. Во-вторых, вторую часть тела цикла снова нужно помещать в условный оператор. В-третьих, читать программы с циклами
repeat
— это сущее наказание: встретив слово
repeat
, судорожно пытаемся найти соответствующий
until
с условием, без этого всё вообще непонятно. Потом опять нужно смотреть наверх: что же там в теле цикла…
Можно, конечно, и так :-):
s := 0; try while True do begin Readln(x); if x = 999 then raise Exception.Create(»); s := s + x; end; except end;
Но по сути это то же самое, что и
break
. Использовать здесь исключения — всё равно, что гвозди микроскопом забивать.
Рассмотрим еще один пример.
Пример 2. Найти в массиве
A[1..N]
элемент, равный
X
, или сообщить, что такого элемента нет.
Решение с помощью
break
:
nX := 0; for i:=1 to N do if A[i] = X then begin nX := i; break; end; if nX = 0 then writeln(‘Не нашли!’) else writeln(‘nX = ‘, nX);
Как и для первого примера, программа с
break
почти дословно повторяет словесное описание идеи решения: «просматриваем все элементы массива с первого до последнего; как только нашли нужный элемент, запоминаем его номер и выходим из цикла».
Вот альтернатива без
break
:
nX := 1; while (nX X) do Inc(nX); if nX > N then writeln(‘Не нашли!’) else writeln(‘nX = ‘, nX);
Теперь представим себе, что будет, если в трансляторе включена проверка выхода за границы массива, логические выражения вычисляются полностью и элемента, равного
X
, в массиве нет: программа вылетит в результате обращения за пределы массива.
Вот еще вариант, с логической переменной:
nX := 1; found := False; repeat if A[nX] = X then found:= True else Inc(nX); until found or (nX > N); if not found then writeln(‘Не нашли!’) else writeln(‘nX = ‘, nX);
Какая программа понятнее, каждый решает сам. 🙂
Итак, подытожим.
- Оператор break есть практически во всех современных языках программирования. «Значит, это кому-нибудь нужно!»
- Это инструмент, который нужно использовать в соответствии с его назначением.
- Само по себе наличие или отсутствие оператора break ничего не говорит о том, грамотно ли написана программа; задача состоит в том, чтобы сделать ее наиболее понятной и «прозрачной».
- Использование оператора break относится к так называемым «структурным» переходам [3], то есть к переходам вперёд в пределах того же модуля, что не нарушает принципы структурного программирования.
Разобравшись с
break
, можно перейти к его непосредственному «родственнику» — оператору
continue
, который передает управление сразу в конец цикла, переходя к следующему шагу, если требуется.
Пример 3. В цикле обрабатываются все элементы массива
A[1:N]
. Для каждого из них сначала выполняются операторы
S1
,
S2
, …,
SN
, в результате вычисляется некоторое значение
x
. Если получено значение
x = 1
, нужно выполнить еще операторы
T1
,
T2
, …,
TM
, а в противном случае перейти к следующему элементу.
«Классическое» решение выглядит так:
for i:=1 to N do begin S1; S2; … x := SN; if x = 1 then begin T1; T2; … TM; end end;
Вроде бы всё хорошо. Но мы потеряли «локальность»: при достаточно длинном теле условного оператора нужно еще «сканировать» цикл до конца, проверяя, не выполняются ли какие-то действия в том случае, когда
x 1
. А эту проблему может элегантно решить
continue
:
for i:=1 to N do begin S1; S2; … x := SN; if x 1 then continue; T1; T2; … TM end;
Здесь уже точно ясно, что при
x 1
никаких дополнительных операций не происходит. По мнению автора, такой вариант более «прозрачен» и, по крайней мере, не хуже предыдущего.
Остается еще один «смежный» вопрос: можно ли писать подпрограммы с несколькими выходами? Давайте посмотрим пример рекурсивной процедуры.
Пример 4. Разработать процедуру, которая выводит на экран решение задачи «Ханойская башня» [4].
Рекурсивное решение этой задачи хорошо известно, одна из реализаций выглядит так:
procedure Hanoi(n, k, m: integer); var p: integer; begin if n = 0 then exit; p := 6 — k — m; Hanoi(n-1, k, p); writeln(k, ‘ -> ‘, m); Hanoi(n-1, p, m) end;
Здесь
n
— количество дисков, которые нужно перенести;
k
— номер начального стержня и
m
— номер конечного стержня.
И все было бы хорошо, но тут нарушен ещё один принцип, который стал «священной коровой» ортодоксального структурного программирования: процедура имеет (увы 🙂 два выхода, один естественный, и второй — по признаку окончания рекурсии.
Можно ли было обойтись без этого? Да, можно, «упаковав» все тело процедуры внутрь условного оператора:
procedure Hanoi(n, k, m: integer); var p: integer; begin if n > 0 then begin p := 6 — k — m; Hanoi(n-1, k, p); writeln(k, ‘ -> ‘, m); Hanoi(n-1, p, m) end end;
Но тут мы опять теряем локальность — при достаточно длинном тексте процедуры нужно еще посмотреть, не выполняются ли какие-то действия после условного оператора. Да и не совсем понятно, зачем добавлять лишний уровень вложенности. «Не плоди лишних сущностей». По мнению автора, первое приведенное решение более понятное и более красивое.
Пример 5. Разработать функцию, которая определяет, если ли в квадратной матрице элемент, равный заданному значению.
Будем предполагать, что введен тип данных
type Matrix = array[1..N,1..N] of integer;
Тогда функцию можно написать так:
Find(const A: Matrix; X: integer): boolean; var i, j: integer; begin Result := True; for i:=1 to N do for j:=1 to N do if A[i,j] = X then exit; Result := False end;
Здесь оператор
exit
фактически выполняет роль
break
для вложенного цикла. С формальной точки зрения у функции два выхода. В общем, «я своим ученикам никогда такое не зачту» — уже слышу я от учителей информатики.
А давайте подумаем, какие альтернативы? Можно вот так:
Find(const A: Matrix; X: integer): Boolean; var i, j: integer; label finish; begin Result := True; for i:=1 to N do for j:=1 to N do if A[i,j] = X then goto finish; Result := False; finish: end;
Но тут вообще «криминал» — метка и
goto
! Хотя по сути ничего не изменилось, тот же выход из вложенного цикла.
Конечно, здесь можно использовать исключение:
Find(const A: Matrix; X: integer): Boolean; var i, j: integer; begin Result := False; try for i:=1 to N do for j:=1 to N do if A[i,j] = X then raise Exception.Create(»); except Result := True end end;
Но ведь это далеко не «исключительная ситуация», поэтому по смыслу исключения здесь всё-таки не особо уместны. Кроме того, нужно учитывать, что при обработке исключений выполняется большое число машинных команд, что снижает эффективность программы.
Любителей «чистого» структурного программирования наверняка устроит такой вариант решения:
Find(A: Matrix; X: integer): Boolean; var i, j: integer; begin Result := False; for i:=1 to N do for j:=1 to N do if A[i,j] = X then Result := True end;
Но, к сожалению, по эффективности он не может составить конкуренцию предыдущим, так как в любом случае рассматриваются все N2 элементов массива, даже если элемент
A[1,1]
равен
X
.
Выводы
Эта статья, прежде всего, о том, что любые идеи и принципы нужно воспринимать в контексте конечной цели. Одна из основных целей концепции структурного программирования — повысить читаемость программ и за счёт этого облегчить их отладку, тестирование и сопровождение. Поэтому применение операторов
break
,
continue
и
exit
нельзя считать отступлением от структурного программирования, если это не ухудшает читаемость программы и не приводит к запутыванию логики алгоритма.
В то же время попытки избавиться от этих операторов (для того, чтобы формально соблюсти «классические правила») могут привести к ухудшению читаемости программы.
Литература
- Dijkstra E.W., Go To ement Considered Harmful // Communications of the ACM, Vol. 11, No. 3, March 1968, pp. 147-148. (PDF)
- Knuth D.E. Structured Programming with GO TO ements // ASM Computing Surveys. 1974. 6(4). P.261-301. (HTML, PDF)
- Непейвода H.H., Скопин И.Н. Основания программирования. — Москва-Ижевск: Институт компьютерных исследований, 2003. (PDF)
- Гарднер М., Математические головоломки и развлечения. — М.: Мир, 1999.
Ярлыки: Дейкстра, Кнут, Паскаль, программирование, break, continue, exit, goto
Источник
Урок №70. Операторы break и continue
Обновл. 15 Сен 2020 |
Хотя вы уже видели оператор break в связке с оператором switch, все же он заслуживает большего внимания, поскольку может использоваться и с циклами. Оператор break приводит к завершению выполнения циклов do, for или while.
break и switch
В контексте оператора switch оператор break обычно используется в конце каждого кейса для его завершения (предотвращая fall-through):
switch (op) { case ‘+’: doAddition(a, b); break; case ‘-‘: doSubtraction(a, b); break; case ‘*’: doMultiplication(a, b); break; case ‘/’: doDivision(a, b); break; } |
break и циклы
В контексте циклов оператор break используется для завершения работы цикла раньше времени:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include <iostream> int main() { int sum = 0; // Разрешаем пользователю ввести до 10 чисел for (int count=0; count < 10; ++count) { std::cout << «Enter a number to add, or 0 to exit: «; int val; std::cin >> val; // Выходим из цикла, если пользователь введет 0 if (val == 0) break; // В противном случае, добавляем число к общей сумме sum += val; } std::cout << «The sum of all the numbers you entered is » << sum << «n»; return 0; } |
Эта программа позволяет пользователю ввести до 10 чисел и в конце подсчитывает их сумму. Если пользователь введет 0, то выполнится break и цикл завершится (не важно, сколько чисел в этот момент успел ввести пользователь).
Обратите внимание, оператор break может использоваться и для выхода из бесконечного цикла:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include <iostream> int main() { while (true) // бесконечный цикл { std::cout << «Enter 0 to exit or anything else to continue: «; int val; std::cin >> val; // Выходим из цикла, если пользователь ввел 0 if (val == 0) break; } std::cout << «We’re out!n»; return 0; } |
break и return
Новички часто путают или не понимают разницы между операторами break и return. Оператор break завершает работу switch или цикла, а выполнение кода продолжается с первого стейтмента, который находится сразу же после этого switch или цикла. Оператор return завершает выполнение всей функции, в которой находится цикл, а выполнение продолжается в точке после вызова функции:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #include <iostream> int breakOrReturn() { while (true) // бесконечный цикл { std::cout << «Enter ‘b’ to break or ‘r’ to return: «; char sm; std::cin >> sm; if (sm == ‘b’) break; // выполнение кода продолжится с первого стейтмента после цикла if (sm == ‘r’) return 1; // выполнение return приведет к тому, что управление сразу возвратится в caller (в этом случае, в функцию main()) } // Использование оператора break приведет к тому, что выполнение цикла продолжится здесь std::cout << «We broke out of the loopn»; return 0; } int main() { int returnValue = breakOrReturn(); std::cout << » breakOrContinue returned » << returnValue << ‘n’; return 0; } |
Оператор continue
Оператор continue позволяет сразу перейти в конец тела цикла, пропуская весь код, который находится под ним. Это полезно в тех случаях, когда мы хотим завершить текущую итерацию раньше времени. Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include <iostream> int main() { for (int count = 0; count < 20; ++count) { // Если число делится нацело на 4, то пропускаем весь код в этой итерации после continue if ((count % 4) == 0) continue; // пропускаем всё и переходим в конец тела цикла // Если число не делится нацело на 4, то выполнение кода продолжается std::cout << count << std::endl; // Точка выполнения после оператора continue перемещается сюда } return 0; } |
Эта программа выведет все числа от 0 до 19, которые не делятся нацело на 4.
В случае с циклом for часть инкремента/декремента счетчика по-прежнему выполняется даже после выполнения continue (так как инкремент/декремент происходит вне тела цикла).
Будьте осторожны при использовании оператора continue с циклами while или do while. Поскольку в этих циклах инкремент счетчиков выполняется непосредственно в теле цикла, то использование continue может привести к тому, что цикл станет бесконечным! Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #include <iostream> int main() { int count(0); while (count < 10) { if (count == 5) continue; // переходим в конец тела цикла std::cout << count << » «; ++count; // Точка выполнения после оператора continue перемещается сюда } return 0; } |
Предполагается, что программа выведет все числа от 0 до 9, за исключением 5. Но на самом деле:
0 1 2 3 4
А затем цикл станет бесконечным. Когда значением count становится 5, то условие оператора if станет true, затем выполнится continue и мы, минуя вывод числа и инкремент счетчика, перейдем к следующей итерации. Переменная count так и не увеличится. Как результат, в следующей итерации переменная count по-прежнему останется со значением 5, а оператор if по-прежнему останется true, и цикл станет бесконечным.
А вот правильное решение, но с использованием цикла do while:
#include <iostream> int main() { int count(0); do { if (count == 5) continue; // переходим в конец тела цикла std::cout << count << » «; // Точка выполнения после оператора continue перемещается сюда } while (++count < 10); // этот код выполняется, так как он находится вне тела цикла return 0; } |
Результат выполнения программы:
0 1 2 3 4 6 7 8 9
break и continue
Многие учебники рекомендуют не использовать операторы break и continue, поскольку они приводят к произвольному перемещению точки выполнения программы по всему коду, что усложняет понимание и следование логике выполнения такого кода.
Тем не менее, разумное использование операторов break и continue может улучшить читабельность циклов в программе, уменьшив при этом количество вложенных блоков и необходимость наличия сложной логики выполнения циклов. Например, рассмотрим следующую программу:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include <iostream> int main() { int count(0); // считаем количество итераций цикла bool exitLoop(false); // контролируем завершение выполнения цикла while (!exitLoop) { std::cout << «Enter ‘e’ to exit this loop or any other key to continue: «; char sm; std::cin >> sm; if (sm == ‘e’) exitLoop = true; else { ++count; std::cout << «We’ve iterated » << count << » sn»; } } return 0; } |
Эта программа использует логическую переменную для выхода из цикла, а также вложенный блок, который запускается только в том случае, если пользователь не использует символ выхода.
А вот более читабельная версия, но с использованием оператора break:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include <iostream> int main() { int count(0); // считаем количество итераций цикла while (true) // выполнение цикла продолжается, если его не завершит пользователь { std::cout << «Enter ‘e’ to exit this loop or any other key to continue: «; char sm; std::cin >> sm; if (sm == ‘e’) break; ++count; std::cout << «We’ve iterated » << count << » sn»; } return 0; } |
Здесь (с одним оператором break) мы избежали использования как логической переменной (а также понимания того, зачем она и где используется), так и оператора else с вложенным блоком.
Уменьшение количества используемых переменных и вложенных блоков улучшают читабельность и понимание кода намного больше, чем операторы break или continue могут нанести вред. По этой причине считается приемлемым их разумное использование.
Оценить статью:
Загрузка…
Источник
BestProg
Содержание
- 1. Особенности применения оператора break
- 2. Особенности применения оператора continue
- 3. Оператор break. Примеры решения задач с использованием циклов
- 3.1. Вычисление суммы чисел, введенных с клавиатуры. Цикл for
- 3.2. Вычисление значения числа π по формуле
- 4. Оператор continue. Примеры решения задач
- 4.1. Вычисление суммы элементов последовательности
- 4.2. Вычисление суммы элементов массива в соответствии с условием
- 5. Как работает оператор break в случае вложенных циклов? Пример
- 6. Можно ли использовать операторы break и continue в операторе if?
- Связанные темы
Поиск на других ресурсах:
1. Особенности применения оператора break
В языке C++ существуют операторы break и continue, которые используются для управления ходом выполнения циклического процесса. Эти операторы могут быть применены только в теле цикла.
Оператор break предназначен для искусственного прерывания выполнения:
- последовательности итераций в операторах цикла for, while или do-while;
- последовательности операторов в операторе выбора switch.
Чаще всего оператор break используется в сочетании с оператором условия if. В этом случае, происходит проверка некоторого условия, и в случае успеха вызывается оператор break.
Пример. В нижеследующем примере при достижении переменной i значения 3 происходит безусловный выход из цикла путем вызова оператора break. Продемонстрирован вызов break для всех видов операторов.
#include <iostream> using namespace std; void main() { int i, j; // Оператор break // 1. Цикл for cout << «Loop for:» << endl; for (i = 0; i < 5; i++) // цикл по i { if (i == 3) break; // выход из цикла for // этот оператор выполняется cout << «i = » << i << endl; } // 2. Цикл while cout << «Loop while:» << endl; i = 0; while (i < 5) { if (i == 3) break; // выход из цикла while cout << «i = » << i << endl; i++; } // 3. Цикл do-while cout << «Loop do-while:» << endl; i = 0; do { if (i == 3) break; // выход из цикла do-while cout << «i = » << i << endl; i++; } while (i < 5); }
Результат выполнения программы
Loop for: i = 0 i = 1 i = 2 Loop while: i = 0 i = 1 i = 2 Loop do-while: i = 0 i = 1 i = 2
⇑
2. Особенности применения оператора continue
Оператор continue предназначен для перехода к выполнению следующей итерации цикла. Если в теле цикла встречается оператор continue, то:
- выполнение текущей итерации останавливается;
- происходит переход к следующей итерации цикла.
Оператор continue может быть применен во всех видах циклов: for, while, do-while.
В большинстве случаев вызов оператора continue осуществляется при выполнении некоторого условия в операторе if.
Пример. В примере демонстрируется использование оператора continue для всех видов циклов C++. В задаче, при достижении переменной i значения 3 происходит переход к следующей итерации с помощью инструкции continue.
#include <iostream> using namespace std; void main() { int i, j; // Оператор continue // 1. Цикл for cout << «Loop for:» << endl; for (i = 0; i < 5; i++) // цикл по i { if (i == 3) continue; // переход к следующей итерации // этот оператор выполняется cout << «i = » << i << endl; } // 2. Цикл while cout << «Loop while:» << endl; i = 0; while (i < 5) { if (i == 3) { i++; // увеличить счетчик — обязательно continue; // переход к следующей итерации } cout << «i = » << i << endl; i++; } // 3. Цикл do-while cout << «Loop do-while:» << endl; i = 0; do { if (i == 3) { i++; // увеличить счетчик — обязательно continue; // переход к следующей итерации } cout << «i = » << i << endl; i++; } while (i < 5); }
Результат работы программы
Loop for: i = 0 i = 1 i = 2 i = 4 Loop while: i = 0 i = 1 i = 2 i = 4 Loop do-while: i = 0 i = 1 i = 2 i = 4
⇑
3. Оператор break. Примеры решения задач с использованием циклов
3.1. Вычисление суммы чисел, введенных с клавиатуры. Цикл for
Пользователь вводит числа с клавиатуры. Окончание ввода — число 0. Вычислить сумму чисел, которые введет пользователь. В программе использовать операторы for и break.
Решение задачи на языке C++ следующее
#include <iostream> using namespace std; void main() { // Вычисление суммы чисел, вводимых с клавиатури int number, summ = 0; cout << «Enter numbers (0-exit):» << ::endl; // вечный цикл for (;;) { // ввод числа cout << «number = «; cin >> number; // если ввести 0, то выход из цикла if (number == 0) break; // увеличить сумму на величину числа summ += number; } // отобразить сумму cout << «summ = » << summ << endl; }
⇑
3.2. Вычисление значения числа π по формуле
Вычислить значение числа π, используя формулу с заданной точностью.
#include <iostream> using namespace std; void main() { // Вычислить значение числа Пи с заданной точностью // 1. Объявить внутренние переменные int n; // количество знаков после запятой double eps; // точность int i, k; double pi; // искомое число Pi double t; // 2. Ввести количество знаков после запятой cout << «Enter the number of decimal places: n = «; cin >> n; // 3. Формирование точности вычислений eps = 1; i = 0; while (i < n) { eps /= 10; // разделить на 10 n раз i++; } // 4. Цикл вычисления числа Pi pi = 1; i = 1; k = 1; t = 0; while (1) // вечный цикл { t = pi; i = i + 2; k = -k; pi = pi + k * 1.0 / i; // проверка, достигнута ли желаемая точность if (fabs(pi — t) < eps) break; // если точность достигнута, выйти из цикла } // 5. Вывести результат pi = 4 * pi; cout << «pi = » << pi << endl; cout << «i = » << i << endl; }
В примере для выхода из цикла while используется оператор break.
⇑
4. Оператор continue. Примеры решения задач
4.1. Вычисление суммы элементов последовательности
Дана последовательность вещественных чисел, которая завершается числом 0. Вычислить сумму элементов последовательности, которые имеют значения в пределах [-5; 5].
Решение задачи на C++ следующее
#include <iostream> using namespace std; void main() { // Вычисление суммы чисел, находящихся в указанных пределах // конец ввода — значение 0 const double MIN = -5.0; // нижний предел const double MAX = 5.0; // верхний предел double number; // вводимое число double summ = 0; // указанная сумма cout << «Enter numbers (exit — 0):» << ::endl; // цикл do-while do { // ввод числа cout << «=> «; cin >> number; // если число за допустимыми пределами if ((number < MIN) || (number > MAX)) continue; // то перейти к следующей итерации цикла // вычислить сумму, если введено коректное число summ += number; } while (number != 0); // числа вводятся до числа 0 // отобразить сумму cout << «summ = » << summ << endl; }
⇑
4.2. Вычисление суммы элементов массива в соответствии с условием
Вычислить сумму элементов массива, лежащих на парных позициях. Поскольку в C++ элементы массива нумеруются с 0, то парными будем считать позиции 1, 3, 5, и т.д.
Решение задачи с использованием оператора continue следующее.
#include <iostream> using namespace std; void main() { // Вычислить сумму элементов массива, лежащих на парных позициях // 1. Объявить внутренние переменные const int MAX = 10; // максимально-возможное количество элементов в массиве double A[MAX]; // указанный массив int n; // количество элементов в массиве double summ; // искомая сумма // 2. Ввести количество элементов в массиве cout << «Enter number of items in the array (1..10): «; cin >> n; // 3. Проверка, корректно ли введены данные if ((n < 1) || (n > MAX)) return; // 4. Ввод массива cout << «Enter the array:» << endl; for (int i = 0; i < n; i++) { cout << «A[» << i << «] = «; cin >> A[i]; } // 5. Вычисление суммы summ = 0; for (int i = 0; i < n; i++) { // проверка, позиции на парность if (i % 2 == 0) continue; // если позиция парная, то перейти к следующей итерации summ = summ + A[i]; // елси позиция непарная, вычислить сумму } // 5. Вывести сумму cout << «summ = » << summ << endl; }
⇑
5. Как работает оператор break в случае вложенных циклов? Пример
В случае вложенных циклов происходит выход из цикла наиболее низшего уровня. В нижеследующем примере вложенный цикл по j никогда не выполнится до конца, так как в нем встречается оператор break.
#include <iostream> using namespace std; void main() { int i, j; // Если циклы вложенные for (i = 0; i < 5; i++) // цикл по i { for (j = 0; j < 5; j++) // цикл по j { if (j == 0) break; // виход из цикла по j cout << «j = » << j << endl; } // этот оператор выполняется cout << «i = » << i << endl; } }
Результат выполнения программы
i = 0 i = 1 i = 2 i = 3 i = 4
⇑
6. Можно ли использовать операторы break и continue в операторе if?
Нет, нельзя. Однако, оператор break может еще использоваться как составная оператора switch.
Если попробовать использовать оператор break в конструкции if, то компилятор сгенерирует ошибку со следующим сообщением
a break ement may only be used within a loop or switch
Если попробовать вызвать оператор continue в конструкции if, то компилятор сгенерирует ошибку со следующим сообщением
a continue ement may only be used within a loop
⇑
Связанные темы
- Оператор выбора switch
- Циклы. Операторы цикла for, while, do…while
⇑
Источник