5C++第五章习题解答文档格式.docx

上传人:b****6 文档编号:22010006 上传时间:2023-02-02 格式:DOCX 页数:25 大小:47.88KB
下载 相关 举报
5C++第五章习题解答文档格式.docx_第1页
第1页 / 共25页
5C++第五章习题解答文档格式.docx_第2页
第2页 / 共25页
5C++第五章习题解答文档格式.docx_第3页
第3页 / 共25页
5C++第五章习题解答文档格式.docx_第4页
第4页 / 共25页
5C++第五章习题解答文档格式.docx_第5页
第5页 / 共25页
点击查看更多>>
下载资源
资源描述

5C++第五章习题解答文档格式.docx

《5C++第五章习题解答文档格式.docx》由会员分享,可在线阅读,更多相关《5C++第五章习题解答文档格式.docx(25页珍藏版)》请在冰豆网上搜索。

5C++第五章习题解答文档格式.docx

(4)常量指针

(5)不能通过该指针修改对象

(6)const放在类型说明之前

5.1.7数组名在表达式中被自动转换为指向

(1)的指针常量,数组名是地址,但数组名中放的地址是

(2),所以数组名(3)。

这样数组名可以由(4)来代替,C++这样做使用时十分方便,但丢失了数组的另一要素(5),数组名是指向数组(6)的指针,而不是指向数组(7)的。

编译器按数组定义的大小分配内存,但运行时对(8)不加检测,这会带来无法预知的严重错误。

(1)数组第一个元素

(2)不可改变的

(3)称指针常量

(4)指针

(5)数组元素的数量

(6)元素

(7)整体

(8)对数组的边界不加检测

5.1.8有一个三维数组:

intz3d[2][3][4];

给出指向三维数组第i行第j列第k页元素的指针的三种表达方式

(1),

(2),(3)。

再给出这些元素的三种表达方式(4),(5),(6)。

(1)z3d[i][j]+k或&

z3d[i][j][k]

(2)*(z3d[i]+j)+k

(3)*(*(z3d+i)+j)+k

(4)z3d[i][j][k]或*(z3d[i][j]+k)

(5)*(*(z3d[i]+j)+k)

(6)*(*(*(z3d+i)+j)+k)

5.2简答题

5.2.1物理上,C++是怎样访问数组元素的?

请对访问方法作简单介绍。

答:

物理上,C++语言的下标运算符[]是以指针作为操作数的,a[i]被编译系统解释为*(a+i),即表示为a所指(固定不可变)元素向后第i个元素。

无论我们是以下标方式或指针方式存取数组元素时,系统都是转换为指针方法实现。

这样做对多维数组尤其方便。

5.2.2什么是回溯算法?

回溯法是对枚举法的一种改进。

回溯法的基本思想是,通过对问题的分析找出解决问题的线索,先在一个局部上找出满足问题条件的局部的解,然后逐步由局部解向整个问题的解的方向试探,若试探成功就得到问题的解,试探失败逐步向后退,改变局部解再向前试探。

回溯法能避免枚举法的许多不必要的搜索,使问题比较快地得到解决。

5.2.3用数组名作为函数的参数时,可否加上数组的长度?

如果需要加则怎样加?

为什么?

被调函数中作为形式参数的一维数组不需要说明长度,即使说明了大小也不起作用,因为C++只传递数组首地址,而对数组边界不加检查。

5.2.4需要编写一个对多维数组通用的算法(即各维的大小未定),怎样才能把实参多维数组的信息全部传递到函数中去?

最佳方法是用函数模板,多维数组用模板类型参数传递,各维的大小作为参数传递。

也可以用一维数组加各维的大小都作为参数传递。

5.2.5解释运算符“*”和“&

”的作用,运算符“.”和“->

”的作用。

在应用指针变量时,“*”是间接引用(dereference)运算符,作用于一个指针类型的变量,访问该指针所指向的内存数据。

因结果是内存中可寻址的数据。

“&

”是取地址运算符,作用于内存中一个可寻址的数据(如:

变量,对象和数组元素等等),操作的结果是获得该数据的地址。

运算符“.”和“->

