如何在不出现此错误的情况下使用 goto?
How to use goto without getting this error?
#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
returns 失败。 fopen
的例子会更合适。但它证明了一般原则。您以相反的顺序进行清理并在失败的情况下跳转到适当的位置。
无论你做什么,都不要使用 goto 向后跳转。只能向前跳。或者至少我从未见过会激发向后跳跃的情况。
在支持异常的语言中,您通常会为这两种情况使用异常。第一个例子是这样的伪:
try {
while(1) {
while(1) {
if(<condition>) throw MyException;
}
}
} catch MyException {}
问题,正如评论中提到的,goto
总是被执行,因为它不依赖于条件,它超出了它的范围。
在 C 中,唯一依赖于条件的语句是下一行中的语句,要有多个语句,您需要使用 {}
来增加条件范围以包含应该依赖的语句它,即:
if(...){
statement;
statement;
}
if you have other solution that restarts the main program after an execution please tell me
实现相同结果的可能性有很多种。我会选择使用 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语句的sub-statement。其实你有
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;
}
#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
returns 失败。 fopen
的例子会更合适。但它证明了一般原则。您以相反的顺序进行清理并在失败的情况下跳转到适当的位置。
无论你做什么,都不要使用 goto 向后跳转。只能向前跳。或者至少我从未见过会激发向后跳跃的情况。
在支持异常的语言中,您通常会为这两种情况使用异常。第一个例子是这样的伪:
try {
while(1) {
while(1) {
if(<condition>) throw MyException;
}
}
} catch MyException {}
问题,正如评论中提到的,goto
总是被执行,因为它不依赖于条件,它超出了它的范围。
在 C 中,唯一依赖于条件的语句是下一行中的语句,要有多个语句,您需要使用 {}
来增加条件范围以包含应该依赖的语句它,即:
if(...){
statement;
statement;
}
if you have other solution that restarts the main program after an execution please tell me
实现相同结果的可能性有很多种。我会选择使用 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语句的sub-statement。其实你有
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;
}