• 全新力作—C++ string类的模拟实现


    引言:本篇文章主要实现一个自定义字符串类string,包括了字符串的基本操作,如拷贝构造、赋值、添加、删除、查找等,还实现了迭代器,支持基本的 STL 算法。

    1.  构造函数:

    • 默认构造函数
    • 从C字符串构造
    • 拷贝构造函数

    2.  析构函数

    • 在析构函数中释放内存

    3.  访问和修改元素函数:

    • c_str() 返回C字符串
    • size() 返回字符串大小
    • capacity() 返回容量
    • operator[] 访问单个字符

    4  查找子串

    • find() 从某个位置查找字串

    5.  迭代器相关:

    • begin()  返回开始迭代器
    • end()  返回结束迭代器

    6.  修改容量相关:

    • push_back() 尾部插入字符
    • append() 尾部插入字符串
    • reserve() 预留空间
    • resize() 重新设置字串的大小

    7.  重载运算符:

    • 实现+=操作符的重载,用于字符串拼接
    • 实现=操作符的重载,用于字符串赋值
    • 重载输出运算符 << 打印字符串

    8.  insert()

    • 插入字符

    9.  erase()

    • 删除从某个位置后面某长度的字符

    10. swap()

    • 交换两个字符串的值

    头文件“my_string.h”:

    1. #include
    2. #include
    3. #include
    4. using std::cout;
    5. using std::endl;
    6. using std::cin;
    7. class string{
    8. public:
    9. typedef char* iterator; // 定义迭代器类型
    10. // 构造函数
    11. string(const char* str ="");
    12. string(const string& str);
    13. // 析构函数
    14. ~string();
    15. // 返回C风格字符串
    16. char* c_str();
    17. // 返回字符串长度
    18. int size()const;
    19. // 返回容量
    20. int capacity()const;
    21. // 字符访问运算符
    22. char& operator[](int n);
    23. const char& operator[](int n)const;
    24. // 获取首尾迭代器
    25. iterator begin();
    26. iterator end();
    27. // 在尾部插入字符
    28. void push_back(char c);
    29. // 连接字符串
    30. string& append(const string& str);
    31. string& append(const char* s);
    32. // 扩容
    33. void reserve(size_t n = 0);
    34. // +=运算符重载
    35. string& operator+=(const char c);
    36. string& operator+=(const char* s);
    37. string& operator+=(const string& str);
    38. // 在pos位置插入字符串
    39. string& insert (size_t pos, const char* s);
    40. string& insert (size_t pos, const string& str);
    41. // 在迭代器p位置插入字符
    42. iterator insert (iterator p, char c);
    43. // 查找子串
    44. size_t find (const char* s, size_t pos = 0) const;
    45. size_t find (const string* str,size_t pos = 0) const;
    46. // 删除字符串的一部分
    47. string& erase (size_t pos = 0, size_t len = npos);
    48. // 赋值运算符重载
    49. string& operator= (const string& str);
    50. string& operator= (const char* s);
    51. string& operator= (char c);
    52. // 改变字符串长度
    53. void resize (size_t n, char c='\0');
    54. // 交换两个字符串内容
    55. void swap(string& str);
    56. private:
    57. char* _str; // 用于保存字符串
    58. int _size; // 字符串长度
    59. int _capacity; // 容量
    60. static const size_t npos = -1; // 表示找不到
    61. };
    62. // 输出运算符重载
    63. std::ostream& operator<< (std::ostream& out,const string& s);

    my_string.cpp

    1. #include "my_string.h"
    2. string::string(const char* str){
    3. _str = new char[strlen(str)+1];
    4. strcpy(_str,str);
    5. _size = strlen(str);
    6. _capacity = _size;
    7. }
    8. string::string(const string& str)
    9. :_str(nullptr)
    10. {
    11. if(&str != this){
    12. char* tmp = new char[str._size+1];
    13. strcpy(tmp,str._str);
    14. delete []_str;
    15. _str = tmp;
    16. _size = str._size;
    17. _capacity = _size;
    18. }
    19. }
    20. string::~string(){
    21. delete []_str;
    22. _str = nullptr;
    23. _size = 0;
    24. _capacity = 0;
    25. }
    26. char* string::c_str(){
    27. return _str;
    28. }
    29. int string::size()const{
    30. return _size;
    31. }
    32. int string::capacity()const{
    33. return _capacity;
    34. }
    35. char& string::operator[](int n){
    36. assert(n<_size);
    37. return *(_str+n);
    38. }
    39. const char& string::operator[](int n)const{
    40. assert(n<_size);
    41. return *(_str+n);
    42. }
    43. string::iterator string::begin(){
    44. return _str;
    45. }
    46. string::iterator string::end(){
    47. return _str+_size;
    48. }
    49. void string::push_back(char c){
    50. if(_size == _capacity){//需要扩容
    51. _capacity++;
    52. char* tmp = new char[_capacity+1];
    53. strcpy(tmp,_str);
    54. delete [] _str;
    55. _str = tmp;
    56. }
    57. _str[_size] = c;//放入元素
    58. _size++;
    59. _str[_size] = '\0';//插入元素后放一个\0
    60. }
    61. string& string::append(const string& str){
    62. if(_size + str.size() > _capacity){//需要扩容
    63. reserve(str.size()+_size);//调用reserve,复用
    64. }
    65. for(int i = 0;isize();i++){//也可以使用strcpy
    66. _str[_size++] = str[i];
    67. }
    68. _str[_size] ='\0';
    69. return *this;
    70. }
    71. string& string::append(const char* s){
    72. int s_size = strlen(s);
    73. if(s_size+_size > _capacity){
    74. reserve(s_size + _size);
    75. }
    76. strcpy(_str + _size,s);
    77. _size += s_size;
    78. return *this;
    79. }
    80. void string::reserve(size_t n ){
    81. char *tmp = new char[n+1];
    82. strcpy(tmp,_str);
    83. delete [] _str;
    84. _str = tmp;
    85. _capacity = n;
    86. }
    87. string& string::operator+=(const char c){
    88. push_back(c);
    89. return *this;
    90. }
    91. string& string::operator+=(const char* s){
    92. append(s);
    93. return *this;
    94. }
    95. string& string::operator+=(const string& str){
    96. append(str);
    97. return *this;
    98. }
    99. string::iterator string::insert(string::iterator p,char c){
    100. assert( p <= end());
    101. int pos = p - begin();
    102. if(_size+1>_capacity){//扩容
    103. reserve(_size+1);
    104. }
    105. p = _str + pos;
    106. for(string::iterator it = end()-1;it >= p;it--){//往后面移
    107. *(it+1) = *it;
    108. }
    109. *p = c;
    110. _size ++;
    111. return p;
    112. }
    113. string& string::insert(size_t pos,const char* s){
    114. assert(pos<=_size);
    115. int s_len = strlen(s);
    116. if(s_len+_size>_capacity){
    117. reserve(_size+s_len);
    118. }
    119. for(int i = _size;i >= (int)pos;i--){
    120. _str[i+s_len] = _str[i];
    121. }
    122. for(int i = 0;i
    123. _str[pos++] = s[i];
    124. }
    125. _size = _size+s_len;
    126. return *this;
    127. }
    128. string& string::insert(size_t pos,const string&str){
    129. const char* s = str._str;
    130. return insert(pos,s);
    131. }
    132. size_t string::find (const char* s,size_t pos)const{
    133. assert(pos<=_size);
    134. int s_len = strlen(s);
    135. for(int i = pos;i<_size;i++){
    136. int flag = 0;//用于判断是否找到字串
    137. for(int j = 0;j
    138. if(i<_size && s[j] != _str[i+j]){
    139. flag =1;
    140. break;
    141. }
    142. }
    143. if(flag == 0) return i;
    144. }
    145. return npos;
    146. }
    147. size_t string::find (const string* str,size_t pos) const{
    148. char* s = str->_str;
    149. return find(s,pos);//复用
    150. }
    151. string& string::erase(size_t pos,size_t len){
    152. assert(pos<_size);//不能在'\0'位置之后的删除
    153. if(len>=(size_t)_size-pos){
    154. _size = pos;
    155. _str[_size] = '\0';
    156. }else{
    157. for(int i = pos;i<=_size-(int)len;i++){
    158. _str[i] = _str[i+len];
    159. }
    160. _size = _size - len;
    161. }
    162. return *this;
    163. }
    164. string& string::operator=(const char* s){
    165. assert(s);
    166. int s_len = strlen(s);
    167. reserve(s_len);
    168. strcpy(_str,s);
    169. _size = s_len;
    170. return *this;
    171. }
    172. string& string::operator=(const string& str){
    173. return operator=(str._str);
    174. }
    175. string& string::operator=(char c){
    176. reserve(1);
    177. _str[0] = c;
    178. _str[1] = '\0';
    179. _size = 1;
    180. return *this;
    181. }
    182. void string::resize(size_t n,char c){
    183. if((int)n>_size){
    184. reserve(n);
    185. for(int i = _size;i<(int)n;i++){
    186. _str[i] = c;
    187. }
    188. _size = n;
    189. _str[_size]='\0';
    190. }else if((int)n>=0&&(int)n<_size){
    191. erase(n);
    192. }
    193. }
    194. void string::swap(string& str){
    195. if(&str == this) return;//如果交换自己直接返回
    196. char* tmp = str._str;
    197. str._str = _str;
    198. _str = tmp;
    199. int tmp_s = str._size;
    200. int tmp_c = str._capacity;
    201. str._size = _size;
    202. _size = tmp_s;
    203. str._capacity = _capacity;
    204. _capacity = tmp_c;
    205. }
    206. std::ostream& operator<< (std::ostream& out,const string& s){
    207. for(int i = 0;isize();i++){
    208. out<
    209. }
    210. return out;
    211. }

    main.cpp

    1. #include "my_string.h"
    2. void test01(){
    3. string s1("ssssss");
    4. string s2;
    5. string s3(s1);
    6. cout<
    7. for(auto e: s1){
    8. cout<" ";
    9. }
    10. cout<
    11. s1.push_back('a');
    12. s1.push_back(' ');
    13. s1.append("xiaomi ");
    14. s1.append(s3);
    15. cout<< s1<
    16. s1 +="hhhh";
    17. s1 +=' ';
    18. s1 += s3;
    19. cout<
    20. s1.insert(s1.begin()+2,'c');
    21. cout<
    22. s3.insert(s3.end()-1,'a');
    23. cout<
    24. s3.insert(7,"xiaomi");
    25. cout<
    26. s3.insert(1,s1);
    27. cout<
    28. int i = s3.find("xiwmi");
    29. cout<
    30. string s4 = "xiaomi";
    31. cout<< s3.find(&s4)<
    32. s4.erase(3,3);
    33. cout<
    34. s4 = "hyper os";
    35. cout << s4 << endl;
    36. string s5;
    37. s5 = s4;
    38. cout<
    39. s5 = 'o';
    40. cout<
    41. s4.resize(11,'6');
    42. cout<
    43. s1.resize(6);
    44. cout<
    45. s1.swap(s4);
    46. cout<
    47. cout<
    48. }
    49. int main(){
    50. test01();
    51. }

    测试结果: 

  • 相关阅读:
    【Deep Learning 1】遗传算法GA
    在MySQL中查看数据库和表的数据大小
    (Mybatis笔记)Mybatis配置文件和映射模板——SqlMapConfig.xml和Mapper.xml
    机动目标跟踪——当前统计模型(CS模型)
    项目通用Makefile的编写(包含Makefile.build文件分析)
    基于Ant Design设计语言的WinForm UI界面库
    Python数据分析-Pandas
    Ubuntu下QT操作Mysql数据库
    管理区解耦架构见过吗?能帮客户搞定大难题的
    [Linux] vim及gdb的使用
  • 原文地址:https://blog.csdn.net/weixin_56821642/article/details/133888020