上一章讲了库中的string函数,这次我们来讲一讲模拟实现
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<assert.h>
using namespace std;
//域名
namespace zzj {class String {public:typedef char* iterator;typedef const char* const_iterator;iterator begin() {return _str;}iterator end() {return _str + _size;}const_iterator begin() const{return _str;}const_iterator end() const {return _str + _size;}//初始化列表String(const char* str = "")//这里不能赋值为nullptr,因为如果用的缺省值,下面的strlen解引用空指针就崩了,我们用一个空串,空串不是什么也没有,空串会自动生成一个"\0".:_size(strlen(str)){_capacity = _size;_str = new char[_capacity + 1];std::strcpy(_str, str);}s2(s1)//String(const String& s) {// _str = new char[s._capacity + 1];// strcpy(_str, s._str);// _size = s._size;// _capacity = s._capacity;//}//拷贝构造,此方法是先构造再交换String(const String& s) {String tmp(s._str);swap(tmp);}// s1 = s3/*String& operator=(const String& s){char* tmp = new char[_capacity + 1];strcpy(tmp, s._str);delete[] _str;_str = tmp;_size = s._size;_capacity = s._capacity;return *this;}*///先构造再交换String& operator=(String tmp){// 现代写法swap(tmp);return *this;}//返回字符串地址const char* c_str() const { return _str;}//析构函数~String() {delete[] _str;_str = nullptr;_size = _capacity = 0;}//扩容void reserve(size_t n) {if (n > _capacity) {char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}//尾插一个字符void push_back(char ch) {/*if (_size == _capacity) {reserve(_capacity == 0 ? 4 : 2 * _capacity);}_str[_size] = ch;_size++;_str[_size] = '\0';*/insert(_size, ch);}//追加字符串void append(const char* str) {/*size_t len = strlen(str);if (_size + len > _capacity) {reserve(len + _size);}strcpy(_str + _size, str);_size += len;*/insert(_size, str);}//重载+=运算符(+=字符串)String& operator+= (const char* str) {append(str);return *this;}//重载+=运算符(+=字符)String& operator+= (char ch) {push_back(ch);return *this;}//插入(字符)void insert(size_t pos , char ch) {assert(pos <= _size);if (_size == _capacity) {reserve(_capacity == 0 ? 4 : 2 * _capacity);}/*int end = _size;while (end >= (int)pos) {_str[end + 1] = _str[end];--end;}*/size_t end = _size + 1;while (end > pos) {_str[end] = _str[end - 1];--end;}_str[pos] = ch;++_size;}//插入(字符串)void insert(size_t pos, const char* str) {assert(pos <= _size);size_t len = strlen(str);if (_size + len > _capacity) {reserve(_size + len);}size_t end = _size + len;while (end > pos + len - 1) {_str[end] = _str[end - len];end--;}strncpy(_str + pos, str, len);_size += len;} //删除void erase(size_t pos, size_t len = npos) {assert(pos <= _size);if (len == npos || len > _size - pos) {_str[pos] = '\0';_size = pos;}else {strcpy(_str + pos, _str + pos + len);_size -= len;}}void resize(size_t n, char ch = '\0') {if (n <= _size) {_str[n] = '\0';_size = n;}else {reserve(n);for (size_t i = _size ; i < n ; i++) {_str[i] = ch;}_str[n] = '\0';_size = n;}}//交换两个字符串void swap(String& s) {std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}//字符查找size_t find(char ch,size_t pos = 0) const {assert(pos < _size);for (size_t i = pos; i < _size; i++) {if (_str[i] == ch) {return i;}}return npos;}//字符串查找size_t find(const char* sub, size_t pos = 0) const {assert(pos < _size);const char* p = strstr(_str + pos, sub);if (p) {return p - _str;}else {return npos;}}//字符串切割String substr(size_t pos = 0, size_t len = npos) {String sub;if (len >= _size - pos) {for (size_t i = pos; i < _size; i++) {sub += _str[i];}}else {for (size_t i = pos; i < pos + len; i++) {sub += _str[i];}}return sub;}size_t size() const {return _size;}size_t capacity() const {return _capacity;}//运算符重载【】char& operator[](size_t pos) {assert(pos < _size);return _str[pos];}//运算符重载【】const char& operator[](size_t pos) const {assert(pos < _size);return _str[pos];}//清除void clear() {_size = 0;_str[_size] = '\0';}static const int npos;private:char* _str;size_t _size;size_t _capacity;};
}
//npos赋值为-1
const int zzj::String::npos = -1;
//为了将x.swap(y)转变成swap(x,y)方便理解
void swap(zzj::String& x,zzj::String& y) {x.swap(y);
}//赋值运算符重载
bool operator==(const zzj::String& s1, const zzj::String& s2) {int ret = strcmp(s1.c_str(), s2.c_str());return ret == 0;
}bool operator<(const zzj::String& s1, const zzj::String& s2) {int ret = strcmp(s1.c_str(), s2.c_str());return ret < 0;
}bool operator<=(const zzj::String& s1, const zzj::String& s2) {return s1 < s2 || s1 == s2;
}bool operator>(const zzj::String& s1, const zzj::String& s2) {return !(s1 < s2);
}bool operator>=(const zzj::String& s1, const zzj::String& s2) {return s1 > s2 || s1 == s2;
}bool operator!=(const zzj::String& s1, const zzj::String& s2) {return !(s1 == s2);
}
//输入流
istream& operator>>(istream& in, zzj::String& s)
{s.clear();char ch;//in >> ch;ch = in.get();char buff[128];size_t i = 0;while (ch != ' ' && ch != '\n'){buff[i++] = ch;// [0,126]if (i == 127){buff[127] = '\0';s += buff;i = 0;}ch = in.get();}if (i > 0){buff[i] = '\0';s += buff;}return in;
}istream& getline(istream& in, zzj::String& s)
{s.clear();char ch;//in >> ch;ch = in.get();char buff[128];size_t i = 0;while (ch != '\n'){buff[i++] = ch;// [0,126]if (i == 127){buff[127] = '\0';s += buff;i = 0;}ch = in.get();}if (i > 0){buff[i] = '\0';s += buff;}return in;
}
//输出流
ostream& operator<<(ostream& out, const zzj::String& s) {for (auto ch : s) {out << ch;}return out;
}void test1() {zzj::String s1;zzj::String s2("Hello world");zzj::String const s3("xxxxxx");for (int i = 0; i < s2.size(); i++) {cout << s2[i] << " ";}cout << endl;for (int i = 0; i < s2.size(); i++) {s2[i]++;}for (int i = 0; i < s2.size(); i++) {cout << s2[i] << " ";}cout << endl;for (int i = 0; i < s3.size(); i++) {//const对象不能被修改//s3[i]++;cout << s3[i] << " ";}}void test2() {zzj::String s3("hello world");zzj::String::iterator it3 = s3.begin();while (it3 != s3.end()) {*it3 -= 3;++ it3;}cout << endl;/*for (auto ch : s3) {cout << ch << " ";}cout << endl;*/zzj::String const s4("hello world");zzj::String::const_iterator it4 = s4.begin();while (it4 != s4.end()) {cout << *it4++ ;}cout << endl;
}void test3() {zzj::String s4("hello world");zzj::String ss4("abc");s4.push_back('x');cout << s4.c_str() << endl;s4.append(ss4.c_str());cout << s4.c_str() << endl;s4 += ss4.c_str();cout << s4.c_str() << endl;
}void test4() {zzj::String s4("hello world");s4.insert(5,'x');cout << s4.c_str() << endl;zzj::String s5("apple");s4.insert(5,s5.c_str());cout << s4.c_str() << endl;s4.erase(5, 6);cout << s4.c_str() << endl;}void test5() {zzj::String s5("hello world");zzj::String s6("apple");cout << "s5:" << s5.c_str() << endl;cout << "s6:" << s6.c_str() << endl;swap(s5, s6);s5.swap(s6);cout << "s5:" << s5.c_str() << endl;cout << "s6:" << s6.c_str() << endl;
}void test6() {zzj::String s6("hello world");size_t pos = s6.find('w', 0);cout << pos << endl;size_t findstr = s6.find("wor", 3);cout << findstr << endl;zzj::String url2("https://legacy.cplusplus.com/reference/string/string/substr/");zzj::String url1("http://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=65081411_1_oem_dg&wd=%E5%90%8E%E7%BC%80%20%E8%8B%B1%E6%96%87&fenlei=256&rsv_pq=0xc17a6c03003ede72&rsv_t=7f6eqaxivkivsW9Zwc41K2mIRleeNXjmiMjOgoAC0UgwLzPyVm%2FtSOeppDv%2F&rqlang=en&rsv_dl=ib&rsv_enter=1&rsv_sug3=4&rsv_sug1=3&rsv_sug7=100&rsv_sug2=0&rsv_btype=i&inputT=1588&rsv_sug4=6786");zzj::String protocol, domain, uri;size_t i1 = url1.find(':');if (i1 != zzj::String::npos){protocol = url1.substr(0, i1 - 0);cout << protocol.c_str() << endl;}// strcharsize_t i2 = url1.find('/', i1 + 3);if (i2 != zzj::String::npos){domain = url1.substr(i1 + 3, i2 - (i1 + 3));cout << domain.c_str() << endl;uri = url1.substr(i2 + 1);cout << uri.c_str() << endl;}}void test7() {zzj::String s7("hello world");zzj::String ss7("apple");cout << (s7 == ss7) << endl;cout << (s7 < ss7) << endl;cout << (s7 <= ss7) << endl;cout << (s7 > ss7) << endl;cout << (s7 >= ss7) << endl;cout << (s7 != ss7) << endl;cout << (s7 == "hello world") << endl;cout << ("apple" == ss7) << endl;}void test8() {zzj::String s8;cin >> s8;cout << s8 << endl;zzj::String ss8("hello world");cout << ss8 << endl;getline(cin,s8);cout << s8 << endl;
}int main() {//test1();//测试构造,拷贝构造,访问//test2();//测试iterator//test3();//测试尾插、追加、+=//test4();//测试插入和删除函数//test5();//测试交换函数//test6();//测试字符串查找和字符串分割//test7();//测试判断大小函数重载test8();//测试输出输入函数
}
我简写了解释,水一篇