ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

STL:一篇带你学会string并明白其原理

STL:一篇带你学会string并明白其原理 一、string的使用string类文档1.1 constrcutor构造函数有无参构造拷贝构造字符串构造等等。void test1() { //无参构造 string s1; cout s1 endl; //用字符串构造 string s2(hello world); cout s2 endl; //拷贝构造 string s3(s2); cout s3 endl; //用字符串的一部分构造 string s4(s2, 6); cout s4 endl; }析构函数对申请对象空间进行释放。赋值重载可以用字符串类型的类、字符串常量、字符进行赋值。void test1() { //无参构造 string s1; cout s1 endl; //用字符串构造 string s2(hello world); cout s2 endl; //拷贝构造 string s3(s2); cout s3 endl; //用字符串的一部分构造 string s4(s2, 6); cout s4 endl; }1.2 Element accessoperator[ ]:获取pos位置的字符。加上const,那么字符只能读不能改。assert断言来判断是否越界。at:at与operator[ ] 功能一样唯一不同的地方是at检查越界的方式是抛异常。void test3() { string s1(hello); s1[2] t; cout s1[2] endl; //s1[6] l; 错误 cout s1.at(4) endl; }1.3 capacitysize/length:返回有效字符的个数不带 \0 。capacity:返回字符串的有效容量大小不带 \0 所以实际空间会比容量大小大1。reserve:提前开好空间。作用是提前开好空间减少多次扩容的消耗缺省参数为0。n与capacity的关系决定是否开空间。n capacity :那么就要按照n来开连续空间。size n capacity:不同编译器处理方式不一样。n size 绝对不会对字符串造成影响这种情况不会缩容。resize:功能调整字符串的长度为n个字符,如果n size那么第一个函数则将多余的字符转化为 \0 。第二个函数则是将多余的字符转化为字符c。当然n capacity时也要扩容然后再看是用 \0 填充还是字符c填充void test4() { string s1(hellxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx); cout size: s1.size() endl; cout capacity: s1.capacity() endl; cout s1 endl; s1.resize(48,k); cout size: s1.size() endl; cout capacity: s1.capacity() endl; cout s1 endl; }clear:功能清除字符串的内容但是并不会缩容的。void test5() { string s1(helloc world); cout 清理之前 endl; cout size: s1.size() endl; cout capacity: s1.capacity() endl; s1.clear(); cout 清理之后 endl; cout size: s1.size() endl; cout capacity: s1.capacity() endl; }empty:功能检查字符串是否为空。void test5() { string s1(helloc world); cout s1.empty() endl; cout 清理之前 endl; cout size: s1.size() endl; cout capacity: s1.capacity() endl; s1.clear(); cout 清理之后 endl; cout size: s1.size() endl; cout capacity: s1.capacity() endl; cout s1.empty() endl; }1.4 Iterator迭代器现在可以简单的理解为指针用法类似但事实上不是指针。迭代器分为正向迭代器反向迭代器const 迭代器const反向迭代器。//现在理解为只是重命名 //普通迭代器 typedef char* iterator; //反向迭代器 reverse_iterator //const 迭代器 typedef const char* const_iterator; //const反向迭代器 const_reverse_iterator遍历的方式size operator[ ]迭代器范围for(实际上底层就是迭代器)void test6() { string s1(jellsdfff); //第一种 cout 第一种; for (int i 0; i s1.size(); i) { cout s1[i] ; } cout endl; //第二种 cout 第二种; string::iterator it s1.begin(); while (it ! s1.end()) { cout *it ; it; } cout endl; //第三种 cout 第三种; for (auto ch : s1) { cout ch ; } cout endl; }API:begin:返回第一个字符的位置。end:返回最后一个字符的下一个位置。cbegin/cend 适用于const迭代器rbegin/rend 适用于反向迭代器crbegin/crend 适用于 const反向迭代器。auto属于自动识别类型返回类型较长使用auto可以提高代码的简洁性。但是使用auto要注意⚠️auto不能修饰函数参数⚠️auto不能修饰数组⚠️auto可以作为返回值但是不建议。范围for:自动赋值自动遍历自动判断结束。实际底层就是迭代器格式for(auto 变量 被迭代对象) { //操作 }使用其他迭代器进行遍历⚠️加上const之后字符串只能读不能修改。string s1(jellsdfff); cout s1: s1 endl; //反向遍历 cout reverse_iterator: ; string::reverse_iterator rit s1.rbegin(); while (rit ! s1.rend()) { cout *rit ; rit; } cout endl; //const 遍历 cout const_iterator: ; string::const_iterator cit s1.cbegin(); while (cit ! s1.cend()) { cout *cit ; cit; } cout endl; //const 反向遍历 cout const_reverse_iterator: ; string::const_reverse_iterator crit s1.crbegin(); while (crit ! s1.crend()) { cout *crit ; crit; } cout endl;1.5 Modifiers操作作用operator尾插在字符串后面加上字符/字符串/字符串常量append尾插兼具operator功能还能尾插字符串的一部分也可以使用迭代器尾插。push_back尾插只能尾插一个字符insert插入在pos位置插入n个字符/子串字符串/字符串常量支持迭代器erase删除删除pos位置删除几个字符不写默认npos,迭代器删除时记住去区间时左闭右开。repalce用新的字符/字符串替代pos位置的部分字符swap交换字符串pop_back尾删字符1.6 string operationc_str返回常量字符串便于与C语言兼容find查找字符串并返回该位置rfind反向查找字符或字符串find_first_of寻找字符串与目标字符串任何字符相同的位置返回第一个位置find_last_of与find_first_of反向寻找substr从pos位置开始的n个字符组成字符串并返回void test8() { string s1(/model/test.cpp); //获取文件名 size_t pos s1.find(.); for (size_t i 0; i pos; i) { cout s1[i]; } cout endl; //获取文件后缀 size_t pos2 s1.rfind(.); size_t i pos2; while (i s1.size()) { cout s1[i]; i; } cout endl; }1.7 全局函数getline:由于cin在输入字符串遇到空格和回车\n就停止读取而getline从输入流中提取字符遇到delim(不设置的话默认\n停止)这样就可以读取到带空格的字符串了。void test9() { string s1; getline(cin, s1); cout s1 endl; }二、string的实现string用char*的指针_size,_capacity来实现string。#include iostream #include assert.h using namespace std; namespace Mystring { class string { public: static const size_t npos; typedef char* iterator; typedef const char* const_iterator; //构造函数 string(const char* str ) { size_t len strlen(str); _size _capacity len; _str new char[_capacity 1]; strcpy(_str, str); } //拷贝构造 string(const string s) { _str new char[s._capacity 1]; strcpy(_str, s._str); _size s._size; _capacity s._capacity; } string operator(const string str) { strcpy(_str, str._str); _size str._size; } //析构函数 ~string() { delete[] _str; _str nullptr; _size _capacity 0; } ////////////////////////////////////////////////////// //iterator iterator begin() { return _str; } iterator end() { return _str _size; } const_iterator begin()const { return _str; } const_iterator end()const { return _str _size; } //////////////////////////////////////////////////// //capacity size_t size()const { return _size; } size_t capacity()const { return _capacity; } bool empty()const { return _size 0; } void resize(size_t n, char c \0); void reserve(size_t n); const char* c_str()const { return _str; } string operator (char c); void push_back(char c); void append(const char* str); string operator (const char* str); void clear() { _str[0] \0; _size 0; } void swap(string s) { std::swap(_str,s._str); std::swap(_size,s._size); std::swap(_capacity,s._capacity); } char operator[](size_t pos) { assert(pos _size); return _str[pos]; } const char operator[](size_t pos)const { assert(pos _size); return _str[pos]; } //返回c在string中第一次出现的位置 size_t find(char c, size_t pos 0)const; //返回子串s在string中第一次出现的位置 size_t find(const char* s, size_t pos 0)const; //在pos位置上插入字符c/字符串str,并返回该字符串 void insert(size_t pos, char c); void insert(size_t pos, const char* str); void erase(size_t pos, size_t len); string substr(size_t pos 0, size_t len npos); private: char* _str; size_t _size; size_t _capacity; }; bool operator(const string s1, const string s2); bool operator(const string s1, const string s2); bool operator(const string s1, const string s2); bool operator(const string s1, const string s2); bool operator(const string s1, const string s2); bool operator!(const string s1, const string s2); istream operator(istream in, string s); ostream operator(ostream out, const string s); istream getline(istream in, string s); }#include string.h namespace Mystring { const size_t string::npos -1; //流提取(从输入流中读取数据) istream operator(istream in, string s) { s.clear(); const int N 256; char buffer[N]; char ch; //流提取默认空格和换行符为分隔符 int i 0; ch in.get(); while (ch ! ch ! \n) { buffer[i] ch; if (i N - 1) { buffer[i] \0; s buffer; i 0; } ch in.get(); } if (i) { buffer[i] \0; s buffer; } return in; } istream getline(istream in, string s) { s.clear(); const int N 256; char buffer[N]; char ch; //流提取默认空格和换行符为分隔符 int i 0; ch in.get(); while (ch ! \n) { buffer[i] ch; if (i N - 1) { buffer[i] \0; s buffer; i 0; } ch in.get(); } if (i) { buffer[i] \0; s buffer; } return in; } //流插入 ostream operator(ostream out, const string s) { for (auto ch : s) { out ch; } return out; } bool operator(const string s1,const string s2) { return strcmp(s1.c_str(), s2.c_str()) 0; } bool operator(const string s1, const string s2) { return strcmp(s1.c_str(), s2.c_str()) 0; } bool operator(const string s1, const string s2) { return s1 s2 || s1 s2; } bool operator(const string s1, const string s2) { return !(s1 s2); } bool operator(const string s1, const string s2) { return !(s1 s2); } bool operator!(const string s1,const string s2) { return !(s1 s2); } string string::substr(size_t pos, size_t len) { assert(pos _size); if (len _size - pos) { len _size - pos; } string tmp; tmp.reserve(len); for (size_t i pos; i len; i) { tmp _str[i]; } return tmp; } void string::insert(size_t pos, char c) { assert(pos _size); if (_size _capacity) { reserve(_capacity 0 ? 4 : 2 * _capacity); } //size_t end _size; //while (end pos) //{ // //_str[pos 1] _str[pos]; // _str[end 1] _str[end]; // end--; //} //错误写法因为end 0 时end-- ,end -1 ,整型提升变为最大的正数死循环 size_t end _size 1; while (end pos) { _str[end] _str[end - 1]; end--; } _str[pos] c; _size; } void string::insert(size_t pos, const char* str) { assert(pos _size); size_t len strlen(str); if (_size len _capacity) { reserve(_size len 2 * _capacity ? _size len : 2 * _capacity); } size_t end _size len; while (end pos len -1) { //_str[pos 1] _str[pos]; _str[end] _str[end - len]; end--; } _size len; /*size_t i pos; size_t j 0; while (len 0) { _str[i] str[j]; len--; }*/ size_t i 0; while (len 0) { _str[i pos] str[i]; i; len--; } } //删除pos位置上的元素并返回该字符 void string::erase(size_t pos, size_t len) { assert(pos _size); assert(_size 0); /*assert(len _size - pos);*/ if (len _size - pos) { _str[pos] \0; _size pos; } else { size_t start pos; while (start _size - len) { //_str[pos] _str[pos len] _str[start] _str[start len]; start; } _size - len; } } size_t string::find(const char* s, size_t pos )const { assert(pos _size); char* ptr strstr(_str pos, s); if (ptr nullptr) { return npos; } else { return ptr - _str; } } size_t string::find(char c, size_t pos)const { assert(pos _size); size_t i 0; while (pos _size) { if (_str[i pos] c) { return i pos; } i; } return npos; } void string::push_back(char c) { *this c; } void string::append(const char* str) { *this str; } string string::operator (const char* str) { size_t len strlen(str); if(_size len _capacity) { reserve(_size len 2 * _capacity ? 2 * (_size len) : _size len); } /*int i 0; while (len 0) { _str[_size] str[i]; len--; } _str[_size] \0;*/ strcpy(_str _size, str); _size len; return *this; } string string::operator(char c) { if (_size _capacity) { reserve(_capacity 0 ? 4 : 2 * _capacity); _capacity * 2; } _str[_size] c; _str[_size] \0; return *this; } void string::reserve(size_t n) { if (n _capacity) { char* tmp new char[n 1]; strcpy(tmp, _str); delete[] _str; _str tmp; _capacity n; } } void string::resize(size_t n, char c ) { if (n _size) { _size n; } else { if (n _capacity) { while (_size ! n) { _str[_size] c; } _str[_size] \0; } else { reserve(n); while (_size ! n) { _str[_size] c; } _str[_size] \0; } } } }; };
返回列表