《C语言程序设计》课后习题参考答案

时间:2019-05-12 23:26:14下载本文作者:会员上传
简介:写写帮文库小编为你整理了多篇相关的《《C语言程序设计》课后习题参考答案》,但愿对你工作学习有帮助,当然你在写写帮文库还可以找到更多《《C语言程序设计》课后习题参考答案》。

第一篇:《C语言程序设计》课后习题参考答案

高等院校计算机基础教育规划教材《C++程序设计》课后习题参考答案

――武汉大学出版社

习题1参考答案

一、选择题 1.A 2.D

二、填空题

1.BASIC、FORTRAN、AL_GOL60和COBOL 2.8 3.关键字

4.编辑、编译、链接和运行

三、简答题 1.答:

(1)C语言具有结构化的控制语句。C语言提供了结构化程序所必需的基本控制语句,实现了对逻辑流的有效控制。

(2)C语言具有丰富的数据结构类型。C语言除提供整型、实型、字符型等基本数据类型外,还提供了用基本数据类型构造出的各种复杂的数据结构,如数组、结构、联合等。C语言还提供了与地址密切相关的指针类型。此外,用户还可以根据需要自定义数据类型。(3)C语言具有丰富的运算符。C语言提供了多达34种运算符,丰富的数据类型与丰富的运算符相结合,使C语言的表达力更具灵活性,同时也提高了执行效率。

(4)C语言简洁、紧凑,使用方便、灵活,程序书写自由,有9种控制语句。

(5)C语言既具有高级语言的功能,又具有低级语言的许多功能,通常被称为中级计算机语言。它既是成功的系统描述语言,又是通用的程序设计语言。(6)C语言与汇编语言相比,可移植性好。

(7)功能强大。C语言具有低级语言的一些功能,所以,生成目标代码质量高,程序执行效率高。现在许多系统软件都用C语言来描述,可以大大提高了编程效率。

2.答:运行一个C语言程序,一般需要经过如下几个步骤:①上机输入并编辑源程序;②编译源程序;③与库函数连接;④生成可执行目标程序;⑤运行目标程序。3.答:

(1)操作系统的设计与实现。C语言是一种应用非常广泛的结构化高级程序设计语言,既适合编写应用软件,又适合编写系统软件。(2)工业控制。由于C语言具有简洁、灵活、代码效率高、能进行位操作等优点,C语言大量应用在单板机、单片机上,以及嵌入式领域等。

(3)图形图像处理。C语言在内存管理和进程控制方面有丰富的指令,而且它能提供快速运行的代码,因而C语言适合进行图形程序设计。

(4)教学领域。C语言是理想的结构化程序设计语言,其描述能力强,应用十分广泛,因此广泛应用于教学领域。许多计算机相关课程,如数据结构及算法大多是用C语言进行描述的。

习题2参考答案

一、选择题 1.A 2.A 3.C

二、填空题

1.基本数据类型、构造数据类型、指针类型、空类型 2.反斜线“\”

3.枚举数据类型(Enumerated Data Type)

三、简答题 1.答:

在C语言中,数据类型可分为:基本数据类型、构造数据类型、指针类型、空类型四大类。

基本类型是数据类型的基础,由它可以构造出其他复杂的数据类型。基本类型的值不可以再分解为其他类型。C语言的基本类型包括整型、实型(浮点型)、字符型和枚举型。

C语言的构造类型包括数组类型、结构类型和联合类型。构造类型是根据已定义的一种或多种数据类型用构造的方法定义的。也就是说,一个构造类型的值可以分解成若干个“成员”或“元素”。每个“成员”或“元素”都是一个基本数据类型,或又是一个构造类型。

指针是一种特殊而又具重要作用的数据类型,其值表示某个量在内存中的地址。虽然指针变量的取值类似于整型量,但这是两种完全不同类型的量,一个是变量的数值,一个是变量在内存中存放的地址。

在调用函数时,被调用函数通常应向调用函数返回一个函数值。返回的函数值具有一定的数据类型,应在函数定义的函数说明中给以说明。例如,在例1-1中给出的max函数定义中,函数头为“int max(int a,int b,int c)”,其中写在函数名max之前的类型说明符“int”表示该函数的返回值为整型量。但是,也有一类函数,被调用后并不向调用函数返回函数值,这种函数可以定义为“空类型”(也称“无值型”),其类型说明符为void。

习题3参考答案

一、选择题 1.C 2.B 3.B 4.D

二、填空题

1.4字节,1字节,4字节,8字节 2.20 3.6

4.26

5.256

三、简答题

1.C语言的基本类型包括整型、实型(浮点型)、字符型和枚举型。

2.定义符号常量和定义变量都要指定数据类型,系统将为其分配一定的存储空间。其不同之处在于:定义符号常量必须给出常量值,且以后不能修改本常量的值;而变量可以在定义变量的同时赋初值,以后可以修改该变量。

3.常量就是在程序的运行过程中该量是不可修改的量;变量在程序的运行过程中允许对该变量的值进行修改。

四、程序题

1.程序运行结果为: 10 10 11-10-11 2.程序运行结果为:

3,12,4,4

习题4参考答案

一、选择题

1.C 2.D 3.C 4.C 5.B 6.D 7.B 8.C 9.B

二、填空题

1.!&&

||

2.0 1 3.1 4.4 5.-1

三、编程题

1.给出等级成绩′A′、′B′、′C′、′D′、′E′,假设,90分以上为′A′,80~89分为′B′,70~79分为′C′,60~69分为′D′,60分以下为′E′,输入一个等级成绩,问属于哪一个分数段。参考代码如下: main(){

int score,m,n;

char grade;

n=1;

while(n)

{ printf(“Please enter the score:”);

scanf(“%d”,&score);

if((score>100)||(score<0))printf(“n Wrong!n”);

else n=0;

}

if(score==100)m=9;

else m=(score-score%10)/10;

switch(m)

{ case 0:case 1:case 2:case 3:case 4:case 5:grade='E';break;

case 6:grade='D';break;

case 7:grade='C';break;

case 8:grade='B';break;

case 9:grade='A';

}

printf(“score=%d,grade=%cn”,score,grade);}

2.编程序打印出以下图形: 1 121 12321 „

***21 参考代码如下: #include main(){

int i,j;

for(i=1;i<=9;i++)

{

for(j=1;j<=i;j++)

printf(“%d”,j);

for(j=i-1;j>0;j--)

printf(“%d”,j);

printf(“n”);

} } 3.用1元5角钱人民币兑换5分、2分和1分的硬币(每一种都要有)共100枚,问共有几种兑换方案?每种方案各换多少枚? [提示:设5分、2分和1分的硬币各换x,y,z枚,依题意有x+y+z=100,5x+2y+z=150,由于每一种硬币都要有,故5分硬币最多可换28枚,2分硬币最多可换73枚,1分硬币可换100-x-y枚,x,y,z只需满足第2个方程即可打印,对每一组满足条件的x,y,z值,用计数器计数即可得到兑换方案的数目。] 参考代码如下: main(){

int x,y,z,s=0;

for(x=1;x<=28;x++)

for(y=1;y<=73;y++)

for(z=1;z<=148;z++)

{

if(150==5*x+2*y+z)

if(100==x+y+z){

printf(“x=%d y=%d z=%dn”,x,y,z);

s++;}

}

printf(“s=%dn”,s);}

4.编程:从键盘输入正整数n,输出1+(1+2)+(1+2+3)+„„+(1+2+3+„+n)。参考代码如下: #include main(){ int n,i,s=0,t=0;printf(“Please enter n=”);scanf(“%d”,&n);for(i=1;i<=n;i++)

{

t=t+i;

s=s+t;

} printf(“s=%dn”,s);}

习题5参考答案

一、选择题

1.B 2.A 3.A 4.D 5.C 6.B 7.A 8.A

二、填空题

1.按行的顺序依次存放的 2.0 3.4 4.6

三、编程题

1.有一个多项式:Pn(x)=a0xn+a1xn-1+„+an

它们的系数a0,a1,„,an存放在一个一维数组中。编制程序,输入系数和x的值,计算并输出Pn(x)。参考代码如下: #define N 4 main(){ int a[N+1],p,x,i;

printf(“Please enter a[%d],...,a[0]:n”,N);

for(i=N;i>=0;i--)

scanf(“%d”,&a[i]);

printf(“Please enter x=n”);

scanf(“%d”,&x);

p=a[N];

for(i=N;i>0;i--)

{

p=p*x+a[i-1];

}

printf(“Pn(x)=%dn”,p);} 2.打印以下的杨辉三角形(要求打印6行)。1 11 121 1331 14641 15101051 参考代码如下: #include #include #define N 6 main(){

int i,j,max[N][N];

