【问题标题】:Switch statement within while loop in CC中while循环内的switch语句
【发布时间】:2013-04-13 14:19:10
【问题描述】:

有几篇关于 while 循环中的 switch 语句的帖子,除了没有一个是在 C 中完成的,至少从我所看到的来看。 C++ 可以创建布尔表达式,我知道,但不是在 C 中。我有一个包含开关控件的 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);
     }
}

【问题讨论】:

  • 您的 break 语句用于跳过其余的 switch 子句,这意味着您在 switch 后的行中转储。打破嵌套范围的常见解决方案是将代码移动到函数中并使用 return 而不是 break。
  • 确定你想在你的开关体内打破while循环的点,设置一个标志来表明这一点,并使while(expression)评估中断状态的标志(即while(true)变为while(stay_in_while),并通过您要中断的开关代码清除stay_in_while
  • 你错了,C有布尔表达式和数据类型。它有一个内置类型_Bool,如果你包含<stdbool.h>,还有boolfalsetrue
  • 你为什么要编辑你的问题?您应该保持原样,以便其他人可以使用您得到的答案。
  • 在编辑时投了反对票,并为其他人删除了它。可能需要一个模组来回滚

标签: c loops while-loop switch-statement infinite-loop


【解决方案1】:

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循环的位置,所以我只是将“退出”改为“退出”的否定。
  • 使用 int 作为布尔值,这很常见,但我绝对更喜欢 stdbool 风格。 whileif 等等都采用布尔表达式,而给它们一个数字在逻辑上并不正确。 quit 不是数字,而是条件。
【解决方案2】:

您也可以在 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 仍然 没有它。但你是对的,我不应该说没有布尔类型。让我们希望他没有被微软困住。
  • Visual Studio 2012 没有 C 编译器。为了反对任何“但有一个'编译为 C 代码'选项”的论点:在过去十年中编写的完全有效的 C 代码无法使用 VS 编译的情况并不少见。如果它不能编译 C 代码,那么它就不是 C 编译器。
【解决方案3】:

你永远不会退出循环。休息只会破坏你的开关。你应该替换

while(1)

其他暗示应该退出while循环的东西

【讨论】:

    【解决方案4】:

    你的 break 只离开 switch 语句,然后在

    中继续
    while(1)
    

    永远循环。

    【讨论】:

      【解决方案5】:

      C++ 可以创建布尔表达式,我知道,但在 C 中却不行。

      哦?那么0 == 0 是什么,如果不是布尔表达式呢?如果您指的是bool 类型的变量,请确保您是#include &lt;stdbool.h&gt;

      但是,当我在 switch 中编写 break 语句时,它会返回 到循环的开头并使我的程序永远运行。忽视 我使用的功能,因为它们确实有效。我只需要一些 澄清我对嵌套的处理。谢谢!

      没有。它不会回到循环的开头。从 switch 语句的末尾继续执行(紧接在 switches 右括号之后,})。在您的情况下,这在功能上与 回到循环的开头 相同。

      有几个选项可供您使用。其他人建议使用唯一变量来控制您的循环。这将是一个好主意,但他们建议使用 new 变量,尽管变量已经存在于您的逻辑中。如果您想以这种方式解决问题,请考虑:

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

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

      在这种情况下,switch 控制结构实际上并不比if/else if/else 分支链更好。如果您要使用if/else if/else 分支,您将能够更轻松地将break; 退出循环。当我希望执行流向其他情况时,我会使用switch 控制结构。

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

      【讨论】:

        【解决方案6】:

        使用 exit(0);
        无论你想离开哪里。

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

        从 while 循环中出来的其他方法可能是使用: return 声明。但这也会退出当前函数。

        适当的解决方案可能是在开关内使用goto label;,然后在while 循环外使用label: statement;

        例如:

        while(1){
          switch(x){
        
           case 0:goto label;
        
           default:break;
           }
        }
        label:
        printf("out of while loop");
        

        【讨论】:

        • 应该在 cmets 中。这是一个非常小的答案 IMO。
        • 这不是只有他想完全退出整个程序才有效吗? return 0 会不会更合适,尽管很可能仍然不正确?
        • 'return' 退出函数,'exit' 退出整个程序。
        猜你喜欢
        • 2019-12-17
        • 1970-01-01
        • 2022-01-03
        • 2013-05-17
        • 2015-12-23
        • 2013-12-20
        • 1970-01-01
        • 1970-01-01
        • 2023-03-03
        相关资源
        最近更新 更多