2010-05-07 23 views
8

Acabo de iniciar C++ pero tengo algunos conocimientos previos de otros lenguajes (vb un tiempo atrás desafortunadamente), pero tengo una situación extraña. Me gustaba usar tantos IF y quería utilizar interruptores/de los casos, ya que parecía más limpio, y quería conseguir en la práctica .. Pero ..¿Sentencia de conmutación avanzada dentro del ciclo while?

Digamos que tengo el siguiente escenario (código 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; 
    } 
} 

Y ese es mi problema. Digamos que quería salir del ciclo WHILE, ¿se necesitarían dos declaraciones de interrupción?

Obviamente, esto se ve mal:

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

Así que sólo puedo hacer una instrucción IF en la 'a' a utilizar ruptura ;? ¿Me estoy perdiendo algo realmente simple?

Esto resolvería muchos de mis problemas que tengo ahora.

+3

Según el título, pensé que esta podría ser una pregunta de Duff Device. Nop. ¿Hay una etiqueta 'aburrida' para eso? –

+0

Me alegra que su pregunta haya sido resuelta, estas cosas no son las más divertidas. –

Respuesta

13

Usted podría simplemente tener la verificación while loop para un valor bool que se establece dentro de una de las declaraciones de su caso.

+1

Diría que esta respuesta es algo subóptima (pero de ninguna manera incorrecta). Si se agregó el código en la instrucción switch, se ejecutará aunque el problema sea salir directamente del bucle externo. Hubiera usado Dimas si (hecho) se rompiera; método, o un goto. –

+0

Sí, esa es una trampa de esta solución, código que se ejecuta bajo ese interruptor. De acuerdo allí. – Robb

+0

gracioso Siempre uso mientras (corriendo) – kenny

5

Sí, C y C++ no tienen forma de decir "salir de varios bloques rompibles" (donde un "bloque divisible" es cualquier bucle o interruptor). Las soluciones incluyen goto sy el uso de variables booleanas para registrar si un "bloque rompible" externo también debería romperse (ninguno de los dos es elegante, pero así es la vida).

5

Dos declaraciones break no lo sacarán del ciclo while. El primer break solo lo saca de la declaración switch y nunca se llega al segundo.

Lo que necesita es hacer que la condición del ciclo while sea falsa, suponiendo que no hay nada en el ciclo después de la instrucción switch. Si hay otro código después del cambio, debe verificar la condición después de switch y break allí.

 

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

por qué no solo hacer mientras (verdadero) si va a verificar si (hecho). Esto es redundante. –

+0

depende ... Puede o no querer romper inmediatamente después del cambio. – Dima

1

También puede encapsular el bucle en una función y devolver llamada dentro de la caja, para el caso de que la bandera no sea suficiente. No es una buena práctica de programación para algunas personas, pero si mantienes la función simple, no veo por qué no.

0

Puede cambiar su interruptor a un sistema if. Se compilará a la misma cosa de todos modos.

+0

Buen argumento, no me importa un código demasiado estructurado si no importa. : P – Nullw0rm

+0

Asegúrese de agregar un comentario explicando por qué está usando 'if/else-if', para que usted (u otra persona) no lo vea más tarde y lo cambie a la declaración de cambio más obvia, rompiendo así todo. Sin juego de palabras. –

+0

Si alguien refactura su código y no nota que han cambiado el comportamiento fundamental del método, no estoy seguro de que confíe en que lo lean en primer lugar. –

3

Usted podría intentar:

  • Uso de Banderas
  • Usando Goto
  • Tener el bloque interior quebradizo en una función
  • Uso de excepciones
  • Uso longjump y setjmp

Un tema muy similar a esta pregunta

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

+0

Banderas y envolviendo el bloque en una función de trabajo. Goto es malo. Y las excepciones no son del todo apropiadas aquí. Salir del bucle no es un error. – Dima

+5

Goto no está mal. Creo que goto es apropiado para usar en este caso, como lo son las banderas. –

+0

En el código de ejemplo que usaría goto, lo mantendrá ordenado si hay código después de la declaración de cambio. – mikek3332002

32

Me refactorizar el cheque en otra función.

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

Esto es realmente bonito y merece más votos ascendentes. – Thomas

+0

Esta debería ser la respuesta. –

+0

Una de las funciones debe modificarse para tener en cuenta las selecciones en mayúsculas o minúsculas. –

0

Se puede sustituir el interruptor con una solución OO poco más de la ingeniería ...

#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

Quizás se encuentre interesado en el named loop idiom en 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); 
    } 
} 
Cuestiones relacionadas