首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >探索C/C++的奥秘之string类(二)

探索C/C++的奥秘之string类(二)

作者头像
用户11290648
发布于 2024-11-21 16:20:23
发布于 2024-11-21 16:20:23
2840
举报
文章被收录于专栏:学习学习

3. string类的模拟实现

string的构造函数一大堆,用常用的去实现就可以了,蓝色的就是最常用的之一。

operator[]有两个版本,意义是不一样的,普通对象调用第一个,能读能写,const对象调用第二个,只能读。

 end()指向的是有效字符的下一个位置。

范围for识别成迭代器,并且名字都不能变,iterator就是迭代器,begin()和end()名字都不能变。

整型提升是小的范围向大的范围提升。

流插入和流提取是允许拷贝的。

常规情况下,流插入和c_str()是没有差别的,有一种情况下是有差别的,c_str()是返回C型的字符串,c型字符串是怎么打印的呢,相当于打印的是一个内置类型,内置类型也就相当于打印的const char* ,const char*打印的原则是遇到“\0”就终止了,而流插入的重载,不管\0,跟\0没有关系,它用范围for或者size()的长度去走,长度是多长,实际就要打印多长。

C语言的字符数组,以\0为终止算长度,string不看\0,以size为终止算长度。

下面是string的模拟实现源代码:

