C语言中while循环内的switch语句

8

关于 while 循环内 switch 语句的问题,有很多帖子讨论,但我没有看到任何使用 C 语言完成的。C++ 可以创建布尔表达式,我知道这一点,但在 C 中不行。我有一个包含 switch 控制的 while 循环。然而,当我在 switch 中写 break 语句时,它会回到循环的开头,程序就会一直运行下去。请忽略我使用的函数,因为它们肯定是有效的。我只需要对嵌套处理做出一些澄清。感谢您的帮助!

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

1
你的break语句用于跳过switch语句中剩余的分支,这意味着你会在switch后的那一行结束。一个常见的解决方案是将代码移动到一个函数中,并使用return代替break来完全退出嵌套作用域。 - 7stud
在您的 switch 体内标识您想要跳出 while 循环的点,设置一个指示此操作的标志,并使 while(expression) 评估该标志以进行中断状态(即 while(true) 变为 while(stay_in_while)),并且由您想要中断的 switch 代码清除 stay_in_while - WhozCraig
1
你错了,C语言有布尔表达式和数据类型。它有一个内置类型 _Bool,如果你包含 <stdbool.h>,还有 boolfalsetrue - Jens Gustedt
1
为什么要编辑掉你的问题?你应该将它保留原样,这样其他人才能使用你得到的答案。 - Gauthier
因为他编辑了它并将其删除,所以被下投票了。也许需要一个mod来回滚它。 - Marriott81
6个回答

19

break;会退出最近的包含switch或循环的代码块。如果要跳出两个级别,您必须使用可怕的goto,或重新组织代码,使return能够实现所需的语义。

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

或者

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

在C中,你完全可以使用一个布尔表达式,只需使用一个int

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

如果你真的需要,C语言也有布尔数据类型。

#include <stdbool.h>

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

还有一种选择,适合于非常疯狂的人

#include <setjmp.h>

jmp_buf jbuf;
if (!setjmp(jbuf))
    while(1) {
        switch(x) {
        case 0: longjmp(jbuf, 1);
        }
    }

你讲得非常清楚!非常感谢!你的代码修复了我的无限循环错误,以及所有人。我意识到我必须标记我想要退出 while 循环的位置,所以我只是将“quit”更改为“quit”的否定形式。 - umarqattan
使用 int 作为布尔值是可行的,也很常见,但我个人更喜欢使用 stdbool 风格。whileif 等都需要布尔表达式,用数字代替它们并不符合逻辑。quit 不是一个数字,而是一个条件。 - Gauthier

1

在 C 语言中也可以使用布尔表达式。1999 年的 C 标准有一个 stdbool.h 头文件和一个数据类型 bool。在旧的 C 方言中,例如 Visual Studio 2012 中的方言,没有布尔数据类型,所以需要使用普通的整数代替:

int keep_looping = 1;
while (keep_looping) {
    ....
    if (....)
        keep_looping = 0;
}

@modifiable lvalue:标准中确实有这个功能。但是Visual Studio 2012仍然没有它。但你说得对,我不应该说没有布尔类型。希望他不会被困在Microsoft里。 - Thomas Padron-McCarthy
Visual Studio 2012没有C编译器。为了反驳任何“但有一个‘编译为C代码’选项”的论点:在过去的十年中编写的完全有效的C代码无法使用VS编译是很常见的。如果它不能编译C代码,那么它就不是C编译器。 - autistic

0
你从未退出循环。break 只会中断 switch。你应该替换。
while(1)

使用其他暗示表示应退出while循环


0
你的休息只在switch语句中,然后继续执行下去。
while(1)

无限循环。


0
C++ 可以创建布尔表达式,这一点我知道,但在 C 中不行。
哦?那么 0 == 0 不是布尔表达式吗?如果你指的是 bool 类型的变量,请确保你包含了 #include <stdbool.h>
然而,当我在 switch 中写 break 语句时,它会回到循环的开头并使我的程序永远运行下去。请忽略我使用的函数,因为它们肯定是有效的。我只需要对嵌套的处理有些澄清。谢谢!
不,它不会回到循环的开头。执行将从 switch 语句的结尾(即 switch 的右括号 } 后面)继续进行。在你的情况下,这与“回到循环的开头”在功能上是相同的。
你有几个选项可供选择。其他人建议使用单独的变量来控制你的循环。这是一个好主意,但他们建议使用新变量,尽管该变量已经存在于你的逻辑中。如果你想用这种方式解决问题,请考虑:
do {
    /* ... */
} while (p != 0);

或者,当您想要退出时,从主函数中return,或从其他函数中调用exit(0);。如果您想运行额外的清理/输出代码,这并不是很有帮助。

在这种情况下,switch控制结构并不比一系列if/else if/else分支更好。如果您使用if/else if/else分支,您将更容易地从循环中break;跳出。当我希望执行流程进入其他情况时,我会使用switch控制结构。

作为另一种选择,您可以使用goto表达式将循环中断到主函数之外的标签处。当循环存在多个可能的退出点时,例如处理和清理分配错误后,这将是最佳选择。


0

在任何想要退出的地方使用 exit(0);

在这种情况下,您必须将条件放在 while 循环参数中

退出 while 循环的其他方法可能是使用:return 语句。但这也会退出当前函数。

适当的解决方案可能是在 switch 中使用 goto label; 然后在 while 循环外部使用 label: statement;

例如:

while(1){
  switch(x){

   case 0:goto label;

   default:break;
   }
}
label:
printf("out of while loop");

1
这是非常微小的答案,我认为。 - Hello World
这只有在他想要完全退出整个程序时才起作用,是吗?虽然可能仍然不正确,但return 0会更合适吗? - Alexej Magura
'return' 退出函数,而 'exit' 退出整个程序。 - abe312

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接