当前位置:   article > 正文

【C++】string 类

【C++】string 类

1. 标准库中的string类

注意:

1. string是表示字符串的字符串类

2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。

3. string在底层实际是:basic_string模板类的别名,typedef basic_string string;

4. 不能操作多字节或者变长字符的序列。 在使用string类时,必须包含#include头文件(#include<string>)以及using namespace std;

a. string类对象的常见构造

代码举例1

  1. #include <iostream>
  2. #include<string>
  3. using namespace std;
  4. int main()
  5. {
  6. string t1; // 相当于类对象的实例化
  7. }

代码举例2

  1. #include <iostream>
  2. #include<string>
  3. using namespace std;
  4. int main()
  5. {
  6. string t1("hello world"); // 调用构造函数
  7. cout << t1 << endl;
  8. string t2 = "hello world"; //隐式类型转换(构造函数 + 拷贝构造 + 优化 -> 构造函数)
  9. cout << t2 << endl;
  10. }

代码举例3

  1. #include <iostream>
  2. #include<string>
  3. using namespace std;
  4. int main()
  5. {
  6. string t1(10, 'a'); // 拷贝 10 个 a
  7. cout << t1 << endl;
  8. }

运行结果:

代码举例4

  1. #include <iostream>
  2. #include<string>
  3. using namespace std;
  4. int main()
  5. {
  6. string t1("hello");
  7. string t2(t1); // 拷贝构造
  8. cout << t2 << endl;
  9. }

b. string类对象的容量操作

  • size (返回字符串有效字符长度,没有 '\0 ')

代码举例1

  1. #include <iostream>
  2. #include<string>
  3. using namespace std;
  4. int main()
  5. {
  6. string t1 = "hello";
  7. cout << t1.size() << endl;
  8. }

运行结果:

  • capacity (返回字符串的总空间大小)

代码举例2

  1. #include <iostream>
  2. #include<string>
  3. using namespace std;
  4. int main()
  5. {
  6. string t1 = "hello";
  7. cout << t1.capacity() << endl;
  8. }

运行结果:

分析:

string 类里面的成员变量有两个可以存储空间,一个是数组,另一个是动态开辟的空间,当数组空间不足时,才会用动态开辟

  • reserve(扩大字符串容量,字符有效长度不变:即 size 不变)

代码举例3

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. string t1 = "hello";
  6. cout << "有效长度:" << t1.size() << " 总容量:" << t1.capacity() << endl;
  7. t1.reserve(100);
  8. cout << "有效长度:" << t1.size() << " 总容量:" << t1.capacity() << endl;
  9. }

运行结果:

分析:

有些编译器在分配空间的时候,可能会对于开辟所需的空间再给大一点

  • resize (将有效字符的个数该成n个,多出的空间用字符c填充)

代码举例4

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. string t1 = "hello";
  6. cout << "有效长度:" << t1.size() << " 总容量:" << t1.capacity() << endl;
  7. t1.resize(100);
  8. cout << "有效长度:" << t1.size() << " 总容量:" << t1.capacity() << endl;
  9. t1.resize(10); //可以缩小有效长度,但总容量不会随意变动
  10. cout << "有效长度:" << t1.size() << " 总容量:" << t1.capacity() << endl;
  11. t1.resize(20, '*'); //对于的空间可以初始化任意字符
  12. cout << t1 << endl;
  13. }

运行结果:

c. string类对象的访问及遍历操作

  • operator[] (返回pos位置的字符,和 C 语言的用法一样,const string类对象调用)
  • begin + end (begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器)

代码举例1

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. string t1 = "hello bit";
  6. string::iterator it = t1.begin();
  7. // it 相当于拿到 首元素的地址了
  8. while (it != t1.end())
  9. {
  10. cout << *it << endl;
  11. it++;
  12. }
  13. }

运行结果:

分析:

  • rbegin + rend (rbegin获取最后一个字符的迭代器 + rend获取第一个字符前一个位置的迭代器)

代码举例2

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. string t1 = "hello bit";
  6. string::reverse_iterator rit = t1.rbegin();
  7. // it 相当于拿到 首元素的地址了
  8. while (rit != t1.rend())
  9. {
  10. cout << *rit << endl;
  11. rit++;
  12. }
  13. }

运行结果:

分析:

  • 范围for

代码举例3

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. string t1 = "hello bit";
  6. for (auto i : t1)
  7. {
  8. cout << i;
  9. }
  10. cout << endl;
  11. for (int i = 0; i < t1.size(); i++)
  12. {
  13. cout << t1[i];
  14. }
  15. }

运行结果:

d. string类对象的修改操作

  • push_back (在字符串后面增加一个字符)

代码举例1

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. string t1 = "hello";
  6. t1.push_back('a');
  7. t1.push_back('a');
  8. t1.push_back('a');
  9. cout << t1 << endl;
  10. }

