2010-05-07 8 views
8

Ho appena iniziato il C++ ma ho una conoscenza pregressa in altre lingue (vb un po 'indietro purtroppo), ma ho una situazione strana. Mi è piaciuta utilizzando tanti istruzioni IF e volevo usare interruttori/casi come sembrava più pulita, e volevo entrare nella pratica .. Ma ..Istruzione switch avanzata all'interno del ciclo while?

Diciamo che ho il seguente scenario (codice theorietical):

while(1) { 

    //Loop can be conditional or 1, I use it alot, for example in my game 
    char something; 
    std::cout << "Enter something\n -->"; 
    std::cin >> something; 

    //Switch to read "something" 
    switch(something) { 
    case 'a': 
     cout << "You entered A, which is correct"; 
     break; 
    case 'b': 
     cout << "..."; 
     break; 
    } 
} 

E questo è il mio problema. Diciamo che volevo uscire dal ciclo WHILE, Avrebbe bisogno di due frasi break?

Questo sembra ovviamente sbagliato:

case 'a': 
    cout << "You entered A, which is correct"; 
    break; 
    break; 

Quindi posso solo fare una dichiarazione IF sulla 'a' da usare pausa ;? Mi sto perdendo qualcosa di veramente semplice?

Questo risolverebbe molti dei miei problemi che ho adesso.

+3

Sulla base del titolo, ho pensato che questa potrebbe essere una domanda di dispositivo di Duff. No. C'è un tag 'noioso 'per quello? –

+0

Felice che la tua domanda sia stata risolta, queste cose non sono le più divertenti. –

risposta

13

Si potrebbe semplicemente avere il controllo del ciclo while per un valore di bool che è impostato all'interno di una delle dichiarazioni del caso.

+1

Direi che questa risposta è alquanto subottimale (ma non in alcun modo sbagliato). Se il codice è stato aggiunto sotto l'istruzione switch, verrebbe eseguito anche se il problema era di uscire direttamente dal ciclo esterno. Avrei usato Dimas se (fatto) pausa; metodo, o un goto. –

+0

Sì, questa è una trappola di questa soluzione, codice che viene eseguito sotto quell'interruttore. D'accordo lì. – Robb

+0

divertente che uso sempre mentre (correndo) – kenny

5

Sì, C e C++ non hanno modo di dire "esci da più blocchi interrompibili" (dove un "blocco interrompibile" è un loop o uno switch). Le soluzioni alternative includono goto s e l'uso di variabili booleane per registrare se un "blocco interrompibile" esterno deve anche interrompersi (nessuno dei due è elegante, ma è la vita).

5

Due istruzioni break non ti faranno uscire dal ciclo while. Il primo break ti fa uscire dall'istruzione switch e il secondo non viene mai raggiunto.

Ciò che serve è rendere falsa la condizione del ciclo while, presupponendo che non ci sia nulla nel ciclo dopo l'istruzione switch. Se dopo l'interruttore è presente un altro codice, è necessario verificare le condizioni dopo switch e break.

 

bool done = false; 

while(! done) 
{ 
    // do stuff 
    switch(something) 
    { 
    case 'a': 
    done = true; // exit the loop 
    break; 
    } 

    // do this if you have other code besides the switch 
    if(done) 
    break; // gets you out of the while loop 

    // do whatever needs to be done after the switch 

} 
 
+0

perché non limitarsi a farlo mentre (vero) se si sta andando a controllare se (fatto). Questo è ridondante. –

+0

dipende ... È possibile o meno rompere immediatamente dopo l'interruttore. – Dima

1

È inoltre possibile incapsulare il ciclo in una funzione e chiamata di ritorno all'interno del case, per il caso che la bandiera rompere il tempo non è sufficiente. Non è una buona pratica di programmazione per alcune persone ma se si mantiene la funzione semplice non vedo perché no.

0

È possibile modificare l'opzione su un ifsystem. Sarà comunque compilato allo stesso modo.

+0

Buon argomento, non mi interessa un codice leggermente troppo strutturato se non importa. : P – Nullw0rm

+0

Assicurati di aggiungere un commento che spieghi perché stai usando 'if/else-if', in modo che tu (o qualcun altro) non lo veda più tardi e lo cambi con l'istruzione switch più ovvia, rompendo così qualunque cosa. Nessun gioco di parole previsto. –

+0

Se qualcuno rifatta il codice e non si accorge di aver cambiato il comportamento fondamentale del metodo, non sono sicuro che mi fiderei di loro per leggere il commento in primo luogo. –

3

Si potrebbe provare:

  • Uso Bandiere
  • Utilizzando Goto
  • Avere il Blocco interno fragili in una funzione
  • usare le eccezioni
  • Uso LongJump e setjmp

Un argomento molto simile a questa domanda

http://www.gamedev.net/community/forums/topic.asp?topic_id=385116

+0

Flags e wrapping del blocco in una funzione di lavoro. Goto è cattivo. E le eccezioni non sono del tutto appropriate qui. Uscire dal ciclo non è un errore. – Dima

+5

Goto non è male. Penso che goto sia appropriato da usare in questo caso, come lo sono le bandiere. –

+0

Nel codice di esempio dovrei usare goto, lo manterrà ordinato se c'è un codice dopo l'istruzione switch. – mikek3332002

32

avrei refactoring del check in un'altra funzione.

bool is_correct_answer(char input) 
{ 
    switch(input) 
    { 
    case 'a': 
     cout << "You entered A, which is correct"; 
     return true; 
    case 'b': 
     cout << "..."; 
     return false; 
    } 
    return false; 
} 

int main() 
{ 
    char input; 
    do 
    { 
     std::cout << "Enter something\n -->"; 
     std::cin >> input; 
    } while (!is_correct_answer(input)); 
} 
+0

Questo è davvero carino e merita più upvotes. – Thomas

+0

Questa dovrebbe essere la risposta. –

+0

Una delle funzioni deve essere modificata per tenere conto delle selezioni minuscole o maiuscole. –

0

Si potrebbe sostituire l'interruttore con una soluzione OO leggermente over-engineered ...

#include <iostream> 
#include <map> 
#include <set> 

class input_responder 
{ 
    std::set<char> correct_inputs; 
    std::map<char, const char*> wrong_inputs; 

public: 

    input_responder() 
    { 
     correct_inputs.insert('a'); 
     wrong_inputs['b'] = "..."; 
    } 

    bool respond(char input) const 
    { 
     if (correct_inputs.find(input) != correct_inputs.end()) 
     { 
      std::cout << "You entered " << input << ", which is correct\n"; 
      return true; 
     } 
     else 
     { 
      std::map<char, const char*>::const_iterator it = wrong_inputs.find(input); 
      if (it != wrong_inputs.end()) 
      { 
       std::cout << it->second << '\n'; 
      } 
      else 
      { 
       std::cout << "You entered " << input << ", which is wrong\n"; 
      } 
      return false; 
     } 
    } 
}; 

int main() 
{ 
    const input_responder responder; 
    char input; 
    do 
    { 
     std::cout << "Enter something\n -->"; 
     std::cin >> input; 
    } while (responder.respond(input) == false); 
} 
1

si potrebbe essere interessato al named loop idiom in C++.

#define named(blockname) goto blockname; \ 
         blockname##_skip: if (0) \ 
         blockname: 

#define break(blockname) goto blockname##_skip; 

named(outer) 
while(1) { 

    //Loop can be conditional or 1, I use it alot, for example in my game 
    char something; 
    std::cout << "Enter something\n -->"; 
    std::cin >> something; 

    //Switch to read "something" 
    switch(something) { 
    case 'a': 
     cout << "You entered A, which is correct"; 
     break(outer); 
    case 'b': 
     cout << "..."; 
     break(outer); 
    } 
}