string.h #include<iostream> #include<assert.h> using namespace std; namespace bit {     class string     {     public:         typedef char* iterator;         typedef const char* const_iterator;         //迭代器也要写两个版本,一个普通对象用,一个const对象用         iterator begin()         {             return _str;         }         iterator end()         {             return _str + _size;         }         const_iterator begin() const         {             return _str;         }         const_iterator end() const         {             return _str + _size;         }         //string 的构造函数不能用字符串直接去初始化,必须要开空间尽可能用初始化列表去初始化。         //string(const char* str)         //    :_str(new char[strlen(str) + 1])         //    ,_size(strlen(str))         //    //capacity不包含\0,一般不包含,因为capacity指的是能包含多少个有效字符,\0不是有效字符         //    ,_capacity(strlen(str))         //{         //    strcpy(_str, str);         //}         //无参默认构造         //下面这样写不行,如果这样写,_str是空指针,相当于c_str对空指针解引用,程序就会崩溃         //string()         //    :_str(nullptr)         //    ,_size(0)         //    ,_capacity(0)         //{}         //这样写才是对的         //string()         //    :_str(new char[1])         //    , _size(0)         //    , _capacity(0)         //{         //    _str[0] = '\0';         //}         //下面是无参和有参初始化合并后的         //string(const char* str = '\0')1.         //string(const char* str = nullptr)2.         //1和2都是错的         //string(const char* str = "\0")可以这样写,但是没必要,这个地方有两个\0         //下面是最优写法         string(const char* str = "")//虽然为空,但是有标识字符\0             :_str(new char[strlen(str) + 1])             ,_size(strlen(str))             //capacity不包含\0,一般不包含,因为capacity指的是能包含多少个有效字符,\0不是有效字符             ,_capacity(strlen(str))         {             memcpy(_str, str, _size + 1);         }         //拷贝构造的传统写法         //string(const string& s)         //{         //    _str = new char[s._capacity + 1];         //    memcpy(_str, s._str, s._size + 1);         //    _size = s._size;         //    _capacity = s._capacity;         //}         //拷贝构造的现代写法         string(const string& s)             :_str(nullptr)             ,_size(0)             ,_capacity(0)         {             string tmp(s._str);             swap(tmp);         }         //下面两个函数建议加const         const char* c_str()const         {             return _str;         }         //遍历string         size_t size()const         {             return _size;         }         //operator[]有两个版本,意义是不一样的,普通对象调用第一个,能读能写,const对象调用第二个,只能读。         char& operator[](size_t pos)         {             assert(pos < _size);             return _str[pos];         }         const char& operator[](size_t pos)const         {             assert(pos < _size);             return _str[pos];         }         //增删查改         //这里的扩容逻辑用reserve就可以         void reserve(size_t n)         {             cout << "reserve->" << n << endl;             if (n > _capacity)             {                 char* tmp = new char[n + 1];                 //strcpy(tmp, _str);                 memcpy(tmp, _str, _size + 1);                 delete[] _str;                 _str = tmp;                 _capacity = n;             }         }         void push_back(char ch)         {             if (_size == _capacity)             {                 //二倍扩容                 reserve(_capacity == 0 ? 4 : _capacity * 2);             }             _str[_size++] = ch;             _str[_size] = '\0';         }         void append(const char* str)         {             size_t len = strlen(str);             if (_size + len > _capacity)             {                 //至少扩容到_size + len                 reserve(_size + len);             }             //strcpy(_str + _size, str);             memcpy(_str + _size, str, len + 1);             _size += len;         }         string& operator+=(const char str)         {             push_back(str);             return *this;         }         string& operator+=(const char* str)         {             append(str);             return *this;         }         void insert(size_t pos, size_t n, char ch)         {             assert(pos <= _size);             if (_size + n > _capacity)             {                 //至少扩容到_size + len                 reserve(_size + n);             }             //挪动数据             size_t end = _size;             while (end >= pos && end != npos)             {                 _str[end + n] = _str[end];                 end--;             }             for (size_t i = 0; i < n; i++)             {                 _str[pos + i] = ch;             }             _size += n;         }         void insert(size_t pos, const char* str)         {             assert(pos <= _size);             size_t len = strlen(str);             if (_size + len > _capacity)             {                 //至少扩容到_size + len                 reserve(_size + len);             }             //挪动数据             size_t end = _size;             while (end >= pos && end != npos)             {                 _str[end + len] = _str[end];                 end--;             }             for (size_t i = 0; i < len; i++)             {                 _str[pos + i] = str[i];             }             _size += len;         }         ~string()         {             if(_str)             {                 delete[] _str;                 _str = nullptr;                 _size = _capacity = 0;             }         }         void erase(size_t pos, size_t len = npos)         {             assert(pos <= _size);             if (len == npos || len + pos >= _size)             {                 _str[pos] = '\0';                 _size = pos;                 _str[_size] = '\0';             }             else             {                 size_t end = pos + len;                 while (pos <= _size)                 {                     _str[pos++] = _str[end++];                 }                 _size -= len;             }         }         size_t find(char ch, size_t pos = 0)         {             assert(pos < _size);             for (size_t i = pos; i < _size; i++)             {                 if (_str[i] == ch)                  {                     return i;                 }             }             //没有找到的话,返回的都是npos             return npos;         }         size_t find(const char* str, size_t pos = 0)         {             assert(pos < _size);             //暴力匹配             const char* ptr = strstr(_str + pos, str);             if (ptr)             {                 return ptr - _str;             }             else             {                 return npos;             }         }         string substr(size_t pos = 0, size_t len = npos)         {             size_t n = len;             if (len == npos || len + pos > _size)             {                 n = _size - pos;             }             string tmp;             tmp.reserve(n);             for (size_t i = pos; i < pos + n; i++)             {                 tmp += _str[i];             }             return tmp;         }         void resize(size_t n, char ch = '\0')         {             if (n < _size)             {                 _size = n;                 _str[_size] = '\0';             }             else             {                 reserve(n);                 for (size_t i = _size; i < n; i++)                 {                     _str[i] = ch;                 }                 _size = n;                 _str[_size] = '\0';             }         }         void clear()         {             _str[0] = '\0';             _size = 0;         }         bool operator<(const string& s) const         {             //size_t i1 = 0;             //size_t i2 = 0;             //while (i1 < _size && i2 < _size)             //{             //    if (_str[i1] < s._str[i2])             //    {             //        return true;             //    }             //    else if (_str[i1] > s._str[i2])             //    {             //        return false;             //    }             //    else             //    {             //        i1++;             //        i2++;             //    }             //}             if (i1 == _size && i2 != s._size)             {                 return true;             }             else             {                 return false;             }             //return i1 == _size && i2 != s._size;             //下面的代码也可以实现             int ret = memcmp(_str, s._str, _size < s._size ? _size : s._size);             return ret == 0 ? _size < s._size : ret < 0;         }         bool operator==(const string& s) const         {             return _size == s._size &&                 memcmp(_str, s._str, _size) == 0;         }         bool operator<=(const string& s) const         {             return *this == s || *this < s;         }         bool operator>(const string& s) const         {             return !(*this <= s);         }         bool operator>=(const string& s) const         {             return !(*this < s);         }         bool operator!=(const string& s) const         {             return !(*this == s);         }         ///传统写法         //string& operator=(const string& s)         //{         //    if (this == &s)         //    {         //        char* tmp = new char[s._capacity + 1];         //        memcpy(tmp, s._str, s._size + 1);         //        delete[] _str;         //        _str = tmp;         //        _size = s._size;         //        _capacity = s._capacity;         //    }         //    return *this;         //}             //上面的代码用现代的写法         void swap(string& s)         {             std::swap(_str, s._str);             std::swap(_size,s._size);             std::swap(_capacity,s._capacity);         }         //string& operator=(const string& s)         //{         //    if (this != &s)         //    {         //        string tmp(s);         //        swap(tmp);         //    }         //    return *this;         //}         string& operator=(string tmp)         {             swap(tmp);             return *this;         }     private:         char* _str;         size_t _size;         size_t _capacity;     public:         static size_t npos;//静态成员变量不走初始化列表,它不属于某一个类,而是属于整个类         //下面这个可以不用定义,但本质还是缺省值         //const static size_t npos = -1;         //const static的整型是可以的,double不可以         //const static double x = 1.1;         const static double x;     };     ostream& operator<<(ostream& out, const string& s)     {         //for (size_t i = 0; i < s.size(); i++)         //{         //    out << s[i];         //}         for (auto ch : s)         {             cout << ch;         }         return out;     }     istream& operator>>(istream& in, string& s)     {         s.clear();         char ch = in.get();         //char ch;         //in >> ch;         //处理缓冲区前面的空格或者换行         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;             }             //in >> ch;             ch = in.get();         }         if (i != 0)         {             buff[i] = '\0';             s += buff;         }         return in;     }     size_t string::npos = -1;     const double string::x = 1.1; }; //ostream& operator<<(ostream& out, const bit::string& s) //{ //    //for (size_t i = 0; i < s.size(); i++) //    //{ //    //    out << s[i]; //    //} //    for (auto ch : s) //    { //        cout << ch; //    } //    return out; //}

