开发者

Advanced switch statement within while loop?

开发者 https://www.devze.com 2022-12-29 05:39 出处:网络
I just started C++ but have some prior knowledge to other languages (vb awhile back unfortunately), but have an odd predicament. I disliked using so many IF statements and wanted to use switch/cases a

I just started C++ but have some prior knowledge to other languages (vb awhile back unfortunately), but have an odd predicament. I disliked using so many IF statements and wanted to use switch/cases as it seemed cleaner, and I wanted to get in the practice.. But..

Lets say I have the following scenario (theorietical code):

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;
  }
}

And that's my problem. Lets say I wanted to exit the WHILE loop, It'd require two break statements?

This obviously looks wrong:

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

So can I only do an IF statement on the 开发者_Python百科'a' to use break;? Am I missing something really simple?

This would solve a lot of my problems that I have right now.


I would refactor the check into another function.

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));
}


You could simply have the while loop check for a bool value that is set within one of your case statements.

bool done = false;    
while(!done)
{
 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";
      done = true; // exit condition here
      break;
    case 'b':
      cout << "...";
      break;
  }
}


Yes, C and C++ have no way to say "exit multiple breakable blocks" (where a "breakable block" is any loop or switch). Workarounds include gotos and use of boolean variables to record whether an outer "breakable block" should also break (neither is elegant, but, that's life).


Two break statements will not get you out of the while loop. The first break only gets you out of the switch statement and the second one is never reached.

What you need is to make the condition of the while loop false, assuming that there is nothing in the loop after the switch statement. If there is other code after the switch, you should check the condition after the switch, and break there.


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

}


You could try:

  • Using Flags
  • Using Goto
  • Having the Inner Breakable block into a function
  • Using Exceptions
  • Using longjump and setjmp

A topic very similar to this question

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


You might be interested in the 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);
  }
}


You can also encapsulate the loop into a function and call return inside the case, for the case that the flag breaking the while is not enough. It is not a good programming practice for some people but if you keep the function simple I don't see why not.


You could replace the switch with a slightly over-engineered OO solution...

#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);
}


You could change your switch to an ifsystem. It will be compiled to the same thing anyway.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号