目录
goto语句
早期版本的BASIC和FORTRAN所依赖的goto语句,在c中仍然可用。但是c和其他两种语言不同,没有goto语句c程序也能运行良好。Kernighan和Ritchie提到goto语句”易被滥用“,并建议”谨慎使用,或者根本不用“。首先,介绍一下如何使用goto语句;然后讲解为什么通常不需要它。
goto语句有两部分:goto和标签名。标签名的命名遵循变量命名规则,如下所示:
goto part2;
要让上面这条语句正常工作,函数还必须包含另一条标为part2的语句,该语句以标签名后紧跟一个冒号开始:
part2:printf(”refined analysis:\n”);
避免使用goto
原则上,根本不必在c程序中使用goto语句。但是,如果你曾经学过FORTRAN或BASIC(goto对这两种语言而言都必不可少),可能还会依赖用goto来编程。为了帮你克服这个习惯,我们先概述一些使用goto的常见情况,然后再介绍c的解决方案。
- 处理包含多条语句的 if 语句:
if(size > 12) goto a; goto b; a:cost = cost * 1.05; flag = 2; b: bill = cost * flag;
对于以前的BASIC和FORTRAN,只有直接跟在 if 条件后面的一条语句才属于 if 。不能使用块或复合语句。我们把以上模式转化成等价的c代码,标准c用复合语句或块来处理这种情况:
if(size > 12) { cost = cost * 1.05; flag = 2; } bill = cost * flag;
- 二选一
if(ibex > 14) goto a; sheds = 2; goto b; a:sheds = 2; b:help = 2 * sheds;
c通过 if else 表达二选一更清楚:
if(ibex > 14){ sheds = 3; }else{ sheds = 2; } help = 2 * sheds;
实际上,新版的BASIC和FORTRAN已经把 else 纳入新的语法中。
- 创建不确定循环
readin: scanf("%d",&score); if(score < 0) goto stage2; lots of statements goto readin; stage2: more stuff;
c用while循环代替:
scandf("%d",&score); while(score >= 0) { lots of statements scanf("%d",&score); } more stuff;
- 跳转至循环末尾,并开始下一轮跌送。c使用continue语句代替。
- 跳出循环。c使用break语句。实际上,break和continue是goto语句的特殊形式。使用break和countin的好处是:其名称已经表明它们的用法,而且这些语句不使用标签,所以不用担心把标签放错位置导致危险。
- 胡乱跳转至程序的不同部分。简而言之,不要这样做!
但是,c程序员可以接受一种goto的用法——从一组嵌套循环中跳出(一条break语句只能跳出当前循环):
while(funct > 0) { for(i = 1; i <= 100; i++) { for(j = 1; j <= 50; j++) { 其他语句 if(问题) goto help; 其他语句 } 其他语句 } 其他语句 } 其他语句 help: 语句
从其他例子中也能看出,程序中使用其他形式比使用goto的条理更清晰。当多种情况混在一起时,这种差异更加明显。哪些goto语句可以帮助 if 语句?哪些可以模仿 if else ?哪些控制循环?哪些是因为程序无路可走才不得已放在那里?过度的使用goto语句,会让程序错综复杂。如果不熟悉goto语句,就不要使用它。如果已经习惯使用goto语句,试着改掉这个毛病。讽刺地是,虽然c根本不需要goto,但是它的goto比其他语言的goto好用,因为c允许在标签中使用描述性的单词而不是数字。
小结:
goto语句使程序控制跳转至相应标签语句。冒号用于分隔标签和标签语句。标签名遵循变量命名规则。标签语句可以出现在goto语句的前面或者后面。
形式:
goto label ;
.
.
label : statement
示例:
top : ch = getchar();
.
.
if (ch != 'y')
goto top;