C++第五章习题解答

C++第五章习题解答
C++第五章习题解答

第五章数组与指针习题

一、.基本概念与基础知识自测题

5.1 填充题

5.1.1 数组定义时有三个要素:数组名,数组元素的(1)和数组元素的(2)。按元

素在数组中的位置进行访问,是通过(3)进行的,称为(4)或(5)访问。

为了使数组声明中数组的大小修改更为方便,总是将(6)用于声明数组长度。

答案:(1)类型

(2)数量

(3)下标运算符

(4)下标

(5)索引

(6)常变量

5.1.2 C/C++中的多维数组用的是一个(1)的定义,即多维数组的基本定义是(2)构

成的数组,三维数组的元素是(3)。

答案:(1)嵌套

(2)以数组作为元素

(3)二维数组

5.1.3 计算机内存是一维编址的,多维数组在内存中的存储(1),C/C++多维在内存中

的排列是(2)方式,即越(3)的下标变化(4)。设数组a有m行n列,每个元素占内存u个字节,则a[i][j]的首地址为(5)+ (6)。

答案:(1)必须要转化为一维方式,

(2)按行方式

(3)右

(4)越快

(5)a数组的首地址

(6)(i*n+j)*u

5.1.4 对于多维数组,(1)的大小是确定的,所谓“不检查数组边界”只是不检查(2)

的边界,而(3)的边界是在控制之中的,所以多维数组名作为函数的参数只可以(4)缺省。

答案:(1)较低各维的

(2)最高维(第一维)

(3)较低各维

(4)最高维

5.1.5 指针变量保存了另一变量的(1)值,不可以任意给指针变量赋一个地址值,只能赋

给它(2)和(3)的地址。使用变量名来访问变量,是按(4)来直接存取变量称为(5)方式;而借助指针变量取得另一变量的地址,访问该变量称为(6)方式。

答案:(1)地址

(2)NULL

(3)已经分配了内存的变量的地址

(4)按变量的地址

(5)直接访问

(6)间接访问

5.1.6 固定指向一个对象的指针,称为(1),即(2),定义时const放在(3)。

而指向“常量”的指针称为(4),指针本身可以指向别的对象,但(5),定义时const放在(6)。

答案:(1)指针常量

(2)指针本身是常量

(3)const放在类型说明之后,变量名之前

