È possibile utilizzare la break
funzione per uscire da più for
loop nidificati ?
Se è così, come faresti a farlo? Puoi anche controllare quanti loop le break
uscite?
È possibile utilizzare la break
funzione per uscire da più for
loop nidificati ?
Se è così, come faresti a farlo? Puoi anche controllare quanti loop le break
uscite?
Risposte:
AFAIK, C ++ non supporta i loop di denominazione, come fanno Java e altre lingue. È possibile utilizzare un goto o creare un valore flag che si utilizza. Alla fine di ogni ciclo, controlla il valore del flag. Se è impostato su true, è possibile interrompere tale iterazione.
goto
se questa è l'opzione migliore.
goto
: programmatori errati e programmatori pragmatici. I primi si spiegano da soli. Quest'ultimo, in cui ti adatteresti se scegli di usarli bene, usa un cosiddetto concetto "malvagio" quando è il minore dei (due) mali. Leggi questo per una migliore comprensione di alcuni concetti C ++ che potresti dover usare di volta in volta (macro, goto, preprocessore, array): parashift.com/c++-faq-lite/big-picture.html#faq-6.15
goto
raramente è l'opzione migliore. Perché non mettere i loop nella loro funzione ( inline
, se sei preoccupato per la velocità) e return
da questo?
No, non rovinarlo con a break
. Questa è l'ultima roccaforte rimasta per l'uso di goto
.
Solo per aggiungere una risposta esplicita 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
}
}
}();
}
Naturalmente questo modello ha alcune limitazioni e ovviamente solo C ++ 11 ma penso che sia abbastanza utile.
Un altro approccio per uscire da un loop nidificato consiste nel fattorizzare entrambi i loop in una funzione separata e return
da quella funzione quando si desidera uscire.
Ovviamente, questo fa emergere l'altro argomento sul fatto che si debba mai esplicitamente return
da una funzione in qualsiasi luogo diverso dalla fine.
continue_processing
) che controllavano l'esecuzione di blocchi di codice più in basso nella funzione.
break uscirà solo dal ciclo più interno che lo contiene.
Puoi usare goto per uscire da qualsiasi numero di loop.
Ovviamente il goto è spesso considerato dannoso .
è corretto utilizzare la funzione di interruzione [...]?
L'uso di break and goto può rendere più difficile ragionare sulla correttezza di un programma. Vedi qui per una discussione su questo: Dijkstra non era pazzo .
break
o return
.
break
e return
hai il vantaggio goto
di non dover cercare un'etichetta per trovare dove vanno. Sì, sotto sono una specie di goto
, ma molto limitati. Sono molto più facili da decifrare dal cervello di un modello programmatore che non senza restrizioni goto
. Quindi sono preferibili l'IMO.
goto
.
Sebbene questa risposta sia già stata presentata, penso che un buon approccio sia quello di fare quanto segue:
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
viene controllato ogni ciclo
goto
rende il core più leggibile e più performante.
Cosa ne pensi di questo?
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;
}
}
}
}
Un esempio di codice che utilizza goto
e un'etichetta per uscire da un ciclo nidificato:
for (;;)
for (;;)
goto theEnd;
theEnd:
Un buon modo per uscire da diversi loop nidificati è di trasformare il codice in una funzione:
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 può essere molto utile per rompere i loop nidificati
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
Penso che a goto
sia valido in questa circostanza:
Per simulare un break
/ continue
, vorresti:
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
goto theEnd;
}
}
}
theEnd:
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
i++;
goto multiCont;
}
}
multiCont:
}
i
. Quindi i++
prima del goto
Altri linguaggi come PHP accettano un parametro per break (ovvero break 2;) per specificare la quantità di livelli di loop nidificati da cui si vuole uscire, C ++ invece non lo fa. Dovrai risolverlo utilizzando un valore booleano impostato su false prima del ciclo, impostato su true nel ciclo se desideri interrompere, più un'interruzione condizionale dopo il ciclo nidificato, controllando se il valore booleano è impostato su true e rompere se sì.
So che questo è un vecchio post. Ma suggerirei una risposta un po 'logica e più semplice.
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
non funzionerà se hai un predicato complesso invece di j < conditionj
.
Rompere qualsiasi numero di loop di una sola bool
variabile, vedere di seguito:
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;
}
}
In questo codice abbiamo break;
tutti i loop.
Non sono sicuro che ne valga la pena, ma puoi emulare i loop denominati di Java con alcune semplici macro:
#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
Esempio di utilizzo:
#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);
}
}
}
Un altro esempio:
#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);
}
Puoi usare 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 devi uscire da più loop contemporaneamente, spesso è comunque un'eccezione.
Uscire da un for-loop è un po 'strano per me, poiché la semantica di un for-loop in genere indica che verrà eseguita un determinato numero di volte. Tuttavia, non è male in tutti i casi; se stai cercando qualcosa in una collezione e vuoi rompere dopo averlo trovato, è utile. In C ++, tuttavia, non è possibile interrompere i loop nidificati; è in altre lingue attraverso l'uso di una pausa etichettata. Puoi usare un'etichetta e un goto, ma questo potrebbe farti venire il bruciore di stomaco durante la notte ..? Sembra l'opzione migliore però.