当前位置:   article > 正文

C++中string类的实现_c++ string代码实现

c++ string代码实现

1.c++库中的string类

在c++的标准库中我们处理字符串的时候需要使用string类,库中的使用接口都非常方便。

 为了让我们更加了解有关库中的相关函数,我们需要自己来实现一遍。

2.string类的实现

2.1类的构造和析构函数

  1. string(const char* str = "")//构造函数
  2. {
  3. _size = strlen(str);
  4. _capacity = _size;
  5. _str = new char[_capacity + 1];
  6. memcpy(_str, str, _size + 1);
  7. }
  8. ~string()//析构函数
  9. {
  10. delete[] _str;
  11. _str = nullptr;
  12. _capacity = _size = 0;
  13. }

 在这里我们需要注意的是我们要使用c语言中的memcpy函数,因为在string类中的字符串是包含'\0'这样的字符的,而在c语言中,规则就是遇到\0就会停止,所以需要以string类中的size为准。

2.2运算符的重载

  1. char& operator[](size_t pos)
  2. {
  3. assert(pos < _size);
  4. return _str[pos];
  5. }
  6. const char& operator[](size_t pos) const
  7. {
  8. assert(pos < _size);
  9. return _str[pos];
  10. }
  11. string& operator+=(char ch)
  12. {
  13. push_back(ch);
  14. return *this;
  15. }
  16. string& operator+=(const char* str)
  17. {
  18. append(str);
  19. return *this;
  20. }

这里实现的是字符串的下标取值和字符串的添加,在字符串的函数添加中我们复用了push_back和append函数。

具体实现如下:

  1. void push_back(char ch)
  2. {
  3. if (_size == _capacity)
  4. {
  5. reserve(_capacity == 0 ? 4 : _capacity * 2);
  6. }
  7. _str[_size] = ch;
  8. _size++;
  9. _str[_size] = '\0';
  10. }
  11. void append(const char* str)
  12. {
  13. size_t len = strlen(str);
  14. if (len + _size > _capacity)
  15. reserve((len + _size) + 2);
  16. memcpy(_str + _size, str,len+1);
  17. _size += len;
  18. }

不管是尾插函数的实现还是扩展字符串的函数实现,我们都需要给字符串在必要的时候扩容,而这里在c++的标准库中提供一个叫reserve的函数,那我们就可以来实现一下。

  1. void reserve(size_t n)
  2. {
  3. if (n > _capacity)
  4. {
  5. char* tmp = new char[n];
  6. memcpy(tmp, _str,n);
  7. delete[] _str;
  8. _str = tmp;
  9. _capacity = n;
  10. }
  11. }

这个函数就是在堆上开辟空间的,申请过后给一个临时指针,临时指针给str。

2.3迭代器的实现

  1. typedef char* iterator;
  2. typedef const char* const_iterator;
  3. iterator end()
  4. {
  5. return _str + _size;
  6. }
  7. iterator begin()
  8. {
  9. return _str;
  10. }
  11. const_iterator end() const
  12. {
  13. return _str + _size;
  14. }
  15. const_iterator begin() const
  16. {
  17. return _str;
  18. }

string的迭代器就是指针的变型,所以当我们使用范围for也是可以的。

