• 【C++--string模拟实现】


    一、基本思路

    新建一个项目,在项目中创建头文件string.h 源文件string.cpp

    在头文件中,先定义一个新的命名空间(为了防止与库中的string发生冲突),命名空间的名字可以按照自己意愿来命名。

    接下来就可以在命名空间中来模拟实现string类辣

    在实现的过程中可以多查查string::operator+= - C++ Reference (cplusplus.com)

    了解函数功能,然后再去实现 

    【1】确定成员变量: size_t _size; size_t _capacity; char* _str;

    【2】成员函数模拟实现

    (1)构造和析构函数

    1. string(const char* str = "")
    2. {
    3. _size = strlen(str);
    4. _capacity = _size;
    5. _str = new char[_size + 1];
    6. my_strcpy(_str, str);//完成初始化工作
    7. }
    8. ~string()
    9. {
    10. delete[] _str;
    11. _str = nullptr;
    12. _size = _capacity = 0;
    13. std::cout << "~string()" << std::endl;
    14. }

    (2)size()和capacity()

    1. size_t size()const
    2. {
    3. return _size;
    4. }
    5. size_t capacity()const
    6. {
    7. return _capacity;
    8. }

    (3)operator[ ]重载

    1. char& operator[](size_t pos)
    2. {
    3. assert(pos <= _size);
    4. return _str[pos];
    5. }

    (4)reserve()

    1. void reserve(size_t n = 0)
    2. {
    3. char* tmp = new char[n];//在堆区开辟空间,出函数不会销毁
    4. my_strcpy(tmp, _str);//由于有的vs使用strcpy会报错,所以可以用自己实现的strcpy
    5. delete[] _str;
    6. _str = tmp;
    7. _capacity = n;
    8. }

    (5)push_back()

    1. void push_back(char c)
    2. {
    3. if (_size == _capacity)
    4. {
    5. reserve(_capacity == 0 ? 6 : _capacity * 2);
    6. }
    7. _str[_size] = c;
    8. _size++;
    9. _str[_size] = '\0';
    10. }

    (6)operator+=的实现

    1. string& operator+= (char c)
    2. {
    3. push_back(c);
    4. return *this;
    5. }
    6. string& operator+= (const char* s)
    7. {
    8. size_t len = strlen(s);
    9. if (_size + len > _capacity)
    10. {
    11. reserve(_size + len+10);
    12. }
    13. append(s);
    14. return *this;
    15. }

    (7)append()

    1. string& append(const char* s)
    2. {
    3. size_t len = strlen(s);
    4. if (_size + len > _capacity)
    5. {
    6. reserve(_size + len + 10);
    7. }
    8. my_strcpy(_str + _size, s);
    9. return *this;
    10. }

    (8)c_str()

    1. const char* c_str()const
    2. {
    3. return _str;
    4. }

    (9)operator<<

    这个函数得在类外实现,因为在类内实现的话,默认第一个参数是this,那么在实际使用的时候对象名就得写在ostream的左边,与我们常规写法不一样。

    由于库中的_str是私有成员,因此可以通过调用函数c_str来获取_str

    1. std::ostream& operator<<(std::ostream& os, const abl::string& str)
    2. {
    3. os << str.c_str() ;
    4. return os;
    5. }

    (10)拷贝构造

    1. //现代写法
    2. string(const string& s)
    3. :_str(nullptr)
    4. ,_size(0)
    5. ,_capacity(0)
    6. {
    7. string tmp(s._str);//调用默认构造函数string(const char* str = "")
    8. swap(tmp);//this可能没有初始化,析构的时候就会报错,因此要写参数初始化列表
    9. }
    10. //string(const string& s)
    11. //{
    12. // _str = new char[s._capacity + 1];
    13. // memcpy(_str, s._str, s._size);
    14. // _size = s._size;
    15. // _capacity = s._capacity;
    16. //}

    (11)insert

    1. string& insert(size_t pos, size_t n, char c)
    2. {
    3. assert(pos <= _size);
    4. if (_size + n > _capacity)
    5. {
    6. reserve(_size + n);
    7. }
    8. size_t end = _size+n;
    9. for (; end>=pos+n; end--)
    10. {
    11. //abcd size==4 pp n==2 end==6 end-n==4
    12. _str[end] = _str[end-n];
    13. }
    14. for (size_t i = 0; i < n; i++)
    15. {
    16. _str[pos + i] = c;
    17. }
    18. _size += n;
    19. return *this;
    20. }
    21. string& insert(size_t pos, const char* s, size_t n)
    22. {
    23. assert(pos <= _size);
    24. size_t len = strlen(s);
    25. if (_size + n > _capacity)
    26. {
    27. reserve(_size + n);
    28. }
    29. size_t end = _size + n;
    30. for (; end >= pos + n; end--)//当pos==0时,end>=pos恒成立,因为end为size_t类型,不可能是负数
    31. {
    32. //abcd size==4 pp n==2 end==6 end-n==4
    33. _str[end] = _str[end - n];
    34. }
    35. for (size_t i = 0; i < n; i++)
    36. {
    37. _str[pos + i] = s[i];
    38. }
    39. _size += n;
    40. return *this;
    41. }

    二、完整代码

    1、string.h
    1. #pragma once
    2. #include
    3. #include
    4. #include
    5. #include
    6. //#include
    7. void my_strcpy(char* dest, const char* src) {
    8. while (*src != '\0') {
    9. *dest++ = *src++;
    10. }
    11. *dest = *src; //拷贝\0
    12. }
    13. namespace abl
    14. {
    15. class string
    16. {
    17. //这里暂时还用不到友元,因为在operator>>中并没有访问string的私有成员
    18. //friend std::istream& operator>>(std::istream& in, string& s);
    19. private:
    20. size_t _size;
    21. size_t _capacity;
    22. char* _str;
    23. static size_t npos;
    24. public:
    25. typedef char* iterator;
    26. typedef const char* const_iterator;
    27. iterator begin()
    28. {
    29. return _str;//指向首元素
    30. }
    31. iterator end()
    32. {
    33. return _str + _size;//指向'\0'
    34. }
    35. const_iterator begin()const
    36. {
    37. return _str;
    38. }
    39. const_iterator end()const
    40. {
    41. return _str + _size;
    42. }
    43. string(const char* str = "")
    44. {
    45. _size = strlen(str);
    46. _capacity = _size;
    47. _str = new char[_size + 1];
    48. memcpy(_str, str,_size+1);//完成初始化工作
    49. }
    50. ~string()
    51. {
    52. //std::cout <<"::"<< _str << std::endl;
    53. delete[] _str;
    54. _str = nullptr;
    55. _size = _capacity = 0;
    56. std::cout << "~string()" << std::endl;
    57. }
    58. //现代写法
    59. string(const string& s)
    60. :_str(nullptr)
    61. ,_size(0)
    62. ,_capacity(0)
    63. {
    64. string tmp(s._str);//调用默认构造函数string(const char* str = "")
    65. swap(tmp);//this可能没有初始化,析构的时候就会报错,因此要写参数初始化列表
    66. }
    67. //string(const string& s)
    68. //{
    69. // _str = new char[s._capacity + 1];
    70. // memcpy(_str, s._str, s._size);
    71. // _size = s._size;
    72. // _capacity = s._capacity;
    73. //}
    74. void swap(string& tmp)
    75. {
    76. std::swap(_str, tmp._str);
    77. std::swap(_size, tmp._size);
    78. std::swap(_capacity, tmp._capacity);
    79. }
    80. //现代写法
    81. string& operator= (string& s)
    82. {
    83. if (this != &s)
    84. {
    85. string tmp(s);//调用拷贝构造(深拷贝)
    86. swap(tmp);
    87. }
    88. return *this;
    89. }
    90. size_t size()const
    91. {
    92. return _size;
    93. }
    94. size_t capacity()const
    95. {
    96. return _capacity;
    97. }
    98. char& operator[](size_t pos)
    99. {
    100. assert(pos <= _size);
    101. return _str[pos];
    102. }
    103. void reserve(size_t n = 0)
    104. {
    105. //多留出一个空位给\0
    106. char* tmp = new char[n+1];//在堆区开辟空间,出函数不会销毁
    107. my_strcpy(tmp, _str);
    108. delete[] _str;
    109. _str = tmp;
    110. _capacity = n;
    111. //只改变了capacity,没有改变size,size不变
    112. }
    113. void push_back(char c)
    114. {
    115. if (_size == _capacity)
    116. {
    117. reserve(_capacity == 0 ? 6 : _capacity * 2);
    118. }
    119. _str[_size] = c;
    120. _size++;
    121. _str[_size] = '\0';
    122. }
    123. string& operator+= (char c)
    124. {
    125. push_back(c);
    126. return *this;
    127. }
    128. string& operator+= (const char* s)
    129. {
    130. size_t len = strlen(s);
    131. if (_size + len > _capacity)
    132. {
    133. reserve(_size + len+10);
    134. }
    135. append(s);
    136. return *this;
    137. }
    138. string& append(const char* s)
    139. {
    140. size_t len = strlen(s);
    141. if (_size + len > _capacity)
    142. {
    143. reserve(_size + len + 1);
    144. }
    145. memcpy(_str + _size, s,len+1);
    146. _size += len;
    147. return *this;
    148. }
    149. string& insert(size_t pos, size_t n, char c)
    150. {
    151. assert(pos <= _size);
    152. if (_size + n > _capacity)
    153. {
    154. reserve(_size + n);
    155. }
    156. size_t end = _size+n;
    157. for (; end>=pos+n; end--)
    158. {
    159. //abcd size==4 pp n==2 end==6 end-n==4
    160. _str[end] = _str[end-n];
    161. }
    162. for (size_t i = 0; i < n; i++)
    163. {
    164. _str[pos + i] = c;
    165. }
    166. _size += n;
    167. return *this;
    168. }
    169. string& insert(size_t pos, const char* s, size_t n)
    170. {
    171. assert(pos <= _size);
    172. size_t len = strlen(s);
    173. if (_size + n > _capacity)
    174. {
    175. reserve(_size + n);
    176. }
    177. size_t end = _size + n;
    178. for (; end >= pos + n; end--)//当pos==0时,end>=pos恒成立,因为end为size_t类型,不可能是负数
    179. {
    180. //abcd size==4 pp n==2 end==6 end-n==4
    181. _str[end] = _str[end - n];
    182. }
    183. for (size_t i = 0; i < n; i++)
    184. {
    185. _str[pos + i] = s[i];
    186. }
    187. _size += n;
    188. return *this;
    189. }
    190. //string& erase(size_t pos = 0, size_t len = npos)
    191. //{
    192. //}
    193. bool operator<(string& s)const
    194. {
    195. size_t i1 = 0, i2 = 0;//遍历两个字符串4
    196. while (i1 < _size && i2 < s._size)
    197. {
    198. if (_str[i1] < s._str[i2])
    199. {
    200. return true;
    201. }
    202. else if (_str[i1] > s._str[i2])
    203. {
    204. return false;
    205. }
    206. else
    207. {
    208. i1++;
    209. i2++;
    210. }
    211. }
    212. //若循环正常进行结束,可能出现的情况:
    213. //hello hello return false
    214. //hellowwww hello return false
    215. //hello hellowww return true
    216. if (_size < s._size)
    217. {
    218. return true;
    219. }
    220. return false;
    221. }
    222. bool operator==(string& s)const
    223. {
    224. //std::cout << s._size << std::endl;
    225. if (_size != s._size)
    226. {
    227. return false;
    228. }
    229. return memcmp(_str, s._str, _size) == 0;
    230. }
    231. bool operator>(string& s)const
    232. {
    233. return !((*this < s) || (*this == s));
    234. }
    235. bool operator<=(string& s)const
    236. {
    237. return !(*this > s);
    238. }
    239. bool operator>=(string& s)const
    240. {
    241. return !(*this < s);
    242. }
    243. //string& operator= (const string& s)
    244. //{
    245. // //开辟新空间,进行拷贝
    246. // if (this != &s)//如果两个对象不相同
    247. // {
    248. // char* tmp = new char[s._capacity + 1];
    249. // memcpy(tmp, s._str, s._size);
    250. // delete[] _str;
    251. // _str = tmp;
    252. // _size = s._size;
    253. // _capacity = s._capacity;
    254. // }
    255. // return *this;
    256. //}
    257. //void swap(string& str)
    258. //{
    259. //
    260. //}
    261. //template
    262. //void swap(T m)
    263. //{
    264. // T tmp = m;
    265. // m = *this;
    266. // *this = tmp;
    267. //}
    268. const char* c_str()const
    269. {
    270. return _str;
    271. }
    272. void clear()
    273. {
    274. _str[0] = '\0';
    275. _size = 0;
    276. }
    277. };
    278. }
    279. //std::ostream& operator<<(std::ostream& os, const abl::string& str)
    280. //{
    281. // os << str._str << std::endl;
    282. // return os;
    283. //}
    284. size_t abl::string::npos = -1;//静态成员变量必须初始化,并且只能在类体外进行初始化
    285. std::ostream& operator<<(std::ostream& out,const abl::string& str)
    286. {
    287. for (auto ch : str)
    288. {
    289. out << ch;
    290. }
    291. //out << str.c_str();
    292. return out;
    293. }
    294. std::istream& operator>>(std::istream& in, abl::string& s)
    295. {
    296. s.clear();
    297. char bucket[128];//相当于一个桶,装满了再往s里边加,减少了开辟空间的次数,充分利用空间
    298. char c=in.get();
    299. int i = 0;
    300. while (c != ' ' && c != '\n')
    301. {
    302. bucket[i] = c;
    303. i++;
    304. if (i == 127)
    305. {
    306. bucket[i] = '\0';//operator+=中要计算bucket的长度,以'\0'为终止条件,因此要在最后加上
    307. s += bucket;
    308. i = 0;//重新往buckt里边放入数据
    309. }
    310. c = in.get();
    311. }
    312. if (i != 0)
    313. {
    314. bucket[i] = '\0';//...
    315. s += bucket;
    316. }
    317. return in;
    318. }
    2、string.cpp
    1. #include
    2. #include
    3. #include "String.h"
    4. using namespace std;
    5. void test_string1()
    6. {
    7. abl::string s1("hello world");
    8. abl::string s2("legacy.cplusplus.com");
    9. string s3("jdksanxkdsd");
    10. string s4;
    11. cout << s3.c_str() << endl;
    12. cout << s4.c_str() << endl;
    13. cout << s1.c_str() << endl;
    14. for (size_t i = 0; i < s1.size(); i++)
    15. {
    16. cout << s1[i] << " ";
    17. }
    18. cout << endl;
    19. cout << s2.c_str() << endl;
    20. abl::string::iterator it = s2.begin();
    21. while(it!=s2.end())
    22. {
    23. cout << *it << " ";
    24. ++it;
    25. }
    26. cout << endl;
    27. cout << s2 << endl;
    28. }
    29. void test_string2()
    30. {
    31. //string s1("hello");
    32. //cout << s1 << endl;
    33. //cout << s1.capacity() << endl;
    34. //abl::string s2("world");
    35. cout << s2.capacity() << endl;
    36. //s2.push_back('c');
    37. //s2.push_back('c');
    38. //s2.push_back('c');
    39. //cout << s2 << endl;
    40. //s2 += 's';
    41. //cout << s2 << endl;
    42. //s2 += "good";
    43. //cout << s2 << endl;
    44. abl::string s3("hello");
    45. s3.append(" judy");
    46. cout << s3 << endl;
    47. //abl::string s4("helloooo");
    48. s4 += '\0';
    49. //cout << s4 << endl;
    50. //s4 += "wwwwwww";
    51. //s4.insert(2, 3, 'y');
    52. //cout << s4 << endl;
    53. //abl::string s5("hello");
    54. //s5.insert(2, 5, 'p');
    55. //cout << s5 << endl;
    56. //s5.insert(9, "world", 6);
    57. //cout << s5 << endl;
    58. //for (auto ch : s5)
    59. //{
    60. // cout << ch;
    61. //}
    62. //cout << endl;
    63. //string s6;
    64. //cin >> s6;
    65. //cout << s6 << endl;
    66. //cin >> s6;
    67. //cout << s6;
    68. /* cout << s4.npos << endl;*/
    69. }
    70. void test_string3()
    71. {
    72. abl::string s1("hello");
    73. abl::string s2("helloxxxxx");
    74. //cout << (s2 < s1) << endl;
    75. abl::string s3("hello");
    76. //cout << (s1 == s2) << endl;
    77. //cout << (s1 == s3) << endl;
    78. cout << (s2 >= s3) << endl;
    79. cout << (s1 >= s2) << endl;
    80. cout << (s1 >= s3) << endl;
    81. }
    82. void test_string4()
    83. {
    84. abl::string s1("helloxxxxxxxxxxx");
    85. //abl::string s2;
    86. //s2 = s1;
    87. //cout << s1 << endl;
    88. //cout << s2 << endl;
    89. //s1.append(" world");
    90. abl::string s2("worldxxx");
    91. s1 = s2;
    92. cout << s1 << endl;
    93. cout << s2 << endl;
    94. }
    95. int main()
    96. {
    97. //test_string4();
    98. string s("hello world");
    99. string::iterator it = s.begin();
    100. while (it != s.end())
    101. {
    102. *it = 'x';
    103. it++;
    104. }
    105. cout << s << endl;
    106. return 0;
    107. }

  • 相关阅读:
    RFSoC应用笔记 - RF数据转换器 -07- RFSoC关键配置之RF-DAC内部解析(一)
    第2-4-5章 规则引擎Drools高级语法-业务规则管理系统-组件化-中台
    Redis的安全网:掌握RDB和AOF的持久化技术【redis第四部分】
    Java23种设计模式-行为型模式之命令模式
    实时天气API
    计算机毕业设计Java学科竞赛管理系统(源码+系统+mysql数据库+Lw文档)
    ArcGIS_地质多样性评价方法
    Vue框架学习记录之环境安装与第一个Vue项目
    如何完善文件传输审批流程,降低企业文件安全风险?
    Serialiable接口和serialVersionUID的作用及其在redisson中的应用
  • 原文地址:https://blog.csdn.net/awww224112/article/details/133952383