c语言入门13,突破重重包围,超强跳转语句指哪去哪,goto语句介绍
发表于: 2018-11-12 08:04:26 | 已被阅读: 44 | 分类于: C语言
在第10节和第11节,我们介绍了 C 语言中的循环语句。上一节还介绍了初学者拿到实际问题,逐步解决问题,写出代码的思路。那作为练习和巩固,来考虑一下这个问题:
利用 C 语言编程,在终端打印出 100 以内的素数。(素数是只能被 1 和他本身整除的数。)
n 从 1 遍历到 100{
m 从 2 遍历到 n-1{
如果 n%m 等于 0
break;
}
如果 m == n
n 是素数
否则
n 不是素数
}
总体逻辑还是比较简单的,如果 n 不是素数,那么在 n-1 之前,总有一个 m 使得 n除以m 的余数为 0, m 的遍历在到达 n-1 之前就结束了。如果从 2 到 n-1 都没有一个 m 可以使 n除以m 等于0,则里面那个遍历结束后,m 应该是等于 n 的。所以最后只需要判断 m 是否等于 n 就可以判断 n 是不是素数了。
好了,思路理清了,可以写代码了:
#include <stdio.h>
int main(void)
{
int i, j;
for (i = 1; i <= 100; i++) {
for (j = 2; j < i; j++)
if (i % j == 0)
break;
if (j == i)
printf("%d\n", i);
}
return 0;
}
#include <stdio.h>
int main(void)
{
int i, j;
for (i=1; i<=9; i++) {
for (j=1; j<=9; j++)
printf("%d\t", i*j);
printf("\n");
}
return 0;
}
内循环每次打印一个数,数与数之间用 Tab(制表符)隔开,外循环每次打印一行。结果如下:
条件变量=0;
for(...){
for(...){
for(...){
...
if(错误){
条件变量 = 1;
break;
}
}
if(条件变量==1)
break;
}
if(条件变量==1)
break;
}
if(条件变量==1){
错误处理;
return 出错了;
}
return 正常;
可以看出,整个代码有很多重复代码,非常臃肿。
好在,C 语言提供了 goto 语句,能够实现无条件跳转
使用 goto 语句来写上述错误处理代码就简洁多了:
for(...){
for(...){
for(...){
...
if(错误){
goto error;
}
}
}
}
return 正常;
error:
错误处理;
return 出错了;
甚至连条件变量都不用了。如果程序正常,执行到 “return 正常;”语句,直接就返回了。如果程序出错,那就会直接跳转到 error 处,执行错误处理语句,再返回 “出错了”。这里的 error: 叫做标号,给标号起名字也遵循标识符的命名规则。事实上我们在“switch语句”一节学过的 case和 default 后面也是跟一个冒号,在语法结构中也起标号的作用。
goto 语句过于强大了,从程序中的任何地方都可以无条件跳转到任何其它地方,只要给那个地方起个标号就行,唯一的限制是 goto 只能跳到同一个函数的某个标号处,而不能跳到别的函数里。所以,滥用 goto 语句会使程序的控制流程非常复杂,可读性很差。
著名的计算机科学家Edsger W. Dijkstra最早指出编程语言中 goto 语句的危害,提倡取消 goto 语句。因为 goto 语句不是必须的,goto 语句能解决的问题,也能用其他手段解决,上面我们给出了例子。不过 goto 语句说到底只是工具,本身并没有危害,危害都是程序员滥用造成的。通常 goto 语句只用于在函数末尾做出错处理(例如释放先前分配的资源、恢复先前改动过的全局变量等),比较上面两种写法,用 goto 语句还是方便很多。但是除了这个用途之外,在任何场合都不要轻易考虑使用 goto 语句。
事实上,linux 内核有大量使用 goto 语句做错误处理的代码。