(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 有一个三维数组:

int z3d[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)运算符,作用于一个指针类型的变量,访问该指针所指向的内存数据。因结果是内存中可寻址的数据。“&”是取地址运算符,作用于内存中一个可寻址的数据(如:变量,对象和数组元素等等),操作的结果是获得该数据的地址。

运算符“.”和“->”是成员访问运算符(Member Access Oprator)。在对象或结构外部去访问公有的数据成员或函数成员时,是在对象名后加“.”(点操作符),再加成员函数名或函数名就可以了。但是这些成员必须是公有的成员,只有公有成员才能在对象的外面对它进行访问。当用指向对象和结构变量的指针访问其公有成员时,则只要在指针变量名后加“->”(箭头操作符),再加公有成员名就可以了。

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’s a book.”;

是否建立了一个字符串,并把”it’s a book.”作为其初值?随后又有语句:

*ps=”It’s a car”;

这又代表什么?是否正确。

答:没有建立字符串,只是让ps指向一个放在代码区中的特殊字符串,而该字符串所在内存是不可写的。后一条语句要求把字符串赋给不可写的字符串空间是错的。

二、编程与综合练习题

5.3 打印杨辉三角形(10行)。使用二维数组并利用每个系数等于其肩上两系数之和。解:好的算法无特例,二维数组共用11列,第1列全0,方便计算

#include

using namespace std;

int main(){

int a[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<10;i++){

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

cout<

}

return 0;

}

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

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

#include

#include

using namespace std;

void inverse(int [], int [],int,int);//注意数组最高维可缺省,例5.5因初学未省

void multi(int [], int [], int [],int,int,int);

void output(int [],int,int);

int main(){

int middle[6*3], result[6*4];//注意写作6*3等可清楚看出矩阵的行列

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

int matrix2[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);

return 0;

}

void inverse(int matrix1_1[],int middle_1[],int a,int b){

int i,j;

for (i=0;i

for (j=0;j

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

return;

}

void multi(int middle_1[],int matrix2_1[],int result_1[],int a,int b,int c){

int i,j,k;

for (i=0;i

for (j=0;j

result_1[i*c+j] = 0;

for (k=0;k

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

}

}

return;

}

void output(int max_1[],int a,int b){

for (int i=0;i

for (int j=0;j

cout <

cout<<'\n';

}

cout<

return;

}

5.5 编写函数int atoi(char s[ ]),将字符串s转化为整型数返回。注意负数处理方法。解:用指针处理字符串非常方便。使用符号位来处理负数。

#include

using namespace std;

int atoi(char s[]){

int temp=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]<'0'||s[i]>'9') cout<<"error!"<

while(s[i]>='0'&&s[i]<='9'){//转换数字串

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

i++;

}

return f*temp;

}

int main(){

char num[20];

cin.getline(num,19);

cout<

return 0;

}

5.6 有如下定义:

int ival=60021;

int *ip;

double *dp;

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

ival=*ip; ival=ip; *ip=ival; ip=ival; *ip=&ival;

ip=&ival; dp=ip; dp=*ip; *dp=*ip;

解:ival=*ip; 错,未确定指针ip初值,用随机内存地址中的数据给ival赋值是危险的。但语法对。

ival=ip; 错,赋值类型错,指针型不能赋给整型。

*ip=ival; 错,未确定指针ip初值,用ival给随机内存赋值是危险的。但语法对。

ip=ival; 错,赋值类型错,整型不能赋给指针型。

*ip=&ival; 错,赋值类型错,地址(指针型)不能赋给整型。

ip=&ival; 对,地址赋给指针型。

dp=ip; 错,整型指针不能赋给双精度指针。

dp=*ip; 错,赋值类型错,整型不能赋给指针型。

*dp=*ip; 对,赋值类型转换

5.7 编程定义一个整型、一个双精度型、一个字符型的指针,并赋初值,然后显示各指针

所指目标的值与地址,各指针的值与指针本身的地址及各指针所占字节数(长度)。

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

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

#include

using namespace std;

int main(){

int *ip,ival=100;

double *dp,dval=99.9;

char *cp,cval='A';

ip=&ival;

dp=&dval;

cp=&cval;

cout<<*ip<<'\t'<<&*ip<<'\t'<

cout<<*dp<<'\t'<<&*dp<<'\t'<

cout<<*cp<<'\t'<<(void*)&*cp<<'\t'<

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

cout<<*cp<<'\t'<<&*cp<<'\t'<

//输出A开头的字符串

cout<

cout<

cout<<(void*)cp<<'\t'<<&cp<<'\t'<

return 0;

}

一个典型的运行结果:

内存分配解释:速度优化时通常以字(4字节)为单位(开始地址可被4整除)给变量安排内存。cval仅用一个字节,也安排了4个字节。

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

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

将串ct接到串s的后面,形成一个长串。【例6.7】以数组为参数,现用指针为参数。

(2)int strlen1(const char * s);

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

(3)char * reverse (char *);

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

(4)char * strchr( const char *cs, char c);

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

(5)char *strstr (const char *cs1,const char *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);

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

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

#include

using namespace std;

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

char* st=s;

while(*s) s++;//*s作为条件,等效*s!=0

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

return st;

}

int strlen1(const char* s){

int i=0;

while(*s++) i++;

return i;

}

char* reverse (char* s){

char temp,* temp1=s,* temp2=s;

while(*temp2) temp2++;

temp2--; //指针移回串尾

while(temp2-temp1>0){//注意此处,从串两头的指针同时向中间移动,重合或交错时停止temp=*temp1;

*temp1=*temp2;

*temp2=temp;

temp1++;

temp2--;

}

return s;

}

char* strchr( const char*cs,char c){

while(*cs!=c&&*cs) cs++;

if(*cs==0) cs=NULL; //未找到返回NALL

return (char*)cs;

}

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

char *temp,*temp1;

while(*cs1){ //只要主串还有字符未查,则继续while(*cs1!=*cs2&&*cs1) cs1++;

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

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

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

temp=(char*)cs1;

temp1=(char*)cs2;

while(*temp==*temp1&&*temp1){temp++;temp1++;};

if(*temp1==0) return (char*)cs1; //找到子串返回

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

}

}

return NULL; //返回NALL

}

