如何解决如何使用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;
}
您只能省略单个语句的花括号。
但是我强烈建议您不要像这样使用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
:
-
打破嵌套循环
-
在失败时清理函数中分配的资源
打破嵌套循环的示例:
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;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。