运行结果:

  • append (在字符串后面再增加一个字符串)

代码举例2

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. string t1 = "hello";
  6. t1.append("abcd");
  7. cout << t1 << endl;
  8. }

运行结果:

  • operator+= (在字符串后面加一个字符或者一个字符串)

代码举例3

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. string t1 = "hello";
  6. t1 += "aabc";
  7. t1 += '*';
  8. cout << t1 << endl;
  9. }

运行结果:

  • c_str (返回存储的字符串)

代码举例4

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. string t1 = "hello";
  6. t1 += '\0';
  7. t1 += 'a';
  8. cout << t1 << endl;
  9. cout << t1.c_str();
  10. }

运行结果:

分析:

c_str() 是直接返回字符串 ,所以遇到 '\0' 就终止了

的完成是根据_size去遍历每个字符串

  • find + npos (从字符串pos位置开始往后找字符c,返回第一次遇到的该字符在字符串中的位置)

代码举例5

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. string t1 = "hello";
  6. cout << t1.find('o',2) << endl;
  7. // 从下标为 2 的位置去找字符 'o'
  8. cout << t1.find("lo") << endl;
  9. // 默认从下标 0 的位置去找字符串
  10. }

注意:

  1. 如果找不到,返回 npos ( size_t npos = -1)
  2. 默认 pos 从 0 下标开始
  • rfind(从字符串pos位置开始往前找字符c,返回第一次遇到该字符在字符串中的位置)

代码举例6

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. string t1 = "hello";
  6. cout << t1.rfind('l') << endl;
  7. }

运行结果:

注意:

  1. 如果找不到,返回 npos ( size_t npos = -1)
  2. 默认 pos 从 字符串中的最后一个字符(不是 '\0' ) 下标开始

e. string类非成员函数

  • operator>> (输入运算符重载)
  • operator<< (输出运算符重载)
  • getline (获取一行字符串)

代码举例

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. int main()
  5. {
  6. string t1;
  7. getline(cin, t1);
  8. cout << t1 << endl;
  9. return 0;
  10. }

注意:

getline 遇到空格不会结束