int main(){

char a[40]="束明";

char b[20]="是东南大学学生";

char c[40]="Southeast University";

char *cp;

cout<

cout<

strcat1(a,b);

cout<<"字符串连接后:"<

cout<

cout<<"字符串长度为:"<

cout<

cp=strchr(c,'U');

if(cp==NULL) cout<<"未找到"<

else cout<

if(cp==NULL) cout<<"未找到"<

else cout<

cout<

cp=strstr(a,"是");

if(cp!=NULL) cout<

cp=strstr(a," 大学生");

if(cp==NULL) cout<<"未找到"<

else cout<

return 0;

}

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

char *itoa (int n,char *string);

将整数n转换为十进制表示的字符串。(在非递归方法中,可使用reverse()函数。)解:递归方法分析。难度大,可用图解法:

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

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

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

char * itoal(int n,char *string){

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

*string++=n%10+48;//字符,ASCII码

return string;

}

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

char * itoal(int n, char *string){

if(n<0){

*string++=’_’;

n=-n;

}

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

*string++=n%10+48;

*string=’\0’;

return string;

}

源代码:

#include

using namespace std;

char* reverse (char* s){

char temp,* temp1=s,* temp2=s;

while(*temp2) temp2++;

temp2--;//指针移回串尾

while(temp2-temp1>0){//注意此处,从串两头的指针同时向中间移动,重合或交错时停止temp=*temp1;

*temp1=*temp2;

*temp2=temp;

temp1++;

temp2--;

}

return s;

}

char *itoa (int n,char *string){

char *temp=string;

if(n<0){

*temp++='-';

n=-n;

}

do{//注意个位放在前了

*temp++=n%10+48;

}while(n=n/10);//显式的循环

*temp='\0';

if(*string=='-') temp=string+1;//有负号仅反转数字部分

else temp=string;

reverse(temp);//个位放到后面

return string;

}

char *itoa1 (int n,char *string){

if(n<0){

*string++='-';

n=-n;

}

if(n/10) string=itoa1(n/10,string);//隐式循环

*string++=n%10+48;

//第一次是数字最高位放串的最前面的字符(不含符号),注意指针移动在后*string='\0';

return string;//注意返回的指针已后移一字符

}

char *itoa0 (int n,char *string){

itoa1(n,string);

return string;

}

int main(){

int num;

char st[20];

cin>>num;

cout<<"输出数字串:"<

cin>>num;

cout<<"输出数字串:"<

return 0;

}

5.10 头文件中定义一个日期时间的结构:

struct tm{

int tm_sec; //秒

int tm_min; //分

int tm_hour; //时

int tm_mday; //日

int tm_mon; //月

int tm_year; //年,实际放的是与1970年的差,如1990年为20

int tm_wday; //星期

int tm_yday; //一年中的第几天

int tm_isdst; //是否夏时制

};

函数time_t time(time_t *tp)是提取当前时间,time_t即长整型,代表从1970年1月1日00:00:00开始计算的秒数(格林尼治时间),放在首地址为tp的单元内。

函数tm *localtime(const time_t *tp) 将tp地址单元中的时间转换为日期时间结构的当地时间;(函数tm *gmtime(const time_t *tp)转换为日期时间结构的格林尼治时间;)函数char *asctime(tm *tb)将tb地址单元中的tm结构的日期时间转换为字符串(供显示),它有固有格式,如:

Sun Sep 16 01:03:52 1973

利用以上资源,重新设计一个日期时间类(DataTime),要求定义对象时取当前时间进行初始化,显示时重取显示时刻的时间并显示出来。

