第 6章 循环结构程序设计
6.1 循环语句概述
6.2 for语句和 while语句
6.3 直到型循环 do-while语句
6.4 break语句与 continue语句
6.5 应用举例良好的源程序书写习惯 ──注释 (续)
[Return]
6.1 循环语句概述求 1~ 100的累计和。
思路:首先设置一个累计器 sum,其初值为 0,利用 sum += n来计算( n依次取 1,2,……,100),只要解决以下 3个问题即可:
( 1)将 n的初值置为 1;
( 2)每执行 1次,sum += n”后,n增 1;
( 3)当 n增到 101时,停止计算。此时,sum的值就是 1~ 100的累计和。
其中( 2)是重复的。由于需要经常使用这种重复计算结构(称为循环结构),C语言提供了 3条循环语句来实现,以简化、并规范循环结构程序设计。
在C语言中,可用以下语句实现循环:
( 1)用 for语句。
( 2)用 do-while语句。
( 3)用 while语句。
( 4)用 goto语句和 if语句构成循环。使用 goto语句实现求解 1~ 100累计和的程序可以如下:
main()
{ int n=1,sum=0;
loop,sum += n; n++;
if (n<=100) goto loop;
printf(“sum=%d\n”,sum);
}
其中,loop:”为语句标号(格式:标号,语句行),其命名遵循标识符命名规则。 goto语句格式,goto 标号,功能为:使系统转向标号所在的语句行执行。
注意,结构化程序设计方法,主张限制使用 goto语句。因为滥用
goto语句,将会导致程序结构无规律、可读性差。
[Return]
6.2 for语句和 while语句在 3条循环语句中,for语句最为灵活,不仅可用于循环次数已经确定的情况,也可用于循环次数虽不确定、但给出了循环继续条件的情况。
[案例 6.1] 求 1~ 100的累计和。
/*案例代码文件名,AL6_1.C*/
/*程序功能:求 1~ 100的累计和 */
main()
{ int i,sum=0; /*将累加器 sum初始化为 0*/
for(i=1; i<=100; i++) sum += i; /*实现累加 */
printf("sum=%d\n",sum);
} [程序演示 ]
[案例 6.2] 求 n的阶乘 n!( n!=1*2*……*n )。
/*案例代码文件名,AL6_2.C*/
/*程序功能:求 n! */
main()
{ int i,n;
long fact=1; /*将累乘器 fact初始化为 1*/
printf(“Input n:,); scanf(“%d”,&n);
for(i=1; i<=n; i++) fact *= i; /*实现累乘 */
printf("%d ! = %ld\n",n,fact);
} [程序演示 ]
1,for语句的一般格式
for([变量赋初值 ]; [循环继续条件 ]; [循环变量增值 ])
{ 循环体语句组; }
2,for语句的执行过程
( 1)求解“变量赋初值”表达式。
( 2)求解“循环继续条件”表达式。如果其值非 0,执行( 3);
否则,转至( 4)。
( 3)执行循环体语句组,并求解“循环变量增值”表达式,然后转向( 2)。
( 4)执行 for语句的下一条语句。
变量赋初值循环表达式循环体语句组变量增值
For语句的下一条语句
3.说明
( 1)“变量赋初值”、“循环继续条件”和“循环变量增值”部分均可缺省,甚至全部缺省,但其间的分号不能省略。
( 2)当循环体语句组仅由一条语句构成时,可以不使用复合语句形式,如上例所示。
( 3)“循环变量赋初值”表达式,既可以是给循环变量赋初值的赋值表达式,也可以是与此无关的其它表达式(如逗号表达式)。
例如,for(sum=0;i<=100;i++) sum += i;
for(sum=0,i=1;i<=100;i++) sum += i;
( 4)“循环继续条件”部分是一个逻辑量,除一般的关系(或逻辑)表达式外,也允许是数值(或字符)
表达式。
4,while语句
( 1)一般格式
while(循环继续条件 )
{ 循环体语句组; }
( 2)执行过程
1)求解“循环继续条件”表达式。如果其值为非 0,转 2);否则转 3)。
2)执行循环体语句组,然后转
1)。
3)执行 while语句的下一条。
显然,while循环是 for循环的一种简化形式(缺省“变量赋初值”
和“循环变量增值”表达式)。
循环条件表达式循环体语句组
While的下一条语句
Y
N
[案例 6.3] 用 while语句求 1~ 100的累计和。
/*案例代码文件名,AL6_3.C*/
/*程序功能:求 1~ 100的累计和 */
main()
{ int i=1,sum=0; /*初始化循环控制变量 i和累计器
sum*/
while( i<=100 )
{ sum += i; /*实现累加 */
i++; /*循环控制变量 i增 1*/
}
printf(“sum=%d\n”,sum);
} [程序演示 ]
6.3 直到型循环 do-while语句
1.一般格式
do
{ 循环体语句组 ; }
while(循环继续条件 ); /*本行的分号不能缺省 */
当循环体语句组仅由一条语句构成时,可以不使用复合语句形式。
2.执行过程
( 1)执行循环体语句组。
( 2)计算“循环继续条件”表达式。如果“循环继续条件”表达式的值为非 0(真),则转向( 1)继续执行;否则,转向( 3)。
( 3)执行 do-while的下一条语句。
do-while循环语句的特点是:先执行循环体语句组,然后再判断循环条件。
[案例 6.4] 用 do-while语句求解 1~ 100的累计和。
main()
{ int i=1,sum=0; /*定义并初始化循环控制变量,以及累计器 */
do
{ sum += i; /*累加 */
i++;
}
while(i<=100); /*循环继续条件,i<=100*/
printf(“sum=%d \n”,sum);
} [程序演示 ]
do-while语句比较适用于处理:不论条件是否成立,
先执行 1次循环体语句组的情况。除此之外,do-while语句能实现的,for语句也能实现,而且更简洁。
[Return]
3.循环嵌套
( 1)循环语句的循环体内,又包含另一个完整的循环结构,
称为循环的嵌套。循环嵌套的概念,对所有高级语言都是一样的。
( 2) for语句和 while语句允许嵌套,do-while语句也不例外。
While( ) do for(;;)
{┆ {┆ {┆
while( ) do while( );
{┆ } {…} { }
} while( );} ┆
while( ); }
For(;;) while( ) do
{ {┆ {
for(;;) do ┆
{┆ } {…} for(;;)
} while( ); { }
┆ }
} while( );
打印下列图案
*
* * *
* * * * *
* * * * * * *
* * * * *
* * *
*
main()
{int i,j,k;
for (i=0;i<=3;i++)
{for (j=0;j<=2-i;j++)
print(" ");
for(k=0;k<=2*i;k++)
printf("*");
printf("\n");
}
for(i-=0;i<=2;i++)
{for(j=0;j<=i;j++)
printf(" ");
For(k=0;k<=4-2*i;k++)
printf("*");
printf("\n");
}
}
}
6.4 break语句与 continue语句为了使循环控制更加灵活,C语言提供了 break语句和 continue语句。
1.一般格式,break;
continue;
2.功能
( 1) break:强行结束循环,转向执行循环语句的下一条语句。
( 2) continue:对于 for循环,跳过循环体其余语句,转向循环变量增量表达式的计算;对于 while和 do-while循环,跳过循环体其余语句,
但转向循环继续条件的判定。
3,break和 continue语句对循环控制的影响
4.说明
( 1) break能用于循环语句和 switch语句中,continue只能用于循环语句中。
( 2)循环嵌套时,break和 continue只影响包含它们的最内层循环,
与外层循环无关。
[Return]
6.5 应用举例
[例 6.5] 求 Fibonacci数列的前 40个数。该数列的生成方法为,F1=1,
F2=1,Fn=Fn-1+Fn-2( n>=3),即从第 3个数开始,每个数等于前 2个数之和。
算法设计,请参见第 2章第 1节( 2.1)。参考源程序如下:
/*案例代码文件名,AL5_5.C*/
main()
{ long int f1=1,f2=1; /*定义并初始化数列的头 2个数 */
int i=1; /*定义并初始化循环控制变量 i*/
for( ; i<=20; i++ ) /*1组 2个,20组 40个数 */
{ printf(“%15ld%15ld”,f1,f2); /*输出当前的 2个数 */
if(i%2==0) printf(“\n”); /*输出 2次( 4个数),换行 */
f1 += f2; f2 += f1; /*计算下 2个数 */
}
} [程序演示 ]
[例 6.6] 输出 10~ 100之间的全部素数。所谓素数 n是指,除 1和 n之外,不能被 2~( n-1)之间的任何整数整除。
算法设计要点:
( 1)显然,只要设计出判断某数 n是否是素数的算法,外面再套一个 for循环即可。
( 2)判断某数 n是否是素数的算法:根据素数的定义,用 2~
( n-1)之间的每一个数去整除 n,如果都不能被整除,则表示该数是一个素数。
判断一个数是否能被另一个数整除,可通过判断它们整除的余数是否为 0来实现。
参考源程序如下:
main()
{ int i=11,j,counter=0;
for( ; i<=100; i+=2) /*外循环:为内循环提供一个整数 i*/
{ for(j=2; j<=i-1; j++) /*内循环:判断整数 i是否是素数 */
if(i%j= =0) /*i不是素数 */
break; /*强行结束内循环,执行下面的 if语句 */
if(counter%10= =0) /*每输出 10个数换一行 */
printf(“\n”);
if( j >= i ) /*整数 i是素数:输出,计数器加 1*/
{ printf(“%6d”,i);
counter++;
}
}
}
思考题,外循环控制变量 i的初值从 11开始、增量为 2的作法有什么好处?为提高运行速度,如何优化内循环?(提示:从减少计算次数角度来考虑)
return
良好的源程序书写习惯 ──注释(续)
( 3)循环结构在 C语言中,循环结构由循环语句 for,while和
do...while来实现。
作为注释,应在它们的前面说明其功能,在循环条件判断语句行的后面,说明循环继续条件的含义,如下所示。
1) for语句
/*功能 */
for(变量初始化 ;循环条件 ;变量增值 ) /*循环继续条件的含义 */
{ …… }
2) while语句
/*功能说明 */
while(循环条件 ) /*循环继续条件的含义 */
{ …… }
3) do...while语句
/*功能说明 */
do { …… }
while(循环条件 ); /*循环继续条件的含义 */
如果循环嵌套,还应说明每层循环各控制什么。
[Return]
作业
P120
6.2,6.3,6.4,6.8,6.10
6.1 循环语句概述
6.2 for语句和 while语句
6.3 直到型循环 do-while语句
6.4 break语句与 continue语句
6.5 应用举例良好的源程序书写习惯 ──注释 (续)
[Return]
6.1 循环语句概述求 1~ 100的累计和。
思路:首先设置一个累计器 sum,其初值为 0,利用 sum += n来计算( n依次取 1,2,……,100),只要解决以下 3个问题即可:
( 1)将 n的初值置为 1;
( 2)每执行 1次,sum += n”后,n增 1;
( 3)当 n增到 101时,停止计算。此时,sum的值就是 1~ 100的累计和。
其中( 2)是重复的。由于需要经常使用这种重复计算结构(称为循环结构),C语言提供了 3条循环语句来实现,以简化、并规范循环结构程序设计。
在C语言中,可用以下语句实现循环:
( 1)用 for语句。
( 2)用 do-while语句。
( 3)用 while语句。
( 4)用 goto语句和 if语句构成循环。使用 goto语句实现求解 1~ 100累计和的程序可以如下:
main()
{ int n=1,sum=0;
loop,sum += n; n++;
if (n<=100) goto loop;
printf(“sum=%d\n”,sum);
}
其中,loop:”为语句标号(格式:标号,语句行),其命名遵循标识符命名规则。 goto语句格式,goto 标号,功能为:使系统转向标号所在的语句行执行。
注意,结构化程序设计方法,主张限制使用 goto语句。因为滥用
goto语句,将会导致程序结构无规律、可读性差。
[Return]
6.2 for语句和 while语句在 3条循环语句中,for语句最为灵活,不仅可用于循环次数已经确定的情况,也可用于循环次数虽不确定、但给出了循环继续条件的情况。
[案例 6.1] 求 1~ 100的累计和。
/*案例代码文件名,AL6_1.C*/
/*程序功能:求 1~ 100的累计和 */
main()
{ int i,sum=0; /*将累加器 sum初始化为 0*/
for(i=1; i<=100; i++) sum += i; /*实现累加 */
printf("sum=%d\n",sum);
} [程序演示 ]
[案例 6.2] 求 n的阶乘 n!( n!=1*2*……*n )。
/*案例代码文件名,AL6_2.C*/
/*程序功能:求 n! */
main()
{ int i,n;
long fact=1; /*将累乘器 fact初始化为 1*/
printf(“Input n:,); scanf(“%d”,&n);
for(i=1; i<=n; i++) fact *= i; /*实现累乘 */
printf("%d ! = %ld\n",n,fact);
} [程序演示 ]
1,for语句的一般格式
for([变量赋初值 ]; [循环继续条件 ]; [循环变量增值 ])
{ 循环体语句组; }
2,for语句的执行过程
( 1)求解“变量赋初值”表达式。
( 2)求解“循环继续条件”表达式。如果其值非 0,执行( 3);
否则,转至( 4)。
( 3)执行循环体语句组,并求解“循环变量增值”表达式,然后转向( 2)。
( 4)执行 for语句的下一条语句。
变量赋初值循环表达式循环体语句组变量增值
For语句的下一条语句
3.说明
( 1)“变量赋初值”、“循环继续条件”和“循环变量增值”部分均可缺省,甚至全部缺省,但其间的分号不能省略。
( 2)当循环体语句组仅由一条语句构成时,可以不使用复合语句形式,如上例所示。
( 3)“循环变量赋初值”表达式,既可以是给循环变量赋初值的赋值表达式,也可以是与此无关的其它表达式(如逗号表达式)。
例如,for(sum=0;i<=100;i++) sum += i;
for(sum=0,i=1;i<=100;i++) sum += i;
( 4)“循环继续条件”部分是一个逻辑量,除一般的关系(或逻辑)表达式外,也允许是数值(或字符)
表达式。
4,while语句
( 1)一般格式
while(循环继续条件 )
{ 循环体语句组; }
( 2)执行过程
1)求解“循环继续条件”表达式。如果其值为非 0,转 2);否则转 3)。
2)执行循环体语句组,然后转
1)。
3)执行 while语句的下一条。
显然,while循环是 for循环的一种简化形式(缺省“变量赋初值”
和“循环变量增值”表达式)。
循环条件表达式循环体语句组
While的下一条语句
Y
N
[案例 6.3] 用 while语句求 1~ 100的累计和。
/*案例代码文件名,AL6_3.C*/
/*程序功能:求 1~ 100的累计和 */
main()
{ int i=1,sum=0; /*初始化循环控制变量 i和累计器
sum*/
while( i<=100 )
{ sum += i; /*实现累加 */
i++; /*循环控制变量 i增 1*/
}
printf(“sum=%d\n”,sum);
} [程序演示 ]
6.3 直到型循环 do-while语句
1.一般格式
do
{ 循环体语句组 ; }
while(循环继续条件 ); /*本行的分号不能缺省 */
当循环体语句组仅由一条语句构成时,可以不使用复合语句形式。
2.执行过程
( 1)执行循环体语句组。
( 2)计算“循环继续条件”表达式。如果“循环继续条件”表达式的值为非 0(真),则转向( 1)继续执行;否则,转向( 3)。
( 3)执行 do-while的下一条语句。
do-while循环语句的特点是:先执行循环体语句组,然后再判断循环条件。
[案例 6.4] 用 do-while语句求解 1~ 100的累计和。
main()
{ int i=1,sum=0; /*定义并初始化循环控制变量,以及累计器 */
do
{ sum += i; /*累加 */
i++;
}
while(i<=100); /*循环继续条件,i<=100*/
printf(“sum=%d \n”,sum);
} [程序演示 ]
do-while语句比较适用于处理:不论条件是否成立,
先执行 1次循环体语句组的情况。除此之外,do-while语句能实现的,for语句也能实现,而且更简洁。
[Return]
3.循环嵌套
( 1)循环语句的循环体内,又包含另一个完整的循环结构,
称为循环的嵌套。循环嵌套的概念,对所有高级语言都是一样的。
( 2) for语句和 while语句允许嵌套,do-while语句也不例外。
While( ) do for(;;)
{┆ {┆ {┆
while( ) do while( );
{┆ } {…} { }
} while( );} ┆
while( ); }
For(;;) while( ) do
{ {┆ {
for(;;) do ┆
{┆ } {…} for(;;)
} while( ); { }
┆ }
} while( );
打印下列图案
*
* * *
* * * * *
* * * * * * *
* * * * *
* * *
*
main()
{int i,j,k;
for (i=0;i<=3;i++)
{for (j=0;j<=2-i;j++)
print(" ");
for(k=0;k<=2*i;k++)
printf("*");
printf("\n");
}
for(i-=0;i<=2;i++)
{for(j=0;j<=i;j++)
printf(" ");
For(k=0;k<=4-2*i;k++)
printf("*");
printf("\n");
}
}
}
6.4 break语句与 continue语句为了使循环控制更加灵活,C语言提供了 break语句和 continue语句。
1.一般格式,break;
continue;
2.功能
( 1) break:强行结束循环,转向执行循环语句的下一条语句。
( 2) continue:对于 for循环,跳过循环体其余语句,转向循环变量增量表达式的计算;对于 while和 do-while循环,跳过循环体其余语句,
但转向循环继续条件的判定。
3,break和 continue语句对循环控制的影响
4.说明
( 1) break能用于循环语句和 switch语句中,continue只能用于循环语句中。
( 2)循环嵌套时,break和 continue只影响包含它们的最内层循环,
与外层循环无关。
[Return]
6.5 应用举例
[例 6.5] 求 Fibonacci数列的前 40个数。该数列的生成方法为,F1=1,
F2=1,Fn=Fn-1+Fn-2( n>=3),即从第 3个数开始,每个数等于前 2个数之和。
算法设计,请参见第 2章第 1节( 2.1)。参考源程序如下:
/*案例代码文件名,AL5_5.C*/
main()
{ long int f1=1,f2=1; /*定义并初始化数列的头 2个数 */
int i=1; /*定义并初始化循环控制变量 i*/
for( ; i<=20; i++ ) /*1组 2个,20组 40个数 */
{ printf(“%15ld%15ld”,f1,f2); /*输出当前的 2个数 */
if(i%2==0) printf(“\n”); /*输出 2次( 4个数),换行 */
f1 += f2; f2 += f1; /*计算下 2个数 */
}
} [程序演示 ]
[例 6.6] 输出 10~ 100之间的全部素数。所谓素数 n是指,除 1和 n之外,不能被 2~( n-1)之间的任何整数整除。
算法设计要点:
( 1)显然,只要设计出判断某数 n是否是素数的算法,外面再套一个 for循环即可。
( 2)判断某数 n是否是素数的算法:根据素数的定义,用 2~
( n-1)之间的每一个数去整除 n,如果都不能被整除,则表示该数是一个素数。
判断一个数是否能被另一个数整除,可通过判断它们整除的余数是否为 0来实现。
参考源程序如下:
main()
{ int i=11,j,counter=0;
for( ; i<=100; i+=2) /*外循环:为内循环提供一个整数 i*/
{ for(j=2; j<=i-1; j++) /*内循环:判断整数 i是否是素数 */
if(i%j= =0) /*i不是素数 */
break; /*强行结束内循环,执行下面的 if语句 */
if(counter%10= =0) /*每输出 10个数换一行 */
printf(“\n”);
if( j >= i ) /*整数 i是素数:输出,计数器加 1*/
{ printf(“%6d”,i);
counter++;
}
}
}
思考题,外循环控制变量 i的初值从 11开始、增量为 2的作法有什么好处?为提高运行速度,如何优化内循环?(提示:从减少计算次数角度来考虑)
return
良好的源程序书写习惯 ──注释(续)
( 3)循环结构在 C语言中,循环结构由循环语句 for,while和
do...while来实现。
作为注释,应在它们的前面说明其功能,在循环条件判断语句行的后面,说明循环继续条件的含义,如下所示。
1) for语句
/*功能 */
for(变量初始化 ;循环条件 ;变量增值 ) /*循环继续条件的含义 */
{ …… }
2) while语句
/*功能说明 */
while(循环条件 ) /*循环继续条件的含义 */
{ …… }
3) do...while语句
/*功能说明 */
do { …… }
while(循环条件 ); /*循环继续条件的含义 */
如果循环嵌套,还应说明每层循环各控制什么。
[Return]
作业
P120
6.2,6.3,6.4,6.8,6.10