É possível usar a break
função para sair de vários for
loops aninhados ?
Se sim, como você faria isso? Você também pode controlar quantos ciclos as break
saídas?
É possível usar a break
função para sair de vários for
loops aninhados ?
Se sim, como você faria isso? Você também pode controlar quantos ciclos as break
saídas?
Respostas:
AFAIK, C ++ não suporta loops de nomeação, como Java e outras linguagens. Você pode usar um goto ou criar um valor de sinalizador usado. No final de cada loop, verifique o valor do sinalizador. Se estiver definido como true, você poderá interromper essa iteração.
goto
se essa for a melhor opção.
goto
: programadores ruins e programadores pragmáticos. Os primeiros são auto-explicativos. O último, no qual você se encaixaria se optar por usá-los bem, usa o chamado conceito de "mal" quando é o menor dos (dois) males. Leia isso para entender melhor alguns conceitos de C ++ que você pode precisar usar de tempos em tempos (macros, goto's, pré-processador, matrizes): parashift.com/c++-faq-lite/big-picture.html#faq-6.15
goto
raramente é a melhor opção. Por que não colocar os loops em sua própria função ( inline
se você está preocupado com a velocidade) e return
com isso?
Não, não estrague tudo com um break
. Esta é a última fortaleza restante para o uso de goto
.
Apenas para adicionar uma resposta explícita usando lambdas:
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
}
}
}();
}
Claro que esse padrão tem certas limitações e, obviamente, apenas C ++ 11, mas acho que é bastante útil.
Outra abordagem para interromper um loop aninhado é fatorar os dois loops em uma função separada e a return
partir dessa função quando você deseja sair.
Obviamente, isso traz outro argumento sobre se você deve explicitamente alguma vez return
de uma função em outro lugar que não seja o final.
continue_processing
) que controlavam a execução de blocos de código mais abaixo na função.
break sairá apenas do loop mais interno que o contém.
Você pode usar o goto para interromper qualquer número de loops.
É claro que o goto é frequentemente considerado nocivo .
é apropriado usar a função de interrupção [...]?
Usar break e goto pode dificultar o raciocínio sobre a correção de um programa. Veja aqui uma discussão sobre isso: Dijkstra não era louco .
break
ou return
.
break
e return
tenha a vantagem de goto
não precisar procurar um rótulo para descobrir para onde ele vai. Sim, por baixo eles são algum tipo goto
, mas muito restrito. Eles são muito mais fáceis de decifrar pelo cérebro de correspondência de padrões de um programador do que pelo irrestrito goto
. Então IMO são preferíveis.
goto
.
Embora essa resposta já tenha sido apresentada, acho que uma boa abordagem é fazer o seguinte:
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
é verificado a cada ciclo #
goto
torna o núcleo mais legível e com melhor desempenho.
Que tal agora?
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;
}
}
}
}
Um exemplo de código usando goto
e um rótulo para interromper um loop aninhado:
for (;;)
for (;;)
goto theEnd;
theEnd:
Uma boa maneira de interromper vários loops aninhados é refatorar seu código em uma função:
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 pode ser muito útil para quebrar loops aninhados
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
Eu acho que a goto
é válido nesta circunstância:
Para simular um break
/ continue
, você deseja:
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
goto theEnd;
}
}
}
theEnd:
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
i++;
goto multiCont;
}
}
multiCont:
}
i
. Por isso, i++
antes do goto
Outras linguagens como o PHP aceitam um parâmetro para break (isto é, break 2;) para especificar a quantidade de níveis de loop aninhados dos quais você deseja interromper, o C ++, no entanto, não. Você precisará resolver isso usando um booleano que você definiu como false antes do loop, definido como true no loop, se você deseja interromper, além de uma quebra condicional após o loop aninhado, verificando se o booleano foi definido como true e quebre se sim.
Eu sei que este é um post antigo. Mas eu sugeriria uma resposta um pouco lógica e mais simples.
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
não funcionará se você tiver um predicado complexo em vez de j < conditionj
.
Quebre qualquer número de loops por apenas uma bool
variável, veja abaixo:
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;
}
}
Neste código, break;
todos os loops.
Não tenho certeza se vale a pena, mas você pode emular os loops nomeados do Java com algumas macros simples:
#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
Exemplo de uso:
#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);
}
}
}
Outro exemplo:
#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);
}
Você pode usar try ... catch.
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
Se você precisar interromper vários loops de uma só vez, geralmente é uma exceção.
Quebrar um loop for é um pouco estranho para mim, uma vez que a semântica de um loop for indica que ele executará um número especificado de vezes. No entanto, não é ruim em todos os casos; se você estiver procurando por algo em uma coleção e quiser quebrar depois de encontrá-lo, é útil. A quebra de loops aninhados, no entanto, não é possível em C ++; está em outros idiomas através do uso de uma quebra rotulada. Você pode usar um rótulo e ir embora, mas isso pode causar azia à noite ..? Parece ser a melhor opção.