解:

#include

#include

using namespace std;

class datatime{

tm *timedata;

long allsecond;

char *tmp;

public:

datatime(){

time(&allsecond);

timedata=localtime(&allsecond);

tmp=asctime(timedata);

cout<

}

void gettime(){

allsecond=time(NULL);//time有两种用法

timedata=localtime(&allsecond);

tmp=asctime(timedata);

cout<

}

};

int main(){

char ch;

datatime dt;

cout<<"需要知道现在的日期和时间吗?(Y或N)"<

cin>>ch;

if(ch=='y'|| ch=='Y') dt.gettime();

return 0;

}

5.11 完善自定义字符串类mystring,函数包括:构造函数、拷贝构造函数、析构函数,并重载运算符[ ],=(分别用mystring和C字符串拷贝),+(strcat),+=,<,>,==(strcmp)。解:此例既是对第4章的复习也是一个提高。拷贝构造函数的应用请参阅4.4.2节末尾两项说明,本例形参使用引用,仅在返回时调用了拷贝构造函数。运算符的重载请参阅4.5节。

5.12 将习题5.8中的字符串处理函数移植到mystring类中,其中strcat已重载为+运算符,

请将其它4个转为成员函数。对比成员函数与独立函数构造上有何不同?

解:这四个函数因mystring内部有串长,又要求下标索引,再加上str字符数组可直接使用,构造大不相同。

#include

using namespace std;

const int n=256;

