如何使用 goto 而不出现此错误? [已关闭]

问题描述 投票:0回答:3
#include <stdio.h>

int main()
{
    repeat:
    printf("choose an option: \n1:Draw\n2:Even or Odd:\n3:Text type\n4:How to Dec\n5:Base to Dec:\n6:Count to Bits\n0:Exit\n"); 
    int x;
    scanf("%d", &x); 
    if (x > 6)
       printf("Wrong option!\n");
       goto repeat;
    if (x == 1) 
       printf("Drawing");
    if (x == 0)
       printf("we are out!\n");
    return 0;
}

我正在使用在线编译器。

我想看到的最终结果是一个简单的菜单,要求用户输入数字并根据数字执行代码,然后转到起点并再次打印菜单。 (这就是我选择 goto 的原因。如果您有其他在执行后重新启动主程序的解决方案,请告诉我。)

我遇到的问题是,无论我输入多少数字,它都会再次输出菜单,没有消息或不退出(当我输入0时)。

c loops if-statement goto labeled-statements
3个回答
6
投票

C 不依赖于缩进。改变一下就好了

if (x > 6)
       printf("Wrong option!\n");
       goto repeat;

if (x > 6) {
       printf("Wrong option!\n");
       goto repeat;
}

您只能省略单个语句的大括号。

但我强烈建议不要像这样使用

goto
goto
有它的用途,但这不是其中之一。你可以像这样重写你的代码:

int main()
{
    while(1) {
        printf("choose an option: \n1:Draw\n2:Even or Odd:\n3:Text type\n4:How to Dec\n5:Base to Dec:\n6:Count to Bits\n0:Exit\n"); 
        int x;
        scanf("%d", &x); 
        if (x > 6) {
           printf("Wrong option!\n");
        }

        if (x == 1) {
           printf("Drawing");
           break;
        }
        if (x == 0) {
           printf("we are out!\n");
           break;
        }
    }
}

我不会这么写的。我改为 while 循环,并进行尽可能少的更改。我会做这样的事情:

int x = 6;
while(x == 6) {
    printf("choose an option: \n1:Draw\n2:Even or Odd:\n3:Text type\n4:How to Dec\n5:Base to Dec:\n6:Count to Bits\n0:Exit\n"); 

    // Always check scanf for errors
    if(scanf("%d", &x) != 1) { perror("Input error"); exit(1); }

    switch(x) {
        case 1: printf("Drawing"); break;
        case 0: printf("we are out!\n"); break;
        default: printf("Wrong option!\n");
    }
}

只有两种情况我会考虑使用

goto

  1. 打破嵌套循环

  2. 在函数失败时清理分配的资源

跳出嵌套循环的示例:

while(1) {
    while(1) {
        if(<condition>) goto END;
    }
}
END:

清理示例:

void foo() {
    char *p = malloc(1);
    if(!p) goto END;
    char *q = malloc(1);
    if(!q) goto P;

    // Do stuff

    free(q);
P:
    free(p);
END:
}

请注意,清理示例不是很好,因为您可以安全地释放 NULL 指针,该指针在失败时会返回。带有

malloc
的示例会更合适。但它展示了一般原则。您以相反的顺序进行清理并在失败时跳转到适当的位置。
无论你做什么,永远不要用 goto 向后跳。只能向前跳跃。或者至少我从未见过会激发向后跳跃的情况。

在支持异常的语言中,您通常会在这两种情况下使用异常。第一个例子是这样的伪:

fopen



2
投票
try { while(1) { while(1) { if(<condition>) throw MyException; } } } catch MyException {}

总是被执行,因为它不依赖于条件,它超出了它的范围。

在 C 中,唯一依赖于条件的语句是下一行中的语句,要拥有多个语句,您需要使用 

goto

来增加 codition 范围以包含应该依赖于它的语句,

i.e.
{}

如果您有其他在执行后重新启动主程序的解决方案,请告诉我

达到相同结果的可能性有很多。我会选择使用
if(...){ statement; statement; }

循环的简单而优雅的解决方案:

do-while



1
投票

int main() { int x = 0; //initialize the control variable to avoid problems in case of bad input do { printf("choose an option: \n1:Draw\n2:Even or Odd:\n3:Text type\n4:How to Dec\n5:Base to Dec:\n6:Count to Bits\n0:Exit\n"); } while (scanf("%d", &x) && x > 6 && printf("Wrong option!\n")); //including scanf in the condition has the advantage of also checking its return value if (x == 1) printf("Drawing"); if (x == 0) printf("we are out!\n"); return 0; }

并不意味着带goto的语句是if语句的子语句。其实你有

if (x > 6) printf("Wrong option!\n"); goto repeat;

因此 goto 语句在任何情况下都能获得控制权。

使用 goto 语句是一个坏主意。例如,按以下方式使用 do-while 语句和 switch 语句会更好

if (x > 6) { printf("Wrong option!\n"); } goto repeat;

您还可以引入一个枚举,其枚举器常量将在 case 标签中使用。

例如

#include <stdio.h> int main() { int x = 0; do { printf("choose an option: \n1:Draw\n2:Even or Odd:\n3:Text type\n4:How to Dec\n5:Base to Dec:\n6:Count to Bits\n0:Exit\n"); scanf("%d", &x); switch( x ) { case 0: printf("we are out!\n"); break; case 1: printf("Drawing"); break; default: printf("Wrong option!\n"); break; } } while ( x != 0 ); return 0; }

© www.soinside.com 2019 - 2024. All rights reserved.