如何使用goto而不出现此错误?

问题描述

#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不依赖于缩进。只是改变

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

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

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

但是我强烈建议您不要像这样使用gotogoto有它的用途,但这不是其中之一。您可以这样重写代码:

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将在失败时返回。使用fopen的示例更为合适。但这说明了一般原则。您以相反的顺序进行清理,并在失败的情况下跳转到相应的位置。

无论您做什么,都不要使用goto向后跳。只向前跳。或者至少我从未见过会引起向后跳动的情况。

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

try {
    while(1) {
        while(1) {
            if(<condition>) throw MyException;
        }
    }
} catch MyException {}
,

正如评论中提到的那样,问题是goto总是被执行,因为它不依赖于条件,超出了范围。

在C语言中,唯一依赖于条件的语句是下一行,要使用多个语句,您需要使用{}来扩大编码范围,以包围应该依赖于该条件的语句,

if(...){ 
   statement; 
   statement;
}

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

有许多可能性可以达到相同的结果。我会选择使用do-while循环的简单而优雅的解决方案:

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

语句的这种格式

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

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

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

因此在任何情况下goto语句都会获得控件。

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

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

您还可以引入枚举,其枚举常量将用于案例标签中。

例如

#include <stdio.h>

int main()
{
    enum { Exit = 0,Draw = 1,EvenOrOdd = 2,Text = 3,/* other constants */ };  
    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 Exit:
           printf("we are out!\n");
           break;
        case Draw: 
           printf("Drawing");
           break;
        default:
            printf("Wrong option!\n");
            break;
        }
    } while ( x != Exit );

    return 0;
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...