goto vs返回C编程中的子菜单和菜单

时间:2013-08-19 09:47:55

标签: c goto

我有一个非常快速的问题。 哪个更“标准”使用? 转到或返回一个函数?

转到示例:

main(){
   start:
   //some code
   goto start;
}

main(){
   //some code
   return main();
}

两者都会循环播放脚本。 但我想知道哪一个更适合使用。

goto似乎非常好,但使用它有什么缺点吗? (我只是想知道,因为一名教练因为goto功能O.o失败了同学,我想知道为什么,或者他做了什么是合理的。)

如果您问为什么要问这个,我正在尝试创建一个带子菜单的菜单,其中子菜单包含“后退”选项(我要么使用goto还是返回)

5 个答案:

答案 0 :(得分:10)

这里合理的做法是使用循环。它具有与goto相同的效果,但被认为是更好的做法,因为它遵循structured programming的规则,而不是以前常见的不可维护的汤面编程。

int main(void) {
   while (1) {
      //some code
   }
}

如果递归具有明确定义的限制,则递归调用函数也可以被认为是好的样式。 C中的无限递归通常会导致堆栈溢出错误,因为很少有编译器实现尾调用优化。

答案 1 :(得分:3)

应该避免

goto。使用它实际上被认为是一种不好的做法,因为它使代码更难以阅读和理解。

我不确定return main();是否正确,在我看来这是非常丑陋而且不安全。

执行无限循环的更好解决方案是使用while(1)for(;;)

答案 2 :(得分:1)

考虑到你需要这个,循环和函数将起到作用:

void submenu(void)
{
    for (;;)
    {
        printf("a: Do something else\n");
        printf("b: Leave sub menu\n");

        char choice;
        scanf(" %c", &choice);
        if (choice == 'a')
            do_something_else();
        else if (choice == 'b')
            break;  /* Break out of loop */
        else
            printf("Invalid choice.\n");
    }

    /* When this function returns, you get back to the main menu */
}

void mainmenu(void)
{
    int goon = 1;

    while (goon)
    {
        printf("1: Do something\n");
        printf("2: Enter sub-menu\n");
        printf("3: Exit\n");

        char choice;
        scanf(" %c", &choice);

        switch (choice)
        {
        case '1':
            do_something();
            break;

        case '2':
            /* Enter the sub-menu */
            submenu();
            break;

        case '3':
            goon = 0;  /* This will cause the loop to end */
            break;

        default:
            printf("Invalid choice.\n");
            break;
        }
    }
}

int main(int, char **)
{
    mainmenu();
    return 0;
}

答案 3 :(得分:0)

如果你有深度nestes循环,那么你应该使用goto,例如,使用break很难返回。 在return中使用main时,您将结束主函数并将控制权返回给操作系统。

你的goto - 实现正在引发无限循环,远远没有完成与返回相同的事情。此外,您不应直接或间接致电main()

使用

实现无限循环
for(;;)

while(1)

这些更为常见,但如果您未在循环中的任何位置明确调用break,则您的程序将永远不会结束。

答案 4 :(得分:0)

return main()可能是一个坏主意,因为您不能保证编译器会优化额外的堆栈帧。如果编译器没有这样做,那么你的堆栈将在循环的每次迭代中继续增长。

它会重新初始化你的局部变量,但你可以通过将这些变量放在循环结构中来获得相同的效果。

goto可能在某些代码中占有一席之地,但事实并非如此。如果你想循环,那么有循环结构。请改用for (;;) { /* some code */ }