前言
模拟实现string类: clear函数、流提取(<<)和流插入(>>)运算符重载、>、<、==、<=、>=、!=的运算符重载、赋值运算符(=)重载等的介绍
string类的上半部分:模拟实现string类对象上半部分
一、 clear函数
- 清除字符串的内容,本质上就是让字符串大小置为0, 将0处的字符置为’\0’
void clear()
{
_size = 0;
_str[_size] = '\0';
}
二、流提取(<<)和流插入(>>)运算符重载
- 流提取,就是循环打印每个字符,可以使用【】运算符重载和范围for语法糖
- 流插入,这里采用临时字符数组的形式:
-
- 首先,先检查并跳过输入字符串之前的空格或换行,然后创建一个128个字节空间的临时字符数组
-
- 然后,不断读取字符,并插入到字符数组中去,当字符数组中存储127个字符后,将最后一个空间置为’\0’
-
- 然后,将使用+=运算符重载将字符数组插入到string类中,循环执行,直到字符串结束
-
- 最后,若下标值不为0,将字符数组末置为’\0’,并+=到string类中。
这样做的好处是,可以减少string类开辟空间的次数, 提高性能。
// 流提取
ostream& operator<<(ostream& out, string& s)
{
for (auto ch : s)
{
out << ch;
}
//for (size_t i = 0; i < s.size(); i++)
//{
// out << s[i];
//}
return out;
}
// 流插入
istream& operator>>(istream& in, string& s)
{
// 检查并跳过输入字符串之前的空格或者换行
char ch = in.get();
while (ch == ' ' || ch == '\n')
{
ch = in.get();
}
char buff[128];
int i = 0;
while (ch != ' ' && ch != '\n')
{
buff[i++] = ch;
if (i == 127)
{
buff[i] = '\0';
s += buff;
i = 0;
}
ch = in.get();
}
if (i != 0)
{
buff[i] = '\0';
s += buff;
}
return in;
}
测试:
void Test_string7()
{
hhb::string s1("hello world");
cout << s1 << endl;
hhb::string s2;
cin >> s2;
cout << s2 << endl;
}
- 只开辟了两次空间。
三、 >、<、==、<=、>=、!=的运算符重载
- 可以循环遍历字符串内容,比较每个字符,根据对应规则返回布尔值,若跳出循环,则比较长度,长的字符大
- 也可以是memcmp函数进行比较,memcmp函数大于返回大于0的值,小于返回小于0的值,等于,返回0。
- 只用书写< 和 == 的逻辑,其他的可以复用。
// < 运算符重载
// hello hello // false
// hello helloxxx // true
// helloxxx hello // false
/*bool operator< (string& s)
{
size_t i1 = 0;
size_t i2 = 0;
while (i1 < _size && i2 < s._size)
{
if (_str[i1] < s._str[i2])
{
return true;
}
else if (_str[i1] > s._str[i2])
{
return false;
}
else
{
++i1;
++i2;
}
}
if (_size < s._size)
{
return true;
}
else
{
return false;
}
}*/
bool operator< (string& s) const
{
int ret = memcmp(_str, s._str, _size > s._size ? _size : s._size);
return (ret < 0);
}
bool operator== (string& s) const
{
return _size == s._size
&& memcmp(_str, s._str, _size) == 0;
}
bool operator> (string& s) const
{
return !(*this < s || *this == s);
}
bool operator<= (string& s) const
{
return !(*this > s);
}
bool operator>= (string& s) const
{
return !(*this < s);
}
bool operator!= (string& s) const
{
return !(*this == s);
}
测试:
void Test_string8()
{
hhb::string s1("hello");
hhb::string s2("helloxxxx");
cout << (s1 < s2) << endl;
cout << (s1 > s2) << endl;
cout << (s1 != s2) << endl;
cout << (s1 == s2) << endl << endl;
hhb::string s3("helloxxxx");
hhb::string s4("hello");
cout << (s3 < s4) << endl;
cout << (s3 > s4) << endl;
cout << (s3 != s4) << endl;
cout << (s3 == s4) << endl << endl;
hhb::string s5("hello");
hhb::string s6("hello");
cout << (s5 < s6) << endl;
cout << (s5 > s6) << endl;
cout << (s5 != s6) << endl;
cout << (s5 == s6) << endl << endl;
}
四、赋值运算符(=)重载
-
- 开辟和s一样空间的大小,进行深拷贝,把字符串内容拷贝到空间中去, 然后释放原来的空间内容,将字符串指向新开辟的空间 ,最后拷贝字符大小和字符串的空间。
-
- 在=运算符重载函数中使用传入的类对象创建临时的类对象,调用std的交换函数,交换临时对象和原来的对象内容。完成赋值,并且当函数结束,临时对象会自动调用析构函数。
-
- 直接传值调用,直接创建临时对象,并与临时对象交换内容。完成赋值。
// =运算符重载
/*string& operator= (const string& s)
{
char* tmp = new char[s._capacity + 1];
delete[] _str;
memcpy(tmp, s._str, s._size);
_str = tmp;
_size = s._size;
_capacity = s._capacity;
return *this;
}*/
/*string& operator= (const string& s)
{
if (this != &s)
{
string tmp(s);
std::swap(_str, tmp._str);
std::swap(_size, tmp._size);
std::swap(_capacity, tmp._capacity);
}
return *this;
}*/
void swap(string& s)
{
std::swap(_str, s._str);
std::swap(_size, s._size);
std::swap(_capacity, s._capacity);
}
string& operator= (string tmp)
{
swap(tmp);
return *this;
}
测试:
void Test_string9()
{
hhb::string s1("hello world");
hhb::string s2("ladys and gentleman");
s1 = s2;
cout << s1 << endl;
}
总结
模拟实现string类: clear函数、流提取(<<)和流插入(>>)运算符重载、>、<、==、<=、>=、!=的运算符重载、赋值运算符(=)重载等的介绍