text.cpp #include"string.h" void test_string1() {     bit::string s1("hello world");     cout << s1.c_str() << endl;     bit::string s2;     cout << s2.c_str() << endl;     for (size_t i = 0; i < s1.size(); i++)     {         ++s1[i];         --s1[i];     }     for (size_t i = 0; i < s1.size(); i++)     {         cout << s1[i];     }     cout << endl;     const bit::string s3("hello world");     s3[0];     //iterator要指定类域,如果没有指定会去全局去找iterator这个东西     bit::string::const_iterator it = s3.begin();     while (it != s3.end())     {         cout << *it;         it++;     }     cout << endl;     for (auto e : s3)     {         cout << e;     } } void test_string2() {     bit::string s1("hello world");     cout << s1.c_str() << endl;     //s1.push_back(' ');     //s1.push_back('#');     //s1.push_back('%');     //s1.append("hello lsw");     //s1.append("hello xsq");     //cout << s1.c_str() << endl;     s1 += ' ';     s1 += '#';     s1 += '%';     s1 += "hello world";     cout << s1.c_str() << endl; } void test_string3() {     bit::string s1("hello world");     cout << s1.c_str() << endl;     s1.insert(0, 3, '#');     cout << s1.c_str() << endl;     bit::string s2("helloworld");     s2.insert(5, "%%%%%");     cout << s2.c_str() << endl; } void test_string4() {     bit::string s1("hello world");     cout << s1.c_str() << endl;     s1.erase(5, 3);     cout << s1.c_str() << endl;         s1.erase(5, 30);     cout << s1.c_str() << endl;     s1.erase(2);     cout << s1.c_str() << endl; } void test_string5() {     // 2118     bit::string url = "ftp://www.baidu.com/?tn=65081411_1_oem_dg";     size_t pos1 = url.find("://");     if (pos1 != bit::string::npos)     {         bit::string protocol = url.substr(0, pos1);         cout << protocol.c_str() << endl;     }     size_t pos2 = url.find('/', pos1 + 3);     if (pos2 != bit::string::npos)     {         bit::string domain = url.substr(pos1 + 3, pos2 - (pos1 + 3));         bit::string uri = url.substr(pos2 + 1);         cout << domain.c_str() << endl;         cout << uri.c_str() << endl;     } } void test_string6() {     bit::string s("hello world");     //s.resize(8);     //cout << s.c_str() << endl;     //s.resize(13, 'x');     //cout << s.c_str() << endl;     //s.resize(20, 'y');     s.resize(8);     cout << s << endl;     s.resize(13, 'x');     cout << s << endl;     s.resize(20, 'y');     cout << s << endl;     bit::string ss("hello world");     ss += '\0';     ss += "!!!!!!!!";     cout << ss.c_str() << endl;     cout << ss << endl;     bit::string copy(ss);     cout << ss << endl;     cout << copy << endl;     copy += "xxxxxxxxxxxxxx";     cout << copy << endl; } void test_string7() {     bit::string s;     cin >> s;     cout << s << endl;         cin >> s;     cout << s << endl; } void test_string8() {     //bit::string s1("bbb");     //bit::string s2("aaa");     //cout << (s1 < s2) << endl;     bit::string s1("hello");     bit::string s2("hello");     cout << (s1 < s2) << endl;     cout << (s1 > s2) << endl;     cout << (s1 == s2) << endl << endl;     bit::string s3("hello");     bit::string s4("helloxxx");     cout << (s3 < s4) << endl;     cout << (s3 > s4) << endl;     cout << (s3 == s4) << endl << endl;     bit::string s5("helloxxx");     bit::string s6("hello");     cout << (s5 < s6) << endl;     cout << (s5 > s6) << endl;     cout << (s5 == s6) << endl << endl; } void test_string9() {     bit::string s1("hello");     bit::string s2(s1);     cout << s1 << endl;     cout << s2 << endl;     bit::string s3("xxxxxxxxxxxxx");     s1 = s3;     cout << s1 << endl;     cout << s3 << endl; } int main() {     test_string9();     return 0; }

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-11-13,如有侵权请联系 cloudcommunity@tencent.com 删除
目录
  • 3. string类的模拟实现
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档