第5章  循环结构程序设计
第一单元  基础知识
一、知识点梳理
内    容
描    述
备    注
for语句
for(表达式1; 表达式2; 表达式3)
{
	循环体语句
}
适合循环次数已知、计数控制的  循环
while语句
while(循环表达式)
{
	循环体语句
}
当型循环结构,适合循环次数未知、条件控制的循环。循环体中通常包含改变循环表达式的语句
do-while语句
do
{
	循环体语句
} while(循环表达式)
直到型循环结构,循环至少执行一次,适合循环次数未知、条件控制的循环。循环体中通常包含改变循环表达式的语句
break语句
用于退出switch或一层循环结构

continue语句
用于结束本次循环,继续执行下一次循环

  
二、基础题
  1.以下程序段    。
  
     x=-1;
     do
     { x=x*x; }
     while (!x);
  
       A)是死循环		B)循环执行两次		C)循环执行一次		D)有语法错误
  2.以下不是无限循环的语句是    。
       A)for(y=0,x=1;x>y;y++) i=x;			B)for(; ;x++);
       C)while(1) {x++;}						D)for(i=10; ;i--) sum=sum+i;
  3.下面程序段的运行结果是    。
  
     for(i=1;i<=5;)
       printf("%d",i);
       i++;
  
       A)12345			B)1234				C)15				D)无限循环
  4.以下程序段的运行结果是    。
  
     int a,y;
     a=10;y=0;
     do
     {  a+=2; y+=a;
        printf("a=%d y=%d\n",a,y);
        if (y>20) break;
     }while(a=14);
  
       A)a=12 y=12		B)a=12 y=12		C)a=12 y=12		D)a=12 y=12
           a=14 y=16        a=16 y=28           a=14 y=26           a=14 y=44
           a=16 y=20                                                    
           a=18 y=24
  5.在执行以下程序时,如果从键盘上输入ABCdef<回车>,则输出结果为    。
  
     #include<stdio.h>
     int main()
     {   char ch;
         while((ch=getchar())!='\n')
         {  if(ch>='A' && ch<='Z')ch=ch+32;
            else if(ch>='a' && ch<'z')ch=ch-32;
            printf("%c",ch);
         }
         printf("\n");
         return  0;
     }
  
       A)ABCdef		B)abcDEF			C)abc				D)DEF
  6.下列选项中,关于for循环描述正确的是    。
       A)for循环只能用于循环次数已经确定的情况
       B)for循环的循环体可以是一个复合语句
       C)在for循环中,不能用break语句跳出循环体
       D)for循环的循环体不能是一个空语句 
  7.设i、j、k均为int型变量,则执行完下面的for循环后,k的值为    。
  
     for(i=0,j=10;i<=j;i++,j--) k=i+j;
  
       A)12			B)10				C)11				D)9
  8.有以下程序段:
  
     int k=0;
     while(k=1)k++;
  
  while循环执行的次数是    。
       A)无限次	B)有语法错,不能执行	C)一次也不执行		D)执行一次
  9.C语言中while和do-while 循环的主要区别是    。
       A)do-while的循环体至少无条件执行一次
       B)while的循环控制条件比do-while的循环控制条件严格
       C)do-while允许从外部转到循环体内
       D)do-while的循环体不能是复合语句
  10.下列选项中,叙述正确的是    。
    A)continue语句的作用是结束整个循环的执行
    B)只能在循环体内和switch语句体内使用break语句
    C)在循环体内使用break语句或continue语句的作用相同
    D)从多层循环嵌套中退出时,只能使用goto语句
  11.下列选项中,对下面程序段描述正确的是    。
  
     for(t=1;t<=100;t++)
     {   scanf("%d", &x);
         if(x<0)continue;
         printf("%d\n", t);
     }
  
    A)当x<0时,整个循环结束			B)当x>=0时,什么也不输出
    C)printf()函数永远不会执行			D)最多允许输出100个非负整数
  12.以下程序的输出结果是    。
  
     #include"stdio.h"
     int	main()
     {  	int i;
       	for(i=1;i<=5;i++)
       	if(i%2) printf("*");
       	else continue;
       	printf("#");
       	printf("$\n");
     }
  
    A)***#$		B)#*#*#*$			C)*#*#*#$			D)**#*$
  13.以下程序的输出结果是    。
  
     #include"stdio.h"
     int	main()
     { 	unsigned int num, k;
       	num=26;k=1;
       	do {
       		k*=num%10;
        		num/=10;
        		} while(num);
      	printf("%d\n", k);
     }
  
    A)2			B)12			C)60			D)18
  14.有以下程序:
  
     #include"stdio.h"
     int	main()
     {	int n1, n2;
      	scanf("%d", &n2);
      	while(n2!=0)
       	{	n1=n2%10;
         		n2=n2/10;
      		printf("%d", n1);
      	}
     }
  
  程序运行后,如果从键盘上输入1298,则输出结果是    。
    A)8921			B)89			C)21			D)1298
  15.以下程序运行后的输出结果是    。
  
     #include"stdio.h"
     int	main()
     {	int s=0, k;
      	for(k=7;k>=0;k--)
      	{	switch(k)
          	{
                 case 1:
                 case 4:
                 case 7: s++; break;
                 case 2:
                 case 3:
                 case 6:break;
                 case 0:
                 case 5: s+=2; break; }
     	}
     	printf("s=%d\n", s);
     }
  
    A)s=5			B)s=1			C)s=3			D)s=7
