2010-05-07 2 views
8

Я только что начал C++, но имею некоторые предварительные знания на других языках (vb awhile назад к сожалению), но имеет странное затруднительное положение. Я не любил, используя так много IF заявления и хотел использовать переключатель/случаи, как это казалось чище, и я хотел бы получить в практике .. Но ..Расширенная инструкция switch внутри цикла while?

Допустим, у меня есть следующий сценарий (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; 
    } 
} 

И это моя проблема. Допустим, я хотел выйти из цикла WHILE. Это потребует двух операторов break?

Это, очевидно, выглядит не так:

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

Так я могу только сделать заявление, если на «а», чтобы использовать перерыв ;? Я пропустил что-то действительно простое?

Это решит многие мои проблемы, которые у меня есть прямо сейчас.

+3

Основываясь на названии, я думал, что это может быть вопрос устройства Даффа. Неа. Есть ли для этого «скучный» тег? –

+0

Рад, что ваш вопрос решен, эти вещи не самые забавные. –

ответ

13

Вы можете просто проверить цикл while для значения bool, которое задано в одном из утверждений вашего случая.

+1

Я бы сказал, что этот ответ несколько субоптимальный (но никак не ошибочный). Если код был добавлен в оператор switch, он будет запущен, хотя проблема заключалась в том, чтобы напрямую выйти из внешнего цикла. Я бы использовал Dimas, если (сделано) сломался; метод или goto. –

+0

Да, это ловушка этого решения, код которого выполняется под этим коммутатором. Согласился. – Robb

+0

смешно я всегда использую во время (работает) – kenny

5

Да, C и C++ не могут сказать «выйти из нескольких разрывающих блоков» (где «разрывный блок» - это любой цикл или переключатель). Методы обхода включают goto s и использование булевых переменных для записи того, должен ли наружный «разрывный блок» также сломаться (ни один из них не является элегантным, но это жизнь).

5

Два заявления break не выведут вас из цикла while. Первый break выведет вас из инструкции switch, а второй никогда не будет достигнут.

Что нужно сделать, чтобы условие while было ложным, если предположить, что в операторе нет ничего после инструкции switch. Если после переключения есть другой код, вы должны проверить состояние после switch и 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

, почему бы не просто сделать while (true), если вы собираетесь проверить, выполнено (сделано). Это избыточно. – 2010-05-07 18:53:35

+0

Это зависит от ... Вы можете или не захотеть разорваться сразу после переключения. – Dima

1

Вы также можете инкапсулировать цикл в функцию и вернуть вызов внутри корпуса, в случае, если флаг, нарушающий время, недостаточно. Это не хорошая практика программирования для некоторых людей, но если вы сохраняете функцию просто, я не понимаю, почему нет.

0

Вы можете изменить свой переключатель на систему ifs. В любом случае это будет скомпилировано.

+0

Хороший аргумент, я не против немного слишком структурированного кода, если это не имеет значения. : P – Nullw0rm

+0

Обязательно добавьте комментарий, объясняющий, почему вы используете 'if/else-if', чтобы вы (или кто-то еще) не видели его позже и меняли его на более очевидный оператор switch, тем самым нарушая все. Каламбур не предназначен. –

+0

Если кто-то реорганизует ваш код и не замечает, что он изменил фундаментальное поведение метода, я не уверен, что буду доверять им, чтобы прочитать комментарий в первую очередь. –

3

Вы можете попробовать:

  • Использование флагов
  • Использование Goto
  • Имея блок Внутренний бьющиеся в функцию
  • Использование исключений
  • Использование LongJump и setjmp

Тема, очень похожая на этот вопрос

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

+0

Флаги и упаковка блока в функциональную работу. Гото плохо. И исключения здесь совсем не подходят. Выход из цикла не является ошибкой. – Dima

+5

Гото неплохо. Я думаю, что goto подходит для использования в этом случае, как и флаги. –

+0

В примере кода, который я использовал бы goto, он будет поддерживать порядок, если после оператора switch есть код. – mikek3332002

32

Я бы реорганизовать чек в другую функцию.

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

Это на самом деле довольно и заслуживает большего внимания. – Thomas

+0

Это должен быть ответ. –

+0

Одна из функций должна быть изменена для учета заглавных или нижних регистров. –

0

Вы могли бы заменить выключатель с чуть более спроектированные решения OO ...

#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

Вы могли бы быть заинтересованы в named loop idiom в 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); 
    } 
}