第控制语句与预处理命令 3 章 3.内容概述 1 本章主要介绍分支语句、循环语句、无条件转移语句以及宏定义、文件 包含和条件编译等编译预处理命令。本章的知识结构如图3. 1所示。 图3. 1 第3章知识结构 考核要求:熟练掌握if语句、switch~case语句的执行过程和用法;熟 练掌握while语句、do~while语句、for语句的执行过程、用法以及三种循 环格式之间的转换和嵌套;掌握宏定义和文件包含的用法;掌握break语 句和continue语句的功能和用法;了解goto语句功能。 重点难点:本章的重点是实现分支结构的两个语句和实现循环结构的 3个语句的用法。本章的难点是分支语句的嵌套和循环语句的嵌套。 核心考点:分支语句的格式及使用,循环语句的格式及使用,宏定义及 宏调用。 3.典型题解析 2 【例3.下列关于i表达式”值的叙述中正确的 是( )。 1】f后面的圆括号内的“ 40 C 语言程序设计(第4 版)学习与实验指导 A.必须是逻辑值 B.必须是整数值 C.必须是正数 D.可以是任意合法的数值 解析:if后面的表达式的值应该是逻辑值,即“真”或“假”,但C语言中没有逻辑类型 数据。C语言规定,表达式的值为0代表“假”,表达式的值为非0代表“真”。因此,表达 式的值可以是任意合法的数值。 答案:D 【例3.2】 若有定义:inta=3,b=2,c;,则以下语句中执行效果与其他三个不同的 是( )。 A.if(a>b)c=a,a=b,b=c; B.if(a>b){c=a,a=b,b=c;} C.if(a>b)c=a;a=b;b=c; D.if(a>b){c=a;a=b;b=c;} 解析:“c=a,a=b,b=c;”是一个逗号表达式语句,根据单分支if语句的执行过程,选 项A、选项B和选项D具有相同的执行效果。在选项C中,单分支语句是“if(a>b)c=a;”, 无论条件是否为真,其后面的两个语句都会顺序执行。 答案:C 【例3.3】 下列条件语句中,功能与其他语句不同的是( )。 A.if(a)printf("%d\n",x);elseprintf("%d\n",y); B.if(a==0)printf("%d\n",y);elseprintf("%d\n",x); C.if(a!=0)printf("%d\n",x);elseprintf("%d\n",y); D.if(a==0)printf("%d\n",x);elseprintf("%d\n",y); 解析:根据双分支if语句的执行过程,选项A、选项B和选项C具有相同的功能,即 若a的值不是0,则输出x,否则输出y。选项D的功能是若a的值是0,则输出x,否则输 出y。本题可使用排除法,因为选项B和选项D 的功能相反,所以答案只能是其中的一 个,再从选项A 和选项C中选择一项,查看其功能与选项B和选项D 中的哪一项不同, 即可得到答案。 答案:D 【例3.4】 下列程序运行后的输出结果是( )。 #include<stdio.h> void main() { int x=5,y=10; if(x>20) y++; else if(x>10) y+=2; else if(x>5) y+=3; else y+=4; printf("%d\n",y); } A.14 B.13 C.12 D.11 解析:表达式x>20、x>10和x>5的值都为0(假),根据多分支if语句的执行过 程,执行语句“y+=4;”,即y=10+4=14。 第3 章 控制语句与预处理命令 41 答案:A 【例3.5】 下列程序运行后的输出结果是( )。 #include<stdio.h> void main() { int a=1,b=2,c=3,d=0; if(a==1) if(b!=2) if(c==3) d=1; else d=2; else if(c!=3) d=3; else d=4; else d=5; printf("%d\n",d); } A.1 B.2 C.3 D.4 解析:程序中的if语句是嵌套格式。先计算表达式a==1的值,其值为1(真),然后 计算表达式b!=2的值,其值为0(假),再计算表达式c!=3的值,其值为0(假),执行语 句“d=4;”。 答案:D 【例3.6】 下列程序段中正确的是( )。 A.inta=1,b=2; B . inta=10,b; switch(a) switch(a) {caseb:a+=2;break; {case10.0:b=3;break; caseb+2:a+=4;break; case10.1:b=4;break; caseb+4:a+=8;break; case10.2:b=5;break; } } C.#defineb11 D.inta=0,b; inta=10,z; switch(a) switch(a) {case3: {case12:z=3;break; case1:b=10;break; caseb+1:a+=10;break; case2:b=15;break; caseb-10:b-=20;break; case0:b=20; } } 解析:选项A 错误,因为C语言要求case后面的表达式必须为常量表达式。选项B 错误,因为C语言要求case后面的常量表达式的值必须为整型、字符型或枚举型。选项 C错误,因为C语言要求各case后面的常量表达式的值必须互不相同,宏替换后b+1的 结果为12;另外,b是常量,不能被赋值。 答案:D 【例3.7】 下列程序运行后的输出结果是( )。 42 C 语言程序设计(第4 版)学习与实验指导 #include<stdio.h> void main() { int a=16,b=22,m=0; switch(a%3) { case 0:m+=1;break; case 1:m+=2; switch(b%3) { default:m+=3; case 1: m+=4;break; } } printf("%d\n",m); } A.2 B.3 C.5 D.6 解析:根据switch~case语句的执行过程,先计算表达式a%3(其值为1),执行语句 “m+=2;”,m 的值为2;然后计算表达式b%3(其值为1),执行语句“m+=4;”,m 的值 为6。 答案:D 【例3.8】 为使下列程序的输出结果为t=4,则输入变量a和b应满足的条件是( )。 #include<stdio.h> void main() { int s,t,a,b; scanf("%d,%d",&a,&b); s=1; t=1; if(a>0) s=s+1; if(a>b) t=s+t; else t=2*s; printf("t=%d",t); } A.a>0 B.a>b C.b<a≤0 D.0<a≤b 解析:若a>0且a>b,则t的值为3;若a>0且a≤b,则t的值为4;若a≤0且a>b, 则t的值为2;若a≤0且a≤b,则t的值为2。 答案:D 【例3.9】 下列程序段中不是死循环的是( )。 A.inti=10; B.inti=1; while(1) while(i);i--; {i=i%10+1; if(i>10)break; } 第3 章 控制语句与预处理命令 43 C.inti; D.inti; do{i=0;i++;}while(i<=0); for(i=1;;i++); 解析:C语言的3个循环语句都有一个循环终止条件,且都是在条件为真(非0)时循 环继续,条件为假(0)时循环终止。另外,可通过在循环体中使用break语句或goto语句 终止循环。 本题中,选项A 是错误的,因为循环条件总为真且表达式i>10的值总为假,循环不 能终止。选项B是错误的,因为循环体是空语句(;),循环变量i的值不变(始终为1),循 环条件总为真,循环不能终止。选项C是正确的,因为循环体执行1次后,i的值为1,循 环条件i<=0的值为假,退出循环。选项D是错误的,因为在for语句中,若表达式2省 略,则认为表达式2的值为真(1),即循环条件总为真,循环不能终止。 答案:C 【例3.10】 若变量已正确定义,则不能计算5!的程序段是( )。 A.for(i=1,p=1;i<=5;i++)p*=i; B.for(i=1;i<=5;i++){p=1;p*=i;} C.i=1;p=1;while(i<=5){p*=i;i++;} D.i=1;p=1;do{p*=i;i++;}while(i<=5); 解析:选项B不能完成5!的计算,因为其每次循环都会先将变量p的值置1,这样,p *=i等价于p=i,p的最终值是5。 答案:B 【例3.11】 下列程序运行后的输出结果是( )。 #include<stdio.h> void main() { int a=1, b=2; for( ;a<8;a++) {b+=a;a+=2;} printf("%d,%d\n",a,b); } A.9,18 B.8,11 C.7,11 D.10,14 解析:根据for语句的执行过程,本题中的for语句等价于语句 for(;a<8;a+=3) b+=a; 循环变量a的初值为1,步长为3,循环次数为3次(a=1,4,7),每次循环将a的值累 加到b。当a的值为10时退出循环,此时b的值为14(2+1+4+7)。 答案:D 【例3.12】 下列程序运行后的输出结果是( )。 #include<stdio.h> void main() { int i,j,m=1; for(i=1;i<3;i++) 44 C 语言程序设计(第4 版)学习与实验指导 { for(j=3;j>0;j--) { if(i*j>3) break; m*=i*j; } } printf("m=%d\n",m); } A.m=6 B.m=2 C.m=4 D.m=5 解析:break语句只能在循环语句和switch语句中使用。用于switch语句时,将退 出包含它的最内层的switch语句;用于循环语句时,将退出包含它的最内层的循环。 本题中,外层循环只执行2次,这2次循环的执行情形如下。 当i=1时,内层循环执行3次(j=3,2,1)。内循环中if语句判断条件i*j>3每次都 为假,执行语句“m*=i*j;”,故内循环结束时m=6。 当i=2时,内循环执行1次(j=3)。由于i*j>3为真,因此执行break语句,退出内 循环,没有执行语句“m*=i*j;”,m 的值没有变化。 答案:A 【例3.13】 下列程序运行后的输出结果是( )。 #include<stdio.h> void main() { int m=14,n=63; while(m!=n) { while(m>n) m=m-n; while(m<n) n=n-m; } printf("%d\n",m); } A.0 B.7 C.14 D.63 解析:该程序的功能是计算两个正整数的最大公约数。 答案:B 【例3.14】 下列程序运行后的输出结果是( )。 #include<stdio.h> void main() { int x=9; do { if(x%3==0) { printf("%d",--x);--x;continue;} else x--; }while(x>1); } 第3 章 控制语句与预处理命令 45 A.741 B.852 C.963 D.876 解析:continue语句只能在循环语句的循环体内使用,其功能是结束本次循环,跳过 循环体中尚未执行的部分,并进行下一次是否执行循环的判断。在while语句和do~ while语句中,continue语句把程序控制转到while后面括号内的表达式处,在for语句 中,continue语句把程序控制转到表达式3处。 该程序的功能是:若x%3==0,则输出x-1,其中,x是9~2的整数。 答案:B 【例3.15】 下列程序运行时,若输入123450↙,则输出结果是( )。 #include<stdio.h> void main() { int s; scanf("%d",&s); while(s>0) { switch(s) { case 1:printf("%d",s+5); case 2:printf("%d",s+4); break; case 3:printf("%d",s+3); default:printf("%d",s+1);break; } scanf("%d",&s); } } A.6566456 B .66656 C.66666 D.6666656 解析:本题中,循环执行5次,执行情形如下。 第1次循环:s=1,依次输出表达式s+5和s+4的值(6和5)。由此可知,选项B、 C、D错误。 第2次循环:s=2,输出表达式s+4的值(6)。 第3次循环:s=3,依次输出表达式s+3和s+1的值(6和4)。 第4次循环:s=4,输出表达式s+1的值(5)。 第5次循环:s=5,输出表达式s+1的值(6)。 答案:A 【例3.16】 以下程序的功能是从键盘输入若干整数,当输入-1时结束输入,输出-1 之前的所有整数的最大值和最小值,并输出这些整数的个数,请填空。 #include<stdio.h> void main() { int x,amax,amin,n=0; scanf("%d",&x); if(x!=-1) { amax=x;amin=x;} 46 C 语言程序设计(第4 版)学习与实验指导 while( ① ) { ② ; if(x>amax) amax=x; if(x<amin) amin=x; ③ ; } if(n==0) printf("no valid input\n" ); else printf("\nn=%d,amax=%d,amin=%d\n",n,amax,amin); } 解析:该程序中,amax存放最大值,amin存放最小值,n存放数据的个数。由于数据 输入的结束条件是-1,故①处填写x!=-1。若输入的数据不为-1,则计数器n的值加 1,故②处填写n++(或++n、n+=1或n=n+1)。当前数据处理之后,需要从键盘接 收下一个数据,故③处填写scanf("%d",&x)。 答案:① x!=-1 ②n++(或++n、n+=1或n=n+1) ③scanf("%d",&x) 【例3.17】 编写程序,从键盘输入10名学生的4门课程的成绩,计算并输出平均分 大于或等于60分的学生的平均成绩。 解析:对每名学生先计算其4门课程的总成绩,然后计算平均分,若大于或等于60 分,则输出。 #include<stdio.h> #define N 10 void main() { int n,k; float score,sum,ave; for(n=1;n<=N;n++) { sum=0; for(k=1;k<=4;k++) { scanf("%f",&score); sum+=score;} ave=sum/4; if(ave>=60) printf("No. %d: %.2f\n",n,ave); } } 【例3.18】 编写程序,输出1000之内的完数。“完数”是指一个数恰好等于它的因子 (包括1但不包括本身)之和。例如,6的因子是1、2、3,6=1+2+3,因此6是一个完数。 解析:对1~999的每个数,找出所有因子并求和,若所有因子之和与该数相等,则 输出。 #include<stdio.h> void main() { int i,j,m; for(i=1;i<1000;i++) { m=0; 第3 章 控制语句与预处理命令 47 for(j=1;j<=i/2;j++) if(i%j==0) m+=j; /* 找因子并求和*/ if(i==m) { for(j=1;j<=i/2;j++) if(i%j==0) printf("%d+",j); printf("\b=%d\n",i); /* 输出完数*/ } } } 【例3.19】 编写程序,从键盘输入一个正整数,输出其各位数字的平方和。 解析:利用取余运算,从个位开始依次取出正整数的每位数,计算每位数的平方并 累加。 #include<stdio.h> void main() { int n,sum=0; /* n 存放正整数,sum 存放n 的各位数字的平方和*/ scanf("%d",&n); /*输入正整数*/ while(n) { sum+=(n%10)*(n%10); /*将n 的个位数的平方累加到sum */ n/=10; /*将n 的个位数删除*/ } printf("%d\n",sum); /*输出n 的各位数的平方和*/ } 【例3.20】 以下程序中,for语句的循环体执行的次数是。 #define N 3 #define M N+1 #define K M+1*M/2 #include<stdio.h> void main() { int i; for(i=1;i<K;i++) { … } . } 解析:宏定义在编译时处理,需要先替换后计算。 K→M+1*M/2→N+1+1*N+1/2→3+1+1*3+1/2=7,循环次数为7-1=6。 若将#defineM N+1改为#defineM (N+1),则K→M+1*M/2→(N+1)+1* (N+1)/2→(3+1)+1*(3+1)/2=6,循环次数为6-1=5。 答案:6 【例3.21】 以下程序运行后的输出结果是。 #include<stdio.h> #define S(x) 4*x*x+1 void main() 48 C 语言程序设计(第4 版)学习与实验指导 { int i=6,j=8; printf("%d\n",S(i+j)); } 解析:宏定义在编译时处理,需要先替换后计算。 S(i+j)→4*i+j*i+j+1=4*6+8*6+8+1=81。 若将#defineS(x)4*x*x+1改为#defineS(x)4*(x)*(x)+1,则S(i+j)→ 4*(i+j)*(i+j)+1=4*(6+8)*(6+8)+1=785。 答案:81 【例3.22】 下列叙述中错误的是( )。 A.#include命令可以包含一个含有函数定义的C语言源程序文件 B.使用“#include<文件名>”的格式比使用“#include"文件名"”的格式更节 省编译时间 C.#include"C:\\USER\\F1.H"是正确包含命令,表示文件F1.H 存放在C盘 的USER目录下 D.“#include<文件名>”格式的文件名之前不能包含路径 解析:文件包含的一般格式为:#include"文件名"或#include<文件名>。文件包 含的基本作用是将指定的文件内容包含到当前文件中,文件可以是由系统提供的,也可以 是由用户编写的。由此可知,选项A 正确。两种格式是有区别的,“#include<文件名 >”格式,系统直接到指定路径搜索文件;“#include"文件名"”格式下,系统先在当前目 录搜索被包含的文件,若未找到,再到系统指定的路径搜索。由此可知,选项B正确。两 种格式的文件名之前都可以包含路径。例如,在VC++ 环境中,要想包含C盘的USER 目录下的文件F1.H,下列4种形式都是正确的包含命令。 #include "C:\\USER\\F1.H" #include<C:\\USER\\F1.H> #include "C:\USER\F1.H" #include<C:\USER\F1.H> 由此可知,选项C正确,选项D错误。 答案:D 3.3 自测试题 1.单项选择题 (1)与语句“k=a>b? (b>c? 1:0):0;”功能相同的程序段是( )。 A.if((a>b)&&(b>c))k=1; B.if((a>b)||(b>c))k=1; elsek=0; elsek=0; C.if(a<=b)k=0; D.if(a>b)k=1; elseif(b<=c)k=1; elseif(b>c)k=1; elsek=0; 第3 章 控制语句与预处理命令 49 (2)以下if语句形式中不正确的是( )。 A.if(x>y&&x!=10); B.if(x!=y)x+=y++; C.if(x==y)scanf("%d",&x) elsescanf("%d",&y); D.if(x>=y){x++;y--;} (3)有以下程序段: int n=0,p; do{ scanf("%d",&p);n++;}while(p!=12345&&n<3); 此处do~while循环的结束条件是( )。 A.p的值不等于12345且n的值小于3 B.p的值等于12345且n的值大于或等于3 C.p的值不等于12345或者n的值小于3 D.p的值等于12345或者n的值大于或等于3 (4)C语言中,while语句和do~while语句的主要区别是( )。 A.do~while语句的循环体至少无条件执行一次 B.while语句的循环控制条件比do~while语句的循环控制条件更严格 C.do~while语句允许从外部转到循环体内 D.do~while语句的循环体不能是复合语句 (5)若i和k都是int类型变量,有以下for语句: for(i=0,k=-1;k=1;k++) printf("%d\n",k); 则下面关于语句执行情况的叙述中正确的是( )。 A.循环体执行两次 B.循环体执行一次 C.循环体一次也不执行 D.构成无限循环 (6)以下描述中错误的是( )。 A.break语句和continue语句的作用是一样的 B.break语句可用于do~while语句 C.在循环语句中使用break语句是为了跳出循环,提前结束循环 D.在循环语句中使用continue语句是为了结束本次循环,而不是退出循环 (7)以下程序中,while循环的执行次数是( )。 #include<stdio.h> void main() { int i=0; while(i<10) { if(i<1) continue; if(i==5) break; i++; } } 50 C 语言程序设计(第4 版)学习与实验指导 A.1 B.死循环,不能确定次数 C.6 D.10 (8)有以下程序: #include<stdio.h> #include<stdlib.h> void main() { int i,n; for(i=0;i<8;i++) { n=rand()%5; switch(n) { case 1: case 3: printf("%d\n",n); break; case 2: case 4: printf("%d\n",n); continue; case 0: exit(0); } printf("%d\n",n); } } 以下叙述中正确的是( )。 A.for循环语句固定执行8次 B.当产生的随机数n为4时结束循环操作 C.当产生的随机数n为1和2时不做任何操作 D.当产生的随机数n为0时结束程序运行 (9)以下叙述中正确的是( )。 A.一行可以书写多个有效的预处理命令 B.宏名必须用大写字母表示 C.宏替换只占用编译时间,不占用运行时间 D.C程序在执行过程中对预处理命令进行处理 (10)有以下程序: #include<stdio.h> #define f(x) (x*x) void main() { int i1, i2; i1=f(8)/f(4);i2=f(4+4)/f(2+2); printf("%d, %d\n",i1,i2); } 程序运行后的输出结果是( )。 A.64,28 B .4,4 C.4,3 D.64,64 2.程序填空题 (1)根据以下函数关系,对输入的x 值计算出相应的y 值。 第3 章 控制语句与预处理命令 51 y= x x≤1 10x 1<x≤2 x2+20 2<x≤10 ì . í .. .. #include<stdio.h> void main() { int x,y; scanf("%d",&x); if( ① ) y=x; else if( ② ) y=10*x; else if( ③ ) y=x*x+20; else y=-1; if(y!=-1) printf("%d\n",y); else printf("error\n"); } (2)根据以下函数关系,对输入的x 值计算出相应的y 值。 y= -10 x<0 x 0≤x<10 5 10≤x<20 5x+20 20≤x<50 ì . í ... .. . #include<stdio.h> void main() { int x,c; float y; scanf("%d",&x); if( ① ) c=-1; else c=x/10; switch(c) { case -1: y=-10;break; case 0: y=x;break; case 1: y=5;break; case 2:case 3:case 4: y=5*x+20;break; default: y=-2; } if( ② ) printf("y=%f\n",y); else printf("error\n"); } (3)求1!+2!+3!+…+10!。 #include<stdio.h> void main() { float s=0,t=1; int n; for(n=1; ① ;n++) 52 C 语言程序设计(第4 版)学习与实验指导 { ② ; ③ ; } printf("1!+2!+3!+...+10!=%.0f",s); } (4)以下程序用于统计从键盘输入的一个正整数中各位数字中0的个数,并求各位 数字中的最大数。例如,1080中0的个数是2,各位数字中的最大数是8。 #include<stdio.h> void main(void) { unsigned long num,max,t; int count; count=max=0; scanf("%ld", &num); do { t= ① ; if(t==0) ++count; else if(max<t) ② ; num/=10; }while( ③ ); printf("count=%d,max=%ld\n", count, max); } (5)下列程序的功能是输出100以内能被3整除且个位数为6的所有整数。 #include<stdio.h> void main() { int i,j; for(i=0; ① ;i++) { j=i*10+6; if( ② ) continue; printf("%4d",j); } } 3.程序分析题 (1)写出下列程序的运行结果。 #include<stdio.h> void main() { int a=5,b=4,c=3,d=2; if(a>b>c) printf("%d\n",d); else if((c-1>=d)==1) printf("%d\n",d+1); else printf("%d\n",d+2); } 第3 章 控制语句与预处理命令 53 (2)写出下列程序的运行结果。 #include<stdio.h> void main() { int c=0,k; for(k=1;k<3;k++) switch(k) { default: c+=k; case 2: c++;break; case 4: c+=2;break; } printf("%d\n",c); } (3)写出下列程序的运行结果。 #include<stdio.h> void main() { int n=2,k=0; while(k++&&n++>2); printf("%d %d\n",k,n); } (4)写出下列程序的运行结果。 #include<stdio.h> void main() { int x=15; do { x++; if(x/3){x++;break;} else continue; }while(x>10&&x<50); printf("%d\n",x); } (5)写出下列程序的运行结果。 #include<stdio.h> #define SUB(a) (a)-(a) void main() { int a=2,b=3,c=5,d; d=SUB(a+b)*c; printf("%d\n",d); } 4.程序设计题 (1)输入整数a和b,若a2+b2>100,则输出a2+b2 百位以上的数字,否则输出a+b。 54 C 语言程序设计(第4 版)学习与实验指导 (2)编写程序,实现两个数的四则运算。要求:数与运算符从键盘输入。 (3)将从键盘输入的偶数写成两个素数之和。 (4)编写程序,给出将100元人民币换成1元、2元、5元的所有兑换方案。 3.4 实验题目 (1)求下列分段函数的值。要求:x的值从键盘输入。 y= 0 x≤0 x 0<x≤10 2x+1 x>10 ì . í .. .. (2)运输公司为用户计算运费。距离越远,每千米的运费越低,标准如下。 s<250km 无折扣 250≤s<500 2% 折扣 500≤s<1000 5% 折扣 1000≤s<2000 8% 折扣 2000≤s<3000 10% 折扣 3000≤s 15% 折扣 设每千米每吨货物的基本运费为p,货物质量为w,距离为s,折扣为d,则总运费的计 算公式为f=p*w*s*(1-d),编写程序计算运费。 要求:① 使用switch~case语句,② p、w、s的值从键盘输入。 (3)猴子吃桃问题。猴子第一天摘下若干桃子,当日吃了一半零一个,以后每天都吃 剩下的一半零一个。猴子到第十天再想吃桃时,只剩一个桃子。请问第一天猴子共摘了 多少个桃子。 (4)编写程序验证下列结论:任何一个自然数n的立方都等于n个连续奇数之和。 例如,13=1,23=3+5,33=7+9+11。 要求:程序对每个输入的自然数进行计算并输出相应的连续奇数,直到输入的自然 数为0时停止。 (5)百鸡问题。100元买100只鸡,一只公鸡5元,一只母鸡3元,3只小鸡1元。求 100元能买公鸡、母鸡、小鸡各多少只? (6)求孪生素数问题。孪生素数是指相差为2的两个素数。例如,3和5,5和7,11 和13等。编写程序,输出从3开始的15对孪生素数。 (7)试分析以下宏替换后的形式,并计算输出结果。 要求:先计算运行结果,然后利用程序验证。 #include "stdio.h" #define CX(y) 2.5+y #define PR(a) printf("%d",(int)(a)) #define PR1(a) PR(a); putchar('\n') void main() 第3 章 控制语句与预处理命令 55 { int x=2; PR1(CX(5)*x); } (8)通过宏调用方式求n个数中的最大值。要求:数据从键盘输入。 3.5 思考题 (1)在if语句的嵌套情况下,else和if是如何配对的? (2)在什么情况下使用一条switch~case语句比使用多条if语句更好? (3)C语言中实现循环结构的方法有哪几种? 各有什么特点? (4)break语句和continue语句在循环体内的功能是否相同? (5)在带参数的宏定义命令中,参数的个数是否受限制? 是否需要对参数进行类型 说明? 3.6 习题解答 1.单项选择题 (1)语句“while(!E);”中的表达式!E等价于( )。 ① E==0 ② E!=1 ③ E!=0 ④ E==1 解答:因为只有!E为真(非0)才能进入循环,所以E必须为假(0),即E==0。 答案:① (2)与for(;0;)等价的是( )。 ① while(1) ② while(0) ③ break ④continue 解答:若for语句中的表达式1和表达式3同时省略,则与while语句等价。 答案:② (3)对于for(表达式1;;表达式3),可以理解为( )。 ①for(表达式1;0;表达式3) ②for(表达式1;1;表达式3) ③for(表达式1;表达式1;表达式3) ④for(表达式1;表达式3;表达式3) 解答:若for语句中的表达式2省略,则默认表达式2的值始终为真。 答案:② (4)下列叙述中正确的是( )。 ①continue语句的作用是结束整个循环 ② 只能在循环语句和switch~case语句中使用break语句 ③ 在循环体中,break语句和continue语句的作用相同 ④ 从多层循环中退出时,只能使用goto语句 解答:break语句只能用于循环语句和switch~case语句中,continue语句只能用于 循环语句中。用于循环语句时,break语句将退出当前循环,continue语句将结束本次循 环。选项①和③错误,选项②正确。从多层循环中退出时,也可以使用break语句,选项 56 C 语言程序设计(第4 版)学习与实验指导 ④错误。 答案:② (5)若有定义:intx=5,y=4;,则下列语句中错误的是( )。 ① while(x==y)5; ② dox++while(x==10); ③ while(0); ④ do2;while(x==y); 解答:在while语句和do~while语句中,while后面的圆括号中的表达式类型可以 是任意的,循环体可以是任意语句,所以选项①、③和④都是正确的,选项②之所以是错误 的,是因为x++后面缺少分号(;),未构成语句。 答案:② (6)若有定义:intx,y;,则循环语句“for(x=0,y=0;(y!=123)||(x<4);x++);” 的循环次数为( )。 ① 无限次 ② 不确定 ③4次 ④3次 解答:y的初值为0且没有修改,y!=123永远为真,(y!=123)||(x<4)也永远为 真。因此该循环为死循环,循环次数为无限次。 答案:① (7)若有定义:inta=1,b=10;,则执行下列程序段后,b的值为( )。 do {b-=a;a++;}while(b--<0); ①9 ② -2 ③ -1 ④8 解答:首先执行循环体,可得b的值为9;然后判断循环条件,9<0的结果为假,退出 循环。循环条件判断完成后b的值为8。 答案:④ (8)下列叙述中不正确的是( )。 ① 宏名无类型,其参数也无类型 ② 宏定义不是C语句,不必在行末加分号 ③ 宏替换只是字符替换 ④ 宏定义命令必须写在文件开头 解答:宏定义可以写在程序中的任何位置,但要独占一行,其作用域是从定义点开始 到文件结束或遇到#undef。 答案:④ (9)有如下嵌套的if语句: if(a<b) if(a<c) k=a; else k=c; else if(b<c) k=b; else k=c; 以下语句中与上述if语句等价的是( )。 第3 章 控制语句与预处理命令 57 ① k=(a<b)?a:b;k=(b<c)?b:c; ② k=(a<b)?((b<c)?a:b):((b>c)?b:c); ③ k=(a<b)?((a<c)?a:c):((b<c)?b:c); ④ k=(a<b)?a:b;k=(a<c)?a:c; 解答:“if(a<c)k=a;elsek=c;”等价于“k=(a<c)?a:c;”,“if(b<c)k=b;elsek=c;” 等价于“k=(b<c)?b:c;”。因此,题干中的if语句等价于“k=(a<b)?((a<c)?a:c): ((b<c)?b:c);”。 答案:③ (10)以下选项中与“if(a==1)a=b;elsea++;”语句功能不同的switch~case语 句是( )。 ①switch(a) ②switch(a==1) {case1:a=b;break; {case0:a=b;break; default:a++; case1:a++; } } ③switch(a) ④switch(a==1) {default:a++;break; {case1:a=b;break; case1:a=b; case0:a++; } } 解答:选项②对应的if语句为“if(a==1)a++;elsea=b;”,与题干中的语句的功 能相反。 答案:② 2.程序填空题(在下列程序的处填上正确的内容,使程序完整) (1)下列程序的功能是把从键盘输入的整数取绝对值后输出。 #include<stdio.h> void main() { int x; scanf("%d",&x); if(x<0) ; printf("%d\n",x); } 解答:因为程序中没有文件包含#include"math.h",所以不能使用求绝对值函数 abs()。方法是:若非负,则原样输出,否则取其相反数。 答案:x=-x (2)下列程序的功能是判断m 是否为素数,如果m 是素数,则输出1,否则输出0。 #include "stdio.h" void main() { int m,i,y=1; 58 C 语言程序设计(第4 版)学习与实验指导 scanf("%d",&m); for(i=2;i<=m/2;i++) if( ){ y=0;break;} printf("%d\n",y); } 解答:本题的解法是:若2~m/2存在能整除m 的整数i,即m%i==0(或!(m%i)) 的值为真,则说明m 不是素数。 答案:m%i==0或!(m%i) (3)下列程序的功能是输出1~100能被7整除的所有整数。 #include<stdio.h> void main() { int i; for(i=1;i<=100;i++) { if(i%7) ; printf("%4d",i); } } 解答:if(i%7)与if(i%7!=0)等价。根据题意,若i不能被7整除,则结束本次循环, 并执行下次循环,能完成此操作的只有continue语句。 答案:continue (4)输入若干字符数据,分别统计其中A、B和C的个数。 #include "stdio.h" void main() { char c; int k1=0,k2=0,k3=0; while((c=getchar())!='\n') { { case 'A': k1++;break; case 'B': k2++;break; case 'C': k3++;break; } } printf("A=%d,B=%d,C=%d\n",k1,k2,k3); } 解答:由程序中的“case”可知,该程序的循环体一定是switch~case语句,并根据输 入的字符进行判断。 答案:switch(c) (5)下列程序的功能是从键盘输入若干学生的成绩,统计并输出最高成绩和最低成 绩,当输入负数时结束输入。