嵌套循环的控制变量——Ada应用实例之十三
以下是解答HDU ACM 2019(判断“回文串”)的一个C程序:
(引自http://zhidao.baidu.com/question/217863132.html)
#include<stdio.h>
#include<string.h>
int main()
{
int n,i,k;
char a[1000];
while(scanf("%d",&n)!=EOF)
{
getchar();
for(i=0;i<n;i++)
{
gets(a);
k=strlen(a);
for(i=0;i<k;i++)
{
if(a[i]!=a[k-i-1])
break;
}
if(i==k)
printf("yes/n");
if(i!=k)
printf("no/n");
}
}
return 0;
}
作者发现一个奇怪现象,当输入是:
4
hahah
haha
程序给出的输出是:
yes
yes
显然第2个输出是错的。原因是程序中2个嵌套的循环:
for(i=0;i<n;i++)
for(i=0;i<k;i++)
使用了同一个变量i来控制循环。以下分析出错过程:
a) 处理第1个输入“hahah”,内层循环“for(i=0;i<k;i++)”结束后i的值是5;
b) 执行外层循环“for(i=0;i<n;i++)”的判断条件“i<n”,结果为假,退出循环;
c) 执行“while(scanf("%d",&n)!=EOF)”,由于此时输入是“haha”,未能读入;
d) 执行“getchar()”,读入‘h’;
e) 执行gets(a),读入“aha”,这是回文串,所以输出“yes”。
变量i是在main中声明的,因此它的作用域包含2个嵌套的循环。如果在外层循环与内层循环之间再声明一个变量i,就可以避免混淆问题:
for(i=0;i<n;i++)
{
int i;
不过还是把外层循环改用另一个循环变量(例如,j),程序的可读性较好。
如果用Ada编写这个程序,就不会出现混淆问题。Ada的for循环的控制变量有如下特点:
a) 它是隐含声明的;
b) 它的作用域限于该循环体;
c) 出了该循环体它就不存在了;
d) 编程者不能对它修改;
e) 它的值域是离散的。
以下例子中2个循环控制变量i虽然同名,但有各自的作用域:
with Text_IO; use Text_IO;
procedure main is
begin
for i in 1 .. 2
loop
put_line ("External i = " & Integer'Image (i));
for i in 1 .. 2
loop
put_line ("Inner i = " & Integer'Image (i));
end loop;
end loop;
end main;
该程序输出:
External i = 1
Inner i = 1
Inner i = 2
External i = 2
Inner i = 1
Inner i = 2