第控制语句与预处理命令
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)下列程序的功能是从键盘输入若干学生的成绩,统计并输出最高成绩和最低成
绩,当输入负数时结束输入。