怎么利用C++实现Mystring类(C++,mystring,开发技术)

时间:2024-04-27 17:48:26 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

接下来,请跟着小编一起来学习吧!

功能实现

<基本功能>

1> 实现头文件的封装:MyString.h

2> 缺省构造函数对字符串的初始化( MyString() )

3> 使用构造函数初始化字符串的另外两种方式 2( 动态指针+拷贝构造函数 )

4> 析构函数( 释放动态申请的字符串空间 )

5> 重载输出运算符( << )

6> 重载赋值运算符 2( = )

7> 重载下标运算符( [],索引输出 )

<拓展功能>

1> 字符串长度的比较

2> 字符串的排序功能

3> 字符串的倒置

4> 字符串中指定两个字符的交换

5> 查找某字符串是否位于指定的字符串中(采用暴力查找)

<细节修改>

1> 使用自定义函数来替换strlen()和strcpy()

一: 基本功能 (实现源码)

1) MyString.h

#pragmaonce

define_CRT_SECURE_NO_WARNINGS

include<iostream>

include<string.h>//会借用strlen与strcpy函数实现相应的功能

usingnamespacestd;

classMyString{
public:
MyString();
MyString(constcharconst);
MyString(constMyString&);
~MyString();
intlength()const;//const函数不能修改其数据成员,仅仅起到输出数据的作用
intsize()const;//和length功能一致
constchar
getString()const;//直接调用字符串首指针返回
friendostream&operator<<(ostream&,constMyString&);//重载输出运算符
MyString&operator=(constMyString&);
MyString&operator=(constchar*);
char&operator;

private:
char*str;//指向数组首地址(此时为野指针)
intlen;

};

2)MyString.cpp

#include"MyString.h"
usingnamespacestd;

MyString::MyString()//构造空字符串
{
str=newchar[1];
str[0]='\0';
len=0;
}

MyString::MyString(constchar*constP)//按照动态指针来构造相应的字符串
{
if(P)
{
len=strlen(P);//取长度
str=newchar[len+1];//开空间
strcpy(str,P);//复制值
}
else
{
MyString();//如果传入的字符串为空,直接调用缺省值构造函数
}
}

MyString::MyString(constMyString&AnotherMyString)//拷贝构造函数,这里的形参使用了const,该形参类中的所有函数都要使用const来修饰
{
len=AnotherMyString.length();
str=newchar[len+1];
strcpy(str,AnotherMyString.str);
}

intMyString::length()const//求长度成员函数
{
returnlen;
}

intMyString::size()const
{
returnlen;
}

constchar*MyString::getString()const
{
returnstr;
}

MyString&MyString::operator=(constMyString&AnotherMyString)
{
if(&AnotherMyString==this)
{
returnthis;
}
delete[]str;
len=AnotherMyString.length();
str=newchar[len+1];
strcpy(str,AnotherMyString.str);
return
this;
//TODO:在此处插入return语句
}

MyString&MyString::operator=(constcharP)
{
delete[]str;
len=strlen(P);
str=newchar[len+1];
strcpy(str,P);
return
this;
//TODO:在此处插入return语句
}

char&MyString::operator
{
if(index>len)//如果索引越界,输出最后一个字符
{
cout<<"Warning!!!"<<endl;
cout<<"Outofboundary!Thelastcharis:";
returnstr[len-1];
}
else
{
returnstr[index-1];
}
//TODO:在此处插入return语句
}

MyString::~MyString()//释放数组空间
{
delete[]str;
len=0;
}

ostream&operator<<(ostream&output,constMyString&str)//重载输出运算符
{
output<<str.getString();
returnoutput;
//TODO:在此处插入return语句
}

这里需要提到的一点是析构函数中的delete[] str;

怎么利用C++实现Mystring类

<delete[]与delete的区别>

使用new得来的空间使用delete释放;使用new[]得来的空间使用delete[]释放;这是永远不会错的。

但是更加深入一点去理解:

使用new[]得到的空间如果 动态申请的数据类型时基本数据类型也可以使用delete直接释放,但是如果使用new[]申请的数据的类型时自定义类型(例如类名),这就必须使用delete[]来进行释放,只有这样才能够调用自定义类型的析构函数进行对自定义类型进行释放。

除此之外,再提一点关于delete[]的注意事项:

当使用new[]动态生成内存的时候,删除的时候必须将删除的指针指向new[]出来的内存的首地址:

#include<iostream>
usingnamespacestd;

intmain()
{
intp=newint[3];
p=1;
p++;
p=2;
delete[]p;
cout<<"
"<<endl;
return0;
}

