8

There are several postings concerning switch statements within while loops, except for the fact that none of them are done in C, at least from what I've seen. C++ can create boolean expressions, which I'm aware of, but not in C. I have a while loop that contains a switch control. However, when I write break statements within my switch, it goes back to the beginning of the loop and makes my program run forever. Ignore the functions I use, for they work for sure. I just need some clarification on my handling of the nesting. Thanks!

Here is my main.c:

while(1)
{
    printf("0) Exit\n1) List Tasks\n2) Add Task\n");                                            
    printf("3)Delete Task\n4) Add Task From File\n");                                           
    printf("What would you like to do?\n");
    fgets(buf1, 50, stdin);                                                                     
    p = atoi(buf1);
    switch(p)
    {
          case 0: 
            break;
          case 1: 
            printTaskList(pTaskList);
            break;
          case 2:
            printf("Enter task name: ");
            fgets(buf2,100,stdin);
            printf("Enter task priority: ");
            fgets(buf3,100,stdin);
            printf("Enter task start date: ");
            fgets(buf4,50,stdin);
            pTask = makeTask(buf2,buf4,buf3);
            addTaskToEnd(pTaskList,pTask);
            break;
          case 3:
            printTaskList(pTaskList);
            printf("What task would you like to delete? ");
            fgets(buf6,50,stdin);
            taskNum = atoi(buf6);
            removeTask(pTaskList,taskNum);
            break;
          case 4:
            printf("Enter the filename ");
            fgets(buf7,50,stdin);
            break;
          default:
            printf("ERROR: %d: Incorrect menu option\n", p);
     }
}
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
umarqattan
  • 499
  • 1
  • 6
  • 13
  • 1
    Your break statement serves to skip the rest of the switch clauses, which means you dump out at the line after the switch. A common solution to breaking all the way out of a nested scope is to move the code into a function and use return instead of break. – 7stud Apr 20 '13 at 06:16
  • identify the points you want to break OUT of the while loop within your switch body, set a flag indicating this, and make the `while(expression)` evaluate the flag for the break-state (i.e. `while(true)` becomes `while(stay_in_while)`, and have `stay_in_while` cleared by the switch code you want to break. – WhozCraig Apr 20 '13 at 06:16
  • 1
    You are mistaken, C has Boolean expressions and data type. It has a builtin type `_Bool` and if you include `` there are also `bool`, `false`, and `true`. – Jens Gustedt Apr 20 '13 at 06:31
  • 1
    Why would you edit out your question? You should leave it as it was, so that other people can use the answers you got. – Gauthier May 29 '13 at 12:05
  • Downvoted it as he edited it and removed it for others. Need a mod to roll it back maybe – Marriott81 Feb 26 '14 at 16:15

6 Answers6

18

break; will exit out of the nearest enclosing switch or loop. To jump two levels, you'll have to use the dreaded goto, or reorganize so a return will accomplish the desired semantics.

while(1) {
    switch(x) {
    case 0: goto EndWhile;
    }
}
EndWhile: ;

Or

void loop() {
    while(1) {
        switch(x) {
        case 0: return;
        }
    }
}
//...
loop();
//...

You can totally use a Boolean expression in C. Just use an int.

int quit = 0;
while(!quit) {
    switch(x) {
    case 0: quit = 1; break;
    }
}

C also has a boolean data type, if you really want it.

#include <stdbool.h>

bool quit = false;
while(!quit) {
    switch(x) {
    case 0: quit = true; break;
    }
}

And one more option, for the totally insane.

#include <setjmp.h>

jmp_buf jbuf;
if (!setjmp(jbuf))
    while(1) {
        switch(x) {
        case 0: longjmp(jbuf, 1);
        }
    }
luser droog
  • 18,988
  • 3
  • 53
  • 105
  • You made it really clear! Thank you so much! Your code fixed my infinite loop error, as well as all of you guys. I realized I had to flag where I wanted to exit the while loop, so I just changed "quit" to become the negation of "quit." – umarqattan Apr 20 '13 at 06:30
  • Using `int` as boolean works, and is very common, but I definitely prefer the stdbool style. `while`, `if`, and so on all take a boolean expression, and it does not feel logically correct to give them a number instead. `quit` is not a number, it is a condition. – Gauthier May 29 '13 at 12:03
1

You can have boolean expressions in C too. The C standard from 1999 has a stdbool.h header and a data type bool. In older C dialects, such as the one in Visual Studio 2012 (!), there is no boolean data type, so you need to use plain ints instead:

int keep_looping = 1;
while (keep_looping) {
    ....
    if (....)
        keep_looping = 0;
}
Thomas Padron-McCarthy
  • 27,232
  • 8
  • 51
  • 75
  • @modifiable lvalue: There certainly is, in the standard. And Visual Studio 2012 _still_ doesn't have it. But you are right, I shouldn't have said that there is no boolean type. Let's hope for his sake that he's not stuck with Microsoft. – Thomas Padron-McCarthy Apr 20 '13 at 06:57
  • Visual Studio 2012 doesn't have a C compiler. In the interest of countering any "but there's a 'compile as C code' option" arguments: It isn't uncommon for perfectly valid C code that's been written in the last decade to fail to compile using VS. If it can't compile C code, then it's not a C compiler. – autistic Apr 20 '13 at 09:25
0

You never exit the loop. The break will just break your switch. You should replace

while(1)

with something else that implies that the while-loop should be exited

Jensd
  • 7,886
  • 2
  • 28
  • 37
0

Your break only leaves the switch statement, then continues on in the

while(1)

loop forever.

koljaTM
  • 10,064
  • 2
  • 40
  • 42
0

C++ can create boolean expressions, which I'm aware of, but not in C.

Oh? So what is 0 == 0, if not a boolean expression? If you're referring to a variable of the type bool, make sure you #include <stdbool.h>.

However, when I write break statements within my switch, it goes back to the beginning of the loop and makes my program run forever. Ignore the functions I use, for they work for sure. I just need some clarification on my handling of the nesting. Thanks!

No. It doesn't go back to the beginning of the loop. Execution continues from the end of the switch statement (immediately after the switches closing brace, }). In your circumstance, this is functionally identical to going back to the beginning of the loop.

There are a few of options available to you. Others are suggesting using a sole variable to control your loop. This would be a good idea, but they're suggesting using new variables, despite the fact that the variable already exists in your logic. If you want to solve your problem this way, consider:

do {
    /* ... */
} while (p != 0);

Alternatively, return from main when you want to exit, or call exit(0); from other functions. This isn't all that helpful if you want to run extra cleanup/output code.

In this scenario, the switch control structure isn't really any better than a chain of if/else if/else branches. If you were to use the if/else if/else branches, you'd be able to break; out of the loop more easily. I'd use a switch control structure when I want execution to flow through into other cases.

As another option, you could use a goto expression to break out of the loop to a label outside of main. This would be best when there are multiple possible exit points from the loop, such as handling and cleanup following allocation errors.

autistic
  • 1
  • 3
  • 35
  • 80
0

use exit(0);
wherever you want to exit.

In this partcular case you have to put the condition in the while loop parameter

other ways to come out from the while loop might be to use: return statement. But this will also exit the current function.

Appropriate solution might be to use goto label; inside the switch and then use label: statement; outside the while loop.

Eg:

while(1){
  switch(x){

   case 0:goto label;

   default:break;
   }
}
label:
printf("out of while loop");
abe312
  • 2,547
  • 25
  • 16