for(i=0;i

{

for(j=0;j

{ max[i][0]=1;

max[i][i]=1;

}

}

for(i=2;i

{

for(j=1;j

{ max[i][j]=max[i-1][j-1]+max[i-1][j];}

}

for(i=0;i

{

for(j=0;j<=i;j++)

{ printf(“%d”,max[i][j]);}

printf(“n”);

} } 3.编写程序,将一个数插入到有序的数列中去,插入后的数列仍然有序。参考代码如下:/*假设原有5个数*/ #include

main()

{ int a[6]={1,2,6,10,15};

int n,i,j;

printf(“Please enter the insert number:”);

scanf(“%d”,&n);

for(i=0;i<5;i++)

if(n>a[i])

continue;

else

break;

for(j=4;j>=i;j--)

a[j+1]=a[j];

a[i]=n;

for(i=0;i<6;i++)

printf(“%d,”,a[i]);

printf(“n”);

}

4.编写程序,在有序的数列中查找某数,若该数在此数列中,则输出它所在的位置,否则输出no found。参考代码如下: #include

main()

{ int a[10]={1,2,3,4,5,6,7,8,9,10};

int n,i,j,k=0;

printf(“Please enter the number:”);

scanf(“%d”,&n);

for(i=0;i<10;i++)

{ while(n==a[i]){k=1;j=i;break;}

}

if(k==1)

printf(“a[%d]n”,j);

else

printf(“no found.n”);} 5.编程将下列矩阵中的元素向右移动一列,最右一列移至第一列。

10 12 [提示:用二维数组v存放矩阵中元素,数组v可在定义时初始化;有两种方法实现这种移动:一种方法是将移动后的元素放在另一个二维数组中;另一种方法是利用一个中间变量仍将移动后的元素放在数组v中。] #include void main(){ int i,j;

int a[2][3]={1,4,6,8,10,12};

int b[2][3];

b[0][0]=a[0][2];

b[0][1]=a[0][0];

b[0][2]=a[0][1];

b[1][0]=a[1][2];

b[1][1]=a[1][0];

b[1][2]=a[1][1];

printf(“a[2][3]:”);

for(i=0;i<2;i++)

{ printf(“n”);

for(j=0;j<3;j++)

printf(“%5d”,a[i][j]);

}

printf(“nresult:n”);

for(i=0;i<2;i++)

{ printf(“n”);

for(j=0;j<3;j++)

printf(“%5d”,b[i][j]);

}

printf(“n”);

getch();} 6.利用公式c(i,j)a(i,j)b(i,j)计算m×n的矩阵A和m×n的矩阵B之和,已知a(i,j)为矩阵A的元素,b(i,j)为矩阵B的元素,c(i,j)为矩阵C的元素,i1,2,...,m,j1,2,...,n。[提示:用二维数组元素做函数参数编程实现矩阵相加。] #include #include #define M 2 #define N 2 int a[M][N];int b[M][N];int c[M][N];void matrix(int a[][M],int b[][N]);main(){

int i,j,t;

clrscr();

printf(“Please input a[%d][%d]n”,M,N);

for(i=0;i

for(j=0;j

{ scanf(“%d”,&t);

a[i][j]=t;

}

printf(“Please input b[%d][%d]n”,M,N);

for(i=0;i

for(j=0;j

{ scanf(“%d”,&t);

b[i][j]=t;

}

matrix(b,c);

printf(“a[%d][%d]”,M,N);

for(i=0;i

{ printf(“n”);

for(j=0;j

printf(“%5d”,a[i][j]);

}

printf(“n”);

printf(“b[%d][%d]”,M,N);

for(i=0;i

{ printf(“n”);

for(j=0;j

printf(“%5d”,b[i][j]);

}

printf(“n”);

printf(“c[%d][%d]=A+B:”,M,N);

for(i=0;i

{ printf(“n”);

for(j=0;j

printf(“%5d”,c[i][j]);

} } void matrix(int a[][M],int b[][N]){ int i,j,k,t;

for(i=0;i

for(j=0;j

c[i][j]=a[i][j]+b[i][j];}

习题6参考答案

一、选择题

1.A 2.D 3.D

二、填空题

1.指针

取地址 2.3 3.9876

876 4.24

三、编程题

1.输入3个整数,按从大到小的次序输出。参考代码如下: main(){

int a[3],i,j,t;

printf(“Please enter three number:n”)

for(i=0;i<3;i++)

scanf(“%d”,&a[i]);

for(i=0;i<2;i++)

for(j=0;j<2;j++)

if(a[j]

{ t=a[j];a[j]=a[j+1];a[j+1]=t;}

for(i=0;i<3;i++)

printf(“%dn”,a[i]);} 2.编写将n阶正方矩阵进行转置的函数。在主函数中对一个4行4列的矩阵调用此函数。参考代码如下: int array[4][4];convert(int array[4][4]){

int i,j,t;

for(i=0;i<4;i++)

for(j=i+1;j<4;j++)

{

t=array[i][j];

array[i][j]=array[j][i];

array[j][i]=t;

} } main(){ int i,j;printf(“Input array:n”);for(i=0;i<4;i++)

for(j=0;j<4;j++)

scanf(“%d”,&array[i][j]);printf(“noriginal array :n”);for(i=0;i<4;i++)

{ for(j=0;j<4;j++)

printf(“%5d”,array[i][j]);

printf(“n”);} convert(array);printf(“convert array:n”);for(i=0;i<4;i++)

{ for(j=0;j<4;j++)

printf(“%5d”,array[i][j]);

printf(“n”);

} } 3.有三个整型变量i,j, k,请编写程序,设置三个指针变量p1,p2,p3,分别指向i, j,k。然后通过指针变量使i,j,k三个变量的值顺序交换,即把i的原值赋给j,把j的原值赋给k,把k的原值赋给i。要求输出i,j, k的原值和新值。参考代码如下: main(){

int i, j , k, temper;

int *p1, *p2, *p3;

printf(“Please input 3 integers:n”);

scanf(“%d%d%d”,&i, &j, &k);

p1=&i;p2=&j;p3=&k;

printf(“before changed ,the 3 numbers are:n”);

printf(“i=%d, j=%d,k=%dn”,i, j, k);

temper=*p1;*p1=*p3;*p3=*p2;*p2=temper;

printf(“after changed ,the 3 numbers are:n”);

printf(“i=%d, j=%d,k=%dn”,i, j, k);}

4.用指针编写程序,把输入的字符串按逆顺序输出。参考代码如下: #include #include char *s=“1a2b3c4d”;void main(){

int i,j;

char t;

for(i=0,j=strlen(s)-1;i

{

t=s[i];

s[i]=s[j];

s[j]=t;

}

printf(“%sn”,s);}

习题7参考答案

一、选择题 1.C 2.B 3.C

二、填空题 1.float 2.自动(auto)3.12 4.9.000000

二、编程题

1.编写函数,已知三角形的三个边长,求三角形的面积。参考代码如下: #include #include main(){

float a,b,c,s,area;

printf(“Please enter three sides:n”);

scanf(“%f,%f,%f”,&a,&b,&c);

if(a+b>c&&b+c>a&&a+c>b)

{

s=(a+b+c)/2;

area=sqrt(s*(s-a)*(s-b)*(s-c));

printf(“area=%.2fn”,area);

}

else printf(“It is not a triangle!n”);}

2.编程计算p=k!(m-k)!的值。参考代码如下: #include void main(){

int k,m;

long p;

printf(“Please enter k,m:”);

scanf(“%d,%d”,&k,&m);

p=f(k)*f(m-k);

printf(“%dn”,p);} int f(int n){

if(n>1)

return n*f(n-1);

else

return 1;}

3.写一函数,使给定的一个二维数组(3×3)转置,即行列互换。并在主函数中调用该函数时,使用数组作为实际参数。参考代码如下: #define N 3 int array[N][N];convert(int array[N][N]){

int i,j,t;

for(i=0;i

for(j=i+1;j

{

t=array[i][j];

array[i][j]=array[j][i];

array[j][i]=t;

} } main(){ int i,j;printf(“Input array(3*3):n”);for(i=0;i

for(j=0;j

scanf(“%d”,&array[i][j]);printf(“noriginal array:n”);for(i=0;i

{ for(j=0;j

printf(“%5d”,array[i][j]);

printf(“n”);} convert(array);printf(“convert array:n”);for(i=0;i

{ for(j=0;j

printf(“%5d”,array[i][j]);

printf(“n”);

} }

4.设计一个函数,用以计算下面数列前n项之和(以n为形参变量)。2/

1、3/

2、5/

3、8/

5、13/

8、21/

13、„。参考代码如下: #define N 6 main(){

int n=N,i=1;

float s=0;

while(i<=n)

{

s=s+(i+1.0)/i;

i++;

}

printf(“s(%d)=%.5fn”,n,s);}

5.如果一个数恰好等于它的因子之和,则该数称为“完数”。例如:6的因子是1、2、3,而6=1+2+3。编程序输出1000之内的所有完数。输出形式是:“6它的因子是1,2,3”。参考代码如下: main(){

static int k[100];

int i,j,n,s;

for(j=2;j<1000;j++)

{

n=-1;

s=j;

for(i=1;i

{

if((j%i)==0)

{

n++;

s=s-i;

k[n]=i;

}

}

if(s==0)

{

printf(“%d is a wanshu”,j);

for(i=0;i

printf(“%d,”,k[i]);

printf(“%dn”,k[n]);

}

} }

一、选择题

1.C 2.A 3.A 4.B

二、填空题

8参考答案

习题1.pt=s1;pt->student.no=1001;2.0,1,2,100,101,102 3.结构体变量

4.Four, Three,Four

三、编程题

1.有10个学生,每个学生的数据包括学号(num)、姓名(name[9])、性别(sex)、年龄(age)、三门课成绩(score[3]),要求在main()函数中输入这10个学生的数据,并对每个学生调用函数count()计算总分。参考代码如下: #include #include #define N 2 struct student { int num;char name[9];char sex;int age;int score[3];}stu[N];main(){ int count(int s[]);

int i,j;

for(i=1;i<=N;i++)

{

printf(“num:”);

scanf(“%d”,&stu[i].num);

printf(“name:”);

scanf(“%s”,&stu[i].name);

printf(“sex:”);

scanf(“%s”,&stu[i].sex);

printf(“age:”);

scanf(“%d”,&stu[i].age);

for(j=0;j<3;j++)

{ printf(“score[%d]:”,j+1);scanf(“%d”,&stu[i].score[j]);

}

}

for(i=1;i<=N;i++)

printf(“stu[%d] sum=%dn”,i,count(stu[i].score));} int count(int s[])

{

int i,sum=0;

for(i=0;i<3;i++)

sum=sum+s[i];

return sum;

}

2.口袋中有若干红、黄、蓝、白、黑5种颜色的球,每次从口袋中取出3个球,编程打印出得到3种不同颜色的球的所有可能取法。参考代码如下: main(){ enum color{red,yellow,blue,white,black};

enum color i,j,k,pri;

int n=0,loop;

for(i=red;i<=black;i++)

for(j=red;j<=black;j++)

if(i!=j)

{ for(k=red;k<=black;k++)if((k!=i)&&(k!=j))

{ n=n+1;

printf(“%-4d”,n);

for(loop=1;loop<=3;loop++)

{ switch(loop)

{ case 1:pri=i;break;

case 2:pri=j;break;

case 3:pri=k;break;

default:break;

}

switch(pri)

{ case red: printf(“%-10s”,“red”);break;

case yellow: printf(“%-10s”,“yellow”);break;

case blue: printf(“%-10s”,“blue”);break;

case white: printf(“%-10s”,“white”);break;

case black: printf(“%-10s”,“black”);break;

default:break;

}

}

printf(“n”);

}

} printf(“ntotal:%5dn”,n);} 3.25个人围成一个圈,从第1个人开始顺序报号,凡报号为3和3的倍数者退出圈子,找出最后留在圈子中的人原来的序号。参考代码如下: #include main(){ int *a;

int i,j,position=1,total=0,chage;

a=(int *)malloc(25*sizeof(int));

for(i=0;i<25;i++)

a[i]=i+1;

while(1)

{ position+=2;

while(position>25-total)

position=position-25+total;

chage=a[position-1];

for(j=position;j<25-total;j++)

a[j-1]=a[j];

a[25-total-1]=chage;

total++;

if(total==25)

{ for(i=0;i<25-1;i++)printf(“%d->”,a[25-i-1]);printf(“%dn”,a[0]);printf(“the last one is %dn”,a[0]);return 0;

}

} }

4.建立一个链表,每个结点包括:学号、姓名、成绩。(1)输入一个学号,检索该学生的有关信息;(2)从链表中删去成绩低于40分的学生。参考代码如下: #include #include struct stu {

int no;

char name[9];

int score;

struct stu *next;};struct stu *create(){ struct stu *head,*p,*q;

int n,s;

head->next=NULL;

p=head;

while(1)

{ printf(“no,name,score:”);

scanf(“%d,%s,%d”,&n,&s);

if(n==0&&s==0)

break;

else

{ q=(struct stu *)malloc(sizeof(struct stu));

q->no=n;q->score=s;q->next=NULL;

p->next=q;p=q;

}

}

return head;} struct stu *search(struct stu *h,int n){ struct stu *p=h->next;

while(p!=NULL&&P->NO!=n)

p=p->next;

return p;} struct stu *delete(struct stu *head,char *s){

struct stu *p1,*p2;

if(head==NULL){

printf(“nempty list!n”);

goto end;} p1=head;while(pi->score>40 && p1->next!=NULL){ p2=p1;p1=p1->next;

free(p1);

}

return head;} main(){ int n;

struct stu *q;

printf(“enter number:”);

scanf(“%d”,&n);

q=create(n);

printf(“list:n”);

while(q!=NULL)

{

printf(“%sn”,q->name);

q=q->next;

} }

习题9参考答案

一、选择题

1.D 2.C 3.A

二、填空题 1.L=18.849558

S=28.274337

三、解答题

预处理命令的功能是什么?包括哪几部分?#include预处理命令的两种格式分别为什么? 答:预处理命令的功能是告诉编译系统在对源程序进行编译之前应该做些什么。预处理命令主要包括文件包含、宏定义和条件编译三个部分。#include预处理命令

格式一:#include<包含文件名> 格式二:#include”包含文件名”

习题10参考答案

一、选择题

1.C 2.B 3.A

二、填空题 1.二进制文件 2.顺序 随机 3.hello, 4.picursound

三、编程题

1.从键盘输入学生姓名,寻找学生记录是否存在,并输出相应信息。参考代码如下: #include #include #define N 10 struct student {

char name[9];

int num;

int age;

char sex;}stu[N];void main(){ int i;

char s[10];

FILE *fp;

if((fp=fopen(“stu”,“rb”))==NULL)

{ printf(“Can not open file!n”);

exit(0);

}

gets(s);

for(i=0;i

{ fseek(fp,i*sizeof(struct student),0);

fread(&stu[i],sizeof(struct student),1,fp);

while(s==stu[i].name)

printf(“%s,%d,%d,%dn”,stu[i].name,stu[i].num,stu[i].age,stu[i].sex);

}

fclose(fp);} 2.有两个磁盘文件a和b,各存放一行字母。要求将两个文件的内容读到内存中,并将其合并到一起(按字母顺序排列),然后输出到一个新文件。参考代码如下: #include “stdio.h” main(){ FILE *fp;

int i,j,n;

char c[160],t,ch;

if((fp=fopen(“A”,“r”))==NULL)

{ printf(“file A cannot be openedn”);

exit(0);

}

printf(“n A contents are :n”);

for(i=0;(ch=fgetc(fp))!=EOF;i++)

{ c[i]=ch;putchar(c[i]);

}

fclose(fp);

if((fp=fopen(“B”,“r”))==NULL)

{ printf(“file B cannot be openedn”);

exit(0);

}

printf(“n B contents are :n”);

for(i=0;(ch=fgetc(fp))!=EOF;i++)

{ c[i]=ch;

putchar(c[i]);

}

fclose(fp);

n=i;

for(i=0;i

for(j=i+1;j

if(c[i]>c[j])

{ t=c[i];c[i]=c[j];c[j]=t;}

printf(“n C file is:n”);

fp=fopen(“C”,“w”);

for(i=0;i

{ putc(c[i],fp);

putchar(c[i]);

}

fclose(fp);}

3.编写将字符串“Turbo C”、“BASIC”、“FORTRAN”、“COBOL”以及“PL_1”写入文件中去的程序。参考代码如下: #include #include #define N 30 void main(){ FILE *fp;

char c,file[N];

scanf(“%s”,file);

if((fp=fopen(file,“w”))==NULL)

{ printf(“Can not open filen”);

exit(0);

}

c=getchar();

c=getchar();

while(c!='n')

{ fputc(c,fp);putchar(c);

c=getchar();

}

putchar(N);

fclose(fp);}

4.设文件student.dat中存放着学生的基本情况,这些情况由以下结构体描述: struct student { long int num;/*学号*/ char name[10];/*姓名*/ int age;/*年龄*/ char speciality[20];/*专业*/ };

请编写程序,输出学号在97010~97020之间的学生学号、姓名、年龄和专业。参考代码如下: #include “stdio.h” struct student

{ long int num;

char name[10];

int age;

char speciality[20];

};

FILE *fp;

main()

{ struct student st;

fp=fopen(“student.dat”,“rb”);

if(fp==NULL)

printf(“file not foundn”);

else

{ while(!feof(fp))

{ fread(&st,sizeof(struct student),1,fp);

if(st.num>=970101&&st.num<=970135)

printf(“%ld,%s,%d,%sn”,st.num,st.name,st.age,st.speciality);

}

} }

第二篇:C语言程序设计教程课后习题答案

C语言程序设计教程课后习题答案

第一章 C语言程序设计概述 -习题答案 算法的描述有哪些基本方法?

1、自然语言

2、专用工具C语言程序的基本结构是怎样的?举一个例子说明。

1、C语言程序由函数构成;

2、“/*”与“*/”之间的内容构成C语言程序的注释部分;

3、用预处理命令#include、#define可以包含有关文件或预定义信息;

4、大小写字母在C语言中是有区别的;

5、除main()函数和标准库函数外,用户也可以自己编写函数,应用程序一般由多个函数组成,这些函数指定实际所需要做的工作。C语言有什么特点?

1、具有结构语言的特点,程序之间很容易实现段的共享;

2、主要结构成分为函数,函数可以在程序中被定义完成独立的任务,独立地编译代码,以实现程序的模块化;

3、运算符丰富,包含的范围很广;

4、数据类型丰富;

5、允许直接访问物理地址,即可直接对硬件进行损伤,实现汇编语言的大部分功能;

6、限制不太严格,程序设计自由度大,这样使C语言能够减少对程序员的束缚;

7、生成的目标代码质量,程序执行效率高,同时C语言编写的程序的可移植性好。★指出合法与不合法的标识符命名。

AB12--√ leed_3--a*b2--× 8stu--× D.K.Jon--× EF3_3--√ PAS--√ if--× XYZ43K2--√ AVE#XY--× _762--√ #_DT5--× C.D--×说明下列Turbo C热键的功能。

F2:源文件存盘 F10:调用主菜单 F4:程序运行到光标所在行(用于调试程序)Ctrl+F9:编译并链接成可执行文件 Alt+F5:将窗口切换到 DOS 下,查看程序运行结果。说明下列Turbo C方式下输入并运行下列程序,记录下运行结果。

①main()

{printf(“********************n”);printf(“ welcome you n”);printf(“ very good n);printf(”********************n“);} ②main()

{ int a,b,c,t;printf(”please input three numbers;“);scanf(”%d,%d,%d“,&a,&b,&c);/*教材S是错误的*/ t=max(max(a,b),c);printf(”max number is:%dn“,t);} int max(int x, int y){ int z;if(x>y)z=x;else z=y;return(z);} 答

运行结果:

******************** welcome you very good ******************** 运行结果:

please input three numbers;3,1,4 /*左侧下划线内容为键盘输入*/ max number is:4 7 一个C程序是由若干个函数构成的,其中有且只能有一个___函数。

main()8 在Turbo C环境下进行程序调试时,可以使用Run下拉菜单的___命令或按___键转到用户屏幕查看程序运行结果。

1、User screen

2、Alt+F5 9 ★C语言对标识符与关键字有些什么规定?

1、标识符用来表示函数、类型及变量的名称,它是由字母、下划线和数字组成,但必须用字母或下划线开头。

2、关键字是一种语言中规定具有特定含义的标识符,其不能作为变量或函数名来使用,用户只能根据系统的规定使用它们。C源程序输入后是如何进行保存的?

是以C为扩展名保存的纯文本文件。

第二章 C语言程序的基本数据类型与表达式 -习题答案 ★指出下列常数中哪些是符合C语法规定的。

''--× '101'--× ”“--× e3--× 019--√ 0x1e--√ ”abn“--√ 1.e5--×(2+3)e(4-2)--× 5.2e2.5--×请找出下列程序中的错误,改正后写出程序运行结果。

①void main(){int x,y=z=5,aver;x=7 AVER=(x+y+z)/3 printf(”AVER=%dn“,aver);} ②void main()

{ char c1='a';c2='b';c3='c';int a=3.5,b='A' printf(”a=%db='“endn”,a,b);printf(“a%cb%cbc%ctabcn”,c1,c2,c3);} 答

main(){int x,y=5,z=5,aver;x=7;aver=(x+y+z)/3;printf(“AVER=%dn”,aver);}

运行结果:AVER=5 ②main()

{ char c1='a', c2='b', c3='c';int a=3,b='A';printf(“a=%d,b='%c'”end“n”,a,b);printf(“a%cb%cbc%ctabcn”,c1,c2,c3);}

运行结果:a=3,b='A'“end”

aabcc abc 3 写出下列赋值的结果,表格中写了数值的是要将它赋给其他类型的变量,将所有的空格填上赋值后的数据(实数保留到小数点后两位)。int 99

-1 char 'h'

unsigned int

float

55.78

long int

答 int 99 104 66 55 68-1 char 'c' 'h' 'B' '7' 'D'

unsigned int 99 104 66 55 68 65535

float 99.00 104.00 66.00 55.78 68.00-1.00

long int 99 104 66 55 68-1

★写出程序运行结果。

①void main(){int i,j;i=8,j=10;printf(“%d,%d,%d,%dn”,i,j,++i,j++);} ②main()

{ int a=1,b=2,c=30;;printf(“%d,%d,%d,%dn”,a=b=c,a=b==c,a==(b=c),a==(b==c));} 注意:a=b=c,a=b==c之间应为逗号,教材有误 答

运行结果: 9,11,9,10 运行结果: 30,1,0,0

③void main()

{int a=10,b=20,c=30,d;d=++a<=10||b-->=20||c++;printf(“%d,%d,%d,%dn”,a,b,c,d);}

运行结果: 11,19,30,1

★写出下面表达式的值(设a=10,b=4,c=5,d=1,x=2.5,y=3.5)。⑴a%=(b%=3)

⑵n++,a+=a-=a*=a ⑶(float)(a+c)/2+(int)x%(int)y ⑷a*=b+c ⑸++a-c+b++ ⑹++a-c+++b ⑺a

⑼a+b,18+(b=4)*3,(a/b,a%b)

⑽x+a%3*(int)(x+y)%2/4+sizeof(int)⑾a

⑴0 ⑵0 ⑶9.500000 ⑷90 ⑸10 ⑹10 ⑺'A' ⑻2 ⑼4.5 ⑽1 ⑾0 ⑿20 ⒀0 下列每组表达式中,被执行后结果完全等价的是哪些(设a、b、m是已被赋值的整型变量)?

①m=(a=4,4*5)与m=a=4,4*5 ②(float)(a/b)与(float)a/b ③(int)a+b与(int)(a+b)④m%=2+a*3与m=m%2+a*3 ⑤m=1+(a=2)+(b=3)与a=2,b=3,m=1+a+b 答

①前面是赋值表达式,而后面的是一个逗号表达式,所以一定不同;

②前面的表达式中a/b结果为一整数,结果已经取整,精度可能受到影响,之后强制float后才为浮点型,后面的是先将a转换为float后再与b相除,其值保证了精度,所以不同。

③因为a、b均为整数,其前后两个表达式的计算结果是一致的。

④前一表达式是一算术表达式,而后者为一赋值表达式,此为一点不同;另外,前一表达式的m只被赋过一次值,后一表达式中的m曾两次被赋值,第一次赋值时与第一表达式中的值一致,第二次赋值后即不再相同。⑤前后表达式的计算结果应该是一致的:a=2, b=3, m=6 7 条件表达式x>0?x:-x的功能是什么?

如果x的值是一正数,则表达式的值为x值;如果x的值是一非正数,则表达式的值为-x。其实该表达式的值即为x的绝对值,C语言中提供了一个函数fabs(x)即可完成此功能,该函数包含在math.h头文件中。用一个条件表达式描述从a、b、c中找出最大都赋给max.答

max=a>(b>c?b:c)?a:(b>c?b:c);9 ★若x为int型变量,则执行以下语句后x的值为()。x=6;x+=x-=x*x;A.36 B.-60 C.60 D.-24 答 B.10 ★若有以下类型说明语句: char w;int x;float y;double z;则表达式w*x+z-y的结果为()类型。A.float B.char C.int D.double 答 D.第三章 顺序结构程序设计 -习题答案 变量k为float类型,调用函数scanf(“%d”,&k),不能使变量k得到正确数值的原因是___。

格式修饰符与变量类型不一致。因为%d输入的数据类型应该为十进制整数,而&k为占用4个字节的float类型变量的地址。★a=1234,b=12,c=34,则执行“printf(“|%3d%3d%-3d|n”,a,b,c);”后的输出是___。

|1234 1234 |

分析如下:

①%3d为右对齐输出变量,且指定输出变量的值宽度为3个字符位,如果变量实际位数小于3,则左端补空格,如果变量实际位数大于3,则按实际长度输出,不受限制。

②%-3d为左对齐输出变量,在输出变量时,如是变量实际位数小于3,则在右端补空格,否则按实际输出。★设有“int a=255,b=8;”,则“printf(“%x,%on”,a,b);”输出是___。答 ff,10 ①如果“printf(“%X,%on”,a,b);”则输出为FF,10。说明在输出十六进制字母时,其大小写受格式修饰符的限制,如果是“%x”则输出小写,如果是“%X”则输出大写。

②如果希望在输出十六进制时输出前导符0x或0X,则以上输出语句应改“printf(“%#x,%on”,a,b);”为或“printf(“%#X,%on”,a,b);”。本条解释不必须掌握。★以下程序输出的结果是___。main(){ int a1=1,a2=0,a3=2;printf(“%d,%d,%dn”,a1,a1+a2+a3,a3-a1);} 答 1,3,1 5 printf函数中用到格式符%5s,其中5表示输出字符占用5列。如果字符串长度大于5,则按___输出;如果字符串长度小于5,则按___输出。

①实际 ②左端补空格 6 ★已定义变量如下: int a1,a2;char c1,c2;若要求输入a1、a2、c1和c2的值,正确的输入函数调用语句是___。

scanf(“%d,%d,%c,%c”,&a1,&a2,&c1,&c2);7 输入两个整型变量a、b的值,输出下列算式以及运算结果___。a+b、a-b、a*b、a/b、(float)a/b、a%b 每个算式占一行。如a=10,b=5,a+b输出为:10+5=15 答

设int a=10,b=5;以下为输出语句及结果: ①printf(“%d+%d=%dn”,a,b,a+b);10+5=15 ②printf(“%d-%d=%dn”,a,b,a-b);10-5=5 ③printf(“%d*%d=%dn”,a,b,a*b);10*5=50 ④printf(“%d/%d=%dn”,a,b,a/b);10/5=2 ⑤printf(“%(float)d/%d=%fn”,a,b,(float)a/b);(float)10/5=2.000000 ⑥printf(“%d%%%d=%dn”,a,b,a%b);10%5=0 8 ★输入一个非负数,计算以这个数为半径的圆周长和面积。答

#define PI 3.1415926 main(){ float r,l,area;printf(“Input a positive:”);scanf(“%f”,&r);l=2*PI*r;area=PI*r*r;printf(“l=%ftarea=%fn”,l,area);} 9 输入任意一个3位数,将其各位数字反序输出(例如输入123,输出321)。

main(){ int x,y;printf(“Input a number(100-999):”);scanf(“%d”,&x);y=100*(x%10)+10*(x/10%10)+x/100;/*注意分析此处算法*/

第三篇:c语言程序设计课后习题答案 第7章

/*练习7-1*/ #include main(){ int a[10],n,sum=0,i;float ave;printf(“enter n:n”);scanf(“%d”,&n);printf(“enter %d ge zheng shu:n”,n);for(i=0;i

scanf(“%d”,&a[i]);

sum=sum+a[i];

} ave=1.0*sum/n;printf(“ave=%.2fn”,ave);}

/*练习7-2*/ #include main(){

int a[10],n,i;printf(“enter n:n”);scanf(“%d”,&n);printf(“enter %d ge zheng shu:n”,n);for(i=0;i

printf(“第%d个:n”,i+1);

scanf(“%d”,&a[i]);

printf(“倒序:n”);

while(a[i]!=0)

{

printf(“%d”,a[i]%10);

a[i]=a[i]/10;

}

printf(“n”);} } /*练习7-3*/ #include main(){

int a[5],x,i,k=0;printf(“enter 5 ge zheng shu:n”);for(i=0;i<5;i++)

scanf(“%d”,&a[i]);printf(“enter x:n”);scanf(“%d”,&x);

for(i=0;i<5;i++)

if(a[i]==x)

{

printf(“xia biao wei : %dn”,i);

k=1;

}

if(k==0)

printf(“Not Foundn”);}

/*练习7-4*/ #include main(){

int a[10],n,i,k=0,x,max;printf(“enter n:n”);scanf(“%d”,&n);printf(“enter %d ge zheng shu:n”,n);for(i=0;i

scanf(“%d”,&a[i]);max=a[0];for(i=1;i<=n-1;i++)

if(max

{

max=a[i];

k=i;

}

printf(“max=%d

xia biao=%d”,max,k);

x=a[n-1];

a[n-1]=a[k];

a[k]=x;

printf(“n”);

for(i=0;i

printf(“

%d

”,a[i]);

printf(“n”);}

/*练习7-11*/ #include main(){ char str[80];int i,j,count=0;printf(“输入一个以回车符结束的字符串:n”);i=0;while((str[i]=getchar())!='n')

i++;str[i]='';printf(“再输入一个字符:n”);str[80]=getchar();for(j=0;j<=i-1;j++)

if(str[80]==str[j])

count++;printf(“%c字符在字符串中出现的次数为:%dn”,str[80],count);for(j=0;j<=i-1;j++)

putchar(str[j]);printf(“n”);

}

/*习题七 1*/ #include main(){ int x,y,n,a[10],i,min,max;printf(“输入 n:n”);scanf(“%d”,&n);printf(“输入%d个整数:n”,n);for(i=0;i

scanf(“%d”,&a[i]);min=0;for(i=1;ia[i])

min=i;max=0;for(i=1;i

max=i;x=a[min];a[min]=a[0];a[0]=x;

y=a[max];a[max]=a[n-1];a[n-1]=y;for(i=0;i

printf(“%4d”,a[i]);

printf(“n”);

}

/*习题七 2*/ #include main(){ int x,n,a[10],i,j,max;printf(“输入 n:n”);scanf(“%d”,&n);printf(“输入%d个整数:n”,n);for(i=0;i

scanf(“%d”,&a[i]);

for(i=1;i

max=i-1;

for(j=i;j

max=j;x=a[max];a[max]=a[i-1];a[i-1]=x;} for(i=0;i

printf(“%4d”,a[i]);

printf(“n”);

}

/*习题七 4*/ #include main(){ int m,n,a[6][6],i,j,b[6]={0};

printf(“输入m:n”);scanf(“%d”,&m);printf(“输入n:n”);scanf(“%d”,&n);

printf(“输入%d和%d的矩阵:n”,m,n);for(i=0;i

for(j=0;j

{scanf(“%d”,&a[i][j]);

b[i]=b[i]+a[i][j];} } printf(“shu chu:n”);

for(i=0;i

for(j=0;j

printf(“

%d”,a[i][j]);

printf(“n”);} printf(“shu chu hang he :n”);for(i=0;i

printf(“%4d”,b[i]);

printf(“n”);

}

/*习题7.6*/ #include main(){ char str[80];int i,j;printf(“输入一个以回车符结束的字符串:n”);i=0;while((str[i]=getchar())!='n')

i++;printf(“倒序输出:n”);

for(j=i-1;j>=0;j--)

putchar(str[j]);

printf(“n”);

}

/*新7.6*/ #include main(){ int a[10],i,n;printf(“输入整数n:n”);scanf(“%d”,&n);printf(“输入%d个整数:n”,n);for(i=0;i

scanf(“%d”,&a[i]);} printf(“倒序输出:n”);for(i=0;i

/*习题7.7*/ #include main(){ char str[80];int i,j,count=0;printf(“输入一个以回车符结束的字符串:n”);i=0;while((str[i]=getchar())!='n')

i++;printf(“输出其中的大写辅音字母:n”);

for(j=0;j<=i-1;j++)

if(str[j]>='B'&&str[j]<='Z'&&str[j]!='E'&&str[j]!='I'&&str[j]!='O'&&str[j]!='U')

{

putchar(str[j]);

count++;

}

printf(“n”);

printf(“大写辅音字母数量为:%dn”,count);}

/*习题7.8*/ #include main(){ char str[80];int i,j,count=0;printf(“输入一个以回车符结束的字符串:n”);i=0;while((str[i]=getchar())!='n')

i++;printf(“输出相应交换后的字符串:n”);

for(j=0;j<=i-1;j++)

if(str[j]>='A'&&str[j]<='Z')

str[j]=155-str[j];

for(j=0;j<=i-1;j++)

putchar(str[j]);printf(“n”);}

第四篇:C语言程序设计教程 课后习题参考答案

《C语言程序设计教程》

课后习题参考答案

习题1 1.(1)编译、链接

.exe(2)函数

主函数(或main函数)(3)编辑

编译

链接 2.(1)-(5):DDBBC(6)-(10):ABBBC 3.(1)答:C语言简洁、紧凑,使用方便、灵活;C语言是高级语言,同时具备了低级语言的特征;C语言是结构化程序设计语言,具有结构化的程序控制语句;C语言有各种各样的数据类型;C语言可移植性好;生成目标代码质量高,程序执行效率高。

(2)编辑、编译、链接、执行

(3)一个C程序由一或多个函数组成,一函数若干条语句构成,每条语句的末尾必须以分号结束。

(4)标识符,关键字,运算符,分隔符,常量,注释符等 4.从键盘输入一个双精度小数,打印出它的余弦值。#include #include main(){ double x;scanf(“%lf”, &x);printf(“%lfn”, cos(x));}

第2章 1.(1)BDE、ACFG(2)D(3)C(4)C

2.(1)错(2)错(3)错(4)对(5)错 3.(1)a=3,b=-27(2)a=11,b=6,c=6(3)3(4)1 0 1 0 1 1 0(5)-9 9 8(6)1)20 2)8 3)70 4)0 5)0 6)0 4.(1)

#include main(){ double r, h ,v;r = 2.5;h = 3.5;v = 3.14*r*r*h;printf(“v=%lfn”, v);}(2)#include main(){ char ch;ch = getchar();printf(“%cn”, ch + 32);}(3)#include main(){ printf(“

*n”);printf(“

***n”);printf(“ *****n”);printf(“*******n”);}(4)#include main(){ double x;scanf(“%lf”, &x);printf(“%d , %lfn”,(int)x, x –(int)x);}(5)#include main(){ double a=3, b=5;double result =(-2 * a +(4*a – b)/(2*a + b))/((a32);}

第4章 1.(1)-(5):CAACA 2.(1)BBB(2)AAABBBCCC(3)end(4)d=20(5)s=2,t=3(6)first

third(7)y=0 y=5 y=10 y=5 3.(1)y=‟A‟ && ch<=‟Z‟

ch>=‟a‟&&ch<=‟z‟

ch = ch-32(3)x>2&&x<=10

x>-1&&x<=2(4)t=x;x=y;y=t;4.(1)#include main(){ int x, y , z, t;scanf(“%d%d%d”, &x, &y, &z);

if(x>y){ t=x;x=y;y=t;} if(x > z){ t = x;x = z;z= t;} if(y > z){ t = y;y= z;z = t;} printf(“%d %d %dn”, x, y ,z);}(2)#include main(){ int score;scanf(“%d”, &score);

if(score < 0 || score > 100)

printf(“成绩不合理n”);

else if(score>=90)

printf(“优秀n”);

else if(score>=80)

printf(“良好n”);

else if(score >= 70)

printf(“中等n”);

else if(score >= 60)

printf(“及格n”);

else

printf(“不及格n”);}(3)#include main(){ int n;int g,s,b,q;//各位上的数值

scanf(“%d”, &n);

g = n%10;//个位

s = n/10%10;//十位

b = n/100%10;//百位

q = n/1000%10;//千位

if(n < 10)//一位数

{

printf(“%dn”, 1);//位数

printf(“%dn”, g);//各位上的数值

} else if(n < 100)//两位数

{

printf(“%dn”, 2);//位数

printf(“%d %dn”, g,s);} else if(n < 1000)//三位数

{

printf(“%dn”, 3);//位数

printf(“%d %d %dn”, g, s, b);

} else if(n < 10000)//四位数

{

printf(“%dn”, 4);//位数

printf(“%d %d %d %dn”, g, s, b, q);

} }(4)#include main(){ int n;scanf(“%d”, &n);

if(n % 3==0 && n%5==0 && n%7==0)

printf(“能同时被3、5、7整除n”);

else if(n%3==0 && n%5==0)

printf(“能被3和5整除n”);

else if(n%3==0 && n%7==0)

printf(“能被3和7整除n”);

else if(n%5==0 && n%7==0)

printf(“能被5和7整除n”);

else if(n%3==0 || n%5==0 || n%7==0){

if(n%3==0)

printf(“能被3整除n”);

else if(n%5==0)

printf(“能被5整除n”);

else

printf(“能被7整除n”);

} else

printf(“不能被3、5、7中任一个数整除n”);}(5)#include main(){ int

carType;//车型。1代表夏利;2代表富康;3代表桑塔纳

double xiali = 2.1;//每公里价格 double fukang = 2.4;double sangtana = 2.7;double distance;//距离

double totalMoney;//总的收费

printf(“请输入您乘坐的车型:1代表夏利;2代表富康;3代表桑塔纳:”);scanf(“%d”, &carType);printf(“请输入您乘车的总路程:”);scanf(“%lf”, &distance);if(carType == 1)//夏利

{

if(distance < 3)

totalMoney = 7.0;

else

totalMoney = 7 + xiali *(distance – 3);} else if(carType == 2)//富康

{

if(distance < 3)

totalMoney = 8.0;

else

totalMoney = 8 + fukang *(distance – 3);} else if(carType == 3)//富康

{

if(distance < 3)

totalMoney = 9.0;

else

totalMoney = 9 + sangtana *(distance – 3);}

printf(“(四舍五入)您的车费为:%.0lfn”, totalMoney);}(6)#include main(){ double a, b, c;scanf(“%lf%lf%lf”, &a, &b, &c);

if(a+b>c && b+c>a && c+a>b){

if(a==b && b==c)

printf(“等边三角形n”);

else if(a==b || b== c || c==a)

printf(“等腰三角形n”);

else

printf(“一般三角形n”);

} else

printf(“不能构成三角形n”);}

第5章

1.(1)C(2)C(3)K=36(4)C(5)B 2.(1)3次

(2)x>=1 && x<=10 || x>=200&&x<210(3)e == 0(4)6次(5)10 3.(1)20,10(2)16,0(3)7BAB4BAB1BC(4)ABABABC(5)****** ****** ******

****** 4.(1)a!= b

(2)n / 10(3)scanf(“%d”, &a);

5.(3)行

int fac = 1, sum = 0;6.(1)#include main(){ char ch;int alpha=0, space=0, digit=0, other=0;while((ch=getchar())!= „n‟)

{

if(ch>=‟A‟&&ch<=‟Z‟ || ch>=‟a‟&&ch<=‟z‟)

alpha++;

else if(ch>=‟0‟ && ch<=‟9‟)

digit++;

else if(„ „ == ch)

space++;

else

other++;} printf(“%d %d %d %dn”, alpha, digit, space, other);}(2)#include main(){ int m20, m10;for(m20=1;m20<5;m20++){

for(m10 = 1;m10<10;m10++)

if(20*m20+10*m10 == 100)

printf(“%d, %dn”, m20, m10);} }(3)#include main(){ int x, y, z;for(x=0;x<10;x++)

for(y=0;y<10;y++)

for(z=0;z<10;z++)

if(x*100+y*10+z + y*100+z*10+z == 532)

printf(“%d %d %dn”, x, y, z);}(4)#include main(){ int row, spaceCount,starCount;int n;scanf(“%d”, &n);

for(row = 1;row <= n;++row){

for(spaceCount = 1;spaceCount <= n1;++starCount)

printf(“*”);//打印出某行上的所有星号

printf(“n”);//换行

} //打印下半部分

for(row=1;row

for(spaceCount = 1;spaceCount <= row;++ spaceCount)

printf(“ ”);//打印出某行上星号前的空格

for(starCount = 1;starCount <= 2*(n-row)byear;if(nmonth

age--;else if(nmonth == bmonth && nday>bday)

age--;return age;}

(4)

#include int sum(int n);main(){ int n,s;scanf(“%d”, &n);s = sum(n);printf(“s=%dn”, s);}

int sum(int n){ int s=0;while(n){

s += n % 10;

n /= 10;} return s;}

(5)

#include double sumfac(int n);main(){ int n;scanf(“%d”, &n);printf(“%.0lfn”, sumfac(n));} double sumfac(int n){ double f=1.0, s = 0.0;

int i;for(i=1;i<=n;i++){

f *= i;

s += f;} return f;}

(6)

#include int gcd(int m , int n);main(){ int m, n;scanf(“%d%d”, &m, &n);printf(“%dn”, gcd(m ,n));} int gcd(int m, int n){ int t,r;if(m < n){ t = m;m= n;n = t;}

r = m % n;while(r){

m = n;

n = r;

r = m % n;} return n;}

(7)

#include int gcd(int m , int n);int lcm(int m, int n);main(){ int m, n;scanf(“%d%d”, &m, &n);printf(“%dn”, lcm(m ,n));} int gcd(int m, int n){ int t,r;if(m < n){ t = m;m= n;n = t;}

r = m % n;while(r){

m = n;

n = r;

r = m % n;} return n;}

int lcm(int m, int n){ return m*n/gcd(m,n);}

(8)

#include double mypower(double x, int y);main(){ double x;

int y;scanf(“%lf%d”, &x, &y);printf(“%lfn”, mypower(x,y));} double mypower(double x, int y){ int i;double f=1.0;for(i=1;i<=y;i++)

f *= x;return f;}

第7章 1.(1)6(2)5(3)不能

(4)int a[3][2]={{1,2}, {3,4}, {5,6} };(5)6 9(6)abc G 2.(1)

#include

void reverse(int a[ ], int n);

int main()

{

int array[10]={0};

int i;

printf(“请输入10个整数:”);

for(i=0;i<10;i++)

scanf(“%d”, &array[i]);

reverse(array, 10);//调用函数逆序存储数组中的数据

printf(“逆序后的元素为:n”);

for(i=0;i<10;i++)

printf(“%5d”, array[i]);

printf(“n”);

return 0;

}

void reverse(int a[ ], int n)

{

int i;

int tmp;

for(i=0;i

{

tmp = a[i];a[i] = a[n-i-1];

}

}

(2)

#include #include void reverseStr(char str[ ]);main(){ char s[100];gets(s);reverseStr(s);puts(s);}

void reverseStr(char str[ ]){ int i,j;char t;i=0;j=strlen(str)-1;while(i < j){

t = str[i];

a[n-i-1] = tmp;

str[i] = str[j];

str[j] = t;

i++;

j--;} }

(3)

#include int copyTo(int s1[], int n, int s2[ ]);main(){ int s1[10], s2[10];int i,count;for(i=0;i<10;i++)

scanf(“%d”, &s1[i]);count = copyTo(s1, 10, s2);for(i=0;i

printf(“%d ”, s2[i]);printf(“n”);}

int copyTo(int s1[], int n, int s2[ ]){ int i, j=0;for(i=0;i

if(s1[i] % 2)

s2[j++] = s1[i];} return j;}

(4)

#include void copyToStr(char str1[ ], char str2[ ]);main(){ char s1[100], s2[100];gets(s1);copyToStr(s1, s2);puts(s2);} void copyToStr(char str1[ ], char str2[ ]){ int i=0,j=0;while(str1[i]!= ''){

if(str1[i]>='a'&&str1[i]<='z')

{

str2[j] = str1[i];

j++;

}

i++;} str2[j] = '';return j;}

