第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************/