”是成员访问运算符(MemberAccessOprator)。

在对象或结构外部去访问公有的数据成员或函数成员时,是在对象名后加“.”(点操作符),再加成员函数名或函数名就可以了。

但是这些成员必须是公有的成员,只有公有成员才能在对象的外面对它进行访问。

当用指向对象和结构变量的指针访问其公有成员时,则只要在指针变量名后加“->

”(箭头操作符),再加公有成员名就可以了。

5.2.6什么是this指针?

简述它的作用。

当我们在对象的外部访问该对象的公有成员时,必须指明是哪一个对象。

但是当我们用对象的成员函数来访问本对象的成员时,在成员函数中只要给出成员名就可以实现对该对象成员的访问。

但同一个类创建的多个对象共用同一份成员函数的拷贝。

既然是同一份拷贝,那么成员函数又怎么知道是取哪一个对象的成员数据呢?

其实每一个对象有一个隐藏的this指针,它始终指向该对象,并将该指针作为一个参数自动传递给该成员函数。

这就是说,成员操作符总是要使用的,只不过在对象内是隐式的,即在对象内省略了this指针。

5.2.7指针变量与整型量的加减运算代表什么意义?

指针变量与整型量的加减表示移动指针,以指向当前目标前面或后面的若干个位置的目标。

指针与整型量i的加减等于指针值(地址)与i*sizeof(目标类型)积的加减,得出新的地址。

5.2.8设a为数组名,那么a++是否合法?

非法。

因为a是指针常量。

5.2.9指针作为函数的参数时,它传递的是什么?

实参要用什么?

而使用引用时实参要用什么?

何时只能用指针而不能用引用?

是地址,是指针所指向的变量或对象的内存首地址,在物理上讲我们传的是指针的值,与传其它变量是没有差异的,函数获得的是另一个变量的地址,在逻辑上讲我们是把另一个变量的地址传过去了,可以看作传地址。

实参要用变量或对象的地址。

而使用引用时实参要用变量或对象本身。

实参为数组时,只能用指针而不能用引用,因为数组的引用不存在。

5.2.10指针作为函数的返回值时,应该注意什么?

指针指向的数据的生命期必须不仅仅在函数域中,函数消亡后,数据仍然存在。

如果返回的指针,它所指的变量或对象已消亡,则该返回值无意义,这一点必须十分小心。

总之直接使用指针不管是作为参数还是返回值,都要注意安全性。

5.2.11设有语句

char*ps=”It’sabook.”;

是否建立了一个字符串,并把”it’sabook.”作为其初值?

随后又有语句:

*ps=”It’sacar”;

这又代表什么?

是否正确。

没有建立字符串,只是让ps指向一个放在代码区中的特殊字符串,而该字符串所在内存是不可写的。

后一条语句要求把字符串赋给不可写的字符串空间是错的。

二、编程与综合练习题

5.3打印杨辉三角形(10行)。

使用二维数组并利用每个系数等于其肩上两系数之和。

解:

好的算法无特例,二维数组共用11列,第1列全0,方便计算

#include<

iostream>

usingnamespacestd;

intmain(){

inta[10][11]={0,1},i,j;

//初始化时写好第1行,其余各行全0

for(i=1;

i<

10;

i++)//为了全部算法无特例,共用11列,第1列全0,方便计算

for(j=1;

j<

=i+1;

j++)a[i][j]=a[i-1][j-1]+a[i-1][j];

for(i=0;

i++){

j++)cout<

<

a[i][j]<

'

\t'

;

cout<

endl;

}

return0;

}

5.4将[例5.5]改用一维数组,附加行、列参数,实现通用算法。

用一维数组,附加行、列参数,实现通用算法难度大。

#include<

iomanip>

voidinverse(int[],int[],int,int);

//注意数组最高维可缺省,例5.5因初学未省

voidmulti(int[],int[],int[],int,int,int);

voidoutput(int[],int,int);

intmiddle[6*3],result[6*4];

//注意写作6*3等可清楚看出矩阵的行列

intmatrix1[3*6]={8,10,12,23,1,3,5,7,9,2,4,6,34,45,56,2,4,6};

