Cicli annidati senza goto



Il C++ non presenta il comando di una break multilivello come avviene, invece, in Java. Quindi si rende necessaria l’utilizzo della keyword goto e delle etichette, cosa piuttosto sgradevole in un linguaggio procedurale come il C++.

Per esempio supponiamo di dover effettuare due cicli uno interno all’altro e di dover uscire da questi due cicli quandi si è verificata una certa condizione.

int j=0;
for (int i=0; i<10; i++)
for (j=0; j<20; j++)
{
if (i==4 && j==5)
{
<esci dai due cicli>
}
}

È evendente come il break non possa fare a caso nostro perchè uscirebbe solo dal ciclo più interno. Allora si renderebbe necessaria l’uso dei goto e delle etichette.

Qui si interviene cambiando la prospettiva per risolvere il problema. Per prima cosa si “raggruppa” la condizione in una funzione o con la direttiva #define (meglio quest’ultima dal punto di vista computazionale).

bool ___COND(int i, int j)
{
return i==4 && j==5;
}

o preferibilmente

#define ___COND (i==4 && j==5)

Ora si inserisce la condizione ___COND tra quelle valutate dal loop esterno

int j=0;
for (int i=0; i<10 && !___COND; i++)
for (j=0; j<20; j++)
{
if (___COND)
{
break;
}
}

In questo esempio è stata usata la condizione esplicita con la direttiva del preprocessore; stesso discorso si ha per la funzione ___COND(int, int). Il codice non è, però, ancora corretto in quanto si deve considerare che quando si esce dal ciclo interno tramite break viene incrementato il valore id i prima di fare verificare le condizione del ciclo esterno con la conseguenza che non esce dal ciclo più interno perchè ___COND non è più true1.

Quindi prima di eseguire il break si decrementa di 1 la variabile del ciclo più esterno.

int j=0;
for (int i=0; i<10 && !___COND; i++)
for (j=0; j<20; j++)
{
if (___COND)
{
i–;
break;
}
}

Con questo inserimento viene valutata la condizione correttamente restituendo il risultato sperato.

int j=0;
for (int i=0; i<10 && !___COND; i++)
for (j=0; j<20; j++)
{
if (___COND)
{
i–;
break;
}
}
cout
<< “i: ” << i << ” – j: ” << j
<< ” – ___COND(” << i << “,” << j << “): ”
<< (___COND ? “true” : “false”) << ” “;

Con queste aggiunte si può vedere che il risultato è corretto.

i: 4 – j: 6 – ___COND(4,6): true Press any key to continue


1 in realtà questo non è sempre vero, infatti certe condizioni potrebbere risultare vere per valori vicini tra un’iterazione e l’altra ma l’obiettivo prefissato e di trovare i valori che soddisfano la condizione per primi e quindi si considera la condizione per i valori successivi falsa.


Annunci sponsorizzati:
Condividi su Facebook Condividi su Twitter!
Pinterest