实现思路:
MyString类:
无参构造函数,初步初始化
带参构造函数,用字符串初始化
复制构造函数
析构函数
重置或重新赋值函数
打印
返回字符串长度
两个字符串(对象)比较
两个字符串(对象)拼接
这是看完老师源码后自己再写的,和老师的源码接近度很高了。之所以放自己的码,是因为写的过程中出现的错误写在注释里了,方便以后查看时注意。
#include<bits/stdc++.h>
using namespace std;
class MyString
{
public:
MyString();
MyString(char *s);
MyString(MyString&);
~MyString();
void show();
void reset(char *s);
int length();
void compar(MyString);
void addstr(MyString);
private:
char *p;
int len;
};
MyString::MyString()
{
len = 0;
p = NULL;
}
MyString::MyString(char* s)
{
if(strlen(s) == 0)
{
len = 0;
p = NULL;
}
else
{
len = strlen(s);
p = new char[len + 1];
///p = s;///这里正在做string类,不能直接赋值。不过话说回来指针直接赋值也可以啊。如果指针赋值是浅拷一样的。贝。两个指针指向的是同一内存。
///所谓复制构造函数,两个指针要指向两个内存(地址),然后两个内存存的东西是
///当下面那句作为注释时做了调试,程序可运行,但会返回错误的东西。
strcpy(p, s);///正确语句
}
}
MyString::MyString(MyString &s)
{
if(s.len == 0)///
{
len = 0;
p = NULL;
}
else
{
///len = strlen(s.p);///复制构造嘛直接用s.len就可以了
len = s.len;
p = new char[len + 1];
strcpy(p, s.p);
}
}
MyString::~MyString()
{
delete [] p;
p = NULL;
len = 0;
}
void MyString::show()
{
if(len == 0)
cout<<""<<endl;
else
cout<<p<<endl;
}
void MyString::reset(char *s)
{
if(strlen(s) == 0)
{
len = 0;
delete [] p;///先释放
p = NULL;///再置NULL;
}
else
{
len = strlen(s);
delete [] p;
p = new char[len + 1];///在重新给p分配内存空间时要先释放它的空间
///p = s;不要搞浅拷贝
strcpy(p, s);
}
}
int MyString::length()
{
return len;
}
void MyString::compar(MyString s)
{
if(p == NULL && s.p == NULL)
cout<<"Illegal operation"<<endl;
else
{
if(strcmp(p, s.p) == 0)
cout<<"Equal."<<endl;
else if(strcmp(p, s.p) > 0)
cout<<"The former biger."<<endl;
else if(strcmp(p, s.p) < 0)
cout<<"The later biger."<<endl;
}
}
void MyString::addstr(MyString s)
{
if(p == NULL && s.p == NULL)
{
cout<<"vain operation."<<endl;
}
else
{
char* newp = new char[len + s.len + 1];
strcpy(newp, p);
strcat(newp, s.p);
delete [] p;
p = newp;///所谓字符串拼接是把后缀字符串加到当前字符串后面,所以p还是要指向newp的
}
}
int main()
{
MyString s1("abc");///简单测试样例
s1.show();
s1.reset("def");
s1.show();
MyString s2;
s2.reset("abab");
s2.show();
s2.addstr(s1);
s2.show();
s2.compar(s1);
MyString s3(s1);
s3.show();
return 0;
}
老师源码:
#include <iostream>
#include <cstring>
using namespace std;
class MyString
{
public:
MyString();///无参构造函数
MyString(char*);///构造函数
MyString(MyString&);///复制构造函数
~MyString();///析构函数
void reset(char*);///重置或重新赋值
void show();///打印
int length();///求字符串长度
void compare(MyString);///两个字符串的比较
void addStr(MyString);///字符串拼接
private:
char* p;///char型指针,指向一个字符数组的首地址
int len;
};
MyString::MyString()
{///无参构造函数初步初始化MyString对象的初始成员
len = 0;
p = NULL;
}
MyString::MyString(char* s)///带参初始化
{
if (strlen(s) == 0)///用空字符串初始化对象数据成员
{
len = 0;
p = NULL;
}
else
{
len = strlen(s);
p = new char[len + 1];
strcpy(p,s);
}
}
MyString::MyString(MyString& s)
{
if (s.len != 0)
{
len = s.len;
p = new char[len+1];
strcpy(p,s.p);
}
else
{
len = 0;///对象数据成员为空时的复制构造
p = NULL;
}
}
MyString::~MyString()///析构
{
len = 0;
delete[] p;
p = NULL;
}
void MyString::show()
{
if (len == 0)///以长度为0来判断为空字符
cout<<""<<endl;///并输出一个空字符
else
cout<<p<<endl;
}
int MyString::length()///接口,输出字符串长度
{
return len;
}
void MyString::reset(char* s)///重新赋值
{
if (strlen(s) == 0)///strlen函数的参数是数组的首地址,s也是数组的首地址。所以strlen可用s作参数
{///以空字符串来重新赋值
len = 0;
delete[] p;
p = NULL;
}
else
{
if(len != 0)
{
delete[] p;///释放p的内存空间,p变为野指针
len = strlen(s);
p = new char[len+1];
strcpy(p,s);
}
else
{
len = strlen(s);
p = new char[len+1];///用字符串s的len重新给p分配空间
strcpy(p,s);
}
}
}
void MyString::compare(MyString s)
{
if (p != NULL && s.p != NULL)///两个指针非空比较才有意义
{
if (strcmp(p, s.p)>0)
cout<<"当前字符串大";
else if (strcmp(p, s.p)==0)
cout<<"一样大";
else
cout<<"另一个字符串大";
}
else
cout<<"没意义";
}
void MyString::addStr(MyString s)///字符串拼接
{
if (p != NULL && s.p != NULL)///仿c++的sting类的。所以要有字符串是对象的意识。而字符串是以char型指针用类来封装的,
{///两个空指针拼接没意义
len = len + s.len;
char* newp = new char[len+1];
strcpy(newp, p);
strcat(newp, s.p);///不能直接拿着被拼接的指针用strcat,每个p初始化时都是用new申请过内存的。
delete[] p;
p = newp;
}
else
cout<<"没意义";
}
int main()
{
MyString s1("aaa");
s1.show();
s1.reset("bbb");
s1.show();
MyString s2;
s2.reset("ccc");
s2.addStr(s1);
s2.show();
MyString s3(s1);
s3.show();
return 0;
}