class mystring{

char str[n]; //存放字符串的数组容器

int maxsize; //最大可用元素数,可防止数组出界,提高健壮性

int last; //已用元素最大下标

public:

mystring(){

last=-1;

maxsize=n;

str[0]='\0';

cout<<"缺省构造函数"<

}

mystring(char *s){//当C字符串过长,初始化时采用截尾处理

last=-1;

maxsize=n;

do{

last++;

str[last]=s[last];

}while(s[last]!='\0'&&last

str[last] ='\0'; //截尾处理时,必须加串结束符

cout<<"构造函数"<

}

mystring(mystring & ms){

last=-1;

maxsize=n;

do{

last++;

str[last]=ms.str[last];

}while(last

cout<<"拷贝构造函数"<

}

~mystring(){

cout<<"析构函数"<

}

void show(){//如需重载<<,则参见9.3.3节,暂时未学到,替代方法是用show()函数cout<

}

int strlen(){return last;};

void reverse();

int strchr(char c);

int strstr (mystring str1);

char & operator[](int i){ //返回引用,可读可写

if(i>last) last=i; //下标运算符,可添加长度但不查边界

return str[i];

}

mystring & operator=(mystring &);

mystring & operator=(char * ms);//这里重载的=是把C风格字符串赋给mystring

mystring operator+(mystring &); //这里返回不能用引用

mystring & operator+=(mystring &);

bool operator<(mystring &);

bool operator==(mystring &);

};

void mystring::reverse(){

int i=0,j=last-1;

char temp;

while(j>i){//注意此处,从串两头同时向中间移动,重合或交错时停止

temp=str[i]; //头尾交换

str[i]=str[j];

str[j]=temp;

i++;

j--;

}

}

int mystring::strchr(char c){

int i;

for(i=0;i!=last;i++) if(str[i]==c) return i;

return -1; //未找到返回-1

}

int mystring::strstr(mystring str1){

int i=0,k=1;

while(str[i]!='\0'){//只要主串还有字符未查,则继续

while(str[i]!=str1[0]&&str[i]!='\0') i++;

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

if(str[i]!='\0'){//核对子串其他字符

while(str[i+k]==str1.str[k]&&k

if(k==https://www.360docs.net/doc/a63614173.html,st) return i;//找到子串返回

k=1;

i++;

}

}

return -1; //未找到返回-1

}

mystring & mystring::operator=(mystring & ms){//这里返回值改为引用,不调用拷贝构造函数last=-1;

do{

last++;

str[last]=ms.str[last];

}while(last

return *this;

}

mystring & mystring::operator=(char* ms){ //这里返回值为引用,不调用拷贝构造函数last=-1;

do{

last++;

str[last]=ms[last];

}while(ms[last]!='\0'&&last

str[last] ='\0'; //截尾处理时,必须加串结束符

return *this;

}

mystring mystring::operator+(mystring & ms){//注意+和+=的不同

mystring temp(*this);//+必须在一份拷贝上进行

int i=-1;

https://www.360docs.net/doc/a63614173.html,st--;//串的结尾是结束符,连接时要覆盖掉

do{

https://www.360docs.net/doc/a63614173.html,st++;

i++;

temp.str[https://www.360docs.net/doc/a63614173.html,st]=ms.str[i];

}while(i

temp.str[https://www.360docs.net/doc/a63614173.html,st] ='\0'; //截尾处理时,必须加串结束符

return temp;//拷贝的临时变量生命期在调用它的表达式中

}

mystring & mystring::operator+=(mystring & ms){//+=在对象自身进行

int i=-1;

last--;//串的结尾是结束符,连接时要覆盖掉

do{

last++;

i++;

str[last]=ms.str[i];

}while(i

str[last] ='\0'; //截尾处理时,必须加串结束符

return *this;

}//这里返回值改为引用,不调用拷贝构造函数

bool mystring::operator<(mystring & ms){ //重载<运算符

int i=0,k;

do{

k=str[i]-ms.str[i];

i++;

}while(k==0&&i

if(k<0) return true;

if(i==last&&i!=https://www.360docs.net/doc/a63614173.html,st) return true;

return false;

}

bool mystring::operator==(mystring & ms){

int i=0,k;

if(last!=https://www.360docs.net/doc/a63614173.html,st) return false;

do{

k=str[i]-ms.str[i];

i++;

}while(k==0&&i

if(k!=0) return false;

else return true;

}

int main(){

int i;

char *sp1="东南大学",*sp2="交通学院",*sp3="学生",*sp4="教师";

mystring ms1(sp1),ms2(sp2),ms3(sp3);//ms1,ms2,ms3是用构造函数生成

mystring ms4(ms3),ms5=ms3,ms6; //ms4,ms5用拷贝构造函数生成;ms6用缺省构造函数ms6=sp4; //ms6赋值是返回引用,不用拷贝构造函数

ms1.show();

ms2.show();

ms3.show();

ms4.show();

ms5.show();

ms6.show();

ms4=ms1+ms2+ms6;//注意+中的temp和临时变量由拷贝构造函数生成

ms4.show();

ms1+=ms2+=ms3;//+=返回引用,不用拷贝构造函数

ms1.show();

if(ms1

ms6=ms1;//ms6赋值不是返回引用,必须调用拷贝构造函数建立临时对象

if(ms1==ms6) cout<<"串ms1与串ms6相同"<

ms1="C++ programming language";

i=0;

while(ms1[i]!='\0') cout<

cout<

ms1[i++]='.';//写入

ms1[i]='\0';

i=0;

ms1.show();

cout<

cout<<"ms1串长:"<

cout<<"字符l在ms1中的下标为:"<

ms2="ing";

cout<<"ms2在ms1中的起始下标为:"<

ms1.reverse();

ms1.show();

return 0;

}

5.13 分析下面程序的执行结果:

int main(){

union{

char word[8];

shor int ksi[4];

}x,*s;

s=&x;

s->ksi[0]=0x6f6d;

s->ksi[1]=0x6e72;

s->ksi[2]=0x6e69;

s->ksi[3]=0x0067;

cout<word<

return 0;

}

仿照上述程序,编写一个输出字符串为“computer!”的程序。

解:参见下图

#include

using namespace std;

union chint{

char word[10];

short int ksi[5];

};

int main(){ //数字转换为字符串chint x,*s;

s = &x;

s->ksi[0] = 0x6f63;

s->ksi[1] = 0x706d;

s->ksi[2] = 0x7475;

s->ksi[3] = 0x7265;

s->ksi[4] = 0x0021;

cout<word<< endl; getchar();

return 0;

}

相关主题
相关文档
最新文档