🔥string介绍见博客或主页查看**:**https://blog.csdn.net/2301_79825793/article/details/144309978?fromshare=blogdetail&sharetype=blogdetail&sharerId=144309978&sharerefer=PC&sharesource=2301_79825793&sharefrom=from_link
一、代码复现
本文给大家提供复现代码+测试代码,仅供参考
🍔复现代码:
💧****复现部分:
cpp//.h文件 复现部分 #include<iostream> #include<assert.h> using namespace std; namespace zj { class string { public: typedef char* iterator; //迭代器 typedef const char* const_iterator; //const迭代器 public: //构造函数 //注意缺省参数的设置 string(const char* str = "") { if (nullptr == str) { assert(false); return; } _size = strlen(str); _capacity = _size; _str = new char[_size + 1]; strcpy(_str, str); } string(const string& s) :_str(nullptr) ,_size(0) ,_capacity(0) { string s_tmp(s._str); Swap(s_tmp); } string& operator=(string s) { Swap(s); return *this; } ~string() { if (_str) { delete[] _str; _str = nullptr; _size = _capacity = 0; } } void Swap(string& s) { swap(_size, s._size); swap(_capacity, s._capacity); swap(_str, s._str); } //**************** 迭代器 ************* iterator begin() { return _str; } iterator end() { return _str + _size; } const_iterator begin() const { return _str; } const_iterator end() const { return _str + _size; } //**************** modify ****************** void push_back(char c) { //检查空间是否足够 if (_size == _capacity) { _capacity *= 2; reserve(_capacity); } _str[_size++] = c; _str[_size] = '\0'; } string& operator+=(char c) { push_back(c); return *this; } string& operator+=(const char* str) { append(str); return *this; } void append(const char* str) { size_t append_size = strlen(str); if (_size + append_size > _capacity) { reserve(_size+append_size); } strcpy(_str + _size, str); _size += append_size; } void clear() { _size = 0; _str[_size] = '\0'; } const char* c_str()const { return _str; } //******************* access *************** char& operator[](size_t index) { assert(index < _size); return _str[index]; } const char& operator[](size_t index)const { assert(index < _size); return _str[index]; } //***************** size ******************* size_t size()const { return _size; } size_t capacity()const { return _capacity; } bool empty()const { return _size == 0; } void resize(size_t newSize, char c = '\0') { //需要按照newSize分情况 //用字符c补充空间 if (newSize > _size) { if (newSize > _capacity) { reserve(newSize); } for (size_t i = _size; i < newSize; i++) { _str[i] = c; } //memset(_str + _size, c, newSize - _size); } _str[newSize] = '\0'; _size = newSize; } void reserve(size_t newCapacity) { //只有newCapactiry > _capacity 时才有效 if (newCapacity > _capacity) { _capacity = newCapacity; char* _strTmp = new char[_capacity+1];//开辟新空间 strcpy(_strTmp, _str); //swap(_strTmp, _str); //delete[] _strTmp; //_strTmp = nullptr; delete[] _str; _str = _strTmp; } } //*********************** 比大小 ***************** //比大小写好两个逻辑后其他可以代码复用 bool operator<(const string& s) { return strcmp(_str, s._str) < 0; } bool operator<=(const string& s) { return *this < s || *this == s; } bool operator>(const string& s) { return !(*this <= s); } bool operator>=(const string& s) { return !(*this < s); } bool operator==(const string& s) { return strcmp(_str, s._str) == 0; } bool operator!=(const string& s) { return !(*this == s); } //*********************** 查找插入删除 ************** // 返回c在string中第一次出现的位置 size_t find(char c, size_t pos = 0) const { assert(pos < _size); for (size_t i = pos; i < _size ; i++) { if (_str[i] == c) { return i; } } return npos; } // 返回子串s在string中第一次出现的位置 size_t find(const char* s, size_t pos = 0) const { //这里直接使用库函数 //strstr assert(pos < _size); const char* ptr = strstr(_str + pos, s); if (ptr == nullptr) { return npos; } else { //地址相减得到位置 return ptr - _str; } } // 在pos位置上插入字符c/字符串str,并返回该字符的位置 string& insert(size_t pos, char c) { assert(pos <= _size); //检查扩容 if (_size == _capacity) { reserve(_capacity == 0 ? 4 : _capacity * 2); } //移动空间 size_t end = _size; while (end > pos) { _str[end + 1] = _str[end]; end--; } _str[end + 1] = _str[end]; _str[pos] = c; _size++; } 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 begin = _size + len; while (begin - len > pos) { _str[begin] = _str[begin - len]; begin--; } _str[begin] = _str[begin - len]; //插入数据 for (size_t i = 0; i < len; i++) { _str[pos] = str[i]; pos++; } _size += len; } // 删除pos位置上的元素,并返回该元素的下一个位置 string& erase(size_t pos, size_t len) { assert(pos <= _size); if (len == npos || len + pos >= _size) { _str[pos] = '\0'; _size = pos; } else { //挪动数据覆盖 size_t begin = pos; while (begin <= _size) { _str[begin] = _str[begin + len]; begin++; } _size -= len; } } private: char* _str; size_t _capacity; size_t _size; const static size_t npos; }; const size_t string::npos = -1; ostream& operator<<(ostream& _cout, const zj::string& s) { // 不能使用这个, 因为string的字符串内部可能会包含\0 //cout << s._str; // 直接cout时, 是将_str当成char*打印的,遇到内部的\0时后序内容就不打印了 for (size_t i = 0; i < s.size(); ++i) { _cout << s[i]; } return _cout; } istream& operator>>(istream& in, string& s) { s.clear(); char buff[129]; size_t i = 0; char ch; //in >> ch; ch = in.get(); while (ch != ' ' && ch != '\n') { if (i == 128) { buff[i] = '\0'; s += buff; i = 0; } //s += ch; //in >> ch; buff[i++] = ch; ch = in.get(); } if (i != 0) { buff[i] = '\0'; s += buff; } return in; } }
🍟测试代码:
💧测试部分:
cpp#include"string.h" // 测试string容量相关的接口 // size/clear/resize void Teststring1() { // 注意:string类对象支持直接用cin和cout进行输入和输出 string s("hello, zj!!!!"); cout << s.size() << endl; cout << s.length() << endl; cout << s.capacity() << endl; cout << s << endl; // 将s中的字符串清空,注意清空时只是将size清0,不改变底层空间的大小 s.clear(); cout << s.size() << endl; cout << s.capacity() << endl; // 将s中有效字符个数增加到10个,多出位置用'a'进行填充 // "aaaaaaaaaa" s.resize(10, 'a'); cout << s.size() << endl; cout << s.capacity() << endl; // 将s中有效字符个数增加到15个,多出位置用缺省值'\0'进行填充 // "aaaaaaaaaa\0\0\0\0\0" // 注意此时s中有效字符个数已经增加到15个 s.resize(15); cout << s.size() << endl; cout << s.capacity() << endl; cout << s << endl; // 将s中有效字符个数缩小到5个 s.resize(5); cout << s.size() << endl; cout << s.capacity() << endl; cout << s << endl; } //==================================================================================== void Teststring2() { string s; // 测试reserve是否会改变string中有效元素个数 s.reserve(100); cout << s.size() << endl; cout << s.capacity() << endl; // 测试reserve参数小于string的底层空间大小时,是否会将空间缩小 s.reserve(50); cout << s.size() << endl; cout << s.capacity() << endl; } // 利用reserve提高插入数据的效率,避免增容带来的开销 //==================================================================================== void TestPushBack() { string s; size_t sz = s.capacity(); cout << "making s grow:\n"; for (int i = 0; i < 100; ++i) { s.push_back('c'); if (sz != s.capacity()) { sz = s.capacity(); cout << "capacity changed: " << sz << '\n'; } } } // 构建vector时,如果提前已经知道string中大概要放多少个元素,可以提前将string中空间设置好 void TestPushBackReserve() { string s; s.reserve(100); size_t sz = s.capacity(); cout << "making s grow:\n"; for (int i = 0; i < 100; ++i) { s.push_back('c'); if (sz != s.capacity()) { sz = s.capacity(); cout << "capacity changed: " << sz << '\n'; } } } // string的遍历 // begin()+end() for+[] 范围for // 注意:string遍历时使用最多的还是for+下标 或者 范围for(C++11后才支持) // begin()+end()大多数使用在需要使用STL提供的算法操作string时,比如:采用reverse逆置string void Teststring3() { string s1("hello ZJ"); const string s2("Hello ZJ"); cout << s1 << " " << s2 << endl; cout << s1[0] << " " << s2[0] << endl; s1[0] = 'H'; cout << s1 << endl; // s2[0] = 'h'; 代码编译失败,因为const类型对象不能修改 } void Teststring4() { string s("hello ZJ!"); //3种遍历方式: //需要注意的以下三种方式除了遍历string对象,还可以遍历是修改string中的字符, //另外以下三种方式对于string而言,第一种使用最多 //1. for+operator[] for (size_t i = 0; i < s.size(); ++i) cout << s[i] << endl; // 2.迭代器 string::iterator it = s.begin(); while (it != s.end()) { cout << *it << endl; ++it; } // 3.范围for for (auto ch : s) cout << ch << endl; } // // 测试string: // 1. 插入(拼接)方式:push_back append operator+= // 2. 正向和反向查找:find() + rfind() // 3. 截取子串:substr() // 4. 删除:erase void Teststring5() { string str; str.push_back(' '); // 在str后插入空格 str.append("hello"); // 在str后追加一个字符"hello" str += 'Z'; // 在str后追加一个字符'b' str += "J!"; // 在str后追加一个字符串"it" cout << str << endl; cout << str.c_str() << endl; // 以C语言的方式打印字符串 // 获取file的后缀 string file("string.cpp"); size_t pos = file.rfind('.'); string suffix(file.substr(pos, file.size() - pos)); cout << suffix << endl; // npos是string里面的一个静态成员变量 // static const size_t npos = -1; // 取出url中的域名 string url("http://www.cplusplus.com/reference/string/string/find/"); cout << url << endl; size_t start = url.find("://"); if (start == string::npos) { cout << "invalid url" << endl; return; } start += 3; size_t finish = url.find('/', start); string address = url.substr(start, finish - start); cout << address << endl; // 删除url的协议前缀 pos = url.find("://"); url.erase(0, pos + 3); cout << url << endl; }
二、结语
🫡 你的点赞和关注是作者前进的动力!
🌞最后,作者主页有许多有趣的知识,欢迎大家关注作者,作者会持续更新有意思的代码 ,在有趣的玩意儿中成长!