写一个string类,能够完成string类的操作:
默认构造函数中,为ptr申请一个字节的堆内存,这样任何情况下,ptr都不为nullptr,避免了ptr是否为nullptr的情况,在随时访问的时候,就可以少写很多if判断。
myString::myString(){
ptr = (char*)malloc(1); //为ptr申请一个字节的堆内存
memset(ptr,0,1);
len = 0; //字符串实际长度为0
}
myString::myString(const char* r){
// 先为ptr申请字符串r长度+1的内存空间,多一个字节是为了保存结束符'\0'
len = strlen(r);
ptr = (char*)malloc(len+1);
memset(ptr,0,len+1);
// 将r所指的内存空间中的内容,拷贝给ptr所指的内存空间,为了避免内存泄漏,使用memmove
memmove(ptr,r,len+1);
}
myString::~myString(){
free(ptr);
}
// 拷贝构造,深拷贝
myString::myString(const myString& r){
//free(ptr);
len = r.len;
ptr = (char*)malloc(len+1);
memset(ptr,0,len+1);// 为p的ptr申请独立的空间
// 将r中的ptr拷贝给p的ptr
memmove(ptr,r.ptr,len+1); // 拷贝数据
}
myString myString::operator= (const myString& r){
if(this != &r) { // 防止自赋值
if(ptr != nullptr)
free(ptr);
len = r.len;
ptr = (char*)malloc(len+1);
memset(ptr, 0, len+1);
memmove(ptr, r.ptr, len+1);
}
return *this; // 应该返回对象的引用
}
// p1 = p1+"hello";
myString myString::operator+(const char* r){
// 创建新的对象,新对象的长度以及ptr指向内存空间是this+r的总和
myString newStr;
free(newStr.ptr); //这里要把newStr.ptr指向的内存进行释放,否则会出现内存泄漏
newStr.len = this->len+strlen(r);
newStr.ptr = (char*)malloc(newStr.len+1);
memset(newStr.ptr,0,newStr.len+1);
memmove(newStr.ptr,ptr,len);
strcat(newStr.ptr,r);
return newStr;
}
// p1 = p1+p2
myString myString::operator+(const myString& r){
myString newStr;
free(newStr.ptr); //这里要把newStr.ptr指向的内存进行释放,否则会出现内存泄漏
newStr.len = this->len+r.len;
newStr.ptr = (char*)malloc(newStr.len+1);
memset(newStr.ptr,0,newStr.len+1);
memmove(newStr.ptr,ptr,len);
strcat(newStr.ptr,r.ptr);
return newStr;
}
myString myString::operator+=(const char* r){
char* temp = ptr;
int l = len; // 保存原来的ptr和len
this->len = this->len+strlen(r);
this->ptr = (char*)malloc(this->len+1); //ptr指向新的内存空间
memset(ptr,0,len+1);
memmove(ptr,temp,l); // 把原来的ptr内容拷贝给新的ptr
strcat(ptr,r);
free(temp);
return *this;
}
myString myString::operator+=(const myString& r){
char* temp = ptr;
int l = len;
len = len+r.len;
ptr = (char*)malloc(len+1);
memset(ptr,0,len+1);
memmove(ptr,temp,l);
strcat(ptr,r.ptr);
free(temp); //temp记得free
return *this;
}
#include
#include
using std::cout;
using std::endl;
/**
* 当myString对象没有保存任何字符串的时候,应该至少为该对象中的ptr申请至少一个字节的空间
* 这样任何情况下,ptr都不为nullptr,避免了ptr是否为nullptr的情况,在随时访问的时候,
* 就可以少写很多if判断。
* · 无参构造函数要重写。
* · 因为有指针进行new堆内存操作,默认的拷贝构造是浅拷贝,需要重写拷贝构造,否则会出现重复释放,造成段错误。
*/
class myString{
public:
myString(); //无参构造函数
myString(const char* r); //单参构造函数
myString(const myString& r); //单参构造函数
~myString();
void show(){cout<<ptr<<endl;}
int size(){return len;}
void clear();
bool empty();
myString operator= (const myString& r);
myString operator+ (const char* r);
myString operator+(const myString& r);
myString operator+= (const char* r);
myString operator+= (const myString& r);
char operator[](int n);
void append(const char* r);
void append(const myString& r);
friend std::ostream& operator<< (std::ostream& out, const myString& r);
friend std::istream& operator>> (std::ostream& in, myString& r);
const char* data(){return this->ptr;};
int toInt();
private:
char* ptr; //指向堆内存空间
int len; // 字符串实际长度,不包含结束符
};
myString::myString(){
ptr = (char*)malloc(1); //为ptr申请一个字节的堆内存
memset(ptr,0,1);
len = 0;
}
myString::myString(const char* r){
// 先为ptr申请字符串r长度+1的内存空间,多一个字节是为了保存结束符'\0'
len = strlen(r);
ptr = (char*)malloc(len+1);
memset(ptr,0,len+1);
// 将r所指的内存空间中的内容,拷贝给ptr所指的内存空间,为了避免内存泄漏,使用memmove
memmove(ptr,r,len+1);
}
// 拷贝构造,深拷贝
myString::myString(const myString& r){
len = r.len;
ptr = (char*)malloc(len+1);
memset(ptr,0,len+1);// 为p的ptr申请独立的空间
// 将r中的ptr拷贝给p的ptr
memmove(ptr,r.ptr,len+1); // 拷贝数据
}
myString::~myString(){
free(ptr);
}
void myString::clear(){
free(ptr);
ptr=(char*) malloc(1);
memset(ptr,0,1);
len = 0;
}
bool myString::empty(){
return !len;
}
myString myString::operator= (const myString& r){
if(this != &r) { // 防止自赋值
if(ptr != nullptr)
free(ptr);
len = r.len;
ptr = (char*)malloc(len+1);
memset(ptr, 0, len+1);
memmove(ptr, r.ptr, len+1);
}
return *this; // 应该返回对象的引用。
}
// p1 = p1+"hello";
myString myString::operator+(const char* r){
// 创建新的对象,新对象的长度以及ptr指向内存空间是this+r的总和
myString newStr;
free(newStr.ptr); //这里要把newStr.ptr指向的内存进行释放,否则会出现内存泄漏
newStr.len = this->len+strlen(r);
newStr.ptr = (char*)malloc(newStr.len+1);
memset(newStr.ptr,0,newStr.len+1);
memmove(newStr.ptr,ptr,len);
strcat(newStr.ptr,r);
return newStr;
}
// p1 = p1+p2
myString myString::operator+(const myString& r){
myString newStr;
free(newStr.ptr); //这里要把newStr.ptr指向的内存进行释放,否则会出现内存泄漏
newStr.len = this->len+r.len;
newStr.ptr = (char*)malloc(newStr.len+1);
memset(newStr.ptr,0,newStr.len+1);
memmove(newStr.ptr,ptr,len);
strcat(newStr.ptr,r.ptr);
return newStr;
}
myString myString::operator+=(const char* r){
char* temp = ptr;
int l = len; // 保存原来的ptr和len
this->len = this->len+strlen(r);
this->ptr = (char*)malloc(this->len+1); //ptr指向新的内存空间
memset(ptr,0,len+1);
memmove(ptr,temp,l); // 把原来的ptr内容拷贝给新的ptr
strcat(ptr,r);
free(temp);
return *this;
}
myString myString::operator+=(const myString& r){
char* temp = ptr;
int l = len;
len = len+r.len;
ptr = (char*)malloc(len+1);
memset(ptr,0,len+1);
memmove(ptr,temp,l);
strcat(ptr,r.ptr);
free(temp); //temp记得free
return *this;
}
char myString::operator[](int n){
return ptr[n];
}
void myString::append(const char* r){
char* temp = ptr;
int l = len; // 保存原来的ptr和len
this->len = this->len+strlen(r);
this->ptr = (char*)malloc(this->len+1); //ptr指向新的内存空间
memset(ptr,0,len+1);
memmove(ptr,temp,l); // 把原来的ptr内容拷贝给新的ptr
strcat(ptr,r);
free(temp);
}
void myString::append(const myString& r){
char* temp = this->ptr;
int l = len;
len = len+r.len;
ptr = (char*)malloc(len+1);
memset(ptr,0,len+1);
memmove(ptr,temp,l);
strcat(ptr,r.ptr);
free(temp); //temp记得free
}
std::ostream& operator<< (std::ostream& out, const myString& r){
out<<r.ptr;
return out;
}
std::istream& operator>> (std::ostream& in, myString& r){
char buf[1024];
std::cin>>buf;
free(r.ptr);
r.len = strlen(buf);
r.ptr = (char*)malloc(r.len+1);
memset(r.ptr,0,r.len+1);
memmove(r.ptr,buf,r.len+1);
}
int myString::toInt(){
return atoi(this->ptr);
}
int main(){
myString str = "hello"; // 转换构造函数,也就是单参构造函数
myString ptr(str); // 拷贝构造
myString atp = str; //拷贝构造
ptr = str; //运算符 operator=
ptr = ptr + " world";
ptr.show();
myString str2 = " world";
str2 = str+str2;
str += " world";
str.show();
ptr+=str2;
ptr.show();
atp.append(" world");
atp.show();
return 0;
}