(5)

#include void deleteAll(char str[ ], char ch);main(){ char s[100], ch;gets(s);ch = getchar();deleteAll(s, ch);puts(s);} void deleteAll(char str[ ], char ch){ int i, j;i = 0;

j = 0;while(str[i]){

if(str[i]!= ch)

{

str[j++] = str[i];

}

i++;

} str[j] = '';}

(6)

#include void replaceAll(char str[ ], int ch1, char ch2);main(){ char s[100], c1, c2;gets(s);c1 = getchar();c2 = getchar();replaceAll(s, c1, c2);puts(s);} void replaceAll(char str[ ], int ch1, char ch2){ int i;i = 0;while(str[i]){

if(str[i] == ch1)

str[i] = ch2;

i++;} }

(7)

#include

int transformToBin(int dnum, int bin[ ]);

int main()

{

int array[32]={0};//保存转换后的二进制数

int num;//待转换的整数

int cc;//最后得到的二进制总共多少位

printf(“请输入一个整数:”);

scanf(“%d”, &num);

cc = transformToBin(num, array);//调用转换函数

cc--;//往回退一个元素下标,使cc指向最后一个元素

for(;cc>=0;cc--)//输出转换后的二进制数

printf(“%d”, array[cc]);

printf(“n”);

return 0;

}

int transformToBin(int dnum, int bin[ ]){

int count = 0;while(dnum)//当dnum还未转换完毕

{ bin[count++] = dnum % 2;//余数保留到数组对应元素中

dnum /= 2;//数本身除2 } return count;}

(8)

#include int transformToHex(int dnum, char hex[ ]);int main(){ char array[32];//保存转换后的进制数

int num;//待转换的整数

int cc;//最后得到的进制总共多少位

printf(“请输入一个整数:”);scanf(“%d”, &num);cc = transformToHex(num, array);//调用转换函数

cc--;//往回退一个元素下标,使cc指向最后一个元素

for(;cc>=0;cc--)//输出转换后的进制数

printf(“%c”, array[cc]);printf(“n”);return 0;}

int transformToHex(int dnum, char hex[ ]){ int count = 0;int t;while(dnum)//当dnum还未转换完毕

{

t = dnum % 16;

if(t < 10)

hex[count] = t+'0';//余数保留到数组对应元素中

else

hex[count] = t-10+'A';

count++;dnum /= 16;//数本身除16 } return count;}(9)

#include #include #include

#define M 5 //行 #define N 6 //列

void generate(int a[ ][N], int row, int col);void display(int a[][N], int row, int col);void getMaxEveryRow(int a[][N], int row, int col, int y[]);main(){ int arr[M][N], y[M]={0};int i;generate(arr, M, N);display(arr, M, N);getMaxEveryRow(arr,M,N,y);//输出最大值

for(i=0;i

printf(“%d ”, y[i]);printf(“n”);} void generate(int a[ ][N], int row, int col){ int i,j;srand(time(NULL));for(i=0;i

for(j=0;j

a[i][j] = rand()%101;} void display(int a[][N], int row, int col){ int i,j;for(i=0;i

for(j=0;j

printf(“%4d”, a[i][j]);

printf(“n”);} } void getMaxEveryRow(int a[][N], int row, int col,int y[]){ int i,j;for(i=0;i

y[i] = a[i][0];

for(j=1;j

if(y[i] < a[i][j])

y[i] = a[i][j];} }

(10)

#include #include #include

#define M 5 //行 #define N 6 //列

void generate(int a[ ][N], int row, int col);void display(int a[][N], int row, int col);void getMinEveryCol(int a[][N], int row, int col);main(){ int arr[M][N];int i;generate(arr, M, N);display(arr, M, N);getMinEveryCol(arr,M,N);//输出最小值

for(i=0;i

printf(“%d ”, arr[0][i]);printf(“n”);} void generate(int a[ ][N], int row, int col){ int i,j;srand(time(NULL));for(i=1;i

for(j=0;j

a[i][j] = rand()%101;} void display(int a[][N], int row, int col){ int i,j;for(i=1;i

for(j=0;j

printf(“%4d”, a[i][j]);

printf(“n”);} } void getMinEveryCol(int a[][N], int row, int col){ int i,j;for(i=0;i

a[0][i] = a[1][i];

for(j=2;j

if(a[0][i] > a[j][i])

a[0][i] = a[j][i];} }

第8章 1.(1)局部

(2)void(3)auto(4)auto(5)return(6)递归

(7)求 1!+2!+3!+4!+5!(8)注意全局变量和局部变量的区别

2.(1)

#include #include double xc(double x, double y);main(){ double a, b;double c;scanf(“%lf%lf”, &a, &b);

c = xc(a, b);printf(“ %lfn”, c);} double xc(double x, double y){ return sqrt(x*x+y*y);}

(2)

static extern

register

#include long seconds(int hour, int minute, int second);main(){ int h,m,s;long sec;printf(“输入时间:”);scanf(“%d%d%d”, &h, &m, &s);sec = seconds(h,m,s);printf(“离12点最近的秒数:%ldn”, sec);} long seconds(int hour, int minute, int second){ long s;if(hour < 6){

s = second+minute*60+hour*60*60;} else {

s = 60-second+(60-minute-1)*60+(12-hour-1)*60*60;} return s;}

(3)

#include int fun(int n);main(){ int n;scanf(“%d”, &n);if(fun(n))//是质数,则输出该数;不是的话,不作任何处理

printf(“%dn”, n);} int fun(int n){ int i;for(i=2;i

if(n%i == 0)

break;if(i

return 0;else

return 1;}

(4)

#include int fun(int n);main(){ int n;int count=0;for(n=2;n<1000;n++)

if(fun(n))

{

printf(“%4d”, n);

count++;

if(count % 10 == 0)

printf(“n”);

}

printf(“n”);} int fun(int n){ int i;for(i=2;i

if(n%i == 0)

break;if(i

return 0;else

return 1;}

(5)

#include int func(int n);main(){ int n;scanf(“%d”, &n);printf(“%dn”, func(n));} int func(int n){ if(1 == n)

return 3;return 2*func(n-1)-1;}

(6)

#include int gcd(int m, int n);main(){ int x,y,t;scanf(“%d%d”, &x, &y);if(x < y){

t=x;x=y;y=t;} printf(“%dn”, gcd(x,y));} int gcd(int m, int n){ if(0==n)

return m;return gcd(n, m%n);}

第9章 1.(1)xyzNKT(2)bcdefgh(3)4,4(4)qponmzyx(5)abcCD(6)0 2.(1)

#include #include void reverse(int *p, int n);main(){ int i;int a[10]={1,2,3,4,5,6,7,8,9,10};

reverse(a,10);for(i=0;i<10;i++)

printf(“%d ”, a[i]);printf(“n”);} void reverse(int *p, int n){ int *q;int t;q = p + n1;while(str < pEnd){

t = *str;

*str = *pEnd;

*pEnd = t;

str++;

pEnd--;} }(3)

#include int copyTo(int *s1, int n, int *s2);main(){ int a[10]={1,2,3,4,5,6,7,8,9, 10};int b[10], count,i;count=copyTo(a,10,b);for(i=0;i

printf(“%d ”, b[i]);printf(“n”);} int copyTo(int *s1, int n, int *s2){ int count=0;int *ps1, *ps2;ps2 = s2;for(ps1 = s1;ps1 < s1 + n;ps1++){

if(*ps1 % 2)//奇数

{

*ps2++ = *ps1;

} } return ps2-s2;}

(4)

#include void copyToStr(char *str1, char *str2);main(){ char s1[100], s2[100];gets(s1);copyToStr(s1, s2);puts(s2);} void copyToStr(char *str1, char *str2){ while(*str1){

if(*str1 >= 'a' && *str1 <= 'z')

{

*str2++=*str1;

}

str1++;} *str2 = '';}

(5)

#include void deleteAll(char *str, char ch);main(){ char s[100], c;gets(s);c = getchar();deleteAll(s, c);puts(s);} void deleteAll(char *str, char ch){ char *p;p = str;while(*str){

if(*str!= ch)

*p++ = *str;

str++;} *p = '';}

(6)

#include void replaceAll(char *str, char ch1, char ch2);main(){ char s[100], c1, c2;printf(“输入字符串:”);gets(s);printf(“输入查找字符:”);c1 = getchar();fflush(stdin);//清除键盘缓冲区

printf(“输入替换字符:”);c2 = getchar();replaceAll(s,c1, c2);puts(s);} void replaceAll(char *str, char ch1, char ch2){ while(*str){

if(*str == ch1)

{

*str = ch2;

}

str++;} }

(7)

#include int transformToBin(int dnum, int *bin);int main(){ int array[32];//保存转换后的进制数

int num;//待转换的整数

int cc;//最后得到的进制总共多少位

printf(“请输入一个整数:”);scanf(“%d”, &num);cc=transformToBin(num, array);//调用转换函数

cc--;//使cc指向最后一个元素

for(;cc>=0;cc--)//输出转换后的进制数

printf(“%d”, array[cc]);printf(“n”);return 0;}

int transformToBin(int dnum, int *bin){ int *pb;int t;pb = bin;while(dnum)//当dnum还未转换完毕

{

t = dnum % 2;

*pb = t;

pb++;

dnum /= 2;//数本身除2 } return pb-bin;}

(8)

#include #include void transformToHex(int dnum, char *hex);int main(){ char array[32];//保存转换后的进制数

int num;//待转换的整数

int cc;//最后得到的进制总共多少位

printf(“请输入一个整数:”);scanf(“%d”, &num);transformToHex(num, array);//调用转换函数

cc=strlen(array)-1;//使cc指向最后一个元素

for(;cc>=0;cc--)//输出转换后的进制数

printf(“%c”, array[cc]);printf(“n”);return 0;}

void transformToHex(int dnum, char *hex){ char *ph;int t;ph = hex;while(dnum)//当dnum还未转换完毕

{

t = dnum % 16;

if(t < 10)

*ph = t+'0';

else

*ph = t-10+'A';

ph++;dnum /= 16;//数本身除16 } *ph = '';}

(9)

#include void strToLow(char *str);main(){ char s[100];gets(s);strToLow(s);puts(s);} void strToLow(char *str){ while(*str){

if(*str>='A'&&*str<='Z')

*str = *str + 32;

str++;} }

第10章 1.(1)12(2)(++p)->num(5)B(6)B

2.(1)

struct myDate{ int year, month, day;};

(2)

struct empInfo{ char empNo[15];char empName[10];char xb;//性别

int age;struct myDate empDay;double salary;};

(3)

#include typedef struct STUDENT { char name[20];float height;

3)D 7)10,A

