View Full Version : [C++] GOTO istruzione, chiarimenti
Albitexm
21-06-2010, 22:43
Due domande sull'uso dell'istruzione di salto GOTO in C++ :
1°:
quando viene chiamata l'istruzione GOTO e l'esecuzione "salta" all'etichetta specificata, le variabili memorizzate fino a quel punto vengono resettate? Se si, vengono distrutte anche eventuali variabili dichiarate prima dell'etichetta? Ovvero esempio:
mettiamo che ho un codice del tipo>
cin>>A
cin>>B
start:
cin>>C
...
if ()
goto start;
in questo caso, quando si torna a start viene distrutta solo la variabile C:
o anche A e B?
2°:
leggo che ogni singola istruzione GOTO deve fare riferimento a una singola etichetta. Ma se io ho bisogno di 5 istruzioni goto in punti differenti, che mi ritornano tutte 5 allo stesso punto del codice devo dichiarare 5 etichette diverse anche se nello stesso punto?
Ovvero, devo scrivere:
start1:
start2:
start3:
start4:
start5:
...
if ()
goto start1;
...
if ()
goto start2 ;
ecc..
oppure posso scrivere un'unica etichetta? :
start:
...
if ()
goto start;
...
if ()
goto start;
ecc..
Le variabili non vengono toccate dal goto e puoi dichiarare una sola etichetta.
Ne sono abbastanza sicuro anche se non vedo un GOTO da quando facevo pascal in 1a superiore. :p
Albitexm
22-06-2010, 00:50
Le variabili non vengono toccate dal goto
Posso esserne sicuro? In questo caso dovrò azzerarne parecchie io.
Puoi dichiarare una sola etichetta.
Come interpreti allora la seguente frase tratta dall'help di VC++ ?
: "A statement label is meaningful only to a goto statement; otherwise, statement labels are ignored. Labels cannot be redeclared".
E' questa frase che mi ha creato dei dubbi.
Ne sono abbastanza sicuro anche se non vedo un GOTO da quando facevo pascal in 1a superiore. :p
Tutti i testi,compreso l'help di VC++ sconsigliano di usare GOTO. Va bene..,
ma il mio programma è costituito da molti loop do while annidati. In più di 15 punti differenti devo ritornare all'inizio. Ho già fatto fatica a "incastrare" i vari cicli, non riesco a trovare altri modi per "saltare" fuori da quel groviglio.
Se devi usare GOTO per fare chiarezza, cancella tutto :D
E' una regola che non mi ha mai tradito :asd:
Ti consiglierei di trovare quali sono i moduli base della tua funzione, metterli in funzioni separate (massimo un while per funzione) e quindi ricostruire il flusso dell'algoritmo.
Perchè se è come dici non si può vedere :read:
DanieleC88
22-06-2010, 01:57
Se devi usare GOTO per fare chiarezza, cancella tutto :D
E' una regola che non mi ha mai tradito :asd:
+1
In C il goto lo posso anche capire, al limite, ma proprio al limite per gestire le condizioni di errore. Ma in C++ mi rifiuto :D
Come interpreti allora la seguente frase tratta dall'help di VC++ ?
: "A statement label is meaningful only to a goto statement; otherwise, statement labels are ignored. Labels cannot be redeclared".
E' questa frase che mi ha creato dei dubbi.
Quella frase vuol dire: "Una etichetta serve solo ai goto; in tutti gli altri casi viene ignorata. Le etichette non posso essere ridefinite". Praticamente non puoi dichiarare due label con lo stesso nome.
Mi accodo agli altri comunque. I GOTO sono considerati delle bestemmie in informatica ormai e sarebbe meglio non usarli. Se hai tutti quei cicli annidati direi che è il caso di rifattorizzare il tuo codice. :)
Tutti i testi,compreso l'help di VC++ sconsigliano di usare GOTO. Va bene..,
ma il mio programma è costituito da molti loop do while annidati. In più di 15 punti differenti devo ritornare all'inizio. Ho già fatto fatica a "incastrare" i vari cicli, non riesco a trovare altri modi per "saltare" fuori da quel groviglio.
Hai molti modi per farlo.
I primi che mi vengono in mente sono le eccezioni, ma probabilmente è ancora migliore lo state pattern.
Ad esempio:
class CycleMap
{
map<string, BaseCycle *> cycleMap;
public:
CycleMap()
{
map.push_back("MainCycle", new MainCycle());
map.push_back("Cycle1", new Cycle1());
map.push_back("Cycle2", new Cycle2());
map.push_back("Cycle3", new Cycle3());
}
};
class BaseCycle
{
BaseCycle(){};
virtual BaseCycle * run() = 0;
virtual bool continue() { return true; };
};
class MainCycle: public BaseCycle
{
public:
MainCycle(){};
virtual BaseCycle * MainCycle::run()
{
do
{
state = state.run();
}
while(state.continue())
}
virtual bool continue() { return false; };
};
class Cycle1: public BaseCycle
{
public:
Cycle1() {};
virtual BaseCycle * run()
{
BaseCycle * next;
do
{
someThing();
if(condition)
next = cycleMap["Cycle2"].run();
}
while(next == this);
return next;
}
};
class Cycle2: public BaseCycle
{
public:
Cycle2() {};
virtual BaseCycle * run()
{
BaseCycle * next;
do
{
someThingOther();
if(condition)
next = cycleMap["Cycle3"].run();
else if(other condition)
next = cycleMap["Cycle4"].run();
else
next = cycleMap["MainCycle"].run();
}
while(next == this);
return next;
}
};
Tra l'altro è carino perché potresti scambiare dinamicamente l'ordine di esecuzione dei cicli...
Premesso che se l'autore ha n cicli annidati con 15 punti in cui puo' uscirne e' forse il caso che riveda il design del programma, la tua soluzione mi sembra molto overkill...
E' sicuramente overkill, ma era per dimostrare che anche nel caso di 15 cicli annidati il goto in C++ non va usato.
Albitexm
22-06-2010, 23:26
E' sicuramente overkill, ma era per dimostrare che anche nel caso di 15 cicli annidati il goto in C++ non va usato.
Grazie per il suggerimento, adesso studierò "state pattern" . Un'altro modo
che mi era venuto in mente era di usare più volte "Break" per uscire da ogni ciclo. Ma ora per un principante come me, la domanda nasce spontanea:
"perchè il goto in C++ non va usato?".
DanieleC88
22-06-2010, 23:56
Grazie per il suggerimento, adesso studierò "state pattern" . Un'altro modo
che mi era venuto in mente era di usare più volte "Break" per uscire da ogni ciclo. Ma ora per un principante come me, la domanda nasce spontanea:
"perchè il goto in C++ non va usato?".
http://it.wikipedia.org/wiki/Spaghetti_code
Albitexm
23-06-2010, 00:13
,
Albitexm
24-06-2010, 14:53
Premesso che se l'autore ha n cicli annidati con 15 punti in cui puo' uscirne e' forse il caso che riveda il design del programma, la tua soluzione mi sembra molto overkill...
Considerate anche che io non sono un programmatore, ed è la prima volta che scrivo un programma. Mi stupisco già che funzioni il programma, ma giustamente è giusto che mi facciate presente che è meglio usare un metodo di stesura migliore se possibile.
Ma io avevo pensato di usare "continue" e "break" per uscire dai loop.
Ma non vedo la differenza, tra usare l'istruzione di "uscita" -continue- invece
che goto. Anche se viene consigliato di usare -continue- o -break- o -return-
invece che goto-
banryu79
24-06-2010, 15:11
Diciamo che l'istruzione continue in un for loop è un caso d'uso specifico del salto incondizionato goto. Lo usi solo nel for loop per interrompere l'esecuzione di una singola iterazione e continuare con la seguente.
Invece goto lo puoi usare per fare "salti" nel codice in modo molto più "arbitrario". In teoria, con le istruzioni e i costrutti che si hanno a disposizione in C++ non dovrebbe essere neccessario ricorrere al goto, poichè esistono alternative che è raccomandabile usare poichè meno error-prone.
Poi uno può fare quello che gli pare ;)
Considerate anche che io non sono un programmatore, ed è la prima volta che scrivo un programma. Mi stupisco già che funzioni il programma, ma giustamente è giusto che mi facciate presente che è meglio usare un metodo di stesura migliore se possibile.
Ma io avevo pensato di usare "continue" e "break" per uscire dai loop.
Ma non vedo la differenza, tra usare l'istruzione di "uscita" -continue- invece
che goto. Anche se viene consigliato di usare -continue- o -break- o -return-
invece che goto-
Come ho già detto, metti quel ciclo in una funzione e invece di break usa return :D
Vedrai che se metti un ciclo per funzione viene parecchio più pulito... scommetto che quello che ti impone breaks e continues è la difficoltà di portare risultati fuori dai cicli no?
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.