cin 遇到空格会结束

 2. string 类的模拟

  1. namespace lhy
  2. {
  3. class string
  4. {
  5. public:
  6. typedef char* iterator;
  7. typedef const char* const_iterater;
  8. iterator begin()
  9. {
  10. return _str;
  11. }
  12. iterator end()
  13. {
  14. return _str + _size;
  15. }
  16. const_iterater begin() const
  17. {
  18. return _str;
  19. }
  20. const_iterater end() const
  21. {
  22. return _str + _size;
  23. }
  24. string(const char* str = "")
  25. :_size(strlen(str))
  26. {
  27. _capacity = _size == 0 ? 3 : _size;
  28. _str = new char[_capacity + 1];
  29. strcpy(_str, str);
  30. }
  31. string(const string& t)
  32. :_size(strlen(t._str))
  33. {
  34. _capacity = t._size;
  35. _str = new char[_capacity + 1];
  36. strcpy(_str, t._str);
  37. }
  38. string(int n, char ch)
  39. :_size(n)
  40. {
  41. _capacity = _size;
  42. _str = new char[_capacity + 1];
  43. for (int i = 0; i < n; i++)
  44. {
  45. _str[i] = ch;
  46. }
  47. _str[_capacity] = '\0';
  48. }
  49. string& operator=(const string& t)
  50. {
  51. _size = t._size;
  52. _capacity = t._capacity;
  53. char* tmp = new char[_capacity + 1];
  54. strcpy(tmp, t._str);
  55. delete[] _str;
  56. _str = tmp;
  57. return *this;
  58. }
  59. char& operator[](int pos)
  60. {
  61. assert(pos < _size);
  62. return _str[pos];
  63. }
  64. const char& operator[](int pos) const
  65. {
  66. assert(pos < _size);
  67. return _str[pos];
  68. }
  69. size_t size() const
  70. {
  71. return _size;
  72. }
  73. const char* c_str() const
  74. {
  75. return _str;
  76. }
  77. bool operator>(const string& t) const
  78. {
  79. if (strcmp(_str, t._str) > 0)
  80. {
  81. return true;
  82. }
  83. return false;
  84. }
  85. bool operator==(const string& t) const
  86. {
  87. if (strcmp(_str, t._str) == 0)
  88. {
  89. return true;
  90. }
  91. return false;
  92. }
  93. bool operator<(const string& t) const
  94. {
  95. if (strcmp(_str, t._str) < 0)
  96. {
  97. return true;
  98. }
  99. return false;
  100. }
  101. bool operator<=(const string& t) const
  102. {
  103. return *this < t || *this == t;
  104. }
  105. bool operator>=(const string& t) const
  106. {
  107. return *this > t || *this == t;
  108. }
  109. bool operator!=(const string& t) const
  110. {
  111. return !(*this == t);
  112. }
  113. void push_back(const char ch)
  114. {
  115. if (_size + 1 > _capacity)
  116. {
  117. reserve(_size * 2);
  118. }
  119. _size++;
  120. _str[_size - 1] = ch;
  121. _str[_size] = '\0';
  122. }
  123. void append(const char* str)
  124. {
  125. int len = strlen(str);
  126. if (_size + len > _capacity)
  127. {
  128. reserve(_size + len);
  129. }
  130. strcpy(_str + _size, str);
  131. _size += len;
  132. }
  133. void reserve(size_t n)
  134. {
  135. if (n > _size)
  136. {
  137. char* tmp = new char[n + 1];
  138. strcpy(tmp, _str);
  139. delete[] _str;
  140. _str = tmp;
  141. _capacity = n;
  142. }
  143. }
  144. void resize(size_t size,char ch = '\0')
  145. {
  146. if (size > _size)
  147. {
  148. reserve(size);
  149. int x = size - _size;
  150. while (x--)
  151. {
  152. *this += ch;
  153. }
  154. _size = size;
  155. }
  156. else
  157. {
  158. _size = size;
  159. _str[_size] = '\0';
  160. }
  161. }
  162. void insert(size_t pos,const char ch)
  163. {
  164. assert(pos <= _size);
  165. if (_size + 1 > _capacity)
  166. {
  167. reserve(_size * 2);
  168. }
  169. _size++;
  170. for (int i = _size; i > pos; i--)
  171. {
  172. _str[i] = _str[i - 1];
  173. }
  174. _str[pos] = ch;
  175. }
  176. void insert(size_t pos,const char* str)
  177. {
  178. assert(pos <= _size);
  179. int len = strlen(str);
  180. if (_size + len > _capacity)
  181. {
  182. reserve(_size + len);
  183. }
  184. _size += len;
  185. for (size_t i = _size; i > pos + len - 1; i--)
  186. {
  187. _str[i] = _str[i - len];
  188. }
  189. strncpy(_str + pos, str, len);
  190. }
  191. void erase(size_t pos,size_t n = npos)
  192. {
  193. assert(pos <= _size);
  194. if (n == npos || pos + n >= _size )
  195. {
  196. _str[pos] = '\0';
  197. _size = pos;
  198. }
  199. else
  200. {
  201. for (int i = pos + n; i <= this->size(); i++)
  202. {
  203. _str[i - n] = _str[i];
  204. }
  205. _size -= n;
  206. }
  207. }
  208. void swap(string &t)
  209. {
  210. std::swap(_size, t._size);
  211. std::swap(_capacity, t._capacity);
  212. std::swap(_str, t._str);
  213. }
  214. size_t find(const char ch, size_t pos = 0)
  215. {
  216. assert(pos < _size);
  217. for (size_t i = pos; i < this->size(); i++)
  218. {
  219. if (_str[i] == ch)
  220. {
  221. return i;
  222. }
  223. }
  224. return -1;
  225. }
  226. size_t find(const char* str, size_t pos = 0)
  227. {
  228. assert(pos < _size);
  229. char *tmp = std ::strstr(_str + pos, str);
  230. if (tmp == nullptr)
  231. {
  232. return -1;
  233. }
  234. else
  235. {
  236. return tmp - _str;
  237. }
  238. }
  239. string& operator+=(const char *str)
  240. {
  241. append(str);
  242. return *this;
  243. }
  244. string& operator+=(const char ch)
  245. {
  246. push_back(ch);
  247. return *this;
  248. }
  249. void clear()
  250. {
  251. _str[0] = '\0';
  252. _size = 0;
  253. }
  254. ~string()
  255. {
  256. delete[] _str;
  257. _str = nullptr;
  258. }
  259. private:
  260. char* _str;
  261. size_t _size;
  262. size_t _capacity;
  263. static size_t npos;
  264. };
  265. size_t string::npos = -1;
  266. ostream& operator<<(ostream& out, const string& t)
  267. {
  268. for (size_t i = 0; i < t.size(); i++)
  269. {
  270. out << t[i];
  271. }
  272. return out;
  273. }
  274. istream& operator>> (istream& in,string& t)
  275. {
  276. t.clear();
  277. int i = 0;
  278. char tmp[128];
  279. char ch = in.get();
  280. while (ch != ' ' && ch != '\n')
  281. {
  282. tmp[i++] = ch;
  283. if (i == 126)
  284. {
  285. tmp[i + 1] = '\0';
  286. t += tmp;
  287. i = 0;
  288. }
  289. ch = in.get();
  290. }
  291. if (i != 0)
  292. {
  293. tmp[i] = '\0';
  294. t += tmp;
  295. }
  296. return cin;
  297. }
  298. }

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

闽ICP备14008679号