【C++】C++STL 揭秘:Strng背后的底层逻辑(二)https://developer.aliyun.com/article/1617336
头文件:string.h
#pragma once #include <assert.h> #include <iostream> using namespace std; //模拟实现string 4.4 //设置命名空间,防止跟库中string有冲突 namespace bit { class string { public: typedef char* iterator; typedef const char* const_iterator; iterator begin() { return _str; } const_iterator begin() const { return _str; } iterator end() { return _str + _size; } const_iterator end() const { return _str + _size; } //\0会占用一块空间 //无参构造 //string() // :_str(new char[1]) // ,_size(0) // ,_capacity(0) //{ // _str[_size] = '\0'; //} //有参构造 //string(const char* str) // :_size(strlen(str)) // ,_capacity(strlen(str)) //{ // _str = new char[_capacity + 1]; // strcpy(_str, str); //} //全缺省值构造 string(const char *str="") :_size(strlen(str)) { _capacity = _size; _str = new char[_capacity + 1]; strcpy(_str, str); } 析构构造 //~string() //{ // delete[]_str; // _size = _capacity = 0; //} //构造函数s1(s2) //传统写法--c_str作用还是不明白 //string(const string& s) //{ // _str = new char[s._capacity + 1]; // strcpy(_str, s._str); // _size = s._size; // _capacity = s._capacity; //} //现代写法s1(s2) //string(const string& s) //{ // //string ss(s);//为什么需要做一份拷贝呢?不会递归死循环吗? // // //不能在拷贝构造里面,调用拷贝构造,应该调用构造,大小和容量可以根据字符串来计算 // string ss(s._str); // swap(ss);//这里完成的是交换,是s1拷贝s2一份,s2本身不跟s1交换 //} //意思是在传参的时候,进行了拷贝构造,但是拷贝构造还没有实现 //string(string ss) //{ // swap(ss); //} //修改string的接口 //赋值operator= //传统写法 s1=s2; string& operator=(const string& s) { char* tmp = new char[s._capacity + 1]; strcpy(tmp, s._str); delete[]_str; _str = tmp; _size = s._size; _capacity = s._capacity; return *this; } //现代写法 string& operator=(const string& s) { //可以使用构造或者使用拷贝构造 string ss(s._str); swap(ss); return *this; } //优化 有拷贝构造基础上 string& operator=(string ss) { swap(ss); return *this; } //遍历 size_t size(const string& s) const { return s._size; } size_t capacity(const string& s) const { return s._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]; } const char& operator[](size_t pos) const { assert(pos < _size); return _str[pos]; } //扩容操作 void reserve(size_t n) { if (n > _capacity) { char* tmp = new char[n + 1]; strcpy(tmp, _str); delete[]_str; _str = tmp; _capacity = n; } } void resize(size_t n, char ch = '\0') { //如果小于该容量 if (n <= _capacity) { _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 push_back(char ch) { //判断容量是否满了 if (_size == _capacity) { //是否为一开始的状态,就是为空待插入 reserve(_capacity == 0 ? 2 : 2 * _capacity); } _str[_size] = ch; _size++; _str[_size] = '\0'; } void append(const char* str) { //不用想这么多,先扩容先 size_t len = strlen(str); //里面会给\0开辟一块空间 reserve(_capacity+len); strncpy(_str + _size, str, len); _size = _size + len; } void swap(string& s)//做值拷贝,属性交换,避免深拷贝 { std::swap(_str, s._str); std::swap(_size, s._size); std::swap(_capacity, s._capacity); } //实现更加轻松的+= string& operator+=(const char ch) { push_back(ch); return *this; } string& operator+=(const char* str) { append(str); return *this; } void insert(size_t pos, char ch) { assert(pos <= _size); if (_size == _capacity) { reserve(_capacity == 0 ? 2 : 2 * _capacity); } //size_t end = _size; 0<end end>=0 //while (end > pos) //{ // _str[end] = _str[end - 1]; // end--; //} //_str[pos] = ch; //_size++; //_str[_size] = '\0'; //从\0开始移动 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 (len + _size > _capacity) { reserve(_size + len); } size_t end = _size + len; while (end > pos + len) { _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 (pos + len > _size || len==npos) { _str[pos] = '\0'; _size = pos; } else { strcpy(_str + pos, _str + pos + len); _size -= len; } } size_t find(char ch, size_t pos = 0) const { assert(pos <= _size); for (size_t i = 0; i < pos; i++) { if (_str[i] == ch) return i; } return npos; } size_t find(char* sub, size_t pos = 0) const { assert(pos <= _size); const char* p = strstr(_str + pos, sub); if (p == nullptr) return npos; else return p - _str; } //功能是从某个位置打印len长度的字符串 string substr(size_t pos = 0, size_t len = npos) { assert(pos <= _size); string sub; //这里怕pos+len会太大 //打印拿出来 if (pos > _capacity - len || len==npos) { for (size_t i = pos; i <_size; i++) { sub += _str[i];//i=size-1 } } //没有超过 else { for (size_t i = pos; i < pos + len; i++) { sub += _str[i]; } } return sub; } //当你将 sub 返回时,std::string 类会自动确保字符串以 null 结尾。不需要手动添加 \0。 const char* c_str() const { return _str; } void clear() { _size = 0; _str[_size] = '\0'; } private: char* _str; size_t _size; size_t _capacity; static const size_t npos; }; static const size_t nops = -1; void swap(string& x,string &y)//实现两个swap 外面的swap实际还是调用里面的swap { x.swap(y); } bool operator==(const string& s1, const string& s2) { int ret = strcmp(s1.c_str(), s2.c_str()); return ret == 0; } bool operator<(const string& s1, const string& s2) { int ret = strcmp(s1.c_str(), s2.c_str()); return ret < 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) { for (auto ch : s) { out << ch; } return out; } iostream& operator>>(iostream& in, string& s) { //先对资源清空 s.clear(); char buff[128]; char ch; ch=in.get(); size_t i = 0; while (ch != '\n' && ch != ' ') { buff[i++] = ch; 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, string& s) { //先对资源清空 s.clear(); char buff[128]; char ch; ch = in.get(); size_t i = 0; while (ch != '\n' && ch != ' ') { buff[i++] = ch; if (i == 127) { buff[127] = '\0'; s += buff; i = 0; } ch = in.get(); } if (i > 0) { buff[i] = '\0'; s += buff; } //已经手动输入过了 return in; } }
以上就是本篇文章的所有内容,在此感谢大家的观看!这里是店小二呀C++笔记,希望对你在学习C++语言旅途中有所帮助!