Можно ли использовать 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 ++ невозможен; это на других языках с помощью помеченного перерыва. Вы можете использовать ярлык и перейти, но это может вызвать у вас изжогу ночью ..? Похоже, лучший вариант, хотя.