intmatrix2[3*4]={3,2,1,0,-1,-2,9,8,7,6,5,4};

output(matrix1,3,6);

inverse(matrix1,middle,3,6);

output(middle,6,3);

output(matrix2,3,4);

multi(middle,matrix2,result,6,3,4);

output(result,6,4);

voidinverse(intmatrix1_1[],intmiddle_1[],inta,intb){

inti,j;

for(i=0;

a;

i++)

for(j=0;

b;

j++)

middle_1[i+j*a]=matrix1_1[i*b+j];

return;

voidmulti(intmiddle_1[],intmatrix2_1[],intresult_1[],inta,intb,intc){

inti,j,k;

c;

j++){

result_1[i*c+j]=0;

for(k=0;

k<

k++)

result_1[i*c+j]+=middle_1[i*b+k]*matrix2_1[k*c+j];

voidoutput(intmax_1[],inta,intb){

for(inti=0;

for(intj=0;

cout<

setw(4)<

max_1[i*b+j]<

"

"

cout<

\n'

5.5编写函数intatoi(chars[]),将字符串s转化为整型数返回。

注意负数处理方法。

用指针处理字符串非常方便。

使用符号位来处理负数。

intatoi(chars[]){

inttemp=0,f=1,i=0;

while(s[i]!

='

\0'

&

s[i]!

-'

(s[i]<

0'

||s[i]>

9'

))i++;

//去除串前部无效字符

if(s[i]=='

){//读负号

f=-1;

i++;

if(s[i]<

)cout<

error!

//串非法时,输出提示,返回0

while(s[i]>

s[i]<

){//转换数字串

temp=temp*10+s[i]-48;

returnf*temp;

charnum[20];

cin.getline(num,19);

atoi(num)<

5.6有如下定义:

intival=60021;

int*ip;

double*dp;

下面哪些赋值非法或可能带来错误,并加以讨论。

ival=*ip;

ival=ip;

*ip=ival;

ip=ival;

*ip=&

ival;

ip=&

dp=ip;

dp=*ip;

*dp=*ip;

错,未确定指针ip初值,用随机内存地址中的数据给ival赋值是危险的。

但语法对。

ival=ip;

错,赋值类型错,指针型不能赋给整型。

*ip=ival;

错,未确定指针ip初值,用ival给随机内存赋值是危险的。

ip=ival;

错,赋值类型错,整型不能赋给指针型。

*ip=&

错,赋值类型错,地址(指针型)不能赋给整型。

对,地址赋给指针型。

dp=ip;

错,整型指针不能赋给双精度指针。

dp=*ip;

*dp=*ip;

对,赋值类型转换

5.7编程定义一个整型、一个双精度型、一个字符型的指针,并赋初值,然后显示各指针所指目标的值与地址,各指针的值与指针本身的地址及各指针所占字节数(长度)。

*其中地址用十六进制显示。

注意:

字符指针输出是字符串,必须强制转换为无类型指针

int*ip,ival=100;

double*dp,dval=99.9;

char*cp,cval='

A'

ip=&

dp=&

dval;

cp=&

cval;

*ip<

sizeof(*ip)<

*dp<

sizeof(*dp)<

*cp<

(void*)&

sizeof(*cp)<

//字符指针输出是字符串,必须强制转换为无类型指针

//输出A开头的字符串

ip<

sizeof(ip)<

dp<

sizeof(dp)<

(void*)cp<

cp<

sizeof(cp)<

一个典型的运行结果:

变量

内容

首地址

长度(字节)

cval

‘A’

0x0012ff64

1

cp

0x0012ff68

4

dval

99.9

0x0012ff6c

8

dp

0x0012ff74

ival

100

0x0012ff78

ip

0x0012ff7c

内存分配解释:

速度优化时通常以字(4字节)为单位(开始地址可被4整除)给变量安排内存。

cval仅用一个字节,也安排了4个字节。

5.8分别编写下列字符串处理函数

(1)char*strcat1(char*s,constchar*ct);

将串ct接到串s的后面,形成一个长串。

【例6.7】以数组为参数,现用指针为参数。

(2)intstrlen1(constchar*s);

求字符串长度的函数,返回串长(不包括串结束符)。

(3)char*reverse(char*);

反置字符串s,即可将“break”成为“kaerb”。

(4)char*strchr(constchar*cs,charc);

查找字符c在串cs中第一次出现的位置,返回指向该字符的指针,若没有出现则返回NULL。

(5)char*strstr(constchar*cs1,constchar*cs2);

返回串cs2作为子串在cs1中第一次出现的位置,若没有出现则返回NULL。

为了函数的通用性,有些可不要返回值的函数,也保留返回值。

反置字符串函数,从串两头的指针同时向中间移动,重合或交错时停止。

查找子串,先找子串的第一个字符,再核对子串其他字符。

查找子串函数是比较难的。

查找分两重循环,第1重主串与子串第1个字符比较,当顺序找到主串中有字符与子串第1个字符相符时,进入第2重循环对所有字符进行比较,比较时要借助工作变量,成功则返回子串所在位置,本轮失败,则主串后移一个字符,回到第1重循环。

在使用++运算符时一定要单用,如本例中:

while(*temp==*temp1&

*temp1){temp++;

temp1++;

};

if(*temp1==0)return(char*)cs1;

千万不可简化为:

while(*temp++==*temp1++&

*temp1);

这里有微妙的差异,主串与子串最后一个字符不同也认为子串找到了。

char*strcat1(char*s,constchar*ct){

char*st=s;

while(*s)s++;

//*s作为条件,等效*s!

=0

while(*s++=*ct++);

returnst;

intstrlen1(constchar*s){

inti=0;

while(*s++)i++;

returni;

char*reverse(char*s){

chartemp,*temp1=s,*temp2=s;

while(*temp2)temp2++;

temp2--;

//指针移回串尾

while(temp2-temp1>

0){//注意此处,从串两头的指针同时向中间移动,重合或交错时停止

temp=*temp1;

*temp1=*temp2;

*temp2=temp;

temp1++;

temp2--;

returns;

char*strchr(constchar*cs,charc){

while(*cs!

=c&

*cs)cs++;

if(*cs==0)cs=NULL;

//未找到返回NALL

return(char*)cs;

char*strstr(constchar*cs1,constchar*cs2){

char*temp,*temp1;

while(*cs1){//只要主串还有字符未查,则继续

while(*cs1!

=*cs2&

*cs1)cs1++;

//与子串第1个字符不符,主串查找位置后移一个字符

//找到主串含有子串的第一个字符,或主串查完停止

if(*cs1){//主串含有子串的第一个字符,核对子串全部字符

temp=(char*)cs1;

temp1=(char*)cs2;

while(*temp==*temp1&

if(*temp1==0)return(char*)cs1;

//找到子串返回

elsecs1++;

//本轮未找到,主串查找位置后移一个字符

}

returnNULL;

//返回NALL

chara[40]="

束明"

charb[20]="

是东南大学学生"

charc[40]="

SoutheastUniversity"

char*cp;

a<

b<

strcat1(a,b);

字符串连接后:

//打印字符数组a

字符串长度为:

strlen1(a)<

c<

cp=strchr(c,'

U'

);

if(cp==NULL)cout<

未找到"

elsecout<

//找到输出由该字符开始的剩余串

reverse(c)<

cp=strstr(a,"

是"

if(cp!

=NULL)cout<

//找到输出由该字符串开始的剩余串

大学生"

5.9使用递归和非递归的两种方法编写函数

char*itoa(intn,char*string);

将整数n转换为十进制表示的字符串。

(在非递归方法中,可使用reverse()函数。

递归方法分析。

难度大,可用图解法:

每次调用除以10,以去除最后一位,以n=3657为例。

由此图可见,由string指向应填入的字符数组的相应位置。

由调用的最底层开始,回归时填入,每次回归,指针后移一位,由此得

char*itoal(intn,char*string){

if(n/10)string=itoal(n/10,string);

*string++=n%10+48;

//字符,ASCII码

returnstring;

考虑,数字串结束符和负数,得完整的函数。

char*itoal(intn,char*string){

if(n<

0){

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 企业管理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1