为实现祖国统一而奋斗!为实现社会主义现代化而奋斗!为实现中华民族复兴而奋斗!
——By 一名社会主义建设积极分子
目录
1.先实现一个简单的string,只考虑资源管理深浅拷贝问题(暂不考虑增删查改)
后记:●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教! ——By 作者:新晓·故知
模拟实现string类,最主要是实现string类的构造、拷贝构造、赋值运算符重载以及析构函数。根据string的底层原理,实现模拟string使其与库里的string(即std::string)具有相似的功能。由于库里的string类的功能较多,这里只模拟实现了较为常用的功能,
例如:iterator(模拟的string迭代器)、push_back、insert、reserve、resize、find、erase、c_str、ostream重载、istream重载、赋值运算符重载、[ ]重载、append以及比较运算符的重载等,甚至深拷贝构造函数的现代写法(资本写法)、赋值运算符重载的现代写法(资本写法)等。std::string中的功能较多,学习使用可登录cplusplus官网,参见string文档。
(1)string.h
(2)test.cpp:
深拷贝:
深拷贝:使得值相同,空间大小相同,但空间地址不同
对于浅拷贝的两个问题:
1.多次析构同一空间:引用计数,即最后一个拷贝构造的对象是否资源
2.一个对象修改会影响其他对象:做深拷贝,写时拷贝
string.h:
test.cpp:
完整源码及注释:
(1)string.h:
#pragma once #define _CRT_SECURE_NO_WARNINGS #include #include #include using namespace std; //模拟实现string //1.先实现一个简单的string,只考虑资源管理深浅拷贝问题 //自定义命名空间,防止与库中的冲突 //namespace my //{ // //先实现一个简单的string,只考虑资源管理深浅拷贝问题 // //暂不考虑增删查改 // class string // { // public: // //构造函数 // string(const char* str) // :_str(new char[strlen(str) + 1]) // { // //不能直接 _str=str; 因为会权限放大 // strcpy(_str, str); //也拷贝了\0 // } // //深拷贝函数 s2(s1) // string(const string& s) // :_str(new char[strlen(s._str) + 1]) // { // strcpy(_str, s._str); // } // ~string() // { // if (_str) // { // delete[] _str; // } // } // //s1=s3 ——>s1.operator=(&s1,s3) // //赋值重载函数 // string& operator = (const string& s) // { // if (this != &s) //解决s1=s1,自己释放自己的空间 // { // //先删除,再开辟赋值 // //如果new开辟失败,那s1作为原始数据被删除 // /*delete[] _str; // _str = new char[strlen(s._str) + 1]; // strcpy(_str, s._str);*/ // //先保存,再开辟赋值 // char* tmp = new char[strlen(s._str) + 1]; // strcpy(tmp, s._str); // delete[] _str; // _str = tmp; // } // return *this; // } // //c_str是string中的一个函数,具体详见string文档 // //获取等效的字符串 // const char* c_str() const // { // return _str; // } // //重载[] // char& operator[](size_t pos) // { // assert(pos < strlen(_str)); // return _str[pos]; // } // //计算字符串大小 // size_t size() // { // return strlen(_str); // } // // private: // char* _str; // // }; //} // 2.string完善的增删查改和使用的string //namespace my //{ // class string // { // public: // 构造函数 // //string(const char* str) // // :_size(strlen(str)) // // ,_capacity(_size) // //{ // // //要注意初始化顺序,取决于类的声明顺序 // // _str = new char[_capacity + 1]; // // //不能直接 _str=str; 因为会权限放大 // // strcpy(_str, str); //也拷贝了\0 // //} // 默认构造函数(无参使用的) // //string() // // :_size(0) // // ,_capacity(0) // //{ // // _str = new char[1]; //将_str初始化为空字符串,string库就是这种做法 // // _str[0] = '0'; // //} // // //默认构造函数(全缺省版) // string(const char* str="") // ""、"\0"均可以,'\0'是字符 // :_size(strlen(str)) // , _capacity(_size) // { // //要注意初始化顺序,取决于类的声明顺序 // _str = new char[_capacity + 1]; // //不能直接 _str=str; 因为会权限放大 // strcpy(_str, str); //也拷贝了\0 // } // 深拷贝函数版本1 s2(s1) // //string(const string& s) // // :_str(new char[strlen(s._str) + 1]) // //{ // // strcpy(_str, s._str); // //} // //深拷贝函数版本2 s2(s1) // string(const string& s) // :_size(strlen(s._str)) // ,_capacity(_size) // { // _str=new char[_capacity + 1]; // strcpy(_str, s._str); // } // // //析构函数 // ~string() // { // if (_str) // { // delete[] _str; // } // } // //s1=s3 ——>s1.operator=(&s1,s3) // //赋值重载函数 // string& operator = (const string& s) // { // if (this != &s) //解决s1=s1,自己释放自己的空间 // { // //先保存,再开辟赋值 // char* tmp = new char[s._capacity + 1]; // strcpy(tmp, s._str); // delete[] _str; // _str = tmp; // _size = s._size; // _capacity = s._capacity; // } // return *this; // } // //c_str是string中的一个函数,具体详见string文档 // //获取等效的字符串 // const char* c_str() const // { // return _str; // } // //重载[] // char& operator[](size_t pos) // { // assert(pos < _size); // return _str[pos]; // } // //重载[] const 提供两个版本的重载[] ,普通对象和const对象都可以调用 // const char& operator[](size_t pos) const // { // assert(pos < _size); // return _str[pos]; // } // //计算字符串大小 // //size_t size(const string* this) // size_t size() const // { // return _size; // } // // size_t capacity() const // { // return _capacity; // } // 尾插数据 // //void push_back(char ch) // //{ // // if (_size == _capacity) //其实为_capacity开辟的多一个为\0存储的空间,但那个不参与比较 // // { // // char* tmp = new char[_capacity * 2 + 1]; // // strcpy(tmp, _str); // // delete[] _str; // // _str = tmp; // // _capacity *= 2; // // } // // _str[_size] = ch; // // ++_size; // // _str[_size] = '\0'; // //} // // //尾插也可以使用+=(附用push_back) // string& operator+=(char ch) // { // push_back(ch); // return *this; // } // //预留扩容 // void reserve(size_t n) // { // if (n > _capacity) // { // char* tmp = new char[n + 1]; // strcpy(tmp, _str); // delete[] _str; // _str = tmp; // _capacity = n; // } // } // //尾插数据——附用reserve // void push_back(char ch) // { // //if (_size == _capacity) //其实为_capacity开辟的多一个为\0存储的空间,但那个不参与比较 // //{ // // //reserve( _capacity * 2);若_capacity为0,则出现bug // // reserve(_capacity==0 ? 4 : _capacity * 2); // //} // //_str[_size] = ch; // //++_size; // //_str[_size] = '\0'; // // //附用insert // insert(_size, ch); // } // //追加到字符 // void append(const char*str) // { // /*size_t len = _size + strlen(str); // if (len > _capacity) // { // reserve(len); // } // strcpy(_str + _size, str); // _size = len;*/ // //附用insert // insert(_size, str); // } // //尾插也可以使用+=(附用append) // string& operator+=(const char* str) // { // append(str); // return *this; // } // //扩空间+初始化 // //删除部分数据,保留前n个 // void resize(size_t n, char ch = '\0') // { // //考虑到内存对齐,可能开辟的空间与n有些许微小出入 // if (n < _size) // { // _size = n; // _str[_size] = '\0'; // } // else // { // if (n > _capacity) // { // reserve(n); // } // for (size_t i = _size; i < n; ++i) // { // _str[i] = ch; // } // _size = n; // _str[_size] = '\0'; // } // } // // //迭代器 // 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& insert(size_t pos, char ch) // { // assert(pos <= _size); //pos = _size相当于尾插 // if (_size == _capacity) // { // reserve(_capacity == 0 ? 4 : _capacity * 2); // } // //size_t end = _size; // //while (end >= pos) //--end会造成负数,而--end是size_t类型 // //{ // // _str[end + 1] = _str[end]; // // --end; // //} // 解决1:强转类型 // //int end = _size; // //while (end >=(int) pos) //--end会造成负数,而--end是size_t类型 // //{ // // _str[end + 1] = _str[end]; // // --end; // //} // //解决2:修改end位置 // size_t end = _size+1; // while (end > pos) //end等于0就停止 // { // _str[end ] = _str[end-1]; // --end; // } // _str[pos] = ch; // _size ++; // return *this; // } // //插入字符串 // string& 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) //或者while (end >= pos + len) ,但pos、len均为0就有问题 // { // _str[end] = _str[end - len]; // --end; // } // strncpy(_str + pos, str, len); //不能使用strcpy // _size += len; // return *this; // } // //删除 // string& erase(size_t pos, size_t len=npos) // { // assert(pos < _size); // if (len == npos || pos + len >= _size) // { // _str[pos] = '\0'; // _size = pos; // } // else // { // size_t begin = pos + len; // while (begin <= _size) // { // _str[begin - len] = _str[begin]; // ++begin; // } // _size -= len; // } // return *this; // } // //查找字符 // //The position of the first character of the first match. // //If no matches were found, the function returns string::npos. // size_t find(char ch,size_t pos=0) // { // for (; pos < _size; ++pos) // { // if (_str[pos] == ch) // { // return pos; // } // } // return npos; // } // //查找字符串 // size_t find(const char*str, size_t pos = 0) // { // const char* p = strstr(_str + pos, str); //strstr暴力算法 // if (p == nullptr) // { // return npos; // } // else // { // return p - _str; // } // } // void clear() // { // _str[0] = '\0'; // _size = 0; // } // private: // char* _str; // size_t _size; //有效字符个数,不包含\0 // size_t _capacity; //实际存储的有效字符的空间 // const static size_t npos; // // }; // //定义 // const size_t string::npos = -1; // //这里不是成员函数,不在类里 // //运算符<重载 // bool operator<(const string& s1, const string& s2) // { // return strcmp(s1.c_str(), s2.c_str()) < 0; // } // //运算符==重载 // bool operator==(const string& s1, const string& s2) // { // return strcmp(s1.c_str(), s2.c_str()) == 0; // } // //运算符<=重载 // bool operator<=(const string& s1, const string& s2) // { // return s1 < s2 || s1 == s2; // } // //运算符>重载 (附用<=实现) // bool operator>(const string& s1, const string& s2) // { // return !(s1 <= s2); // } // //运算符>=重载 (附用<实现) // bool operator>=(const string& s1, const string& s2) // { // return !(s1 < s2); // } // //运算符!=重载 (附用==实现) // bool operator!=(const string& s1, const string& s2) // { // return !(s1 == s2); // } // //流运算符重载 // ostream& operator<<(ostream& out, const string& s) // { // //out << s.c_str(); //无法打印不可见字符\0 // for (auto ch : s) // { // out << ch; // } // return out; // } // istream& operator>>(istream& in, string& s) // { // //s.clear(); // //char ch; // in >> ch; // //ch = in.get(); // //while (ch != ' ' && ch != '\n') // //{ // // s += ch; // // //in >> ch; // // ch = in.get(); // //} // //return in; // //优化 // s.clear(); // char ch; // ch = in.get(); // char buff[128] = { '\0' }; // size_t i = 0; // while (ch != ' ' && ch != '\n') // { // buff[i++] = ch; // if (i == 127) // { // s += buff; // memset(buff, '\0', 128); // i = 0; // } // ch = in.get(); // } // s += buff; // return in; // } // //getline // //} //3.string完善的增删查改和使用的string(现代写法) namespace my { class string { public: 构造函数 //string(const char* str) // :_size(strlen(str)) // ,_capacity(_size) //{ // //要注意初始化顺序,取决于类的声明顺序 // _str = new char[_capacity + 1]; // //不能直接 _str=str; 因为会权限放大 // strcpy(_str, str); //也拷贝了\0 //} 默认构造函数(无参使用的) //string() // :_size(0) // ,_capacity(0) //{ // _str = new char[1]; //将_str初始化为空字符串,string库就是这种做法 // _str[0] = '0'; //} //默认构造函数(全缺省版) string(const char* str = "") // ""、"\0"均可以,'\0'是字符 :_size(strlen(str)) , _capacity(_size) { //要注意初始化顺序,取决于类的声明顺序 _str = new char[_capacity + 1]; //不能直接 _str=str; 因为会权限放大 strcpy(_str, str); //也拷贝了\0 } 深拷贝函数版本1 s2(s1) //string(const string& s) // :_str(new char[strlen(s._str) + 1]) //{ // strcpy(_str, s._str); //} 深拷贝函数版本2 s2(s1) //传统写法:本分实现,自劳 //string(const string& s) // :_size(strlen(s._str)) // , _capacity(_size) //{ // _str = new char[_capacity + 1]; // strcpy(_str, s._str); //} //深拷贝函数版本3 s2(s1) //现代写法:剥削行为,借他人之手,行私利,但简单 //tmp去调用构造函数:s1->s2:构造函数->拷贝构造函数->构造函数->swap //tmp->s2 void swap(string& s) { //库里的swap,可交换任意类型 std::swap(_str, s._str); std::swap(_size, s._size); std::swap(_capacity, s._capacity); } string(const string& s) :_str(nullptr) , _size(0) , _capacity(0) { string tmp(s._str); //tmp是局部对象,出作用域会调用析构函数 /*swap(_str, tmp._str); swap(_size, tmp._size); swap(_capacity, tmp._capacity);*/ swap(tmp); } //析构函数 ~string() { if (_str) { delete[] _str; } } //s1=s3 ——>s1.operator=(&s1,s3) 赋值重载函数--版本1 传统写法 //string& operator = (const string& s) //{ // if (this != &s) //解决s1=s1,自己释放自己的空间 // { // //先保存,再开辟赋值 // char* tmp = new char[s._capacity + 1]; // strcpy(tmp, s._str); // delete[] _str; // _str = tmp; // _size = s._size; // _capacity = s._capacity; // } // return *this; //} 赋值重载函数--版本2 现代写法 //string& operator = (const string& s) //{ // if (this != &s) //解决s1=s1,自己释放自己的空间 // { // string tmp(s._str); // swap(tmp); // } // return *this; //} 赋值重载函数--版本3 现代写法 string& operator = (string s) //传值传参,引用返回 { swap(s); return *this; } //c_str是string中的一个函数,具体详见string文档 //获取等效的字符串 const char* c_str() const { return _str; } //重载[] char& operator[](size_t pos) { assert(pos < _size); return _str[pos]; } //重载[] const 提供两个版本的重载[] ,普通对象和const对象都可以调用 const char& operator[](size_t pos) const { assert(pos < _size); return _str[pos]; } //计算字符串大小 //size_t size(const string* this) size_t size() const { return _size; } size_t capacity() const { return _capacity; } 尾插数据 //void push_back(char ch) //{ // if (_size == _capacity) //其实为_capacity开辟的多一个为\0存储的空间,但那个不参与比较 // { // char* tmp = new char[_capacity * 2 + 1]; // strcpy(tmp, _str); // delete[] _str; // _str = tmp; // _capacity *= 2; // } // _str[_size] = ch; // ++_size; // _str[_size] = '\0'; //} //尾插也可以使用+=(附用push_back) string& operator+=(char ch) { push_back(ch); return *this; } //预留扩容 void reserve(size_t n) { if (n > _capacity) { char* tmp = new char[n + 1]; strcpy(tmp, _str); delete[] _str; _str = tmp; _capacity = n; } } //尾插数据——附用reserve void push_back(char ch) { //if (_size == _capacity) //其实为_capacity开辟的多一个为\0存储的空间,但那个不参与比较 //{ // //reserve( _capacity * 2);若_capacity为0,则出现bug // reserve(_capacity==0 ? 4 : _capacity * 2); //} //_str[_size] = ch; //++_size; //_str[_size] = '\0'; //附用insert insert(_size, ch); } //追加到字符 void append(const char* str) { /*size_t len = _size + strlen(str); if (len > _capacity) { reserve(len); } strcpy(_str + _size, str); _size = len;*/ //附用insert insert(_size, str); } //尾插也可以使用+=(附用append) string& operator+=(const char* str) { append(str); return *this; } //扩空间+初始化 //删除部分数据,保留前n个 void resize(size_t n, char ch = '\0') { //考虑到内存对齐,可能开辟的空间与n有些许微小出入 if (n < _size) { _size = n; _str[_size] = '\0'; } else { if (n > _capacity) { reserve(n); } for (size_t i = _size; i < n; ++i) { _str[i] = ch; } _size = n; _str[_size] = '\0'; } } //迭代器 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& insert(size_t pos, char ch) { assert(pos <= _size); //pos = _size相当于尾插 if (_size == _capacity) { reserve(_capacity == 0 ? 4 : _capacity * 2); } //size_t end = _size; //while (end >= pos) //--end会造成负数,而--end是size_t类型 //{ // _str[end + 1] = _str[end]; // --end; //} 解决1:强转类型 //int end = _size; //while (end >=(int) pos) //--end会造成负数,而--end是size_t类型 //{ // _str[end + 1] = _str[end]; // --end; //} //解决2:修改end位置 size_t end = _size + 1; while (end > pos) //end等于0就停止 { _str[end] = _str[end - 1]; --end; } _str[pos] = ch; _size++; return *this; } //插入字符串 string& 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) //或者while (end >= pos + len) ,但pos、len均为0就有问题 { _str[end] = _str[end - len]; --end; } strncpy(_str + pos, str, len); //不能使用strcpy _size += len; return *this; } //删除 string& erase(size_t pos, size_t len = npos) { assert(pos < _size); if (len == npos || pos + len >= _size) { _str[pos] = '\0'; _size = pos; } else { size_t begin = pos + len; while (begin <= _size) { _str[begin - len] = _str[begin]; ++begin; } _size -= len; } return *this; } //查找字符 //The position of the first character of the first match. //If no matches were found, the function returns string::npos. size_t find(char ch, size_t pos = 0) { for (; pos < _size; ++pos) { if (_str[pos] == ch) { return pos; } } return npos; } //查找字符串 size_t find(const char* str, size_t pos = 0) { const char* p = strstr(_str + pos, str); //strstr暴力算法 if (p == nullptr) { return npos; } else { return p - _str; } } void clear() { _str[0] = '\0'; _size = 0; } private: char* _str; size_t _size; //有效字符个数,不包含\0 size_t _capacity; //实际存储的有效字符的空间 const static size_t npos; }; //定义 const size_t string::npos = -1; //这里不是成员函数,不在类里 //运算符<重载 bool operator<(const string& s1, const string& s2) { return strcmp(s1.c_str(), s2.c_str()) < 0; } //运算符==重载 bool operator==(const string& s1, const string& s2) { return strcmp(s1.c_str(), s2.c_str()) == 0; } //运算符<=重载 bool operator<=(const string& s1, const string& s2) { return s1 < s2 || s1 == s2; } //运算符>重载 (附用<=实现) bool operator>(const string& s1, const string& s2) { return !(s1 <= s2); } //运算符>=重载 (附用<实现) bool operator>=(const string& s1, const string& s2) { return !(s1 < s2); } //运算符!=重载 (附用==实现) bool operator!=(const string& s1, const string& s2) { return !(s1 == s2); } //流运算符重载 ostream& operator<<(ostream& out, const string& s) { //out << s.c_str(); //无法打印不可见字符\0 for (auto ch : s) { out << ch; } return out; } istream& operator>>(istream& in, string& s) { //s.clear(); //char ch; in >> ch; //ch = in.get(); //while (ch != ' ' && ch != '\n') //{ // s += ch; // //in >> ch; // ch = in.get(); //} //return in; //优化 s.clear(); char ch; ch = in.get(); char buff[128] = { '\0' }; size_t i = 0; while (ch != ' ' && ch != '\n') { buff[i++] = ch; if (i == 127) { s += buff; memset(buff, '\0', 128); i = 0; } ch = in.get(); } s += buff; return in; } //getline } //类型转换函数 //atoi C //itoa C //stoi C++11 //to_string(2)test.cpp:
#include "string.h" //1.基本初始化测试 void TestString1() { my::string s1("hello,world"); cout << s1.c_str() << endl; //修改测试 s1[0] = 'x'; //s1.operator[](0)='x'; cout << s1.c_str() << endl; //读取测试 for (size_t i = 0; i < s1.size(); ++i) { cout << s1[i] << " "; } cout << endl; } //2.浅拷贝及其问题测试 void TestString2() { //浅拷贝带来的问题: //1.析构两次,程序崩溃 2.修改一个值,另一个也被改变 my::string s1("hello,world"); my::string s2(s1); //调用拷贝构造函数 cout << s1.c_str() << endl; cout << s2.c_str() << endl; } //3.深拷贝测试 void TestString3() { //深拷贝:使得值相同,空间大小相同,但空间地址不同 my::string s1("hello,world"); my::string s2(s1); //调用深拷贝构造函数 cout << s1.c_str() << endl; cout << s2.c_str() << endl; s1[0] = 'x'; cout << s1.c_str() << endl; cout << s2.c_str() << endl; } //4.赋值重载测试 void TestString4() { //赋值面临的问题与浅拷贝相似 my::string s1("hello,world"); my::string s2(s1); //调用深拷贝构造函数 my::string s3("qqqqqqqqqq"); s1 = s3; //赋值 cout << s1.c_str() << endl; cout << s2.c_str() << endl; cout << s3.c_str() << endl; } //int main() //{ // //TestString1(); // //TestString2(); // //TestString3(); // TestString4(); // //对于new的异常捕获 // try // { // TestString4(); // } // catch (const exception& e) // { // cout << e.what() << endl; // } // return 0; //} //5.增删查改测试 void TestString5() { my::string s1("hello,world"); cout << s1.c_str() << endl; my::string s2; cout << s2.c_str() << endl; } //6.尾插测试+扩容测试 void TestString6() { //my::string s1("hello,world"); //cout << s1.c_str() << endl; 使用push_back //s1.push_back('y'); //cout << s1.c_str() << endl; //s1.push_back('y'); //cout << s1.c_str() << endl; 使用重载+= (附用push_back) //s1 += '6'; //s1 += '7'; //s1 += '8'; //cout << s1.c_str() << endl; 使用重载+= (附用reserve) //s1 += 'a'; //s1 += 'b'; //s1 += 'c'; //cout << s1.c_str() << endl; //my::string s2; //reserve解决空串_capacity=0,再去_capacity*2仍为0 //s2.reserve(20); //直接开辟指定空间 //库里的string::resize std::string s3("cplusplus"); s3.resize(20, 'x'); s3.resize(5, 'x'); cout << s3 << endl; //模拟实现的string::resize my::string s4("stringtest"); s4.resize(5, 'y'); s4.resize(15, 'g'); cout << s4.c_str() << endl; } //7.遍历测试 void TestString7() { my::string s1("hello,world"); //方式1:下标+[] for (size_t i = 0; i < s1.size(); ++i) { s1[i] += 1; cout << s1[i] << " "; } cout << endl; //方式2:迭代器 my::string::iterator it = s1.begin(); while (it != s1.end()) { *it -= 1; cout << *it << " "; ++it; } cout << endl; //方式3:范围for——底层被替换成迭代器访问 for (auto& ch : s1) { cout << ch << " "; ch += 1; } cout << endl; for (auto ch : s1) { cout << ch << " "; } cout << endl; } //const对象权限测试 void func(const my::string& s) //string的拷贝是深拷贝,使用引用减少拷贝 { //方式1:下标+[] for (size_t i = 0; i < s.size(); ++i) { //s[i] += 1; //这里传给const形参,不能写 cout << s[i] << " "; } cout << endl; //方式2:迭代器 my::string::const_iterator it = s.begin(); while (it != s.end()) { //*it -= 1; //这里调用的是const_iterator,不支持写 cout << *it << " "; ++it; } cout << endl; //方式3:范围for——底层被替换成迭代器访问 for (auto& ch : s) //s是const修饰,会调用对应的迭代器 { //cout << ch << " "; //ch += 1; //这里调用的是const_iterator,不支持写 cout << ch << " "; } cout << endl; } //8.insert测试 void TestString8() { my::string s1("hello,world"); //插入字符 //s1.insert(6, '@'); //cout << s1.c_str() << endl; //s1 += '#'; //cout << s1.c_str() << endl; 遍历:范围for,按照实际长度去遍历 //for (auto& ch : s1) //{ // cout << ch << " "; //} //cout << endl; //s1 += '\0'; //无法打印,不可见字符,使用范围for可确定,但不显示 //cout << s1.c_str() << endl; //s1 += '&'; //cout << s1.c_str() << endl; 遍历:范围for,按照实际长度去遍历 //for (auto& ch : s1) //{ // cout << ch << " "; //} //cout << endl; //s1.insert(0, '#'); //cout << s1.c_str() << endl; //插入字符串 s1.insert(0, "###"); cout << s1.c_str() << endl; s1.insert(10, "@@@"); cout << s1.c_str() << endl; } //9.erase测试 void TestString9() { my::string s1("hello,world"); cout << s1.c_str() << endl; //删除字符串 s1.erase(0, 3); cout << s1.c_str() << endl; s1.erase(5, 10); cout << s1.c_str() << endl; s1.erase(1); //位置1之后全删完 cout << s1.c_str() << endl; } //10.find测试 void TestString10() { my::string s1("hello,world"); cout << s1.c_str() << endl; //查找字符 size_t found = s1.find('w'); cout << "Object found at : "< //查找字符 found = s1.find('l'); cout << "Object found at : " << found << endl; //查找字符串 found = s1.find("hell"); cout << "Object found at : " << found << endl; } //11.流重载测试 void TestString11() { //1.<< 测试 //my::string s1("hello,world"); //cout << s1.c_str() << endl; //s1 += 'x'; //cout << s1 << endl; //s1 += '\0'; //s1 += '@'; //cout << s1 << endl; //cout << s1.c_str() << endl; //读取到\0就结束 //2.>>测试 /*my::string s2,s3; cin >> s2>>s3; cout << s2 << endl; cout << s3 << endl;*/ my::string s4("hello,world"); cin >> s4; cout << s4 << endl; } //12.赋值重载测试 void TestString12() { my::string s1("hello,world"); my::string s2(s1); cout << s2<< endl; my::string s3; s3 = s1; cout << s3 << endl; } //13.转换函数测试 void TestString13() { int i; cin >> i; string s1 = to_string(i); //to_string是库里的 cout << s1 << endl; int val = stoi(s1); //stoi是库里的 cout << s1 << endl; } int main() { //TestString1(); //TestString2(); //TestString3(); //TestString4(); //TestString5(); //TestString6(); //TestString7(); //func("hello,world"); //TestString8(); //TestString9(); //TestString10(); //TestString11(); //TestString12(); TestString13(); //对于new的异常捕获 /*try { TestString4(); } catch (const exception& e) { cout << e.what() << endl; }*/ return 0; }
后记:
●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教!
——By 作者:新晓·故知