4)p2!= NULL

(((int score;}STUD;main(){ STUD a;printf(“姓名:”);

gets(a.name);printf(“身高:”);

scanf(“%f”, &a.height);

printf(“成绩:”);

scanf(“%d”, &a.score);

//输出信息(仅为测试用)

printf(“%s %.2f %d n”, a.name, a.height, a.score);}

第11章 1.(1)打开文件:fopen

关闭文件:fclose 使用:

FILE *fp;

fp = fopen(“myfile”, “r”);

fclose(fp);

(2)”w”

(3)文本文件:内容均以字符的形式存储,占的字节数可能会大些

二进制文件:内容以二进制编码的形式存储,占的字节数可能会稍小。

(4)第一个参数:读取得到的信息存储在内存的哪个地方

第二个参数:读取的字节数

第三个参数:读取的块数

第四个参数:文件指针,表示从哪个文件中读取数据

(5)第一个参数:待写入文件的信息存储在内存的哪个地方

第二个参数:写入的字节数

第三个参数:写入的块数

第四个参数:文件指针,表示要写入到哪个文件中(6)为了安全,gets少用,因为其没有指定输入字符的大小,限制输入缓冲区得大小,如果输入的字符大于定义的数组长度,会发生内存越界,堆栈溢出。后果非常怕怕fgets会指定大小,如果超出数组大小,会自动根据定义数组的长度截断。

2.(1)

#include #include main(){ FILE *fpr, *fpw;char ch;

fpr = fopen(“a.txt”, “r”);fpw = fopen(“b.txt”, “a”);

if(NULL==fpr){

printf(“文件打开不成功n”);

return 0;} if(NULL == fpw){

printf(“文件打开不成功n”);

return 0;}

while(!feof(fpr)){

ch = fgetc(fpr);

fprintf(fpw, “%c”, ch);}

fclose(fpr);fclose(fpw);}

(2)

#include main(){ FILE *fp1, *fp2;double pi = 3.1415926;fp1 = fopen(“a.txt”, “w”);//以文本的形式写入

fp2 = fopen(“b.txt”, “wb”);//以二进制的形式写入

if(NULL==fp1){

printf(“文件打开不成功n”);

return 0;} if(NULL == fp2){

printf(“文件打开不成功n”);

return 0;}

fprintf(fp1, “%lf”, pi);fwrite(&pi,sizeof(pi),1,fp2);

fclose(fp1);fclose(fp2);}

打开之后的效果:

(3)

#include #include main(){ FILE *fpr;fpr = fopen(“a.txt”, “r”);

if(NULL==fpr){

printf(“文件打开不成功n”);

return 0;}

while(!feof(fpr)){

putchar(fgetc(fpr));} fclose(fpr);}

(4)

#include typedef struct STUDENT { char no[15];char name[10];int score;}STUD;#define N 3 main(){ STUD s[N];int i;FILE *fp;int count;//读取文件时才使用

for(i=0;i

printf(“请输入第%d个学生信息:n” , i+1);

printf(“

学号:”);

gets(s[i].no);

printf(“

姓名:”);

gets(s[i].name);

printf(“

成绩:”);

scanf(“%d”, &s[i].score);

fflush(stdin);//清除键盘缓冲区

}

//打开文件,并写入

fp = fopen(“a.txt”, “wb”);if(NULL == fp){

printf(“文件打开不成功,不能写入n”);

return 0;} for(i=0;i

fwrite(&s[i], sizeof(s[i]), 1, fp);fclose(fp);

//以下代码从文件中读取出信息,并显示在屏幕上

fp = fopen(“a.txt”, “rb”);

} count = 0;while(!feof(fp)){ if(fread(&s[count], sizeof(s[count]), 1, fp))

count++;} fclose(fp);//输出

for(i=0;i

第五篇:C语言程序设计(郑莉)课后习题答案

C++语言程序设计(清华大学郑莉)课后习题答案

第 一 章 概述

1-1 简述计算机程序设计语言的发展历程。

解:

迄今为止计算机程序设计语言的发展经历了机器语言、汇编语言、高级语言等阶段,C++语言是一种面向对象的编程语言,也属于高级语言。

1-2 面向对象的编程语言有哪些特点?

解:

面向对象的编程语言与以往各种编程语言有根本的不同,它设计的出发点就是为了能更直接的描述客观世界中存在的事物以及它们之间的关系。面向对象的编程语言将客观事物看作具有属性和行为的对象,通过抽象找出同一类对象的共同属性(静态特征)和行为(动态特征),形成类。通过类的继承与多态可以很方便地实现代码重用,大大缩短了软件开发周期,并使得软件风格统一。因此,面向对象的编程语言使程序能够比较直接地反问题域的本来面目,软件开发人员能够利用人类认识事物所采用的一般思维方法来进行软件开发。C++语言是目前应用最广的面向对象的编程语言。

1-3 什么是结构化程序设计方法?这种方法有哪些优点和缺点?

解:

结构化程序设计的思路是:自顶向下、逐步求精;其程序结构是按功能划分为若干个基本模块;各模块之间的关系尽可能简单,在功能上相对独立;每一模块内部均是由顺序、选择和循环三种基本结构组成;其模块化实现的具体方法是使用子程序。结构化程序设计由于采用了模块分解与功能抽象,自顶向下、分而治之的方法,从而有效地将一个较复杂的程序系统设计任务分解成许多易于控制和处理的子任务,便于开发和维护。虽然结构化程序设计方法具有很多的优点,但它仍是一种面向过程的程序设计方法,它把数据和处理数据的过程分离为相互独立的实体。当数据结构改变时,所有相关的处理过程都要进行相应的修改,每一种相对于老问题的新方法都要带来额外的开销,程序的可重用性差。

由于图形用户界面的应用,程序运行由顺序运行演变为事件驱动,使得软件使用起来越来越方便,但开发起来却越来越困难,对这种软件的功能很难用过程来描述和实现,使用面向过程的方法来开发和维护都将非常困难。

1-4 什么是对象?什么是面向对象方法?这种方法有哪些特点?

解:

从一般意义上讲,对象是现实世界中一个实际存在的事物,它可以是有形的,也可以是无形的。对象是构成世界的一个独立单位,它具有自己的静态特征和动态特征。面向对象方法中的对象,是系统中用来描述客观事物的一个实体,它是用来构成系统的一个基本单位,由一组属性和一组行为构成。面向对象的方法将数据及对数据的操作方法放在一起,作为一个相互依存、不可分离的整体--对象。对同类型对象抽象出其共性,形成类。类中的大多数数据,只能用本类的方法进行处理。类通过一个简单的外部接口,与外界发生关系,对象与对象之间通过消息进行通讯。这样,程序模块间的关系更为简单,程序模块的独立性、数据的安全性就有了良好的保障。通过实现继承与多态性,还可以大大提高程序的可重用性,使得软件的开发和维护都更为方便。

面向对象方法所强调的基本原则,就是直接面对客观存在的事物来进行软件开发,将人们在日常生活中习惯的思维方式和表达方式应用在软件开发中,使软件开发从过分专业化的方法、规则和技巧中回到客观世界,回到人们通常的思维。

1-5 什么叫做封装?

解:

封装是面向对象方法的一个重要原则,就是把对象的属性和服务结合成一个独立的系统单位,并尽可能隐蔽对象的内部细节。

1-6 面向对象的软件工程包括哪些主要内容?

解:

面向对象的软件工程是面向对象方法在软件工程领域的全面应用,它包括面向对象的分析(OOA)、面向对象的设计(OOD)、面向对象的编程(OOP)、面向对象的测试(OOT)和面向对象的软件维护(OOSM)等主要内容。

1-7 简述计算机内部的信息可分为几类?

解:

计算机内部的信息可以分成控制信息和数据信息二大类;控制信息可分为指令和控制字两类;数据信息可分为数值信息和非数值信息两类。

1-8 什么叫二进制?使用二进制有何优点和缺点?

解:

二进制是基数为2,每位的权是以2 为底的幂的进制,遵循逢二进一原则,基本符号为0和1。采用二进制码表示信息,有如下几个优点:1.易于物理实现;2.二进制数运算简单;3.机器可靠性高;4.通用性强。其缺点是它表示数的容量较小,表示同一个数,二进制较其他进制需要更多的位数。

1-9 请将以下十进制数值转换为二进制和十六进制补码:(1)2(2)9(3)93(4)-32(5)65535(6)-1

解:

(1)(2)10 =(10)2 =(2)16(2)(9)10 =(1001)2 =(9)16(3)(93)10 =(1011101)2 =(5D)16(4)(-32)10 =(11100000)2 =(E0)16(5)(65535)10 =(11111111 11111111)2 =(FFFF)16(6)(-1)10 =(11111111 11111111)2 =(FFFF)16

1-10 请将以下数值转换为十进制:

(1)(1010)2(2)(10001111)2(3)(01011111 11000011)2(4)(7F)16(5)(2D3E)16(6)(F10E)16

解:

(1)(1010)2 =(10)10(2)(10001111)2 =(143)10(3)(01011111 11000011)2 =(24515)10

(4)(7F)16 =(127)10(5)(2D3E)16 =(11582)10(6)(F10E)16 =(61710)10

1-11 简要比较原码、反码、补码等几种编码方法。

解:

原码:将符号位数字化为 0 或 1,数的绝对值与符号一起编码,即所谓“符号──绝对值表示”的编码。正数的反码和补码与原码表示相同。负数的反码与原码有如下关系:

符号位相同(仍用1表示),其余各位取反(0变1,1变0)。补码由该数反码的最末位加1求得。

第 二 章 C++简单程序设计

2-1 C++语言有那些主要特点和优点?

解:

C++语言的主要特点表现在两个方面,一是全面兼容C,二是支持面向对象的方法。C++是一个更好的C,它保持了C的简洁、高效、接近汇编语言、具有良好的可读性和可移植性等特点,对C的类型系统进行了改革和扩充,因此C++比C更安全,C++的编译系统能检查出更多的类型错误。C++语言最重要的特点是支持面向对象。

2-2 下列标识符哪些是合法的?

Program,-page,_lock,test2,3in1,@mail,A_B_C_D

解:

Program,_lock,test2,A_B_C_D是合法的标识符,其它的不是。

2-3 例2.1中每条语句的作用是什么? #include void main(void){

cout<<“Hello!n”;cout<<“Welcome to c++!n”;}

解:

#include //指示编译器将文件iostream.h中的代码

//嵌入到该程序中该指令所在的地方

void main()//主函数名,void 表示函数没有返回值 { //函数体标志

cout<<“Hello!n”;//输出字符串Hello!到标准输出设备(显示器)上。

cout<<“Welcome to c++!n”;//输出字符串Welcome to c++!} 在屏幕输出如下: Hello!Welcome to c++!

2-4 使用关键字const而不是#define语句的好处有哪些?

解:

const定义的常量是有类型的,所以在使用它们时编译器可以查错;而且,这些变量在调试时仍然是可见的。

2-5 请写出C++语句声明一个常量PI,值为3.1416;再声明一个浮点型变量a,把PI的值赋给a。

解:

const float PI = 3.1416;float a = PI;

2-6 在下面的枚举类型中,Blue的值是多少?

enum COLOR { WHITE,BLACK = 100,RED,BLUE,GREEN = 300 };

解: Blue = 102

2-7 注释有什么作用?C++中有哪几种注释的方法?他们之间有什么区别?

解:

注释在程序中的作用是对程序进行注解和说明,以便于阅读。编译系统在对源程序进行编译时不理会注释部分,因此注释对于程序的功能实现不起任何作用。而且由于编译时忽略注释部分,所以注释内容不会增加最终产生的可执行程序的大小。适当地使用注释,能够提高程序的可读性。在C++中,有两种给出注释的方法:一种是延用C语言方法,使用“/*”和“*/”括起注释文字。另一种方法是使用“//”,从“//”开始,直到它所在行的行尾,所有字符都被作为注释处理。

2-8 什么叫做表达式?x = 5 + 7是一个表达式吗?它的值是多少?

解:

任何一个用于计算值的公式都可称为表达式。x = 5 + 7是一个表达式,它的值为12。

2-9 下列表达式的值是多少? 1.201 / 4 2.201 % 4 3.201 / 4.0

解: 1. 50 2. 1 3. 50.25

2-10 执行完下列语句后,a、b、c三个变量的值为多少? a = 30;b = a++;c = ++a;

解:

a:32 ; b:30 ; c:32;

2-11 在一个for循环中,可以初始化多个变量吗?如何实现?

解:

在for循环设置条件的第一个“;”前,用,分隔不同的赋值表达式。例如:

for(x = 0,y = 10;x < 100;x++,y++)

2-12 执行完下列语句后,n的值为多少? int n;for(n = 0;n < 100;n++)

解: n的值为100

2-13 写一条for语句,计数条件为n从100到200,步长为2;然后用while和do„while语句完成同样的循环。

解: for循环:

for(int n = 100;n <= 200;n += 2);

while循环: int x = 100;while(n <= 200)n += 2;

do„while循环: int n = 100;do { n += 2;} while(n <= 200);

2-14 if(x = 3)和 if(x = = 3)这两条语句的差别是什么?

解:

语句if(x = 3)把3赋给x,赋值表达式的值为true,作为if语句的条件;语句if(x == 3)首先判断x的值是否为3,若相等条件表达式的值为ture,否则为false。

2-15 什么叫做作用域?什么叫做局部变量?什么叫做全局变量,如何使用全局变量?

解:

作用域是一个标识符在程序正文中有效的区域。局部变量,一般来讲就是具有块作用域的变量;全局变量,就是具有文件作用域的变量。

2-16 已知x、y两个变量,写一条简单的if语句,把较小的的值赋给原本值较大的变量。

解: if(x > y)x = y;

else // y > x || y == x y = x;

2-17 修改下面这个程序中的错误,改正后它的运行结果是什么?

#include void main()int i int j;

i = 10;/* 给i赋值 j = 20;/* 给j赋值 */

cout << “i + j = << i + j;/* 输出结果 */ return 0;}

解: 改正:

#include int main(){ int i;int j;

i = 10;// 给i赋值 j = 20;/* 给j赋值 */

cout << ”i + j = “ << i + j;/* 输出结果 */ return 0;}

程序运行输出: i + j = 30

2-18 编写一个程序,运行时提示输入一个数字,再把这个数字显示出来。

解: 源程序:

#include

int main(){ int i;cout << ”请输入一个数字:“;cin >> i;cout << ”您输入一个数字是“ << i << endl;return 0;} 程序运行输出: 请输入一个数字:5 您输入一个数字是5

2-19 C++有哪几种数据类型?简述其值域。编程显示你使用的计算机中的各种数据类型的字节数。

解: 源程序:

#include

int main(){ cout << ”The size of an int is:tt“ << sizeof(int)<< ” bytes.n“;cout << ”The size of a short int is:t“ << sizeof(short)<< ” bytes.n“;cout << ”The size of a long int is:t“ << sizeof(long)<< ” bytes.n“;cout << ”The size of a char is:tt“ << sizeof(char)<< ” bytes.n“;cout << ”The size of a float is:tt“ << sizeof(float)<< ” bytes.n“;cout << ”The size of a double is:t“ << sizeof(double)<< ” bytes.n“;return 0;} 程序运行输出:

The size of an int is: 4 bytes.The size of a short int is: 2 bytes.The size of a long int is: 4 bytes.The size of a char is: 1 bytes.The size of a float is: 4 bytes.The size of a double is: 8 bytes.2-20 打印ASCII码为32~127的字符。

解:

#include int main(){

for(int i = 32;i<128;i++)cout <<(char)i;return 0;}

程序运行输出:

!”#$%G'()*+,./0123456789:;<>?@ABCDEFGHIJKLMNOP_QRSTUVWXYZ[]^'abcdefghijklmnopqrstuvwxyz<|>~s

2-21 运行下面的程序,观察其输出,与你的设想是否相同? #include int main(){

unsigned int x;unsigned int y = 100;unsigned int z = 50;x= yy;

cout << “nNow difference is: ” << x <

解:

程序运行输出: Difference is: 50

Now difference is: 4294967246

注意,第二行的输出并非-50,注意x、y、z的数据类型。

2-22 运行下面的程序,观察其输出,体会i++与++i的差别。#include int main(){ int myAge = 39;// initialize two integers int yourAge = 39;cout << “I am: ” << myAge << “ years old.n”;cout << “You are: ” << yourAge << “ years oldn”;myAge++;// postfix increment ++yourAge;// prefix increment 变量有以下几种存储类型:

auto存储类型:采用堆栈方式分配内存空间,属于一时性存储,其存储空间可以被若干变量多次覆盖使用; register存储类型:存放在通用寄存器中;

extern存储类型:在所有函数和程序段中都可引用; static存储类型:在内存中是以固定地址存放的,在整个程序cout << “One year passes...n”;cout << “I am: ” << myAge << “ years old.n”;cout << “You are: ” << yourAge << “ years oldn”;cout << “Another year passesn”;cout << “I am: ” << myAge++ << “ years old.n”;cout << “You are: ” << ++yourAge << “ years oldn”;cout << “Let's print it again.n”;cout << “I am: ” << myAge << “ years old.n”;cout << “You are: ” << yourAge << “ years oldn”;return 0;}

解:

程序运行输出: I am 39 years old You are 39 years old One year passes I am 40 years old You are 40 years old Another year passes I am 40 years old You are 41 years old Let's print it again I am 41 years old You are 41 years old

2-23 什么叫常量?什么叫变量?

解:

所谓常量是指在程序运行的整个过程中其值始终不可改变的量,除了用文字表示常量外,也可以为常量命名,这就是符号常量;在程序的执行过程中其值可以变化的量称为变量,变量是需要用名字来标识的。

2-24 变量有哪几种存储类型?

解:

运行期间都有效。

2-25 写出下列表达式的值: 1.2 < 3 && 6 < 9 2.!(4<7)

3.!(3 > 5)||(6 < 2)

解: 1.true 2.false 3.true

2-26 若a = 1,b = 2,c = 3,下列各式的结果是什么? 1.a | b32)* 5/9;在主程序中提示用户输入一个华氏温度,转化后输出相应的摄氏温度。

