Estou escrevendo um código parecido com este:
while(true) {
switch(msg->state) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
break; // **HERE, I want to break out of the loop itself**
}
}
Existe alguma maneira direta de fazer isso?
Sei que posso usar um sinalizador e interromper o loop colocando uma quebra condicional logo após a troca. Só quero saber se o C ++ já tem alguma construção para isso.
goto
atraente e, às vezes, a única saída limpa. Se você tende a organizar seu código em pequenas funções com apenas algumas linhas e fazer uma única coisa cada, você nunca terá esse problema. (Aliás, seu código também será mais fácil de ler.):)
Respostas:
Premissa
O código a seguir deve ser considerado um formato incorreto, independentemente do idioma ou da funcionalidade desejada:
Argumentos de Apoio
O
while( true )
loop é de má forma porque:while(true)
loops for que não são infinitos, perdemos a capacidade de nos comunicarmos concisamente quando os loops, na verdade, não têm condição de terminação. (Provavelmente, isso já aconteceu, então a questão é discutível.)Alternativa para "Ir para"
O código a seguir é melhor:
Vantagens
Sem bandeira. Não
goto
. Sem exceção. Fácil de mudar. Fácil de ler. Fácil de consertar. Além disso, o código:O segundo ponto é importante. Sem saber como o código funciona, se alguém me pedir para fazer o loop principal permitir que outros threads (ou processos) tenham algum tempo de CPU, duas soluções vêm à mente:
Opção 1
Insira prontamente a pausa:
Opção 2
Substituir executar:
Este código é mais simples (portanto, mais fácil de ler) do que um loop com um incorporado
switch
. OisValidState
método deve determinar apenas se o loop deve continuar. O burro de carga do método deve ser abstraído noexecute
método, o que permite que as subclasses substituam o comportamento padrão (uma tarefa difícil usando umswitch
egoto
).Exemplo Python
Compare a seguinte resposta (a uma pergunta Python) que foi postada no StackOverflow:
Versus:
Aqui,
while True
resulta em código enganoso e excessivamente complexo.fonte
while(true)
deveria ser prejudicial me parece bizarra. Existem loops que verificam antes de serem executados, há aqueles que verificam depois e há aqueles que verificam no meio. Como o último não tem construção sintática em C e C ++, você terá que usarwhile(true)
oufor(;;)
. Se você considera isso errado, é porque ainda não pensou o suficiente nos diferentes tipos de loops.while(true) {string line; std::getline(is,line); if(!is) break; lines.push_back(line);}
é claro que eu poderia transformar isso em um loop pré-condicionado (usandostd::getline
como condição de loop), mas isso tem desvantagens por si só (line
teria que ser uma variável fora do escopo do loop). E se eu fizesse, eu teria que perguntar: Por que temos três loops de qualquer maneira? Sempre poderíamos transformar tudo em um loop pré-condicionado. Use o que for melhor. Sewhile(true)
couber, use-o.Você pode usar
goto
.fonte
goto
. O OP claramente mencionado sem usar sinalizadores . Você pode sugerir uma maneira melhor, considerando as limitações do OP? :)Uma solução alternativa é usar a palavra-chave
continue
em combinação combreak
, ou seja:Use a
continue
instrução para terminar cada rótulo de caso em que deseja que o loop continue e use obreak
instrução para terminar os rótulos de caso que devem encerrar o loop.É claro que essa solução só funciona se não houver código adicional a ser executado após a instrução switch.
fonte
:(
:(
Caso contrário, uma implementação muito limpa.Uma maneira elegante de fazer isso seria colocar isso em uma função:
Opcionalmente (mas 'más práticas'): como já sugerido, você pode usar um goto ou lançar uma exceção dentro do switch.
fonte
AFAIK não há "quebra dupla" ou construção semelhante em C ++. O mais próximo seria um
goto
- que, embora tenha uma conotação ruim para seu nome, existe na língua por uma razão - desde que usado com cuidado e parcimônia, é uma opção viável.fonte
Você pode colocar seu switch em uma função separada como esta:
fonte
Mesmo se você não gostar de goto, não use uma exceção para sair de um loop. O exemplo a seguir mostra como isso pode ser feio:
Eu usaria
goto
como nesta resposta. Nesse casogoto
, o código ficará mais claro do que qualquer outra opção. Espero que esta pergunta seja útil.Mas acho que usar
goto
é a única opção aqui por causa da stringwhile(true)
. Você deve considerar a refatoração de seu loop. Suponho que a seguinte solução:Ou mesmo o seguinte:
fonte
goto
, não use uma exceção para sair de um loop:"?Não há construção C ++ para quebrar o loop neste caso.
Use um sinalizador para interromper o loop ou (se apropriado) extraia seu código em uma função e use
return
.fonte
Você poderia usar goto, mas prefiro definir um sinalizador que interrompa o loop. Em seguida, saia do interruptor.
fonte
Por que não apenas corrigir a condição em seu loop while, fazendo com que o problema desapareça?
fonte
Não, C ++ não possui uma construção para isso, visto que a palavra-chave "break" já está reservada para sair do bloco switch. Alternativamente, um do..while () com um sinalizador de saída pode ser suficiente.
fonte
Eu acho que;
fonte
A maneira mais simples de fazer isso é colocar um IF simples antes de fazer o SWITCH, e que IF teste sua condição para sair do loop .......... o mais simples possível
fonte
A
break
palavra-chave em C ++ apenas termina a iteração ouswitch
instrução envolvente mais aninhada . Portanto, você não poderia sair dowhile (true)
loop diretamente dentro daswitch
instrução; no entanto, você pode usar o seguinte código, que considero um excelente padrão para esse tipo de problema:Se você precisava fazer algo quando
msg->state
igualDONE
(como executar uma rotina de limpeza), coloque esse código imediatamente após ofor
loop; ou seja, se você atualmente tem:Em seguida, use:
fonte
Me surpreende como isso é simples, considerando a profundidade das explicações ... Aqui está tudo que você precisa ...
RI MUITO!! Realmente! É tudo que você precisa! Uma variável extra!
fonte
fonte
Eu tive o mesmo problema e resolvi usando um flag.
fonte
Se bem me lembro da sintaxe C ++, você pode adicionar um rótulo às
break
instruções, assim como paragoto
. Portanto, o que você deseja seria facilmente escrito:fonte
fonte