Можно ли использовать break
функцию для выхода из нескольких вложенныхfor
циклов?
Если так, как бы вы поступили? Можете ли вы также контролировать, сколько петель break
выходов?
Можно ли использовать break
функцию для выхода из нескольких вложенныхfor
циклов?
Если так, как бы вы поступили? Можете ли вы также контролировать, сколько петель break
выходов?
Ответы:
AFAIK, C ++ не поддерживает циклы именования, как Java и другие языки. Вы можете использовать goto или создать значение флага, которое вы используете. В конце каждого цикла проверьте значение флага. Если установлено значение true, вы можете выйти из этой итерации.
goto
если это лучший вариант.
goto
: плохие программисты и прагматичные программисты. Первые говорят сами за себя. Последний, в который вы бы вписались, если вы решите использовать их хорошо, использует так называемую «злую» концепцию, когда это меньшее из (двух) зол. Прочитайте это для лучшего понимания некоторых концепций C ++, которые вам, возможно, придется время от времени использовать (макросы, goto, препроцессор, массивы): parashift.com/c++-faq-lite/big-picture.html#faq-6.15
goto
редко когда-либо является лучшим вариантом. Почему бы не поставить петли в их собственную функцию ( inline
если вы беспокоитесь о скорости) и return
из этого?
Нет, не портите это break
. Это последний оставшийся оплот для использования goto
.
Просто чтобы добавить явный ответ, используя лямбды:
for (int i = 0; i < n1; ++i) {
[&] {
for (int j = 0; j < n2; ++j) {
for (int k = 0; k < n3; ++k) {
return; // yay we're breaking out of 2 loops here
}
}
}();
}
Конечно, этот шаблон имеет определенные ограничения и, очевидно, только C ++ 11, но я думаю, что он весьма полезен.
Другой подход к разрыву вложенного цикла состоит в том, чтобы выделить оба цикла в отдельную функцию, и return
из этой функции, когда вы хотите выйти.
Конечно, это приводит к другому аргументу о том, следует ли вам когда-либо явно return
из функции где-либо, кроме как в конце.
continue_processing
), которые контролировали выполнение блоков кода ниже в функции.
перерыв будет выходить только из самого внутреннего цикла, содержащего его.
Вы можете использовать GoTO чтобы выйти из любого числа циклов.
Конечно, Гото часто считается вредным .
Правильно ли использовать функцию прерывания [...]?
Использование break и goto может затруднить рассуждение о правильности программы. Смотрите здесь для обсуждения этого: Дейкстра не была безумной .
break
или return
.
break
и return
имейте преимущество перед тем, goto
что вам не нужно охотиться за лейблом, чтобы найти, куда они идут. Да, под ними какие-то goto
, но очень ограниченные. Их гораздо легче расшифровать с помощью мозга, сопоставляющего шаблоны, чем неограниченный goto
. Так что имо они предпочтительнее.
goto
.
Хотя этот ответ уже был представлен, я думаю, что хороший подход заключается в следующем:
for(unsigned int z = 0; z < z_max; z++)
{
bool gotoMainLoop = false;
for(unsigned int y = 0; y < y_max && !gotoMainLoop; y++)
{
for(unsigned int x = 0; x < x_max && !gotoMainLoop; x++)
{
//do your stuff
if(condition)
gotoMainLoop = true;
}
}
}
gotoMainLoop
каждый цикл проверяется
goto
делает ядро более читабельным и более производительным.
Как насчет этого?
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < 50; j++)
{
for(unsigned int k=0; k < 50; k++)
{
//Some statement
if (condition)
{
j=50;
k=50;
}
}
}
}
Пример кода с использованием goto
метки для выхода из вложенного цикла:
for (;;)
for (;;)
goto theEnd;
theEnd:
Хороший способ вырваться из нескольких вложенных циклов - это преобразовать код в функцию:
void foo()
{
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < 50; j++)
{
for(unsigned int k=0; k < 50; k++)
{
// If condition is true
return;
}
}
}
}
goto может быть очень полезным для разрыва вложенных циклов
for (i = 0; i < 1000; i++) {
for (j = 0; j < 1000; j++) {
for (k = 0; k < 1000; k++) {
for (l = 0; l < 1000; l++){
....
if (condition)
goto break_me_here;
....
}
}
}
}
break_me_here:
// Statements to be executed after code breaks at if condition
break
Оператор прекращает выполнение ближайшего объемлющегоdo
,for
,switch
илиwhile
заявление , в котором он появляется. Управление переходит к оператору, который следует за завершенным оператором.
из MSDN .
Я действительно думаю, что это goto
справедливо в следующих обстоятельствах:
Чтобы смоделировать break
/ continue
, вы хотите:
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
goto theEnd;
}
}
}
theEnd:
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
i++;
goto multiCont;
}
}
multiCont:
}
i
. Следовательно, i++
до перехода
Другие языки, такие как PHP, принимают параметр для разрыва (то есть, для разрыва 2;), чтобы указать количество уровней вложенных циклов, из которых вы хотите разорвать, однако C ++ этого не делает. Вы должны будете решить это, используя логическое значение, которое вы установили в false перед циклом, установите значение true в цикле, если вы хотите разорвать, плюс условный разрыв после вложенного цикла, проверяя, было ли логическое значение установлено в true и сломаться, если да.
Я знаю, что это старый пост. Но я бы предложил немного логичный и более простой ответ.
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < conditionj; j++)
{
for(unsigned int k=0; k< conditionk ; k++)
{
// If condition is true
j= conditionj;
break;
}
}
}
j = conditionj
не будет работать, если вместо вас есть сложный предикат j < conditionj
.
Разбейте любое количество циклов только одной bool
переменной, см. Ниже:
bool check = true;
for (unsigned int i = 0; i < 50; i++)
{
for (unsigned int j = 0; j < 50; j++)
{
for (unsigned int k = 0; k < 50; k++)
{
//Some statement
if (condition)
{
check = false;
break;
}
}
if (!check)
{
break;
}
}
if (!check)
{
break;
}
}
В этом коде мы break;
все циклы.
Я не уверен, стоит ли это того, но вы можете эмулировать именованные циклы Java с помощью нескольких простых макросов:
#define LOOP_NAME(name) \
if ([[maybe_unused]] constexpr bool _namedloop_InvalidBreakOrContinue = false) \
{ \
[[maybe_unused]] CAT(_namedloop_break_,name): break; \
[[maybe_unused]] CAT(_namedloop_continue_,name): continue; \
} \
else
#define BREAK(name) goto CAT(_namedloop_break_,name)
#define CONTINUE(name) goto CAT(_namedloop_continue_,name)
#define CAT(x,y) CAT_(x,y)
#define CAT_(x,y) x##y
Пример использования:
#include <iostream>
int main()
{
// Prints:
// 0 0
// 0 1
// 0 2
// 1 0
// 1 1
for (int i = 0; i < 3; i++) LOOP_NAME(foo)
{
for (int j = 0; j < 3; j++)
{
std::cout << i << ' ' << j << '\n';
if (i == 1 && j == 1)
BREAK(foo);
}
}
}
Другой пример:
#include <iostream>
int main()
{
// Prints:
// 0
// 1
// 0
// 1
// 0
// 1
int count = 3;
do LOOP_NAME(foo)
{
for (int j = 0; j < 3; j++)
{
std::cout << ' ' << j << '\n';
if (j == 1)
CONTINUE(foo);
}
}
while(count-- > 1);
}
Вы можете использовать попробовать ... поймать.
try {
for(int i=0; i<10; ++i) {
for(int j=0; j<10; ++j) {
if(i*j == 42)
throw 0; // this is something like "break 2"
}
}
}
catch(int e) {} // just do nothing
// just continue with other code
Если вам нужно разорвать несколько петель одновременно, это все равно часто является исключением.
Выход из цикла for немного странен для меня, поскольку семантика цикла for обычно указывает на то, что он будет выполняться определенное количество раз. Тем не менее, это не плохо во всех случаях; если вы ищете что-то в коллекции и хотите сломать ее после того, как найдете ее, это полезно Однако выход из вложенных циклов в C ++ невозможен; это на других языках с помощью помеченного перерыва. Вы можете использовать ярлык и перейти, но это может вызвать у вас изжогу ночью ..? Похоже, лучший вариант, хотя.