这一段小程序中:

因为p指针不是指向了首地址,所以程序虽然没报错,但是无法正常运行!我们可以将申请的首地址保存起来,供删除的时候使用。

3)test_main.cpp

#include"MyString.h"
usingnamespacestd;

intmain()
{
MyStringa;
cout<<"【调用缺省构造函数实现初始化】"<<endl;
cout<<"stringa="<<a<<endl;
cout<<"Length="<<a.length()<<endl<<endl;

MyStringb("123456");
cout<<"【调用普通构造函数实现初始化】"<<endl;
cout<<"stringb="<<b<<endl;
cout<<"Length="<<b.length()<<endl<<endl;

MyStringc(b);
cout<<"【调用拷贝构造函数实现初始化】"<<endl;
cout<<"stringc="<<c<<endl;
cout<<"Length="<<c.length()<<endl<<endl;

MyStringd=b;//这里不会再次调用缺省构造函数进行初始化
cout<<"【调用=(对象)实现赋值】"<<endl;
cout<<"stringd="<<d<<endl;
cout<<"Length="<<d.length()<<endl<<endl;

MyStringe="00000000";
cout<<"【调用=(动态指针)实现赋值】"<<endl;
cout<<"stringd="<<e<<endl;
cout<<"Length="<<e.length()<<endl<<endl;

MyStringf="abcdefghijklmn";
charstr=f[5];
cout<<"【调用[]实现索引定位输出】"<<endl;
cout<<"f[5]="<<str<<endl<<endl;

return0;
}

二:拓展功能

字符串长度的比较

使用</>/>=/<=等符号进行比较,返回bool值

  • bool operator >(const MyString &str);

  • bool operator >(const char c_str);

  • bool operator <(const MyString &str);

  • bool operator <(const char c_str);

  • bool operator >=(const MyString &str);

  • bool operator >=(const char c_str);

  • bool operator <=(const MyString &str);

  • bool operator <=(const char c_str);

字符串的排序功能

使用类中的成员函数对类中的私有字符串进行从小到大的排序:

  • A.Sort_String_LB();

  • A.Sort_String_BL();

字符串的倒置

使用类中的成员函数对类中的私有字符串进行倒置:

A.Reverse();

字符串中指定两个字符的交换

A.ChangeTwoCharPosition(int firstposition,int second position);

查找某字符串是否位于指定的字符串中(采用暴力查找)

A.Find(char *search_string);

完整版源码

MyString.h

#pragmaonce

define_CRT_SECURE_NO_WARNINGS

include<iostream>

include<string.h>//会借用strlen与strcpy函数实现相应的功能

usingnamespacestd;

classMyString{
public:
//构造函数+析构函数
MyString();
MyString(constchar*const);
MyString(constMyString&);
~MyString();

//直接调用字符串首指针返回,返回的指针可以直接使用cout<<输出
constchar*getString()const;

//求字符串的长度(直接返回类中的私有成员len的值)
//const函数不能修改其数据成员,仅仅起到输出数据的作用
intlength()const;
intsize()const;

//重载赋值运算符,使得可以使用对象与"xxxxxx"来赋值
MyString&operator=(constMyString&);
MyString&operator=(constchar*);

//重载下标运算符
char&operator;

//重载输出运算符
friendostream&operator<<(ostream&,constMyString&);

//字符串长度比较
booloperator>(constMyString&str);
booloperator>(constcharc_str);
booloperator<(constMyString&str);
booloperator<(constchar
c_str);
booloperator>=(constMyString&str);
booloperator>=(constcharc_str);
booloperator<=(constMyString&str);
booloperator<=(constchar
c_str);

//字符串内部内容的冒泡排序(ASCII码),Little->Big
voidSort_String_LB();
voidSort_String_BL();

//对字符串进行倒置
voidReverse();

//交换字符串中两个字符的位置
voidChangeTwoCharPosition(intfirstposition,intsecondposition);

//查询某字符串是否是指定字符串的子串(暴力模式)
boolFind(char*search_string);

private:
char*str;//指向数组首地址(此时为野指针)
intlen;//字符串的长度

};

MyString.cpp

#include"MyString.h"
usingnamespacestd;

MyString::MyString()//构造空字符串
{
str=newchar[1];
str[0]='\0';
len=0;
}

MyString::MyString(constchar*constP)//按照动态指针来构造相应的字符串
{
if(P)
{
len=strlen(P);//取长度
str=newchar[len+1];//开空间
strcpy(str,P);//复制值
}
else
{
MyString();//如果传入的字符串为空,直接调用缺省值构造函数
}
}

