• 【数据结构】模拟实现string


    1. namespace simulate_string
    2. {
    3. class string
    4. {
    5. private:
    6. char* _str;
    7. size_t _size;
    8. size_t _capacity;
    9. const static int npos = -1;//类型说明+作用域变量;
    10. public:
    11. typedef char* iterator;
    12. typedef const char* const_iterator;
    13. //迭代器相当于直接调用该类型的指针
    14. iterator begin()//指向首元素地址
    15. {
    16. return _str;
    17. }
    18. const_iterator begin() const
    19. {
    20. return _str;
    21. }
    22. iterator end()//指向末尾元素的下一个地址,在string类中该地址存放的是‘\0’
    23. {
    24. return _str+_size;
    25. }
    26. const_iterator end()const
    27. {
    28. return _str + _size;
    29. }
    30. //构造函数
    31. string(const char* str="")
    32. :_size(strlen(str))
    33. {
    34. _capacity = _size;//防止_size和_capacity声明顺序与初始化列表顺序相反;
    35. //开空间(_capacity是有效容量不包括'\0')
    36. _str = new char[_capacity+1];
    37. strcpy(_str,str);
    38. }
    39. //拷贝构造
    40. string(const string& s)
    41. :_size(s._size)
    42. {
    43. _capacity = s._capacity;
    44. _str = new char[_capacity + 1];//多一个空间存放'\0'
    45. strcpy(_str,s._str);//会拷贝‘\0’;
    46. std::cout << "string(const string& s)" << std::endl;
    47. }
    48. //移动拷贝构造(移动语义)
    49. string(string&& s)//这里右值引用为什么不需要加const?因为要对右值进行资源转移。
    50. {
    51. swap(s);
    52. std::cout << "string(string&& s)" << std::endl;
    53. }
    54. void swap(string& s)
    55. {
    56. std::swap(_str, s._str);
    57. std::swap(_size, s._size);
    58. std::swap(_capacity, s._capacity);
    59. }
    60. ~string()
    61. {
    62. delete[] _str;
    63. _str = nullptr;
    64. _capacity = _size = 0;
    65. }
    66. size_t size() const
    67. {
    68. return _size;
    69. }
    70. char& operator[](size_t pos)
    71. {
    72. assert(pos<_size);
    73. return _str[pos];
    74. }
    75. const char& operator[](size_t pos) const
    76. {
    77. assert(pos < _size);
    78. return _str[pos];
    79. }
    80. const char* c_str()
    81. {
    82. return _str;
    83. }
    84. //赋值运算符重载
    85. string& operator=(const string& s)
    86. {
    87. if (this != &s)
    88. {
    89. char* tmp = new char[s._capacity + 1];
    90. strcpy(tmp, s._str);
    91. delete[] _str;
    92. _str = tmp;
    93. _size = s._size;
    94. _capacity = s._capacity;
    95. }
    96. return *this;
    97. }
    98. // 不修改成员变量数据的函数,最好都加上const
    99. //strcmp会返回0,-1,1;分别代表相等,小于,大于;
    100. bool operator==(const string& s)const
    101. {
    102. return strcmp(_str,s._str)==0;
    103. }
    104. bool operator>(const string& s)const
    105. {
    106. return strcmp(_str, s._str)>0;
    107. }
    108. bool operator>=(const string& s)const
    109. {
    110. return *this>s||*this==s;
    111. }
    112. bool operator<(const string& s)const
    113. {
    114. return !(*this >= s);
    115. }
    116. bool operator<=(const string& s)const
    117. {
    118. return !(*this > s);
    119. }
    120. bool operator!=(const string& s)const
    121. {
    122. return !(*this == s);
    123. }
    124. void push_back(char& ch)
    125. {
    126. insert(_size,ch);
    127. }
    128. void append(const char* str)
    129. {
    130. insert(_size,str);
    131. }
    132. //如果出现s1+=s1的情况,阁下该如何应对?
    133. string& operator+=(const string& s)
    134. {
    135. if (this!= &s)
    136. {
    137. append(s._str);
    138. }
    139. else
    140. {
    141. //创建临时对象;
    142. string news(s);
    143. append(news._str);
    144. }
    145. return *this;
    146. }
    147. string& operator+=(char& ch)
    148. {
    149. push_back(ch);
    150. return *this;
    151. }
    152. string& operator+=(const char* str)
    153. {
    154. append(str);
    155. return *this;
    156. }
    157. void reserve(size_t n)//不能缩容
    158. {
    159. if (n > _capacity)//需要的空间大于当前容量才进行扩容!
    160. {
    161. char* tmp = new char[n + 1];
    162. strcpy(tmp, _str);
    163. delete[] _str;
    164. _str = tmp;
    165. _capacity = n;//有效容量不包括\0;
    166. }
    167. }
    168. void resize(size_t n,char ch='\0')//开空间加初始化
    169. {
    170. if (n <= _size)
    171. {
    172. _size = n;
    173. _str[_size] = '\0';
    174. }
    175. else
    176. {
    177. if (n>_capacity)
    178. {
    179. reserve(n);
    180. }
    181. int i = _size;
    182. while (i < n)
    183. {
    184. _str[i] = ch;//初始化为传递的字符,没有就使用默认缺省;
    185. ++i;
    186. }
    187. _size = n;
    188. _str[_size] = '\0';
    189. }
    190. }
    191. string& insert(size_t pos,char ch)
    192. {
    193. assert(pos<=_size);
    194. if (_size + 1 > _capacity)//需要扩容
    195. {
    196. reserve(_capacity * 2);
    197. }
    198. size_t end = _size+1;
    199. while (end>pos)//当pos为0这种情况时,无符号整数0再减1是无符号整数的最大值而不是-1,所以当end从0再减1时,会继续循环,访问_str[max],程序会崩;
    200. {
    201. //_str[end+1] = _str[end];不可以程序会崩;
    202. _str[end] = _str[end-1];
    203. --end;
    204. }
    205. _str[pos] = ch;
    206. ++_size;
    207. return *this;
    208. }
    209. string& insert(size_t pos, const char* str)
    210. {
    211. assert(pos <= _size);
    212. size_t len = strlen(str);//计算要插入字符的长度;
    213. if (_size + len > _capacity)
    214. {
    215. reserve(len + _size);//需要开辟的有效空间,不包括'\0'
    216. }
    217. size_t end =_size;
    218. while (end>pos)//当end最小为1;
    219. {
    220. _str[end+len-1]=_str[end-1];
    221. --end;
    222. }
    223. strncpy(_str+pos,str,len);//strcpy会把默认字符串的'\0'也加在后面,会覆盖原字符串的后面第一个字符;
    224. _size += len;
    225. _str[_size] = '\0';
    226. return *this;
    227. }
    228. string& erase(size_t pos=0,size_t len=npos)//如果不说明删除多少个,默认从当前位置删到完;
    229. {
    230. assert(pos<_size);
    231. if (len==npos||pos+len>=_size)//如果前面不判断len==npos,后面pos+len会溢出,size_t无符号正整数最大就是-1的补码,因为是无符号;
    232. {
    233. _size = pos;
    234. _str[_size] = '\0';
    235. }
    236. else
    237. {
    238. //连‘\0’都拷贝,把_str+pos+len以后的所有字符都拷贝过来;
    239. strcpy(_str+pos,_str+pos+len);
    240. _size -= len;
    241. }
    242. return *this;
    243. }
    244. //返回一个字符在_str中第一次出现的位置;
    245. size_t find(char ch,size_t pos=0)
    246. {
    247. assert(pos<_size);
    248. int i = 0;
    249. while (i<_size)
    250. {
    251. if (_str[i]==ch)
    252. {
    253. return i;
    254. }
    255. ++i;
    256. }
    257. return npos;
    258. }
    259. //返回一个字符在_str中最后一次出现的位置;
    260. //实质是在_str中从后往前找与ch相等的下标索引;
    261. size_t rfind(char ch,size_t pos=npos)//size_t类型的pos被赋予size_t类型的npos=-1,则npos等于max int;
    262. {
    263. assert(pos>=0);
    264. if (pos == npos||pos>=_size)
    265. pos = _size-1;
    266. int i =pos;
    267. while (i>=0)
    268. {
    269. if (_str[i]==ch)
    270. {
    271. return i;
    272. }
    273. --i;
    274. }
    275. return npos;
    276. }
    277. //按顺序找_str中在str中第一次出现的位置,返回一个指针,指向这个字符;
    278. size_t find(const char* str,size_t pos=0)
    279. {
    280. assert(pos<_size);
    281. //解释strstr();实际上就是找字符串str在_str中第一次出现的位置;
    282. //Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1.
    283. char* p = strstr(_str+pos,str);
    284. //库里面的,按顺序找字符串2在字符串1中第一次出现的位置;
    285. if (p==nullptr)
    286. {
    287. return npos;
    288. }
    289. else
    290. {
    291. return p-_str;
    292. }
    293. }
    294. };
    295. //************* 类外 ***************
    296. //流插入(写到类外保证cout<
    297. std::ostream& operator<<(std::ostream& out,const string& s)
    298. {
    299. for (int i=0;isize();++i)
    300. {
    301. out << s[i] <<' ';
    302. }
    303. return out;
    304. }
    305. //cout和cin分别是输入输出头文件下的一个ostream类对象和istream类对象;
    306. //流提取
    307. std::istream& operator>>(std::istream& in,string& s)
    308. {
    309. char ch=in.get();//输入流中的函数,每次取一个字符;相当于连空格都可以取到的cin;
    310. while (ch!=' '&&ch != '\n')//只要不读到enter也就是换行符,就一直提取;
    311. {
    312. s += ch;
    313. ch = in.get();
    314. }
    315. return in;//支持连续提取;
    316. }

  • 相关阅读:
    解决方案:可以ping别人,但是别人不能ping我
    【infiniband】用udaddy测试RDMA_CM API通过GID连接
    for await of的使用
    【UE5】 虚拟制片教程
    Openstack部署
    如何评价GPT-4o?
    SpringBoot(三) - Slf4j+logback 日志,异步请求,定时任务
    .NET的PLC帮助类
    CRM项目记录(七)
    【k8s】5、资源管理命令-声明式
  • 原文地址:https://blog.csdn.net/zzxz8/article/details/134476602