解:

源程序见“实验指导”部分实验三

3-9 编写函数判断一个数是否是质数,在主程序中实现输入、输出。

解:

#include #include

int prime(int i);//判一个数是否是质数的函数

void main(){ int i;

cout << “请输入一个整数:”;cin >> i;if(prime(i))

cout << i << “是质数.” << endl;else

cout << i << “不是质数.” << endl;}

int prime(int i){ int j,k,flag;flag = 1;k = sqrt(i);for(j = 2;j <= k;j++){ if(i%j == 0){ flag = 0;break;} } if(flag)return 1;else return 0;} 程序运行输出: 请输入一个整数:1151 1151是质数.3-10 编写函数求两个整数的最大公约数和最小公倍数。

解: 源程序:

#include #include

int fn1(int i,int j);//求最大公约数的函数

void main(){ int i,j,x,y;cout << “请输入一个正整数:”;cin >> i;cout << “请输入另一个正整数:”;cin >> j;

x = fn1(i,j);y = i * j / x;cout << i << “和” << j << “的最大公约数是:” << x << endl;cout << i << “和” << j << “的最小公倍数是:” << y << endl;}

int fn1(int i, int j){ int temp;if(i < j)

{

temp = i;i = j;j = i;}

while(j!= 0){

temp = i % j;i = j;j = temp;}

return i;}

程序运行输出: 请输入一个正整数:120 请输入另一个正整数:72 120和72的最大公约数是:24 120和72的最小公倍数是:360

3-11 什么叫作嵌套调用?什么叫作递归调用?

解:

函数允许嵌套调用,如果函数1调用了函数2,函数2再调用函数3,便形成了函数的嵌套调用。

函数可以直接或间接地调用自身,称为递归调用。

3-12 在主程序中提示输入整数n,编写函数用递归的方法求1 + 2 + „ + n的值。

解:

#include #include

int fn1(int i);