MyString::MyString(constMyString&AnotherMyString)//拷贝构造函数,这里的形参使用了const,该形参类中的所有函数都要使用const来修饰
{
len=AnotherMyString.length();
str=newchar[len+1];
strcpy(str,AnotherMyString.str);
}

intMyString::length()const//求长度成员函数
{
returnlen;
}

intMyString::size()const
{
returnlen;
}

constchar*MyString::getString()const
{
returnstr;
}

MyString&MyString::operator=(constMyString&AnotherMyString)
{
if(&AnotherMyString==this)
{
returnthis;
}
//delete[]str;
len=AnotherMyString.length();
str=newchar[len+1];
strcpy(str,AnotherMyString.str);
return
this;
//TODO:在此处插入return语句
}

MyString&MyString::operator=(constcharP)
{
//delete[]str;
len=strlen(P);
str=newchar[len+1];
strcpy(str,P);
return
this;
//TODO:在此处插入return语句
}

char&MyString::operator
{
if(index>len)//如果索引越界,输出最后一个字符
{
cout<<"Warning!!!"<<endl;
cout<<"Outofboundary!Thelastcharis:";
returnstr[len-1];
}
else
{
returnstr[index-1];
}
//TODO:在此处插入return语句
}

boolMyString::operator>(constMyString&str)
{
if(this->len>str.len)
{
returntrue;
}
else
{
returnfalse;
}
returnfalse;
}

boolMyString::operator>(constchar*c_str)
{
if(this->len>int(strlen(c_str)))
{
returntrue;
}
else
{
returnfalse;
}
returnfalse;
}

boolMyString::operator<(constMyString&str)
{
if(this->len<str.len)
{
returntrue;
}
else
{
returnfalse;
}
returnfalse;
}

boolMyString::operator<(constchar*c_str)
{
if(this->len<int(strlen(c_str)))
{
returntrue;
}
else
{
returnfalse;
}
returnfalse;
}

boolMyString::operator>=(constMyString&str)
{
if(this->len>str.len)
{
returntrue;
}
elseif(this->len=str.len)
{
returntrue;
}
else
{
returnfalse;
}
returnfalse;
}

boolMyString::operator>=(constchar*c_str)
{
if(this->len>int(strlen(c_str)))
{
returntrue;
}
elseif(this->len=strlen(c_str))
{
returntrue;
}
else
{
returnfalse;
}
returnfalse;
}

boolMyString::operator<=(constMyString&str)
{
if(this->len<str.len)
{
returntrue;
}
elseif(this->len=str.len)
{
returntrue;
}
else
{
returnfalse;
}
returnfalse;
}

boolMyString::operator<=(constchar*c_str)
{
if(this->len>int(strlen(c_str)))
{
returntrue;
}
elseif(this->len=strlen(c_str))
{
returntrue;
}
else
{
returnfalse;
}
returnfalse;
}

voidMyString::Sort_String_LB()
{
intlength=this->len;
chartemp_data;
char*c_str=this->str;
boolischanged=false;
for(inti=length-1;i>0;i--)
{
for(intj=0;j<i;j++)
{
if(c_str[j]>c_str[j+1])
{
temp_data=c_str[j];
c_str[j]=c_str[j+1];
c_str[j+1]=temp_data;
ischanged=true;
}
}
if(!ischanged)
{
return;
}
}
}

voidMyString::Sort_String_BL()
{
intlength=this->len;
chartemp_data;
char*c_str=this->str;
boolischanged=false;
for(inti=length-1;i>0;i--)
{
for(intj=0;j<i;j++)
{
if(c_str[j]<c_str[j+1])
{
temp_data=c_str[j];
c_str[j]=c_str[j+1];
c_str[j+1]=temp_data;
ischanged=true;
}
}
if(!ischanged)
{
return;
}
}
}

voidMyString::Reverse()
{
intlength=this->len;
char*c_str=this->str;
chartemp_data;
for(inti=0;i<length/2;i++)
{
temp_data=c_str[i];
c_str[i]=c_str[length-1-i];
c_str[length-1-i]=temp_data;
}
}

voidMyString::ChangeTwoCharPosition(intfirstposition,intsecondposition)
{
intlength=this->len;
char*c_str=this->str;
chartemp_data;
if(firstposition>len||secondposition>len)
{
cout<<"输入下标越界,数组实际长度为:"<<length<<endl;
return;
}
else
{
temp_data=c_str[firstposition-1];
c_str[firstposition-1]=c_str[secondposition-1];
c_str[secondposition-1]=temp_data;
}
}