第二单元  实验 
一、常见错误小结
常见错误实例
错 误 描 述
错 误 类 型
while(i<=n)
{   sum=sum+i;
   i++;   }
在循环开始前,未对计数器变量、累加器变量初始化
正确写法:
i=1;sum=0;
while(i<=n)
{  sum=sum+i;
   i++; }
运行错误
i=1;sum=0;
while(i<=n)
   sum=sum+i;
   i++;
for、while循环的循环体未加{ }
正确写法:
i=1;sum=0;
while(i<=n)
{  sum=sum+i;
   i++; }
运行错误
for(i=1;i<=n;i++);
{  …  }
或
while(i<=n);
{  …  }
for/while语句后面加分号,使得for/while循环变成了空循环
运行错误
i=1;sum=0;
while(i<=100)
{   sum=sum+i;
}
循环体中缺少改变循环条件的语句,导致死循环
正确写法:
i=1;sum=0;
while(i<=100)
{   sum=sum+i;
    i=i+1;    }
运行错误
do{
  …
}while(i<=100)
while后面缺少分号
正确写法:  
do{
  …
}while(i<=100);
编译错误
for(i=1,i<n,i++)
用逗号分隔for语句中的3个表达式
正确写法:
for(i=1; i<n; i++)
编译错误
二、编程技能——学会程序排错 
  程序调试是一个修正错误的过程。为了修正错误,需要根据错误的迹象,分析错误的原因,确定错误的准确位置,这主要依靠的是排错技术。排错过程开始于一个测试用例的执行,当测试结果与期望输入有出入时就表现出了错误征兆,此时应先找出错误的原因,再修正错误。
  常用的排错方法如下。
  (1)缩减输入数据,设法找到导致失败的最小输入。
  (2)采用注释的方法“切掉”一些代码,减少有关的代码区域,调试无误后再还原被“切掉”的代码。
  (3)在合适的地方安排打印语句。
  (4)以单步方式运行关键代码。
  找到程序的错误后,就要考虑如何进行改错。改错时要注意如下几个问题。
  (1)不要急于修改错误,先思考一下,修改相关代码行会不会引发其他问题。
  (2)程序中可能“潜伏”着同一类型的错误,这时要改正所有的类似错误。
  (3)改错后要立即进行回归测试(regression test),即回过头来,对以前修复过的bug重新进行测试,看该bug是否会重新出现,以免修复一个bug,又引起其他新的bug。
  【例5-1】 编程计算1~200中所有能被3整除但不能被5整除的整数之和。
  源代码如下:
  
     #include<stdio.h>
     int main()
     {   int i,sum=0;
         for(i=1;i<=200;i++)
     		 if(i%3==0&&i%5!=0) sum=sum+i;
         printf("s=%d\n",sum);
         return 0;
     }
  
  程序运行结果如下:
  
  
  
  运行结果是否正确?可以用如下方法测试。
  ① 缩小数据范围,例如,将测试范围改成?1~20,将语句修改为?for(i=1;i<=20;i++),检测输出结果是否正确。
  ② 增加打印语句,以检查每次循环的中间结果,代码如下。
  
     #include<stdio.h>
     int main()
     {	int i,sum=0;
     	for(i=1;i<=200;i++)
     		 if(i%3==0&&i%5!=0) 
     		 {   sum=sum+i;
     		     printf("%5d",i);//输出每个符合条件的i的值
     		 }
     	printf("\ns=%d\n",sum);
     	return 0;
     }
  
  程序运行结果如下:

  
  ③ 以单步方式运行代码。
  首先,将光标定位在for语句,选择“组建”→“开始调试”→Run to Cursor命令,如图5-1所示。