void main(){ int i;

cout << “请输入一个正整数:”;cin >> i;

cout << “从1累加到” <

3-13 编写递归函数GetPower(int x,int y)计算x的y次幂,在主程序中实现输入输出。

解: 源程序:

#include long GetPower(int x,int y);int main(){ int number,power;long answer;cout << “Enter a number: ”;cin >> number;cout << “To what power? ”;cin >> power;answer = GetPower(number,power);cout << number << “ to the ” << power << “th power is ” <

long GetPower(int x,int y){ if(y == 1)return x;else return(x * GetPower(x,y-1));} 程序运行输出: Enter a number: 3 To what power? 4 3 to the 4th power is 81

3-14 用递归的方法编写函数求Fibonacci 级数,公式为fib(n)

= fib(n-1)+ fib(n-2),n>2;

fib(1)= fib(2)= 1;观察递归调用的过程。

解:

源程序见“实验指导”部分实验三

3-15 用递归的方法编写函数求n阶勒让德多项式的值,在主程序中实现输入、输出;

解:

#include

float p(int n, int x);

void main(){ int n,x;

cout << “请输入正整数n:”;cin >> n;

cout << “请输入正整数x:”;cin >> x;

cout << “n = ” << n << endl;cout << “x = ” << x << endl;

cout << “P” << n << “(” << x << “)= ” << p(n,x)<< endl;}

float p(int n, int x){

if(n == 0)return 1;else if(n == 1)return x;else

return((2*n-1)*x*p(n-1,x)itsBottom;return(Width * Height);}

int main(){ Rectangle MyRectangle(100, 20, 50, 80);

int Area = MyRectangle.GetArea();

cout << “Area: ” << Area << “n”;return 0;} 程序运行输出: Area: 3000 Upper Left X Coordinate: 20

4-10 设计一个用于人事管理的People(人员)类。考虑到通用性,这里只抽象出所有类型人员都具有的属性:number(编号)、sex(性别)、birthday(出生日期)、id(身份证号)等等。其中“出生日期”定义为一个“日期”类内嵌子对象。用成员函数实现对人员信息的录入和显示。要求包括:构造函数和析构函数、拷贝构造函数、内联成员函数、带缺省形参值的成员函数、聚集。

解:

本题用作实验四的选做题,因此不给出答案。

4-11 定义一个矩形类,有长、宽两个属性,有成员函数计算矩形的面积

解:

#include

class Rectangle { public:

Rectangle(float len, float width){

Length = len;Width = width;}

~Rectangle(){};

float GetArea(){ return Length * Width;} float GetLength(){ return Length;} float GetWidth(){ return Width;} private: float Length;float Width;};

void main(){

float length, width;

cout << “请输入矩形的长度:”;cin >> length;

cout << “请输入矩形的宽度:”;cin >> width;

Rectangle r(length, width);

cout << “长为” << length << “宽为” << width << “的矩形的面积为:”

<< r.GetArea()<< endl;}

程序运行输出: 请输入矩形的长度:5 请输入矩形的宽度:4

长为5宽为4的矩形的面积为:20

4-12 定义一个“数据类型” datatype类,能处理包含字符型、整型、浮点型三种类型的数据,给出其构造函数。解:

#include

class datatype{ enum{ character, integer, floating_point } vartype;union { char c;int i;float f;};public: datatype(char ch){ vartype = character;c = ch;} datatype(int ii){ vartype = integer;i = ii;} datatype(float ff){ vartype = floating_point;f = ff;} void print();};

void datatype::print(){ switch(vartype){ case character: cout << “字符型: ” << c << endl;break;case integer: cout << “整型: ” << i << endl;break;case floating_point: cout << “浮点型: ” << f << endl;break;} }

void main(){ datatype A('c'), B(12), C(1.44F);

A.print();B.print();C.print();}

程序运行输出: 字符型: c 整型: 12 浮点型: 1.44

4-13 定义一个Circle类,有数据成员半径Radius,成员函数GetArea(),计算圆的面积,构造一个Circle的对象进行测试。

解:

#include

class Circle { public:

Circle(float radius){ Radius = radius;} ~Circle(){}

float GetArea(){ return 3.14 * Radius * Radius;} private: float Radius;};

void main(){

float radius;

cout << “请输入圆的半径:”;cin >> radius;Circle p(radius);

cout << “半径为” << radius << “的圆的面积为:” << p.GetArea()<< endl;}

程序运行输出: 请输入圆的半径:5

半径为5的圆的面积为:78.5

4-14 定义一个tree类,有成员ages,成员函数grow(int years)对ages加上years,age()显示tree对象的ages的值。解:

#include

class Tree { int ages;public: Tree(int n=0);~Tree();void grow(int years);void age();};

Tree::Tree(int n){ ages = n;}

Tree::~Tree(){ age();}

void Tree::grow(int years){ ages += years;}

void Tree::age(){ cout << “这棵树的年龄为” << ages << endl;}

void main(){ Tree t(12);

t.age();t.grow(4);}

程序运行输出: 这棵树的年龄为12 这棵树的年龄为16

第 五 章 C++程序的基本结构

5-1 什么叫做作用域?有哪几种类型的作用域?

解:

作用域讨论的是标识符的有效范围,作用域是一个标识符在程序正文中有效的区域。C++的作用域分为函数原形作用域、块作用域(局部作用域)、类作用域和文件作用域.5-2 什么叫做可见性?可见性的一般规则是什么?

解:

可见性是标识符是否可以引用的问题;

可见性的一般规则是:标识符要声明在前,引用在后,在同一作用域中,不能声明同名的标识符。对于在不同的作用域声明的标识符,遵循的原则是:若有两个或多个具有包含关系的作用域,外层声明的标识符如果在内层没有声明同名标识符时仍可见,如果内层声明了同名标识符则外层标识符不可见。

5-3 下面的程序的运行结果是什么,实际运行一下,看看与你的设想有何不同。#include void myFunction();

int x = 5,y = 7;int main(){

cout << “x from main: ” << x << “n”;cout << “y from main: ” << y << “nn”;myFunction();

cout << “Back from myFunction!nn”;cout << “x from main: ” << x << “n”;cout << “y from main: ” << y << “n”;return 0;}

void myFunction(){

int y = 10;

cout << “x from myFunction: ” << x << “n”;cout << “y from myFunction: ” << y << “nn”;}

解:

程序运行输出:

x from main: 5 y from main: 7

x from myFunction: 5 y from myFunction: 10

Back from myFunction!

x from main: 5 y from main: 7

5-4 假设有两个无关系的类Engine和Fuel,使用时,怎样允许Fuel成员访问Engine中的私有和保护的成员?

解: 源程序: class fuel;class engine { friend class fuel;private;int powerlevel;public;engine(){ powerLevel = 0;} void engine_fn(fuel &f);};class fuel { friend class engine;private;int fuelLevel;public: fuel(){ fuelLevel = 0;} void fuel_fn(engine &e);};

5-5 什么叫做静态数据成员?它有何特点?

解:

类的静态数据成员是类的数据成员的一种特例,采用static关键字来声明。对于类的普通数据成员,每一个类的对象都拥

有一个拷贝,就是说每个对象的同名数据成员可以分别存储不同的数值,这也是保证对象拥有自身区别于其它对象的特征的需要,但是静态数据成员,每个类只要一个拷贝,由所有该类的对象共同维护和使用,这个共同维护、使用也就实现了同一类的不同对象之间的数据共享。

5-6 什么叫做静态函数成员?它有何特点?

解:

使用static关键字声明的函数成员是静态的,静态函数成员属于整个类,同一个类的所有对象共同维护,为这些对象所共享。静态函数成员具有以下两个方面的好处,一是由于静态成员函数只能直接访问同一个类的静态数据成员,可以保证不会对该类的其余数据成员造成负面影响;二是同一个类只维护一个静态函数成员的拷贝,节约了系统的开销,提高程序的运行效率。

5-7 定义一个Cat类,拥有静态数据成员HowManyCats,记录Cat的个体数目;静态成员函数GetHowMany(),存取HowManyCats。设计程序测试这个类,体会静态数据成员和静态成员函数的用法。

解: 源程序:

#include

class Cat { public:

Cat(int age):itsAge(age){HowManyCats++;} virtual ~Cat(){ HowManyCats--;} virtual int GetAge(){ return itsAge;} virtual void SetAge(int age){ itsAge = age;} static int GetHowMany(){ return HowManyCats;} private: int itsAge;

static int HowManyCats;};

int Cat::HowManyCats = 0;

void TelepathicFunction();

int main(){ const int MaxCats = 5;Cat *CatHouse[MaxCats];int i;for(i = 0;i

for(i = 0;i

void TelepathicFunction(){ cout << “There are ” << Cat::GetHowMany()<< “ cats alive!n”;}

程序运行输出:

There are 1 cats alive!There are 2 cats alive!There are 3 cats alive!There are 4 cats alive!There are 5 cats alive!There are 4 cats alive!There are 3 cats alive!There are 2 cats alive!There are 1 cats alive!There are 0 cats alive!

5-8 什么叫做友元函数?什么叫做友元类?

解:

友元函数是使用friend关键字声明的函数,它可以访问相应类的保护成员和私有成员。友元类是使用friend关键字声明的类,它的所有成员函数都是相应类的友元函数。

5-9 如果类A是类B的友元,类B是类C的友元,类D是类A的派生类,那么类B是类A的友元吗?类C是类A的友元吗?类D是类B的友元吗?

解:

类B不是类A的友元,友元关系不具有交换性; 类C不是类A的友元,友元关系不具有传递性; 类D不是类B的友元,友元关系不能被继承。

5-10 静态成员变量可以为私有的吗?声明一个私有的静态整型成员变量。

解: 可以,例如: private: static int a;

5-11 在一个文件中定义一个全局变量n,主函数main(),在另一个文件中定义函数fn1(),在main()中对n赋值,再调用fn1(),在fn1()中也对n赋值,显示n最后的值。

解:

#include #include “fn1.h” int n;

void main(){ n = 20;fn1();

cout << “n的值为” <

// fn1.h文件 extern int n;

void fn1(){ n=30;}

程序运行输出: n的值为30 5-12 在函数fn1()中定义一个静态变量n,fn1()中对n的值加1,在主函数中,调用fn1()十次,显示n的值。

解:

#include

void fn1(){ static int n = 0;n++;cout << “n的值为” << n <

void main(){ for(int i = 0;i < 10;i++)fn1();}

程序运行输出: n的值为1 n的值为2 n的值为3 n的值为4 n的值为5 n的值为6 n的值为7 n的值为8 n的值为9 n的值为10

5-13 定义类X、Y、Z,函数h(X*),满足:类X有私有成员i,Y的成员函数g(X*)是X的友元函数,实现对X的成员i加1,类Z是类X的友元类,其成员函数f(X*)实现对X的成员i加5,函数h(X*)是X的友元函数,实现对X的成员i加10。在一个文件中定义和实现类,在另一个文件中实现main()函数。

解:

#include “my_x_y_z.h” void main(){ X x;Z z;z.f(&x);}

// my_x_y_z.h文件 #ifndef MY_X_Y_Z_H

class X;class Y { void g(X*);};

class X { private: int i;public: X(){i=0;}

friend void h(X*);friend void Y::g(X*);friend class Z;};

void h(X* x){ x->i =+10;}

void Y::g(X* x){ x->i ++;}

class Z { public:

void f(X* x){ x->i += 5;} };

#endif // MY_X_Y_Z_H

程序运行输出:无

5-14 定义Boat与Car两个类,二者都有weight属性,定义二者的一个友元函数totalWeight(),计算二者的重量和。

解: 源程序:

#include

class Boat;class Car { private: int weight;public: Car(int j){weight = j;} friend int totalWeight(Car &aCar,Boat &aBoat);};

class Boat { private: int weight;public: Boat(int j){weight = j;} friend int totalWeight(Car &aCar,Boat &aBoat);};

int totalWeight(Car &aCar,Boat &aBoat){ return aCar.weight + aBoat.weight;}

void main(){ Car c1(4);Boat b1(5);

cout << totalWeight(c1,b1)<< endl;} 程序运行输出: 9

5-15 如果在类模板的定义中有一个静态数据成员,则在程序运行中会产生多少个相应的静态变量?

解:

这个类模板的每一个实例类都会产生一个相应的静态变量。

第 六 章 数组、指针与字符串

6-1 数组A[10][5][15]一共有多少个元素?

解:

10×5×15 = 750 个元素

1-2 在数组A[20]中第一个元素和最后一个元素是哪一个? 解:

第一个元素是A[0],最后一个元素是A[19]。

6-3 用一条语句定义一个有五个元素的整型数组,并依次赋予1~5的初值。

解: 源程序:

int IntegerArray[5] = { 1,2,3,4,5 };或:int IntegerArray[] = { 1,2,3,4,5 };

6-4 已知有一个数组名叫oneArray,用一条语句求出其元素的个数。

解: 源程序:

nArrayLength = sizeof(oneArray)/ sizeof(oneArray[0]);

6-5 用一条语句定义一个有5×3个元素的二维整型数组,并依次赋予1~15的初值。

解: 源程序:

int theArray[5][3] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };

或:int theArray[5][3] = { {1,2,3},{4,5,6},{7,8,9},{10,11,12},{13,14,15} };

6-6 运算符*和&的作用是什么?

解:

*称为指针运算符,是一个一元操作符,表示指针所指向的对象的值;&称为取地址运算符,也是一个一元操作符,是用来得到一个对象的地址。

6-7 什么叫做指针?指针中储存的地址和这个地址中的值有何区别?

解:

指针是一种数据类型,具有指针类型的变量称为指针变量。指针变量存放的是另外一个对象的地址,这个地址中的值就是另一个对象的内容。

6-8 定义一个整型指针,用new语句为其分配包含10个整型元素的地址空间。

解: 源程序:

int *pInteger = new int[10];

6-9 在字符串”Hello,world!”中结束符是什么?

解:

是NULL字符。

6-10 定义一个有五个元素的整型数组,在程序中提示用户输入元素值,最后再在屏幕上显示出来。

解: 源程序:

#include

int main(){ int myArray[5];int i;for(i=0;i<5;i++){ cout << “Value for myArray[” << i << “]: ”;cin >> myArray[i];} for(i = 0;i<5;i++)cout << i << “: ” << myArray[i] << “n”;return 0;} 程序运行输出:

Value for myArray[0]: 2 Value for myArray[1]: 5 Value for myArray[2]: 7 Value for myArray[3]: 8 Value for myArray[4]: 3 0: 2

1: 5 2: 7 3: 8 4: 3

6-11 引用和指针有何区别?何时只能使用指针而不能使用引用?

解:

引用是一个别名,不能为NULL值,不能被重新分配;指针是一个存放地址的变量。当需要对变量重新赋以另外的地址或赋值为NULL时只能使用指针。

6-12 声明下列指针:float类型变量的指针pFloat,char类型的指针pString和struct customer型的指针prec。

解:

float *pfloat;char *pString;

struct customer *prec;

6-13 给定float类型的指针fp,写出显示fp所指向的值的输出流语句。

解:

cout << “Value == ” << *fp;

6-14 程序中定义一个double类型变量的指针。分别显示指针占了多少字节和指针所指的变量占了多少字节。

解:

double *counter;

cout << “nSize of pointer == ”sizeof(counter);cout <<

'nSize

of

addressed

value

==

“<

6-15 const int * p1 和 int * const p2的区别是什么?解:

const int * p1 声明了一个指向整型常量的指针p1,因此不能通过指针p1来改变它所指向的整型值;int * const p2声明了一个指针型常量,用于存放整型变量的地址,这个指针一旦初始化后,就不能被重新赋值了。

6-16 定义一个整型变量a,一个整型指针p,一个引用r,通过p把a的值改为10,通过r把a的值改为5

解: void main(){ int a;int *p = &a;int &r = a;*p = 10;r = 5;}

6-17 下列程序有何问题,请仔细体会使用指针时应避免出现这个的问题。

#include int main(){ int *p;*pInt = 9;cout << ”The value at p: “ << *p;return 0;}

解:

指针p没有初始化,也就是没有指向某个确定的内存单元,它指向内存中的一个随机地址,给这个随机地址赋值是非常危险的。

6-18 下列程序有何问题,请改正;仔细体会使用指针时应避免出现的这个问题。#include int Fn1();int main(){ int a = Fn1();cout << ”the value of a is: “ << a;return 0;}

int Fn1(){

int * p = new int(5);return *p;}

解:

此程序中给*p分配的内存没有被释放掉。改正:

#include int* Fn1();int main(){

int *a = Fn1();

cout << ”the value of a is: “ << *a;delete a;return 0;}

int* Fn1(){

int * p = new int(5);return p;}

6-19 声明一个参数为整型,返回值为长整型的函数指针;声明类A的一个成员函数指针,其参数为整型,返回值长整型。

解:

long(* p_fn1)(int);long(A::*p_fn2)(int);

6-20 实现一个名为SimpleCircle的简单圆类,其数据成员int *itsRadius为一个指向其半径值的指针,设计对数据成员的各种操作,给出这个类的完整实现并测试这个类。

解: 源程序:

#include

class SimpleCircle { public: SimpleCircle();SimpleCircle(int);SimpleCircle(const SimpleCircle &);~SimpleCircle(){}

void SetRadius(int);int GetRadius()const;

private: int *itsRadius;};

SimpleCircle::SimpleCircle(){ itsRadius = new int(5);}

SimpleCircle::SimpleCircle(int radius){ itsRadius = new int(radius);}

SimpleCircle::SimpleCircle(const SimpleCircle & rhs){ int val = rhs.GetRadius();itsRadius = new int(val);}

int SimpleCircle::GetRadius()const { return *itsRadius;} int main(){ SimpleCircle CircleOne, CircleTwo(9);cout << ”CircleOne: “ << CircleOne.GetRadius()<< endl;cout << ”CircleTwo: “ << CircleTwo.GetRadius()<< endl;return 0;}程序运行输出: CircleOne: 5 CircleTwo: 9

6-21 编写一个函数,统计一个英文句子中字母的个数,在主程序中实现输入、输出。

解: 源程序:

#include #include

int count(char *str){

int i,num=0;

for(i=0;str[i];i++){

if((str[i]>='a' && str[i]<='z')||(str[i]>='A' && str[i]<='Z'))num++;}

return num;}

void main(){

char text[100];

cout << ”输入一个英语句子:“ << endl;gets(text);

cout << ”这个句子里有“ << count(text)<< ”个字母。“ << endl;}

程序运行输出: 输入一个英语句子: It is very interesting!这个句子里有19个字母。

6-22 编写函数int index(char *s,char *t),返回字符串t 在字符串s中出现的最左边的位置,如果在s中没有与t匹配的子串,就返回-1。

解: 源程序:

#include

int index(char *s, char *t){

int i,j,k;

for(i = 0;s[i]!= '';i++){

for(j = i, k = 0;t[k]!= '' && s[j] == t[k];j++, k++);if(t[k] =='')return i;} return-1;}

void main(){ int n;char str1[20],str2[20];cout << ”输入一个英语单词:“;cin >> str1;cout << ”输入另一个英语单词:“;cin >> str2;n = index(str1,str2);if(n > 0)cout << str2 << ”在“ << str1 << ”中左起第“ << n+1 << ”个位置。“<

输入一个英语单词:abcdefgh 输入另一个英语单词:de de在abcdefghijk中左起第4个位置。

6-23 编写函数reverse(char *s)的倒序递归程序,使字符串s倒序。

解: 源程序:

#include #include

void reverse(char *s, char *t){ char c;if(s < t){ c = *s;*s = *t;*t = c;reverse(++s,--t);} }

void reverse(char *s)

{

reverse(s, s + strlen(s)-1);}

void main(){

char str1[20];

cout << ”输入一个字符串:“;cin >> str1;

cout << ”原字符串为:“ << str1 << endl;reverse(str1);

cout << ”倒序反转后为:“ << str1 << endl;}

程序运行输出:

输入一个字符串:abcdefghijk 原字符串为:abcdefghijk 倒序反转后为:kjihgfedcba

6-24 设学生人数N=8,提示用户输入N个人的考试成绩,然后计算出平均成绩,显示出来。

解: 源程序:

#include #include

#define N 8

float grades[N];//存放成绩的数组

void main(){ int i;

float total,average;

//提示输入成绩

for(i = 0;i < N;i++){

cout << ”Enter grade #“ <<(i +1)<< ”: “;cin >> grades[i];}

total = 0;

for(i = 0;i < N;i++)total += grades[i];average = total / N;cout << ”nAverage grade: “ << average << endl;} 程序运行输出: Enter grade #1: 86 Enter grade #2: 98 Enter grade #3: 67 Enter grade #4: 80 Enter grade #5: 78 Enter grade #6: 95 Enter grade #7: 78 Enter grade #8: 56

Average grade: 79.75

6-25 设计一个字符串类MyString,具有构造函数、析构函数、拷贝构造函数,重载运算符+、=、+=、[],尽可能地完善它,使之能满足各种需要。(运算符重载功能为选做,参见第8章)

解:

#include #include

class MyString { public: MyString();MyString(const char *const);MyString(const MyString &);~MyString();

char & operator[](unsigned short offset);char operator[](unsigned short offset)const;MyString operator+(const MyString&);void operator+=(const MyString&);MyString & operator=(const MyString &);

unsigned short GetLen()const { return itsLen;} const char * GetMyString()const { return itsMyString;}

private: MyString(unsigned short);// private constructor char * itsMyString;unsigned short itsLen;};

MyString::MyString()

{

itsMyString = new char[1];itsMyString[0] = '';itsLen=0;}

MyString::MyString(unsigned short len){

itsMyString = new char[len+1];

for(unsigned short i = 0;i<=len;i++)itsMyString[i] = '';itsLen=len;}

MyString::MyString(const char * const cMyString){

itsLen = strlen(cMyString);itsMyString = new char[itsLen+1];

for(unsigned short i = 0;i

MyString::MyString(const MyString & rhs){

itsLen=rhs.GetLen();

itsMyString = new char[itsLen+1];for(unsigned short i = 0;i

MyString::~MyString(){

delete [] itsMyString;itsLen = 0;}

MyString& MyString::operator=(const MyString & rhs){

if(this == &rhs)return *this;

delete [] itsMyString;itsLen=rhs.GetLen();

itsMyString = new char[itsLen+1];for(unsigned short i = 0;i

return *this;}

char & MyString::operator[](unsigned short offset){ if(offset > itsLen)return itsMyString[itsLen-1];else return itsMyString[offset];}

char MyString::operator[](unsigned short offset)const { if(offset > itsLen)return itsMyString[itsLen-1];else return itsMyString[offset];}

MyString MyString::operator+(const MyString& rhs){ unsigned short totalLen = itsLen + rhs.GetLen();MyString temp(totalLen);for(unsigned short i = 0;i

void MyString::operator+=(const MyString& rhs){ unsigned short rhsLen = rhs.GetLen();unsigned short totalLen = itsLen + rhsLen;MyString temp(totalLen);for(unsigned short i = 0;i

int main(){ MyString s1(”initial test“);cout << ”S1:t“ << s1.GetMyString()<< endl;

char * temp = ”Hello World“;s1 = temp;

cout << ”S1:t“ << s1.GetMyString()<< endl;

char tempTwo[20];

strcpy(tempTwo,”;nice to be here!“);s1 += tempTwo;

cout << ”tempTwo:t“ << tempTwo << endl;cout << ”S1:t“ << s1.GetMyString()<< endl;

cout << ”S1[4]:t“ << s1[4] << endl;s1[4]='x';

cout << ”S1:t“ << s1.GetMyString()<< endl;

cout << ”S1[999]:t“ << s1[999] << endl;

MyString s2(” Another myString“);MyString s3;s3 = s1+s2;

cout << ”S3:t“ << s3.GetMyString()<< endl;

MyString s4;

s4 = ”Why does this work?“;

cout << ”S4:t“ << s4.GetMyString()<< endl;return 0;}

程序运行输出: S1: initial test S1: Hello World

tempTwo:;nice to be here!S1: Hello World;nice to be here!S1[4]: o

S1: Hellx World;nice to be here!S1[999]:!

S3: Hellx World;nice to be here!Another myString S4: Why does this work?

6-26 编写一个3×3矩阵转置的函数,在main()函数中输入数据。

解:

#include void move(int matrix[3][3]){ int i, j, k;for(i=0;i<3;i++)for(j=0;j

void main(){ int i, j;int data[3][3];cout << ”输入矩阵的元素“ << endl;for(i=0;i<3;i++)for(j=0;j<3;j++){ cout << ”第“ << i+1 << ”行第“ << j+1 <<”个元素为:“;cin >> data[i][j];} cout << ”输入的矩阵的为:“ << endl;for(i=0;i<3;i++){ for(j=0;j<3;j++)cout << data[i][j] << ” “;cout << endl;} move(data);cout << ”转置后的矩阵的为:“ << endl;for(i=0;i<3;i++){ for(j=0;j<3;j++)cout << data[i][j] << ” “;cout << endl;} }

程序运行输出: 输入矩阵的元素 第1行第1个元素为:1 第1行第2个元素为:2 第1行第3个元素为:3 第2行第1个元素为:4 第2行第2个元素为:5

第2行第3个元素为:6 第3行第1个元素为:7 第3行第2个元素为:8 第3行第3个元素为:9 输入的矩阵的为: 1 2 3 4 5 6 7 8 9

转置后的矩阵的为: 1 4 7 2 5 8 3 6 9

6-27 编写一个矩阵转置的函数,矩阵的维数在程序中由用户输入。

解:

#include

void move(int *matrix ,int n){

int i, j, k;for(i=0;i

k = *(matrix + i*n + j);

*(matrix + i*n + j)= *(matrix + j*n + i);*(matrix + j*n + i)= k;} }

void main(){

int n, i, j;int *p;

cout << ”请输入矩阵的维数:“;cin >> n;

p = new int[n*n];

cout << ”输入矩阵的元素“ << endl;for(i=0;i

cout << ”第“ << i+1 << ”行第“ << j+1 <<”个元素为:“;cin >> p[i*n + j];} cout << ”输入的矩阵的为:“ << endl;for(i=0;i

6-28 定义一个Employee类,其中包括表示姓名、街道地址、城市和邮编等属性,包括chage_name()和display()等函数;display()使用cout语句显示姓名、街道地址、城市和邮编等属性,函数change_name()改变对象的姓名属性,实现并测试这个类。

解: 源程序:

#include

#include

class Employee { private: char name[30];char street[30];char city[18];char zip[6];public:

Employee(char *n, char *str, char *ct, char *z);void change_name(char *n);void display();};

Employee::Employee(char *n,char *str,char *ct, char *z){

strcpy(name, n);strcpy(street, str);strcpy(city, ct);strcpy(zip, z);}

void Employee::change_name(char *n){

strcpy(name, n);}

void Employee::display(){

cout << name << ” “ << street << ” “;cout << city << ” “<< zip;}

void main(void){

Employee e1(”张三“,”平安大街3号“, ”北京“, ”100000“);e1.display();cout << endl;

e1.change_name(”李四“);e1.display();cout << endl;}

程序运行输出:

张三平安大街3号 北京 100000 李四平安大街3号 北京 100000

第 七 章 继承与派生

7-1 比较类的三种继承方式public公有继承、protected保护继承、private私有继承之间的差别。

解:

不同的继承方式,导致不同访问属性的基类成员在派生类中的访问属性也有所不同:

公有继承,使得基类public(公有)和protected(保护)成员的访问属性在派生类中不变,而基类private(私有)成员不可访问。

私有继承,使得基类public(公有)和protected(保护)成员都以private(私有)成员身份出现在派生类中,而基类private(私有)成员不可访问。

保护继承中,基类public(公有)和protected(保护)成员都以protected(保护)成员身份出现在派生类中,而基类private(私有)成员不可访问。

7-2 派生类构造函数执行的次序是怎样的?

解:

派生类构造函数执行的一般次序为:调用基类构造函数;调用成员对象的构造函数;派生类的构造函数体中的内容。

7-3 如果在派生类B已经重载了基类A的一个成员函数fn1(),没有重载成员函数fn2(),如何调用基类的成员函数fn1()、fn2()?

解:

调用方法为: A::fn1();fn2();

7-4 什么叫做虚基类?有何作用?

解:

当某类的部分或全部直接基类是从另一个基类派生而来,这些直接基类中,从上一级基类继承来的成员就拥有相同的名称,派生类的对象的这些同名成员在内存中同时拥有多个拷贝,我们可以使用作用域分辨符来唯一标识并分别访问它们。我们也可以将直接基类的共同基类设置为虚基类,这时从不同的路径

继承过来的该类成员在内存中只拥有一个拷贝,这样就解决了同名成员的唯一标识问题。

虚基类的声明是在派生类的定义过程,其语法格式为: class 派生类名:virtual 继承方式 基类名

上述语句声明基类为派生类的虚基类,在多继承情况下,虚基类关键字的作用范围和继承方式关键字相同,只对紧跟其后的基类起作用。声明了虚基类之后,虚基类的成员在进一步派生过程中,和派生类一起维护一个内存数据拷贝。

7-5 定义一个Shape基类,在此基础上派生出Rectangle和Circle,二者都有GetArea()函数计算对象的面积。使用Rectangle类创建一个派生类Square。

解: 源程序:

#include

class Shape { public: Shape(){} ~Shape(){}

virtual float GetArea(){ return-1;} };

class Circle : public Shape { public:

Circle(float radius):itsRadius(radius){} ~Circle(){}

float GetArea(){ return 3.14 * itsRadius * itsRadius;} private:

float itsRadius;};

class Rectangle : public Shape { public:

Rectangle(float len,float width): itsLength(len),itsWidth(width){};~Rectangle(){};

virtual float GetArea(){ return itsLength * itsWidth;} virtual float GetLength(){ return itsLength;} virtual float GetWidth(){ return itsWidth;} private: float itsWidth;

float itsLength;};

class Square : public Rectangle { public: Square(float len);~Square(){} };

Square::Square(float len): Rectangle(len,len){ }

void main(){ Shape * sp;

sp = new Circle(5);cout << ”The area of the Circle is “ << sp->GetArea()<< endl;delete sp;sp = new Rectangle(4,6);cout << ”The area of the Rectangle is “ << sp->GetArea()<< endl;delete sp;sp = new Square(5);cout << ”The area of the Square is “ << sp->GetArea()<< endl;delete sp;}

程序运行输出:

The area of the Circle is 78.5 The area of the Rectangle is 24 The area of the Square is 25

7-6 定义一个哺乳动物Mammal类,再由此派生出狗Dog类,定义一个Dog类的对象,观察基类与派生类的构造函数与析构函数的调用顺序。

解: 源程序:

#include enum myColor{ BLACK,WHITE };

class Mammal { public:

// constructors Mammal();~Mammal();

//accessors

int GetAge()const { return itsAge;} void SetAge(int age){ itsAge = age;} int GetWeight()const { return itsWeight;} void SetWeight(int weight){ itsWeight = weight;}

//Other methods

void Speak()const { cout << ”Mammal sound!n“;}

protected: int itsAge;int itsWeight;};

class Dog : public Mammal { public: Dog();~Dog();

myColor GetColor()const { return itsColor;} void SetColor(myColor color){ itsColor = color;}

void WagTail(){ cout << ”Tail wagging...n“;}

private:

myColor itsColor;};

Mammal::Mammal(): itsAge(1),itsWeight(5){

cout << ”Mammal constructor...n“;}

Mammal::~Mammal(){

cout << ”Mammal destructor...n“;}

Dog::Dog(): itsColor(WHITE){ cout << ”Dog constructor...n“;}

Dog::~Dog(){ cout << ”Dog destructor...n“;} int main(){ Dog Jack;Jack.Speak();Jack.WagTail();cout << ” Jack is “ << Jack.GetAge()<< ” years oldn“;

return 0;}

程序运行输出: Mammal constructor...Dog constructor...Mammal sound!Tail wagging...Fido is 1 years old Dog destructor...Mammal destructor...7-7 定义一个基类,构造其派生类,在构造函数中输出提示信息,观察构造函数的执行情况。

解:

#include

class BaseClass { public: BaseClass();};

BaseClass::BaseClass(){ cout << ”构造基类对象!“ << endl;}

class DerivedClass : public BaseClass { public:

DerivedClass();};

DerivedClass::DerivedClass(){

cout << ”构造派生类对象!“ << endl;}

void main(){

DerivedClass d;}

程序运行输出: 构造基类对象!构造派生类对象!

7-8 定义一个Document类,有name成员变量,从Document派生出Book类,增加PageCount变量。

解:

#include #include

class Document { public: Document(){};

Document(char *name);char *Name;// Document name.void PrintNameOf();// Print name.};

Document::Document(char *name){

Name = new char[ strlen(name)+ 1 ];strcpy(Name, name);};

void Document::PrintNameOf(){

cout << Name << endl;

}

class Book : public Document { public: Book(char *name, long pagecount);void PrintNameOf();private: long PageCount;};Book::Book(char *name, long pagecount):Document(name){ PageCount = pagecount;} void Book::PrintNameOf(){ cout << ”Name of book: “;Document::PrintNameOf();}

void main(){ Document a(”Document1“);Book b(”Book1“,100);b.PrintNameOf();} 程序运行输出: Name of book: Book1

7-9 定义基类Base,有两个共有成员函数fn1()、fn2(),私有派生出Derived类,如果想在Derived类的对象中使用基类函数fn1(),应怎么办?

解: class Base { public: int fn1()const { return 1;} int fn2()const { return 2;} };

class Derived : private Base { public:

int fn1(){ return Base::fn1();};int fn2(){ return Base::fn2();};};

void main(){

Derived a;a.fn1();}

7-10 定义object类,有weight属性及相应的操作函数,由此派生出box类,增加Height和width属性及相应的操作函数,声明一个box对象,观察构造函数与析构函数的调用顺序。

解:

#include

class object { private: int Weight;public: object(){

cout << ”构造object对象“ << endl;Weight = 0;}

int GetWeight(){ return Weight;} void SetWeight(int n){ Weight = n;}

~object(){ cout << ”析构object对象“ << endl;} };

class box : public object { private:

int Height,Width;public: box(){

cout << ”构造box对象“ << endl;Height = Width = 0;}

int GetHeight(){ return Height;} void SetHeight(int n){ Height = n;} int GetWidth(){ return Width;} void SetWidth(int n){ Width = n;}

~box(){ cout << ”析构box对象“ << endl;} };

void main(){ box a;}

程序运行输出: 构造object对象 构造box对象 析构box对象 析构object对象

7-11 定义一个基类BaseClass,从它派生出类DerivedClass,BaseClass有成员函数fn1()、fn2(),DerivedClass也有成员函数fn1()、fn2(),在主程序中定义一个DerivedClass的对象,分别用DerivedClass的对象以及BaseClass和DerivedClass的指针来调用fn1()、fn2(),观察运行结果。

解:

#include

class BaseClass { public: void fn1();void fn2();};void BaseClass::fn1(){ cout << ”调用基类的函数fn1()“ << endl;} void BaseClass::fn2(){ cout << ”调用基类的函数fn2()“ << endl;}

class DerivedClass : public BaseClass { public: void fn1();void fn2();};

void DerivedClass::fn1(){

cout << ”调用派生类的函数fn1()“ << endl;}

void DerivedClass::fn2(){

cout << ”调用派生类的函数fn2()“ << endl;}

void main(){

DerivedClass aDerivedClass;

DerivedClass *pDerivedClass = &aDerivedClass;BaseClass *pBaseClass = &aDerivedClass;

aDerivedClass.fn1();aDerivedClass.fn2();pBaseClass->fn1();pBaseClass->fn2();pDerivedClass->fn1();pDerivedClass->fn2();}

程序运行输出: 调用派生类的函数fn1()调用派生类的函数fn2()调用基类的函数fn1()调用基类的函数fn2()调用派生类的函数fn1()调用派生类的函数fn2()

7-12 为例9-1的吹泡泡程序加一版权(About)对话框。然后修改例9-1的程序,加入以下内容:

程 序:

1.在程序首部加上文件包含命令 #include “resource.h”

2.在框架窗口类之前加入从CDialog类派生的对话框类:// 对话框类

class CAboutDlg: public CDialog { public: CAboutDlg();

enum {IDD = IDD_DIALOG1};};inline

CAboutDlg::CAboutDlg():CDialog(CAboutDlg::IDD){} 3.在框架窗口类中添加响应鼠标右键消息的代码,包括消息响应函数说明、消息响应宏和消息响应函数定义。鼠标右键消息响应函数为:

void CMyWnd::OnRButtonDown(UINT nFlags, CPoint point){ CAboutDlg dlg;dlg.DoModal();}

7-13 签名留念簿程序。该程序模仿签名簿,用户使用鼠标左键点击窗口客户区后会弹出一个对话框,输入姓名后可在鼠标点击位置显示出该签名。签名的颜色、字体大小和方向随机确定。说 明:项目建立及添加对话框模板资源的方法同例14-1。修改对话框模板的ID为IDD_NAMEDLG,Caption为“签名对话框”,并添加一个静态文本控件(Caption改为“签名”)和一个编辑控件(ID改为IDC_EDITNAME)。

程 序:

// Example 14-2:签名留念簿程序 #include #include ”resource.h“ // 对话框类

class CNameDlg: public CDialog { public: CPoint m_pointTopLeft;CString m_strNameEdit;public: CNameDlg();enum {IDD = IDD_NAMEDLG};protected: virtual void DoDataExchange(CDataExchange* pDX);virtual BOOL OnInitDialog();};// 对话框类的构造函数

CNameDlg::CNameDlg():CDialog(CNameDlg::IDD){ m_strNameEdit = _T(”“);} // 数据交换和数据检验

void CNameDlg::DoDataExchange(CDataExchange* pDX){ CDialog::DoDataExchange(pDX);DDX_Text(pDX, IDC_EDITNAME, m_strNameEdit);DDV_MaxChars(pDX, m_strNameEdit, 20);}

// 初始化对话框

BOOL CNameDlg::OnInitDialog(){

CDialog::OnInitDialog();CRect rect;

GetWindowRect(&rect);

rect = CRect(m_pointTopLeft, rect.Size());MoveWindow(rect);return TRUE;}

// 签名类

class CSignal: public CObject {

CString m_sName;// 姓名

CPoint m_pointSignal;// 签名位置 int m_nHeight;// 字体高 int m_nColor;// 签名颜色 int m_nEscapement;// 签名倾角 public: CSignal(){}

void SetValue(CString name,CPoint point,int height,int color,int escapement);

void ShowSignal(CDC *pDC);};

// 签名类成员函数

void CSignal::SetValue(CString name,CPoint point,int height,int color, int escapement){

m_sName = name;m_pointSignal = point;m_nHeight = height;m_nColor = color;

m_nEscapement = escapement;}

// 显示签名

void CSignal::ShowSignal(CDC *pDC){

CFont *pOldFont, font;

font.CreateFont(m_nHeight, 0, m_nEscapement,0, 400, FALSE,FALSE,0, OEM_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, DEFAULT_PITCH, ”楷体“);

pOldFont = pDC->SelectObject(&font);switch(m_nColor){

case 0: pDC->SetTextColor(RGB(0, 0, 0));break;case 1: pDC->SetTextColor(RGB(255, 0, 0));break;case 2: pDC->SetTextColor(RGB(0, 255, 0));break;case 3: pDC->SetTextColor(RGB(0, 0, 255));break;} pDC->TextOut(m_pointSignal.x, m_pointSignal.y, m_sName);pDC->SelectObject(pOldFont);} // 框架窗口类 #define MAX_NAME 250 class CMyWnd: public CFrameWnd { CSignal m_signalList[MAX_NAME];int m_nCount;public: CMyWnd(): m_nCount(0){} protected: afx_msg void OnLButtonDown(UINT nFlags, CPoint point);afx_msg void OnPaint();DECLARE_MESSAGE_MAP()};// 消息映射

BEGIN_MESSAGE_MAP(CMyWnd, CFrameWnd)ON_WM_LBUTTONDOWN()ON_WM_PAINT()END_MESSAGE_MAP()// 框架窗口类的成员函数 // 鼠标右键消息响应函数

void CMyWnd::OnLButtonDown(UINT nFlags, CPoint point){ if(m_nCount < MAX_NAME){ CNameDlg dlg;dlg.m_pointTopLeft = point;if(dlg.DoModal()== IDOK){ int height = rand()%60+12;int color = rand()%4;int escapement =(rand()%1200)-600;

CString name = dlg.m_strNameEdit;

m_signalList[m_nCount].SetValue(name,point,height, color,escapement);m_nCount++;Invalidate();} } }

// 绘制框架窗口客户区函数 void CMyWnd::OnPaint(){

CPaintDC dc(this);

for(int i=0;i

// 应用程序类

class CMyApp: public CWinApp { public:

BOOL InitInstance();};

// 应用程序类的成员函数 BOOL CMyApp::InitInstance(){

CMyWnd *pFrame = new CMyWnd;

pFrame->Create(0,_T(”签字留念簿程序“));pFrame->ShowWindow(m_nCmdShow);this->m_pMainWnd = pFrame;return TRUE;}

// 全局应用程序对象 CMyApp ThisApp;

7-14 将例14-2的签名留念簿中的对话框改为无模式对话框。用户可用鼠标右键调出签名对话框,并在不退出该对话框的情况下用鼠标左键将输入的签名显示在窗口客户区。

说 明:在向项目中添加对话框模板资源时,要在其属性对话框的More Styles页中选择Visible项。其他同例14-2。

程 序:

该程序中的签名类CSignal和应用程序类与上例相同,因此下面仅列出了框架窗口类和对话框类。由于这两个类的成员函数中存在相互引用的情况,所以我们将框架窗口类的声明放在前面,接下来是对话框类的定义,并在框架窗口类之前加入了一

条对对话框类的声明。最后是这两个类的成员函数定义。// 框架窗口类 #define MAX_NAME 250 class CNameDlg;class CMyWnd: public CFrameWnd { CSignal m_signalList[MAX_NAME];int m_nCount;CNameDlg *m_pNameDlg;public: CMyWnd();~CMyWnd();protected: afx_msg void OnLButtonDown(UINT nFlags, CPoint point);afx_msg void OnRButtonDown(UINT nFlags, CPoint point);afx_msg void OnPaint();DECLARE_MESSAGE_MAP()};// 对话框类

class CNameDlg: public CDialog { public: BOOL m_bActive;CString m_strNameEdit;enum {IDD = IDD_NAMEDLG};CNameDlg();BOOL Create();protected: virtual void DoDataExchange(CDataExchange* pDX);virtual BOOL OnInitDialog();virtual void OnOK();virtual void OnCancel();};// 框架窗口类的消息映射

BEGIN_MESSAGE_MAP(CMyWnd, CFrameWnd)ON_WM_LBUTTONDOWN()ON_WM_RBUTTONDOWN()ON_WM_PAINT()END_MESSAGE_MAP()// 框架窗口类的成员函数 // 框架窗口类的构造函数 CMyWnd::CMyWnd(){ m_nCount = 0;m_pNameDlg = new CNameDlg;} // 框架窗口类的析构函数 CMyWnd::~CMyWnd()

{

delete m_pNameDlg;}

// 鼠标右键消息响应函数

void CMyWnd::OnRButtonDown(UINT nFlags, CPoint point){

if(m_pNameDlg->m_bActive)

m_pNameDlg->SetActiveWindow();// 激活对话框 else

m_pNameDlg->Create();// 显示对话框 }

// 鼠标左键消息响应函数

void CMyWnd::OnLButtonDown(UINT nFlags, CPoint point){

if(m_nCount < MAX_NAME){

int height = rand()%60+12;int color = rand()%4;

int escapement =(rand()%1200)-600;CString name = m_pNameDlg->m_strNameEdit;

m_signalList[m_nCount].SetValue(name, point, height, color, escapement);m_nCount++;Invalidate();} }

// 绘制框架窗口客户区函数 void CMyWnd::OnPaint(){

CPaintDC dc(this);

for(int i=0;i

// 对话框类的成员函数 // 对话框类的构造函数

CNameDlg::CNameDlg():CDialog(CNameDlg::IDD){

m_bActive = FALSE;m_strNameEdit = _T(”“);}

// 数据交换

void CNameDlg::DoDataExchange(CDataExchange* pDX){

CDialog::DoDataExchange(pDX);

DDX_Text(pDX, IDC_EDIT1, m_strNameEdit);}

// 初始化对话框

BOOL CNameDlg::OnInitDialog(){ CDialog::OnInitDialog();CRect rect;GetWindowRect(&rect);MoveWindow(0, 0, rect.Width(), rect.Height());return TRUE;} // 显示无模态对话框 BOOL CNameDlg::Create(){ m_bActive = TRUE;return CDialog::Create(CNameDlg::IDD);} // 退出对话框

void CNameDlg::OnCancel(){ m_bActive = FALSE;DestroyWindow();} // 更新数据

void CNameDlg::OnOK(){ UpdateData(TRUE);}

7-15 为例14-2的签名程序加上字体选择对话框。

说 明:本程序使用字体选择公用对话框(通过鼠标右键调出)选择签名的字体、字号和颜色等参数,在签名对话框中要输入姓名和签名与X轴的倾斜角。建立项目的方法与例14-2相似,只是要在签名对话框模板中再添加一个编辑控件用于输入签名的倾斜角,其标识符为IDD_EDIT2。

程 序:

// Example 14-4:签名留念簿程序 #include #include #include #include ”resource.h“ // 对话框类

class CNameDlg: public CDialog { public: CPoint m_pointTopLeft;// 对话框位置 CString m_strNameEdit;// 签名

LONG m_lEscapement;// 签名倾角 public: CNameDlg();

enum {IDD = IDD_NAMEDLG};protected:

virtual void DoDataExchange(CDataExchange* pDX);virtual BOOL OnInitDialog();};

// 对话框类的构造函数

CNameDlg::CNameDlg():CDialog(CNameDlg::IDD), m_pointTopLeft(0, 0){

m_strNameEdit = _T(”“);m_lEscapement = 0;}

// 数据交换和数据检验

void CNameDlg::DoDataExchange(CDataExchange* pDX){

CDialog::DoDataExchange(pDX);

DDX_Text(pDX, IDC_EDIT1, m_strNameEdit);DDX_Text(pDX, IDC_EDIT2, m_lEscapement);DDV_MaxChars(pDX, m_strNameEdit, 20);

DDV_MinMaxLong(pDX, m_lEscapement,-600, 600);}

// 初始化对话框

BOOL CNameDlg::OnInitDialog(){

CDialog::OnInitDialog();CRect rect;

GetWindowRect(&rect);

rect = CRect(m_pointTopLeft, rect.Size());MoveWindow(rect);return TRUE;}

// 签名类

class CSignal: public CObject {

CString m_strSignal;// 姓名 COLORREF m_colorSignal;// 签名颜色 CPoint m_pointSignal;// 签名位置 LOGFONT m_fontSignal;// 签名字体 public: CSignal(){}

void SetValue(CString signal, CPoint point, COLORREF color,LONG escapement, LOGFONT *pfont);void ShowSignal(CDC *pDC);};

// 签名类成员函数

void CSignal::SetValue(CString signal, CPoint point, COLORREF color, int escapement, LOGFONT *pfont){ m_strSignal = signal;m_pointSignal = point;m_colorSignal = color;memcpy(&m_fontSignal, pfont, sizeof(LOGFONT));m_fontSignal.lfEscapement = escapement;} // 显示签名

void CSignal::ShowSignal(CDC *pDC){ CFont font, *pOldFont;font.CreateFontIndirect(&m_fontSignal);pOldFont = pDC->SelectObject(&font);pDC->SetTextColor(m_colorSignal);pDC->TextOut(m_pointSignal.x, m_pointSignal.y, m_strSignal);pDC->SelectObject(pOldFont);} // 框架窗口类 #define MAX_NAME 250 class CMyWnd: public CFrameWnd { CSignal m_signalList[MAX_NAME];// 签名数组 int m_nCount;// 签名数量

LOGFONT m_fontSignal;// 签名字体 COLORREF m_colorSignal;// 签名颜色 public: CMyWnd();protected: afx_msg void OnLButtonDown(UINT nFlags, CPoint point);afx_msg void OnRButtonDown(UINT nFlags, CPoint point);afx_msg void OnPaint();DECLARE_MESSAGE_MAP()};// 消息映射

BEGIN_MESSAGE_MAP(CMyWnd, CFrameWnd)ON_WM_LBUTTONDOWN()ON_WM_RBUTTONDOWN()ON_WM_PAINT()END_MESSAGE_MAP()// 框架窗口类的成员函数 CMyWnd::CMyWnd(){ m_nCount = 0;

m_colorSignal = RGB(0, 0, 0);m_fontSignal.lfHeight = 40;m_fontSignal.lfWidth = 0;m_fontSignal.lfEscapement = 0;m_fontSignal.lfOrientation = 0;m_fontSignal.lfWeight = 400;m_fontSignal.lfItalic = FALSE;m_fontSignal.lfUnderline = FALSE;m_fontSignal.lfStrikeOut = 0;

m_fontSignal.lfCharSet = OEM_CHARSET;

m_fontSignal.lfOutPrecision = OUT_DEFAULT_PRECIS;m_fontSignal.lfClipPrecision = CLIP_DEFAULT_PRECIS;m_fontSignal.lfQuality = DEFAULT_QUALITY;m_fontSignal.lfPitchAndFamily = DEFAULT_PITCH;strcpy(m_fontSignal.lfFaceName, ”Arial“);}

// 鼠标右键消息响应函数

void CMyWnd::OnLButtonDown(UINT nFlags, CPoint point){

if(m_nCount < MAX_NAME){

CNameDlg dlg;

dlg.m_pointTopLeft = point;if(dlg.DoModal()== IDOK){

LONG escapement = dlg.m_lEscapement;CString name = dlg.m_strNameEdit;m_signalList[m_nCount].SetValue(name, point,m_colorSignal,escapement, &m_fontSignal);m_nCount++;Invalidate();} } }

// 鼠标右键消息响应函数

void CMyWnd::OnRButtonDown(UINT nFlags, CPoint point){

CFontDialog dlg(&m_fontSignal);if(dlg.DoModal()== IDOK){

dlg.GetCurrentFont(&m_fontSignal);m_colorSignal = dlg.GetColor();} }

// 绘制框架窗口客户区函数 void CMyWnd::OnPaint(){

CPaintDC dc(this);for(int i=0;i

class CMyApp: public CWinApp { public: BOOL InitInstance();};// 应用程序类的成员函数 BOOL CMyApp::InitInstance(){ CMyWnd *pFrame = new CMyWnd;pFrame->Create(0,_T(”签字留念簿程序“));pFrame->ShowWindow(SW_SHOWMAXIMIZED);this->m_pMainWnd = pFrame;return TRUE;} // 全局应用程序对象 CMyApp ThisApp;

7-16 为例9-3的吹泡泡程序添加颜色选择对话框,使其可以绘出五颜六色的泡泡。

程 序:在例9-3的程序基础上作如下修改: 1.在程序首部添加文件包含命令: #include 2.在框架窗口类声明中添加一个COLORREF类型的数组,存放各泡泡的颜色:

COLORREF m_colorBubble [MAX_BUBBLE];3.修改鼠标左键消息映射函数,添加使用颜色选择公用对话框的代码:

void CMyWnd::OnLButtonDown(UINT nFlags, CPoint point){ if(m_nBubbleCount < MAX_BUBBLE){ m_colorBubble[m_nBubbleCount] = RGB(200, 200, 200);CColorDialog dlg(m_colorBubble[m_nBubbleCount]);if(dlg.DoModal()== IDOK)m_colorBubble[m_nBubbleCount] = dlg.GetColor();int r = rand()%50+10;CRect rect(point.x-r, point.y-r, point.x+r, point.y+r);m_rectBubble[m_nBubbleCount] = rect;m_nBubbleCount++;

InvalidateRect(rect, FALSE);} }

4.修改OnPaint()成员函数,添加根据泡泡颜色使用画刷的代码:

void CMyWnd::OnPaint(){

CPaintDC dc(this);

CBrush brushNew, *pbrushOld;for(int i=0;i

brushNew.CreateSolidBrush(m_colorBubble[i]);pbrushOld = dc.SelectObject(&brushNew);dc.Ellipse(m_rectBubble[i]);dc.SelectObject(pbrushOld);brushNew.DeleteObject();} }

7-17 序列化。如果例12-1的吹泡泡程序使用一般的数组存放泡泡数据(参看例9-1的程序): CRect m_rectBubble[MAX_BUBBLE];int m_nBubbleCount;

为其文档类重新设计Serialize()函数。

说 明:按例12-1的方法建立项目和输入源代码,但将文档类中的泡泡数据改为以上两行的形式。修改文档类的Serialize()函数,代码如下。

程 序: // 序列化函数

void CMyDoc::Serialze(CArchive& ar){

if(ar.IsStoring()){

ar << m_nBubbleCount;

for(int i=0;i

ar >> m_nBubbleCount;

for(int i=0;i> m_rectBubble[i];} }

7-18 修改例12-1的程序并观察其打印结果。

程 序:

在例12-1程序的视图类CMyView类的成员函数OnDraw()中,添加代码沿窗口客户区轮廓画一矩形: void CMyView::OnDraw(CDC* pDC){ CRect rect;GetClientRect(&rect);pDC->Rectangle(rect);

CMyDoc* pDoc = GetDocument();// 取文档指针 ASSERT_VALID(pDoc);pDC->SelectStockObject(LTGRAY_BRUSH);// 在视图上显示文档数据

for(int i=0;i

GetListSize();i++)pDC->Ellipse(pDoc->GetBubble(i));}

7-19 改进吹泡泡程序,使之打印输出与屏幕显示的比例相近。

程 序:

在例12-1基础上修改。首先在CMyView类中重载虚函数OnPrepareDC()。在CMyView类的声明中增加一行: virtual void OnPrepareDC(CDC

*pDC,CPrintInfo *pInfo=NULL);然后添加该函数的定义,设置映射模式为MM_LOMETRIC: // 设置映射模式

void CMyView::OnPrepareDC(CDC *pDC, CPrintInfo *pInfo){ pDC->SetMapMode(MM_LOMETRIC);CView::OnPrepareDC(pDC, pInfo);} 然后修改消息映射函数OnLButtonDown(),将物理坐标转换为逻辑坐标:

// 响应点击鼠标左键消息

void CMyView::OnLButtonDown(UINT nFlags, CPoint point){ CMyDoc* pDoc = GetDocument();// 取文档指针 ASSERT_VALID(pDoc);CClientDC dc(this);// 设置设备环境

OnPrepareDC(&dc);

int r = rand()%50+5;// 生成泡泡

CRect rect(point.x-r, point.y-r, point.x+r, point.y+r);InvalidateRect(rect, FALSE);// 更新视图 dc.DPtoLP(rect);// 转换物理坐标为逻辑坐标 pDoc->AddBubble(rect);// 修改文档数据 pDoc->SetModifiedFlag();// 设置修改标志 }

7-20 声明一个Person类,并使之支持序列化。

程 序:

class CPerson: public CObject {

DECLARE_SERIAL(CPerson)LONG m_IDnumber;// 身份证号码 CString m_strName;// 姓名 CString m_strNation;// 民族 int m_nSex;// 性别 int m_nAge;// 年龄 BOOL m_bMarried;// 婚否 public: CEmployee(){};

CPerson& operator =(CPerson& person);void Serialize(CArchive& ar);};

IMPLEMENT_SERIAL(CPerson, CObject, 1)CPerson& CPerson::operator =(CPerson& person){

m_IDnumber = person.m_IDnumber;m_strName = person.m_strName;m_strNation = person.m_strNation;m_nSex = person.m_nSex;m_nAge = person.m_nAge;

m_bMarried = person.m_bMarried;return *this;}

void CPerson::Serialize(CArchive& ar){

CObject::Serialize(ar);// 首先调用基类的Serialize()方法

if(ar.IsStoring()){

ar << m_IDnumber;ar << m_strName;ar << m_strNation;

ar << m_nSex;ar << m_nAge;ar <<(int)m_bMarried;} else { ar >> m_IDnumber;ar >> m_strName;ar >> m_strNation;ar >> m_nSex;CFont *pOldFont =(CFont *)(pDC->SelectObject(&font));CRect rectPaper = pInfo->m_rectDraw;// 取页面打印矩形 // 页眉: 页面顶端中央打印文档名称 CMyDoc *pDoc = GetDocument();ASSERT_VALID(pDoc);CString str;str.Format(”Bubble

(LPCSTR)pDoc->GetTitle());

CSize sizeText = pDC->GetTextExtent(str);

CPoint point((rectPaper.Width()-sizeText.cx)/2, 0);Report:

%s“, ar >> m_nAge;ar >>(int)m_bMarried;} }

7-21 修改例13-3的吹泡泡程序,使其打印每个泡泡的数据值。打印格式为每页40行,页眉为文档名,页脚为页号。说 明:首先为视图类添加一个数据成员m_nLinePerPage,用来存放每页行数,并在视图类CMyView的构造函数中将m_nLinePerPage初始化为40。

修改视图类成员函数OnPrepareDC(),设置映射模式为MM_TWIPS。该模式为每英寸1440点,很适合打印机输出。

程 序:

重载视图类的成员函数OnPreparePrinting(),在其中添加计算打印页数的代码:

BOOL CMyView::OnPreparePrinting(CPrintInfo* pInfo){ CMyDoc *pDoc = GetDocument();int nPageCount = pDoc->GetListSize()/m_nLinePerPage;if(pDoc->GetListSize()% m_nLinePerPage)nPageCount ++;pInfo->SetMaxPage(nPageCount);return DoPreparePrinting(pInfo);} 最后重载视图类的OnPrint()函数并添加打印代码: void CMyView::OnPrint(CDC* pDC, CPrintInfo* pInfo){ int nPage = pInfo->m_nCurPage;// 当前页号

int nStart =(nPage-1)*m_nLinePerPage;// 本页第一行 int nEnd = nStart+m_nLinePerPage;// 本页最后一行 CFont font;// 设置字体

font.CreateFont(-280, 0, 0, 0, 400, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_MODERN, ”Courier New“);

pDC->TextOut(point.x, point.y, str);point.x = rectPaper.left;// 打印页眉下划线 point.y = rectPaper.top-sizeText.cy;pDC->MoveTo(point);point.x = rectPaper.right;pDC->LineTo(point);// 打印表头

str.Format(”%6.6s %6.6s %6.6s %6.6s %6.6s“, ”Index“, ”Left“, ”Top“, ”Right“, ”Bottom“);point.x = 720;point.y-= 720;

pDC->TextOut(point.x, point.y, str);TEXTMETRIC tm;// 取当前字体有关信息 pDC->GetTextMetrics(&tm);

int nHeight = tm.tmHeight+tm.tmExternalLeading;point.y-= 360;// 下移 1/4 英寸

for(int i=nStart;i

if(i >= pDoc->GetListSize())break;

str.Format(”%6d %6d %6d %6d %6d“, i+1, pDoc->GetBubble(i).left, pDoc->GetBubble(i).top, pDoc->GetBubble(i).right, pDoc->GetBubble(i).bottom);point.y-= nHeight;

pDC->TextOut(point.x, point.y, str);}

// 在页面底部中央打印页号 str.Format(”-%d-“, nPage);sizeText = pDC->GetTextExtent(str);

point.x =(rectPaper.Width()-sizeText.cx)/2;point.y = rectPaper.Height()+sizeText.cy;pDC->TextOut(point.x, point.y, str);// 释放字体对象

pDC->SelectObject(pOldFont);}

7-22 修改例11-4的拼图程序,使之在难度菜单的相应选项前打钩。

程 序:

首先在框架窗口类的消息响应函数声明处增加以下消息响应函数的声明: afx_msg void CPuzzleWnd::OnUpdateGrad01(CCmdUI* pCmdUI);afx_msg void CPuzzleWnd::OnUpdateGrad02(CCmdUI* pCmdUI);afx_msg void CPuzzleWnd::OnUpdateGrad03(CCmdUI* pCmdUI);然后在框架窗口类的消息映射宏中加入相应内容: BEGIN_MESSAGE_MAP(CPuzzleWnd, CFrameWnd)ON_WM_LBUTTONDOWN()ON_WM_LBUTTONUP()ON_WM_MOUSEMOVE()ON_WM_PAINT()ON_COMMAND(ID_SHOWFIG, OnShowFig)ON_COMMAND(ID_GRAD01, OnGrad01)ON_COMMAND(ID_GRAD02, OnGrad02)ON_COMMAND(ID_GRAD03, OnGrad03)ON_UPDATE_COMMAND_UI(ID_GRAD01, OnUpdateGrad01)ON_UPDATE_COMMAND_UI(ID_GRAD02, OnUpdateGrad02)ON_UPDATE_COMMAND_UI(ID_GRAD03, OnUpdateGrad03)END_MESSAGE_MAP()注意更新命令用户接口消息映射宏将菜单标识符与相应的消息映射函数联系在一起。最后编写相应的更新命令用户接口消息映射函数:

void CPuzzleWnd::OnUpdateGrad01(CCmdUI* pCmdUI){ pCmdUI->SetCheck(m_nColCount == 4);} void CPuzzleWnd::OnUpdateGrad02(CCmdUI* pCmdUI){ pCmdUI->SetCheck(m_nColCount == 8);} void CPuzzleWnd::OnUpdateGrad03(CCmdUI* pCmdUI){ pCmdUI->SetCheck(m_nColCount == 16);} 输入输出:在选择拼图难度时,可在相应选项前打钩(图13-4)。

// Example 13-7: 七巧板程序

////////////////////////////////// #include #include //

//////////////////////////////////////////////////// #define MAX_POINTS 4 #define CHIP_WIDTH 240 #define DELTA 30

class CChip : public CObject {

DECLARE_SERIAL(CChip)int m_nType;

CPoint m_pointList[MAX_POINTS];int m_nPointCount;public: CChip(){}

void SetChip(int type, POINT *ppointlist, int count);void DrawChip(CDC *pDC);BOOL PtInChip(POINT point);LPCRECT GetRect();

void MoveTo(CSize offset);void Rotation();

void Serialize(CArchive &ar);};

IMPLEMENT_SERIAL(CChip, CObject, 1)// 设置拼图块参数

void CChip::SetChip(int type, POINT *ppointlist, int count){

m_nType = type;m_nPointCount = count;for(int i=0;i

// 绘出拼图块

void CChip::DrawChip(CDC *pDC){

CPen penNew, *ppenOld;CBrush brushNew, *pbrushOld;switch(m_nType){ case 1:

brushNew.CreateSolidBrush(RGB(127, 127, 127));break;case 2:

brushNew.CreateSolidBrush(RGB(255, 0, 0));break;

case 3: brushNew.CreateSolidBrush(RGB(0, 255, 0));break;case 4: brushNew.CreateSolidBrush(RGB(0, 0, 255));break;case 5: brushNew.CreateSolidBrush(RGB(127, 127, 0));break;case 6: brushNew.CreateSolidBrush(RGB(127, 0, 127));break;case 7: brushNew.CreateSolidBrush(RGB(0, 127, 127));break;} penNew.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));ppenOld = pDC->SelectObject(&penNew);pbrushOld = pDC->SelectObject(&brushNew);pDC->Polygon(m_pointList, m_nPointCount);pDC->SelectObject(ppenOld);pDC->SelectObject(pbrushOld);} // 检测一点是否在拼图块中

BOOL CChip::PtInChip(POINT point){ CRgn rgn;rgn.CreatePolygonRgn(m_pointList, m_nPointCount, 0);return rgn.PtInRegion(point);} // 取拼图块的包含矩形 LPCRECT CChip::GetRect(){ static RECT rect;CRgn rgn;rgn.CreatePolygonRgn(m_pointList, m_nPointCount, 0);rgn.GetRgnBox(&rect);rect.right++;rect.bottom++;return ▭} // 旋转拼图块

void CChip::Rotation(){ CRect rect;CRgn rgn;rgn.CreatePolygonRgn(m_pointList, m_nPointCount, 0);rgn.GetRgnBox(&rect);

double x = rect.left+rect.Width()/2;// 计算旋转中心 double y = rect.top+rect.Height()/2;double dx, dy;

for(int i=0;i

dx = m_pointList[i].x-x;dy = m_pointList[i].y-y;

m_pointList[i].x =(int)(x+dx*0.7071-dy*0.7071);m_pointList[i].y =(int)(y+dx*0.7071+dy*0.7071);} }

// 移动拼图块

void CChip::MoveTo(CSize offset){

for(int i=0;i

// 序列化

void CChip::Serialize(CArchive &ar){

if(ar.IsStoring()){

ar << m_nType;ar << m_nPointCount;

for(int i=0;i

ar >> m_nType;ar >> m_nPointCount;

for(int i=0;i> m_pointList[i];} } //

//////////////////////////////////////////////////// #define CHIP_COUNT 7

class CMyDoc : public CDocument {

DECLARE_DYNCREATE(CMyDoc)CChip m_chipList[CHIP_COUNT];public: void Reset();

virtual void DeleteContents();virtual void Serialize(CArchive& ar);};

IMPLEMENT_DYNCREATE(CMyDoc, CDocument)

// 初始化拼图块 void CMyDoc::Reset(){ POINT pointList[MAX_POINTS];pointList[0].x = DELTA;pointList[0].y = DELTA;pointList[1].x = DELTA+CHIP_WIDTH;pointList[1].y = DELTA;pointList[2].x = DELTA+CHIP_WIDTH/2;pointList[2].y = DELTA+CHIP_WIDTH/2;m_chipList[0].SetChip(1, pointList, 3);

pointList[0].x = DELTA;pointList[0].y = DELTA;pointList[1].x = DELTA;pointList[1].y = DELTA+CHIP_WIDTH;pointList[2].x = DELTA+CHIP_WIDTH/2;pointList[2].y = DELTA+CHIP_WIDTH/2;m_chipList[1].SetChip(2, pointList, 3);

pointList[0].x = DELTA+CHIP_WIDTH;pointList[0].y = DELTA;pointList[1].x = DELTA+CHIP_WIDTH;pointList[1].y = DELTA+CHIP_WIDTH/2;pointList[2].x = DELTA+(CHIP_WIDTH*3)/4;pointList[2].y = DELTA+CHIP_WIDTH/4;m_chipList[2].SetChip(3, pointList, 3);

pointList[0].x = DELTA+CHIP_WIDTH/2;pointList[0].y = DELTA+CHIP_WIDTH/2;pointList[1].x = DELTA+CHIP_WIDTH/4;pointList[1].y = DELTA+(CHIP_WIDTH*3)/4;pointList[2].x = DELTA+(CHIP_WIDTH*3)/4;pointList[2].y = DELTA+(CHIP_WIDTH*3)/4;m_chipList[3].SetChip(4, pointList, 3);

pointList[0].x = DELTA+CHIP_WIDTH;pointList[0].y = DELTA+CHIP_WIDTH/2;pointList[1].x = DELTA+CHIP_WIDTH;pointList[1].y = DELTA+CHIP_WIDTH;pointList[2].x = DELTA+CHIP_WIDTH/2;pointList[2].y = DELTA+CHIP_WIDTH;m_chipList[4].SetChip(5, pointList, 3);

pointList[0].x = DELTA+(CHIP_WIDTH*3)/4;pointList[0].y = DELTA+CHIP_WIDTH/4;pointList[1].x = DELTA+CHIP_WIDTH/2;pointList[1].y = DELTA+CHIP_WIDTH/2;

pointList[2].x = DELTA+(CHIP_WIDTH*3)/4;pointList[2].y = DELTA+(CHIP_WIDTH*3)/4;pointList[3].x = DELTA+CHIP_WIDTH;pointList[3].y = DELTA+CHIP_WIDTH/2;m_chipList[5].SetChip(6, pointList, 4);

pointList[0].x = DELTA;

pointList[0].y = DELTA+CHIP_WIDTH;pointList[1].x = DELTA+CHIP_WIDTH/4;pointList[1].y = DELTA+(CHIP_WIDTH*3)/4;pointList[2].x = DELTA+(CHIP_WIDTH*3)/4;pointList[2].y = DELTA+(CHIP_WIDTH*3)/4;

pointLis ¨t[3].x = DELTA+CHIP_WIDTH/2;pointList[3].y = DELTA+CHIP_WIDTH;m_chipList[6].SetChip(7, pointList, 4);// 清理文档:关闭文档、建立新文档和打开文档前调用 void CMyDoc::DeleteContents(){ Reset();

CDocument::DeleteContents();}

// 系列化:读写文档时自动调用 void CMyDoc::Serialize(CArchive &ar){

for(int i=0;i

/////////////////////////////////////////////////// class CMyView : public CView {

DECLARE_DYNCREATE(CMyView)BOOL m_bCaptured;CPoint m_pointMouse;int m_nCurrIndex;public:

CMyView(){m_bCaptured = FALSE;}

CMyDoc* GetDocument(){return(CMyDoc*)m_pDocument;} virtual void OnInitialUpdate();

virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);virtual void OnDraw(CDC* pDC);

afx_msg void OnLButtonDown(UINT nFlags, CPoint point);afx_msg void OnLButtonUp(UINT nFlags, CPoint point);afx_msg void OnMouseMove(UINT nFlags, CPoint point);afx_msg void OnRButtonDown(UINT nFlags, CPoint point);DECLARE_MESSAGE_MAP()};

IMPLEMENT_DYNCREATE(CMyView, CView)

BEGIN_MESSAGE_MAP(CMyView, CView)ON_WM_LBUTTONDOWN()ON_WM_LBUTTONUP()ON_WM_MOUSEMOVE()ON_WM_RBUTTONDOWN()ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)END_MESSAGE_MAP()// 更新初始化:当建立新文档或打开文档时调用 void CMyView::OnInitialUpdate(){ CView::OnInitialUpdate();Invalidate();} // 绘制视图:程序开始运行或窗体发生变化时自动调用 void CMyView::OnDraw(CDC* pDC){ CMyDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);for(int i=0;im_chipList[i].DrawChip(pDC);} // 消息响应:用户点击鼠标左键时调用

void CMyView::OnLButtonDown(UINT nFlags, CPoint point){ CMyDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);for(int i=CHIP_COUNT-1;i>=0;i--)if(pDoc->m_chipList[i].PtInChip(point)){ SetCapture();m_bCaptured = TRUE;m_pointMouse = point;m_nCurrIndex = i;break;} } // 释放鼠标左键

void CMyView::OnLButtonUp(UINT nFlags, CPoint point){ if(m_bCaptured){ ::ReleaseCapture();m_bCaptured = FALSE;} }

// 移动鼠标左键

void CMyView::OnMouseMove(UINT nFlags, CPoint point){

if(m_bCaptured){

CMyDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);

InvalidateRect(pDoc->m_chipList[m_nCurrIndex].GetRect());

CSize offset(point-m_pointMouse);

pDoc->m_chipList[m_nCurrIndex].MoveTo(offset);InvalidateRect(pDoc->m_chipList[m_nCurrIndex].GetRect());

m_pointMouse = point;pDoc->SetModifiedFlag();} }

// 按下鼠标右键: 旋转拼图块

void CMyView::OnRButtonDown(UINT nFlags, CPoint point){

CMyDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);

for(int i=CHIP_COUNT-1;i>=0;i--)if(pDoc->m_chipList[i].PtInChip(point)){

InvalidateRect(pDoc->m_chipList[i].GetRect());pDoc->m_chipList[i].Rotation();

InvalidateRect(pDoc->m_chipList[i].GetRect(), FALSE);pDoc->SetModifiedFlag();break;} }

// 准备打印:设置打印参数

BOOL CMyView::OnPreparePrinting(CPrintInfo* pInfo){

pInfo->SetMaxPage(1);

return DoPreparePrinting(pInfo);} //

////////////////////////////////////////////////// class CMainFrame : public CFrameWnd {

DECLARE_DYNCREATE(CMainFrame)};

IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)//

///////////////////////////////////////////////

#define IDR_MAINFRAME 128 // 主框架的资源代号 class CMyApp : public CWinApp { public: virtual BOOL InitInstance();DECLARE_MESSAGE_MAP()};BEGIN_MESSAGE_MAP(CMyApp, CWinApp)ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)END_MESSAGE_MAP()// 初始化程序实例:建立并登记文档模板 BOOL CMyApp::InitInstance(){ CSingleDocTemplate* pDocTemplate;pDocTemplate = new CSingleDocTemplate(IDR_MAINFRAME, RUNTIME_CLASS(CMyDoc), RUNTIME_CLASS(CMainFrame), RUNTIME_CLASS(CMyView));AddDocTemplate(pDocTemplate);CCommandLineInfo cmdInfo;ParseCommandLine(cmdInfo);if(!ProcessShellCommand(cmdInfo))return FALSE;m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);return TRUE;} // 全局应用程序对象 CMyApp theApp;

7-23 为例9-3的吹泡泡程序添加一标识符为IDI_MAINICON的图标(该图标应已按11.8:“向项目中添加资源”中的方法建立并加入项目)。

说 明:建立项目的方法见9.8:“用Visual C++集成开发环境开发Win32应用程序”。

程 序:

在例9-3程序前面添加一文件包含命令: #include ”resource.h”

并将CMyApp::InitInstance()函数修改为: BOOL CMyApp::InitInstance(){

HICON hIcon;

hIcon = LoadIcon(IDI_MAINICON);// 载入图标 CMyWnd *pFrame = new CMyWnd;pFrame->Create(0,_T(”吹泡泡程序“));

pFrame->SetIcon(hIcon, TRUE);// 设置大图标 pFrame->SetIcon(hIcon, FALSE);// 设置小图标 pFrame->ShowWindow(m_nCmdShow);this->m_pMainWnd = pFrame;return TRUE;}

7-24 显示一张位图文件(.BMP)。

说 明:首先建立Win32 Application空白项目和源代码文件(不要忘记设置项目使之可以使用MFC类库),然后按11.8:“向项目中添加资源”的方法为项目建立资源文件,并将待显示的位图文件作为资源装入项目。

程 序:

// Example 11-2:显示BMP图片 #include #include ”resource.h“ // 框架窗口类

class CMyWnd: public CFrameWnd {

CBitmap m_Bitmap;int m_nHeight;int m_nWidth;public: CMyWnd();protected:

afx_msg void OnPaint();DECLARE_MESSAGE_MAP()};

// 消息映射

BEGIN_MESSAGE_MAP(CMyWnd, CFrameWnd)ON_WM_PAINT()END_MESSAGE_MAP()// 框架窗口类的成员函数 CMyWnd::CMyWnd(){

m_Bitmap.LoadBitmap(IDB_BITMAP1);BITMAP BM;

m_Bitmap.GetBitmap(&BM);m_nWidth = BM.bmWidth;m_nHeight = BM.bmHeight;}

// 响应绘制窗口客户区消息 void CMyWnd::OnPaint(){ CPaintDC dc(this);CDC MemDC;MemDC.CreateCompatibleDC(NULL);MemDC.SelectObject(&m_Bitmap);dc.BitBlt(0,0,m_nWidth,m_nHeight,&MemDC,0,0,SRCCOPY);} // 应用程序类

class CMinMFCApp: public CWinApp { public: BOOL InitInstance();};// 应用程序类的成员函数 // 初始化应用程序实例

BOOL CMinMFCApp::InitInstance(){ CMyWnd *pFrame = new CMyWnd;pFrame->Create(0,_T(”Beautiful Cats”));pFrame->ShowWindow(m_nCmdShow);this->m_pMainWnd = pFrame;return TRUE;} // 全局应用程序对象 CMinMFCApp ThisApp;

7-25 修改11-2,使之可以不同比例放大或缩小图象。说 明:使用StretchBlt()函数代替BitBlt()函数就可实现图象的缩放显示。在项目中加入一个弹出式菜单(将标识符改为IDR_MAINMENU),内含3个菜单选项:缩小1倍显示,按原尺寸显示和放大1倍显示,其标识符分别改为ID_SHRINK,ID_BESTFIT和ID_ZOOMOUT。

程 序:

// Example 11-3:以不同尺寸显示BMP图片 #include #include “resource.h” // 框架窗口类

class CMyWnd: public CFrameWnd { CBitmap m_Bitmap;float m_fTimes;int m_nHeight;

int m_nWidth;public: CMyWnd();

BOOL PreCreateWindow(CREATESTRUCT &cs);protected:

afx_msg void OnPaint();afx_msg void OnShrink();afx_msg void OnBestFit();afx_msg void OnZoomOut();DECLARE_MESSAGE_MAP()};

// 消息映射

BEGIN_MESSAGE_MAP(CMyWnd, CFrameWnd)ON_WM_PAINT()

ON_COMMAND(ID_SHRINK, OnShrink)ON_COMMAND(ID_BESTFIT, OnBestFit)ON_COMMAND(ID_ZOOMOUT, OnZoomOut)END_MESSAGE_MAP()// 主窗口类的成员函数 CMyWnd::CMyWnd(){

BITMAP BM;

m_Bitmap.LoadBitmap(IDB_BITMAP1);m_Bitmap.GetBitmap(&BM);m_nWidth = BM.bmWidth;m_nHeight = BM.bmHeight;m_fTimes = 1.0;}

// 装入菜单

BOOL CMyWnd::PreCreateWindow(CREATESTRUCT &cs){ cs.hMenu

=

LoadMenu(NULL,MAKEINTRESOURCE(IDR_MAINMENU));return CFrameWnd::PreCreateWindow(cs);}

// 缩小图象

void CMyWnd::OnShrink(){

m_fTimes = 0.5;Invalidate();}

// 放大图象

void CMyWnd::OnZoomOut(){

m_fTimes = 2.0;Invalidate();}

// 原样显示

下载《C语言程序设计》课后习题参考答案word格式文档
下载《C语言程序设计》课后习题参考答案.doc
将本文档下载到自己电脑,方便修改和收藏,请勿使用迅雷等下载。
点此处下载文档

文档为doc格式


声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:645879355@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。

相关范文推荐

    C语言课后习题答案5篇

    C语言课后习题答案-第四版- 第一章 5、请参照本章例题,编写一个C语言程序,输出以下信息: **************************** V e r y G o o d ! **************************** #inc......

    c语言课后习题

    C语言程序设计实验报告 学院 数学与信息技术班级学号 11130730 姓名指导教师 实验1 简单程序设计 1. 实验目的 (1) 熟悉C语言开发环境并掌握在该环境下如何编辑、编译、连接......

    C语言课后习题

    习题 第三章 #include #include int main { int d,p; double r,a,m; scanf("%d %d %lf",&d,&p,&r); a=(p/(p-d*r)); m=log(a)/log(1+r); if(p>0&&d>0) { if(d23) h=0;......

    c语言程序设计课后习题答案 第五章[样例5]

    /*练习5-3*/ #include int prime(int m) { int i; for(i=2;i......

    C语言程序设计教程_杨路明__课后习题答案

    C语言程序设计教程 杨路明 课后习题答案 北京邮电大学出版社 第一章 1、算法描述主要是用两种基本方法:第一是自然语言描述,第二是使用专用工具进行算法描述 2、c语言程序的结......

    《C语言程序设计教程》课后题答案

    《C语言程序设计教程》课后题答案 第一章 一选择题 1.A 2.B 3.C 4.D 5.B 6.C 二.填空题 1.程序 2.算法 3.main或主 4.编译 5.编译 6. .obj 7.库函数 8.文本或ASCII码......

    C语言程序设计课后习题1-8参考答案[最终版]

    C语言程序设计课后习题1-8参考答案习题1参考答案 一、简答题 1、冯 诺依曼计算机模型有哪几个基本组成部分?各部分的主要功能是什么? 答:冯 诺依曼计算机模型是由运算器、控制......

    c语言程序设计(科学出版社)课后习题解答

    第3章习题解答 第1章 1.C 语言程序主要由预处理命令、函数、注释等组成。2.填空分号main stdio.h 3. 源程序: #include main { printf(“************......