boolMyString::Find(charsearch_string)
{
intlength=this->len;
char
c_str=this->str;
booljudge=false;
//确保i每次可以往后移动一位
inttemp_data=0;

for(inti=0,j=0;j<strlen(search_string)&&i<length;)
{
if(c_str[i]==search_string[j])
{
//cout<<c_str[i]<<"=="<<search_string[j]<<endl;
//cout<<i<<"::"<<j<<endl;
judge=true;
i++;
j++;
}
else
{
judge=false;
temp_data++;
i=temp_data;
j=0;
}
}
returnjudge;
}

MyString::~MyString()//释放数组空间
{
delete[]str;
len=0;
}

ostream&operator<<(ostream&output,constMyString&str)//重载输出运算符
{
output<<str.getString();
returnoutput;
//TODO:在此处插入return语句
}

Test_Possess.cpp

#include"MyString.h"
usingnamespacestd;

intmain()
{
MyStringa;
cout<<"【调用缺省构造函数实现初始化】"<<endl;
cout<<"stringa="<<a<<endl;
cout<<"Length="<<a.length()<<endl<<endl;

MyStringb("123456");
cout<<"【调用普通构造函数实现初始化】"<<endl;
cout<<"stringb="<<b<<endl;
cout<<"Length="<<b.length()<<endl<<endl;

MyStringc(b);
cout<<"【调用拷贝构造函数实现初始化】"<<endl;
cout<<"stringc="<<c<<endl;
cout<<"Length="<<c.length()<<endl<<endl;

MyStringd=b;//这里不会再次调用缺省构造函数进行初始化
cout<<"【调用=(对象)实现赋值】"<<endl;
cout<<"stringd="<<d<<endl;
cout<<"Length="<<d.length()<<endl<<endl;

MyStringe="00000000";
cout<<"【调用=(动态指针)实现赋值】"<<endl;
cout<<"stringd="<<e<<endl;
cout<<"Length="<<e.length()<<endl<<endl;

MyStringf="abcdefghijklmn";
charstr=f[5];
cout<<"【调用[]实现索引定位输出】"<<endl;
cout<<"f[5]="<<str<<endl<<endl;

//测试字符串的大小比较功能
MyStringA1="123456789";
MyStringB1="4321";
MyStringC1="456";
MyStringD1="456789";
if(A1>=B1)
{
cout<<"A1>=B1"<<endl;
}
else
{
cout<<"A1<B1"<<endl;
}

//测试字符串的排序功能
B1.Sort_String_LB();
cout<<B1<<endl;

//测试字符串的倒置功能
A1.Reverse();
cout<<A1<<endl;

//测试指定两个字符的交换
A1.ChangeTwoCharPosition(1,9);
cout<<A1<<endl;

//判断某字符串是否为指定字符串的子串
if(D1.Find("678"))
{
cout<<"Successful!"<<endl;
}
else
{
cout<<"Fail!"<<endl;
}
return0;
}

三:细节部分修改

本次更新了 "取消了strlen()与strcpy()的使用,在间接调用该接口的自定义函数中,使用自定义方法实现这两个接口的功能"

这里仅仅给出了替换部分部分示例,其他部分也可按照相同原理替换:

1.使用指针实例化对象部分

MyString::MyString(charP)//按照动态指针来构造相应的字符串
{
char
temp_P=P;//使得指针指向的内存重置
if(P)
{
intxx_length=0;
while(P!='\0')
{
xx_length++;
P=P+sizeof(char);
}
len=xx_length;
P=temp_P;
//len=strlen(P);//取长度
str=newchar[len+1];//开空间
strcpy(str,P);//复制值
}
else
{
MyString();//如果传入的字符串为空,直接调用缺省值构造函数
}
}

2.重载 "=" 运算符函数的过程

MyString&MyString::operator=(charP)
{
//delete[]str;
chartemp_P=P;
intxx_length=0;
chartemp='0';
while(
P!='\0')
{
xx_length++;
P=P+sizeof(char);
}
//len=strlen(P);
len=xx_length;
P=temp_P;
str=newchar[len+1];
for(inti=0;i<len;i++)
{
str=P;
str+=sizeof(char);
P+=sizeof(char);
}
//strcpy(str,P);
return*this;
//TODO:在此处插入return语句
}

( 附加:对于自定义的类,需要尽量减少对其他头文件的需求。)

若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

本文:怎么利用C++实现Mystring类的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:Go gorilla/sessions库安装使用的方法下一篇:

26 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18