5

I have the following code:

void takeOrder(void)
{
int stop = 0;
while(stop != 1)
{
    printf("What is your order?\n");
    printf("%c - fruitShake\n%c - milkShake\n", FRUIT_SHAKE_CHOICE, MILK_SHAKE_CHOICE); 
    scanf("%c", &typeChoice); 
    if(typeChoice != FRUIT_SHAKE_CHOICE || typeChoice != MILK_SHAKE_CHOICE)
    {
        printf("***Error! Wrong type***");
        stop = 1;
    }
    //more code below
}

}

I'm trying to exit the while-loop with the flag "stop", but it doesn't work and it simply continues with the rest of the code below. Is there any way to exit this while-loop with a flag and without using break?

1
  • Comments are not for extended discussion; this conversation has been moved to chat. Commented Dec 1, 2017 at 17:32

4 Answers 4

9

You can do it in several ways, all of which are grossly inferior to using break:

  • You could add else and increase code nesting of the // more code part, or
  • You could set the variable and use continue instead of break to confuse your readers, or
  • You could add a label and use goto to infuriate your co-workers

The best approach is to use break, and drop the stop variable altogether, replacing it with a "forever" loop:

for (;;) {
    ...
    if (condition) {
        break;
    }
    ...
}

This construct is idiomatic in situations when none of the three built-in loop give you a particularly good fit, i.e. when the decision to break or continue is made in the middle of the loop, as opposed to the top of the loop (as in for and while loops) or the bottom of the loop (as in do/while loop).

Note: The reason why your code does not end the loop when you set the variable is that loop condition is not checked continuously. Rather, it is checked once before each iteration begins. After that the condition may become invalid at any point inside the body of the loop.

Sign up to request clarification or add additional context in comments.

1 Comment

Yes. In this situation, I tend also to put a comment beside the break: // JUMP OUT. That means (a) the arguably (marginally) defective flow-of-control stands out when scanning the code; and (b) it suggests to me-in-the-future and anyone else that ‘yes, I did think about this and I still think it's the best way to do this’. Also, if I get the nesting wrong (the possibility/probability of doing which is one of the reasons why this is regarded as a dubious pattern), this indicates the intention.
7

The only way I see is to put in conditional the more code below part

 int stop = 0;

 while (stop != 1) {
   if (typeChoice == FRUIT_SHAKE_CHOICE || typeChoice == MILK_SHAKE_CHOICE) {
     stop = 1;
   } else {
     // more code below
   }
 }

The second only way using a function :

while (doStuff() == 0);

int doStuff(void) {
   if (typeChoice == FRUIT_SHAKE_CHOICE || typeChoice == MILK_SHAKE_CHOICE) {
     return 1;
   } 

   // more code below

   return 0;
}

PS: Maybe I'm a nazi but this should definitely be a do ... while

 int stop = 0;

 do {
   if (typeChoice == FRUIT_SHAKE_CHOICE || typeChoice == MILK_SHAKE_CHOICE) {
     stop = 1;
   } else {
     // more code below
   }
 } while (stop != 1);

1 Comment

Yes I think that you're right! I'll try it! Btw, the first advice worked to me.
2

First replace

if(typeChoice != FRUIT_SHAKE_CHOICE || typeChoice != MILK_SHAKE_CHOICE)

with

if(typeChoice != FRUIT_SHAKE_CHOICE && typeChoice != MILK_SHAKE_CHOICE)
                                   ^^^^

otherwise the if is never true - based on the choices offered above, that's what you want to do.

Then ensure the "more code" is not executed in this case

if(typeChoice != FRUIT_SHAKE_CHOICE && typeChoice != MILK_SHAKE_CHOICE) {
   printf("Wrong type\n");
   stop = 1;
}
else {
    // more stuff
}

in your current code, even if stop is set to 1, you do the "more stuff".

You could also test the opposite, and add continue to the OK code, else set stop

if(typeChoice == FRUIT_SHAKE_CHOICE || typeChoice == MILK_SHAKE_CHOICE) {
    // do more stuff
    continue; // keep going
}
printf("Wrong choice, same player shoot again\n");
stop = 1;

Comments

0

I hope FRUIT_SHAKE_CHOICE is macro(char value)

another thing is because of scanf("%c", &typeChoice); buffer is not getting clear before 2nd input

Either use (give the space) or use getchar()/fgetc()

scanf(" %c", &typeChoice);

Here is my understanding

#define FRUIT_SHAKE_CHOICE 'a'
#define MILK_SHAKE_CHOICE 'b'
void takeOrder(void)
{
char typeChoice;
int stop = 0;
while(stop != 1)
{
    printf("What is your order?\n");
    printf("%c - fruitShake\n%c - milkShake\n", FRUIT_SHAKE_CHOICE, MILK_SHAKE_CHOICE); 
    scanf(" %c", &typeChoice); 
    if(typeChoice != FRUIT_SHAKE_CHOICE && typeChoice != MILK_SHAKE_CHOICE)
    {
        printf("***Error! Wrong type***");
        stop = 1;
        continue;// bcz once stop becomes 1 , you don't to want to execute below part, it will jump to while condition checking part & come out from loop
    }
    //more code below
}
}
int main()
{
     takeOrder();
     return 0;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.