2.4流提取和流插入的重载

  1. ostream& operator<< (ostream& out, const string& s)//无法改变的字符串,所以需要加const
  2. {
  3. for (auto ch : s)
  4. {
  5. out << ch;
  6. }
  7. return out;
  8. }
  9. istream& operator >>(istream& in, string& s)//输入的字符
  10. {
  11. s.clear();
  12. char ch = in.get();
  13. //消除字符缓存区的字符
  14. while (ch == ' ' || ch == '\n')
  15. {
  16. ch = in.get();
  17. }
  18. char buff[128];
  19. size_t i = 0;
  20. while (ch != ' ' && ch != '\n')
  21. {
  22. buff[i++] = ch;
  23. if (i == 127)
  24. {
  25. buff[i] = '\0';
  26. s += buff;
  27. i = 0;
  28. }
  29. ch = in.get();
  30. }
  31. if (i != 0)
  32. {
  33. buff[i] = '\0';
  34. s += buff;
  35. }
  36. return in;

在之前的流提取的函数中,我们使用这个buff数组可以减少扩容的次数,是一种比较好的优化方案,只要buff数组被填满之后,我们就需要给重新置空,不会多次扩容。

2.5增删查改

  1. void erase(size_t pos, size_t len = npos)
  2. {
  3. assert(pos <= _size);
  4. if (len == npos || len + pos >= _size)
  5. {
  6. _str[pos] = '\0';
  7. _size = pos;
  8. _str[_size] = '\0';
  9. }
  10. else
  11. {
  12. size_t end = len + pos;
  13. while (end <= _size)
  14. {
  15. _str[pos++] = _str[end++];
  16. }
  17. _size -= len;
  18. }
  19. }
  20. size_t find(char ch, size_t pos = npos)
  21. {
  22. assert(pos <= _size);
  23. for (size_t i = pos; i < _size; i++)
  24. {
  25. if (ch == _str[i])
  26. return i;
  27. }
  28. return npos;
  29. }
  30. size_t find(const char* str, size_t pos = 0)
  31. {
  32. assert(pos < _size);
  33. const char* ptr = strstr(_str + pos, str);
  34. if (ptr)
  35. {
  36. return ptr - _str;
  37. }
  38. else
  39. return npos;
  40. }
  41. string substr(size_t pos = 0, size_t len = npos)
  42. {
  43. assert(pos < _size);
  44. size_t n = len;
  45. if (len == npos || pos + len > _size)
  46. {
  47. n = _size - pos;
  48. }
  49. string tmp;
  50. tmp.reserve(n + 2);
  51. for (size_t i = pos; i < pos + n; i++)
  52. {
  53. tmp += _str[i];
  54. }
  55. return tmp;
  56. }
  57. void insert(size_t pos, size_t n, char ch)
  58. {
  59. assert(pos < _size);
  60. if (n + _size >= _capacity)
  61. reserve(n + _size + 2);
  62. int end = _size;
  63. //挪动数据
  64. while ((int)pos <= end)//当end减小到最小时会转换成很大的数,这里会隐式转换。//while(pos<=end&&end!=npos)
  65. {
  66. _str[end + n] = _str[end];
  67. end--;
  68. }
  69. for (size_t i = 0; i < n; i++)
  70. {
  71. _str[pos + i] = ch;
  72. }
  73. _size += n;
  74. }
  75. void insert(size_t pos, const char* str)
  76. {
  77. assert(pos < _size);
  78. size_t len = strlen(str);
  79. size_t end = _size;
  80. if (len + _size > _capacity)
  81. {
  82. reserve(len + _size + 2);
  83. }
  84. while (pos <= end && end != npos)
  85. {
  86. _str[end + len] = _str[end];
  87. end--;
  88. }
  89. for (size_t i = 0; i < len; i++)
  90. {
  91. _str[pos + i] = str[i];
  92. }
  93. _size += len;
  94. }

这里就是简单的函数实现的数据插入和查找,唯一需要注意的是insert的size_t和int的强转。

2.6字符串大小的比较函数重载

这一系列的函数其实只需要写几个函数,其余的只需要逻辑的互斥性就可以实现,非常容易。

  1. bool operator < (const string & s) const
  2. {
  3. int ret = memcmp(_str, s._str, _size < s._size ? _size : s._size);//这里比较字符串的大小,将小的字符串长度来进行比较
  4. return ret == 0 ? _size < s._size : ret < 0;//如果比较的长度一样长,注意三种情况
  5. //"world"
  6. //"world" false
  7. //"world"
  8. //"worldxxx" true
  9. //"worldxxx"
  10. //"world" false 只有一种情况为真,_size<s._size
  11. }
  12. bool operator ==(const string& s) const
  13. {
  14. return _size == s._size &&
  15. memcmp(_str, s._str, s._size) == 0;
  16. }
  17. bool operator <=(const string& s)const
  18. {
  19. return *this < s || *this == s;
  20. }
  21. bool operator >(const string& s) const
  22. {
  23. return !(*this <= s);
  24. }
  25. bool operator >=(const string& s)const
  26. {
  27. return !(*this < s);
  28. }

3.总代码

  1. #pragma once
  2. #include<iostream>
  3. #include<assert.h>
  4. using namespace std;
  5. namespace mystring
  6. {
  7. class string
  8. {
  9. public:
  10. /*string(const char* str="")
  11. :_size(strlen(str))
  12. ;_capacity(_size)
  13. ;_str(new char[_capacity + 1])
  14. {
  15. strcpy(_str, str);
  16. }*/
  17. string(const char* str = "")//构造函数
  18. {
  19. _size = strlen(str);
  20. _capacity = _size;
  21. _str = new char[_capacity + 1];
  22. memcpy(_str, str, _size + 1);
  23. }
  24. string(const string& str) //拷贝构造函数
  25. {
  26. _str = new char[str._capacity + 1];
  27. //strcpy(_str, str._str);
  28. memcpy(_str, str._str, str._size + 1);
  29. _size = str._size;
  30. _capacity = str._capacity;
  31. }
  32. void swap(string &s)
  33. {
  34. std::swap(_size, s._size);
  35. std::swap(_capacity, s._capacity);
  36. std::swap(_str, s._str);
  37. }
  38. string& operator =( string tmp)
  39. {
  40. swap(tmp);
  41. return *this;
  42. }
  43. ~string()//析构函数
  44. {
  45. delete[] _str;
  46. _str = nullptr;
  47. _capacity = _size = 0;
  48. }
  49. const char* c_str()const
  50. {
  51. return _str;
  52. }
  53. size_t size() const
  54. {
  55. return _size;
  56. }
  57. char& operator[](size_t pos)
  58. {
  59. assert(pos < _size);
  60. return _str[pos];
  61. }
  62. const char& operator[](size_t pos) const
  63. {
  64. assert(pos < _size);
  65. return _str[pos];
  66. }
  67. void reserve(size_t n)
  68. {
  69. if (n > _capacity)
  70. {
  71. char* tmp = new char[n];
  72. memcpy(tmp, _str,n);
  73. delete[] _str;
  74. _str = tmp;
  75. _capacity = n;
  76. }
  77. }
  78. void push_back(char ch)
  79. {
  80. if (_size == _capacity)
  81. {
  82. reserve(_capacity == 0 ? 4 : _capacity * 2);
  83. }
  84. _str[_size] = ch;
  85. _size++;
  86. _str[_size] = '\0';
  87. }
  88. void append(const char* str)
  89. {
  90. size_t len = strlen(str);
  91. if (len + _size > _capacity)
  92. reserve((len + _size) + 2);
  93. memcpy(_str + _size, str,len+1);
  94. _size += len;
  95. }
  96. string& operator+=(char ch)
  97. {
  98. push_back(ch);
  99. return *this;
  100. }
  101. string& operator+=(const char* str)
  102. {
  103. append(str);
  104. return *this;
  105. }
  106. void insert(size_t pos, size_t n, char ch)
  107. {
  108. assert(pos < _size);
  109. if (n + _size >= _capacity)
  110. reserve(n + _size + 2);
  111. int end = _size;
  112. //挪动数据
  113. while ((int)pos <= end)//当end减小到最小时会转换成很大的数,这里会隐式转换。//while(pos<=end&&end!=npos)
  114. {
  115. _str[end + n] = _str[end];
  116. end--;
  117. }
  118. for (size_t i = 0; i < n; i++)
  119. {
  120. _str[pos + i] = ch;
  121. }
  122. _size += n;
  123. }
  124. void insert(size_t pos, const char* str)
  125. {
  126. assert(pos < _size);
  127. size_t len = strlen(str);
  128. size_t end = _size;
  129. if (len + _size > _capacity)
  130. {
  131. reserve(len + _size + 2);
  132. }
  133. while (pos <= end && end != npos)
  134. {
  135. _str[end + len] = _str[end];
  136. end--;
  137. }
  138. for (size_t i = 0; i < len; i++)
  139. {
  140. _str[pos + i] = str[i];
  141. }
  142. _size += len;
  143. }
  144. typedef char* iterator;
  145. typedef const char* const_iterator;
  146. iterator end()
  147. {
  148. return _str + _size;
  149. }
  150. iterator begin()
  151. {
  152. return _str;
  153. }
  154. const_iterator end() const
  155. {
  156. return _str + _size;
  157. }
  158. const_iterator begin() const
  159. {
  160. return _str;
  161. }
  162. void erase(size_t pos, size_t len = npos)
  163. {
  164. assert(pos <= _size);
  165. if (len == npos || len + pos >= _size)
  166. {
  167. _str[pos] = '\0';
  168. _size = pos;
  169. _str[_size] = '\0';
  170. }
  171. else
  172. {
  173. size_t end = len + pos;
  174. while (end <= _size)
  175. {
  176. _str[pos++] = _str[end++];
  177. }
  178. _size -= len;
  179. }
  180. }
  181. size_t find(char ch, size_t pos = npos)
  182. {
  183. assert(pos <= _size);
  184. for (size_t i = pos; i < _size; i++)
  185. {
  186. if (ch == _str[i])
  187. return i;
  188. }
  189. return npos;
  190. }
  191. size_t find(const char* str, size_t pos = 0)
  192. {
  193. assert(pos < _size);
  194. const char* ptr = strstr(_str + pos, str);
  195. if (ptr)
  196. {
  197. return ptr - _str;
  198. }
  199. else
  200. return npos;
  201. }
  202. /*string substr(size_t pos=0, size_t len=npos)
  203. {
  204. assert(pos <= _size);
  205. size_t n=len;
  206. if (len == npos || pos + len >= _size)
  207. {
  208. n = _size - pos;
  209. }
  210. string tmp;
  211. reserve(n);
  212. for (int i = 0; i < n; i++)
  213. {
  214. tmp += _str[pos + i];
  215. }
  216. return tmp;
  217. }*/
  218. string substr(size_t pos = 0, size_t len = npos)
  219. {
  220. assert(pos < _size);
  221. size_t n = len;
  222. if (len == npos || pos + len > _size)
  223. {
  224. n = _size - pos;
  225. }
  226. string tmp;
  227. tmp.reserve(n + 2);
  228. for (size_t i = pos; i < pos + n; i++)
  229. {
  230. tmp += _str[i];
  231. }
  232. return tmp;
  233. }
  234. void clear()
  235. {
  236. _str[_size] = '\0';
  237. _size = 0;
  238. }
  239. bool operator < (const string & s) const
  240. {
  241. int ret = memcmp(_str, s._str, _size < s._size ? _size : s._size);//这里比较字符串的大小,将小的字符串长度来进行比较
  242. return ret == 0 ? _size < s._size : ret < 0;//如果比较的长度一样长,注意三种情况
  243. //"world"
  244. //"world" false
  245. //"world"
  246. //"worldxxx" true
  247. //"worldxxx"
  248. //"world" false 只有一种情况为真,_size<s._size
  249. }
  250. bool operator ==(const string& s) const
  251. {
  252. return _size == s._size &&
  253. memcmp(_str, s._str, s._size) == 0;
  254. }
  255. bool operator <=(const string& s)const
  256. {
  257. return *this < s || *this == s;
  258. }
  259. bool operator >(const string& s) const
  260. {
  261. return !(*this <= s);
  262. }
  263. bool operator >=(const string& s)const
  264. {
  265. return !(*this < s);
  266. }
  267. static const size_t npos;
  268. private:
  269. size_t _size;
  270. size_t _capacity;
  271. char* _str;
  272. };
  273. const size_t string::npos = -1;
  274. //实现流的提取和插入
  275. ostream& operator<< (ostream& out, const string& s)//无法改变的字符串,所以需要加const
  276. {
  277. for (auto ch : s)
  278. {
  279. out << ch;
  280. }
  281. return out;
  282. }
  283. istream& operator >>(istream& in, string& s)//输入的字符
  284. {
  285. s.clear();
  286. char ch = in.get();
  287. //消除字符缓存区的字符
  288. while (ch == ' ' || ch == '\n')
  289. {
  290. ch = in.get();
  291. }
  292. char buff[128];
  293. size_t i = 0;
  294. while (ch != ' ' && ch != '\n')
  295. {
  296. buff[i++] = ch;
  297. if (i == 127)
  298. {
  299. buff[i] = '\0';
  300. s += buff;
  301. i = 0;
  302. }
  303. ch = in.get();
  304. }
  305. if (i != 0)
  306. {
  307. buff[i] = '\0';
  308. s += buff;
  309. }
  310. return in;
  311. }
  312. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/43821
推荐阅读
相关标签
  

闽ICP备14008679号