图5-1  Run to Cursor命令
  页面显示如图5-2所示,按F11键单步执行命令或单击图标,程序会一步一步执行,窗口中i和sum的值也会随之改变。若要终止调试,选择“调试”菜单下的Stop Debugging命令。具体的调试流程,可以查看附录A中的“三、程序调试——逻辑错误”。

图5-2  程序单步运行窗口

  
三、实验指导
实验5  循环结构程序设计-单重循环
  1. 实验目的
  (1)掌握用while语句、do-while语句和for语句实现单重循环的方法。
  (2)掌握在程序设计中用循环的方法实现一些常用算法(如求和、求积和分类统       计等)。
  (3)学习调试程序的一些技巧。
  2. 实验内容和步骤
【基础部分】理解单重循环结构
  (1)给定程序c5-1-1.c的功能是:在屏幕中输出如图5-3所示图形。分析程序的运行结果,并回答问题。

图5-3  程序c5-1-1.c的运行结果
     /*c5-1-1.c */
     #include<stdio.h>
     int main()
     {
         int i=1;
         while(i<=5)
         {    
             printf("*****\n");
             i=i+1;
         }
         return 0;
     }
  
  ① 画出该程序的流程图。
  ② 编辑并运行该程序,查看程序运行的结果。
  ③ 将c5-1-1.c稍作改动,去掉程序中的一对花括号,并另存为c5-1-2.c。程序代码如下:
  
     /* c5-1-2.c */
     #include<stdio.h>
     int main()
     {
         int i=1;
         while(i<=5)
         printf("*****\n");
         i=i+1;
         return 0;
     }
  
  运行程序,观察程序运行的结果,分析出现这个结果的原因。
【提高部分】掌握单重循环结构程序设计
  1)程序填空
  说明:程序中有多个空,如(1)、(2)等需要补充完整。将程序中的 (1) 、 (2) 等删除后,在相应的位置填入正确答案并调试直到得到正确结果为止。
  注意:不要随意改动程序,不得增行或删行,也不得更改程序的结构!
  (1)给定程序c5-2-1.c的功能是:计算1~M(M为偶数)的奇数之和及偶数之和。完善程序,使程序运行结果如图5-4所示。

图5-4  程序c5-2-1.c的运行结果
     /*   c5-2-1.c    */
     #include <stdio.h>
     #define  M   100
     int main()
     {
          int a,b,i;
          a=0;b=0;
          /**************found************/
          for(i=1; (1) ;i+=2)
          {     
               a=a+i;
               /**************found************/
                  (2)   ;
          }
          printf("偶数之和是: %d\n",b);
          printf("奇数之和是: %d\n",a);
          return 0;  
     }
  
  (2)给定程序c5-2-2.c的功能是:从键盘输入整数,分别计算所输入的正整数的和、负整数的和。当键盘输入为0时,结束输入并输出计算结果。完善程序,使程序运行结果如图5-5所示。

图5-5  程序c5-2-2.c的运行结果
     /*   c5-2-2.c    */
     #include <stdio.h>
     int main()
     {     
         int  x, sum1, sum2;
         /**************found************/
               (1)  
         printf("请输入一些整数(输入0时结束输入):\n");
         scanf("%d", &x);
         while ( x != 0 )
         {     
              /**************found************/
                    (2)  
                  sum1 = sum1+x;
             else
                 sum2 =sum2+x;
             scanf("%d", &x);
         }
         printf("大于0的整数之和为: %d\n", sum1);
         printf("小于0的整数之和为: %d\n", sum2);  
         return 0;
     }
  
  (3)给定程序c5-2-3.c的功能是:计算正整数num的各位上的数字之积。
  例如,若从键盘输入252,则运行结果如图5-6(a)所示;若从键盘输入202,则运行结果如图5-6(b)所示,请完善程序。
    
(a)                           (b)
图5-6  程序c5-2-3.c的运行结果
     /*   c5-2-3.c    */
     #include <stdio.h>
     int main( )
     {
          int num,k;
          /************found************/