1.学习string类
C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。
2.标准库中的string类
string类的文档介绍
string是表示字符串的字符串类
3.string类的常用接口及模拟实现
3.1string类对象的常见构造
string(const char* str = ""): _capacity(strlen(str)), _size(_capacity)
{_str = new char[_capacity + 1];strcpy(_str, str);
}string(const string& str): _size(0), _capacity(0), _str(nullptr)
{string temp(str._str);swap(temp);
}//两种方法都可以
/*string(const string& str)
{_str = new char[str._capacity + 1];strcpy(_str, str._str);_size = str._size;_capacity = str._capacity;
}*/
3.2string类对象的容量操作
size_t size() const
{return _size;
}size_t length() const
{return _size;
}size_t capacity() const
{return _capacity;
}bool empty() const
{return _size == 0;
}void clear()
{_str[0] = '\0';_size = 0;
}void reserve(size_t n)
{if (n > _capacity){char* temp = new char[n + 1];strcpy(temp, _str);delete[] _str;_str = temp;_capacity = n;}
}void resize(size_t n, char c = '\0')
{if (n > _size){reserve(n);for (size_t i = _size; i < n; i++){_str[i] = c;}}_str[n] = '\0';_size = n;
}
注意:
1. size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()。
2. clear()只是将string中有效字符清空,不改变底层空间大小。
3. resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。
4. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserver不会改变容量大小
3.3string类对象的访问及遍历操作
char& operator[](size_t pos)
{assert(pos < _size);return _str[pos];
}const char& operator[](size_t pos) const
{assert(pos < _size);return _str[pos];
}//迭代器
iterator begin()
{return _str;
}iterator end()
{return _str + _size;
}const_iterator begin() const
{return _str;
}const_iterator end() const
{return _str + _size;
}
3.4string类对象的修改操作
void Push_back(char c)
{if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size++] = c;_str[_size] = '\0';
}void append(const char* str)
{size_t len = strlen(str);if (len + _size > _capacity){reserve(len + _size);}strcat(_str, str);_size += len;_str[_size] = '\0';
}string& operator+=(const char* str)
{append(str);return *this;
}string& operator+=(const char c)
{Push_back(c);return *this;
}const char* c_str() const
{return _str;
}size_t find(char c, size_t pos = 0) const
{assert(pos < _size);for (size_t i = pos; i < _size; i++){if (_str[i] == c){return i;}}return nops;
}size_t find(const char* s, size_t pos = 0) const
{assert(pos < _size);const char* p = strstr(_str + pos, s);if (p){return p - _str;}else{return nops;}
}string substr(size_t pos, size_t len = nops)
{assert(pos);string s;size_t end = pos + len;if (len == nops || len + pos >= _size){len = _size - pos;end = _size;}s.reserve(len);for (size_t i = pos; i < end; i++){s += _str[pos];}return s;
}
4.string的模拟实现
namespace cola
{class string{public:typedef char* iterator;typedef const char* const_iterator;//默认成员函数string(const char* str = ""): _capacity(strlen(str)), _size(_capacity){_str = new char[_capacity + 1];strcpy(_str, str);}~string(){delete[] _str;_str = nullptr;_capacity = _size = 0;}string(const string& str): _size(0), _capacity(0), _str(nullptr){string temp(str._str);swap(temp);}string& operator=(string& temp){swap(temp);return *this;}/*string(const string& str){_str = new char[str._capacity + 1];strcpy(_str, str._str);_size = str._size;_capacity = str._capacity;}*/string& operator=(const string& str){if (*this == str){return *this;}char* temp = new char[str._capacity];strcpy(temp, str._str);delete[] _str;_str = temp;_size = str._size;_capacity = str._capacity;return *this;}//迭代器iterator begin(){return _str;}iterator end(){return _str + _size;}const_iterator begin() const{return _str;}const_iterator end() const{return _str + _size;}//修改void reserve(size_t n){if (n > _capacity){char* temp = new char[n + 1];strcpy(temp, _str);delete[] _str;_str = temp;_capacity = n;}}void resize(size_t n, char c = '\0'){//扩容if (n > _size){reserve(n);for (size_t i = _size; i < n; i++){_str[i] = c;}}_str[n] = '\0';_size = n;}void Push_back(char c){if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size++] = c;_str[_size] = '\0';}void append(const char* str){size_t len = strlen(str);if (len + _size > _capacity){reserve(len + _size);}strcat(_str, str);_size += len;_str[_size] = '\0';}string& operator+=(const char* str){append(str);return *this;}string& operator+=(const char c){Push_back(c);return *this;}void clear(){_str[0] = '\0';_size = 0;}void swap(string& str){std::swap(_str, str._str);std::swap(_size, str._size);std::swap(_capacity, str._capacity);}bool empty() const{return _size == 0;}//返回私有成员size_t size() const{return _size;}size_t capacity() const{return _capacity;}const char* c_str() const {return _str;}char& operator[](size_t pos){assert(pos < _size);return _str[pos];}const char& operator[](size_t pos) const{assert(pos < _size);return _str[pos];}size_t find(char c, size_t pos = 0) const{assert(pos < _size);for (size_t i = pos; i < _size; i++){if (_str[i] == c){return i;}}return nops;}size_t find(const char* s, size_t pos = 0) const{assert(pos < _size);const char* p = strstr(_str + pos, s);if (p){return p - _str;}else{return nops;}}string substr(size_t pos, size_t len = nops){assert(pos);string s;size_t end = pos + len;if (len == nops || len + pos >= _size){len = _size - pos;end = _size;}s.reserve(len);for (size_t i = pos; i < end; i++){s += _str[pos];}return s;}string& insert(size_t pos, char c){assert(pos < _size);if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}size_t end = _size + 1;while (end > pos){_str[end] = _str[end - 1];--end;}_str[pos] = c;++_size;return *this;}string& insert(size_t pos, const char* str){assert(pos < _size);size_t len = strlen(str);if (len + _size > _capacity){reserve(len + _size);}size_t end = _size + len;while (end >= pos + len){_str[end] = _str[end - len];end--;}for (size_t i = pos; i < pos + len; i++){_str[i] = str[i - pos];}_size += len;return *this;}string& erase(size_t pos, size_t len = nops){assert(pos < _size);if (len == nops || len + _size > _capacity){_str[pos] = '\0';_size = pos;}else{size_t i = pos;while (i + len <= _size){_str[i] = _str[i + len];++i;}_size -= len;}return *this;}//比值bool operator==(const string& str) const{return strcmp(_str, str._str) == 0;}bool operator!=(const string& str) const{return !(*this == str);}bool operator>(const string& str) const{return strcmp(_str, str._str) > 0;}bool operator>=(const string& str) const{return *this == str && *this > str;}bool operator<(const string& str) const{return !(*this > str) && !(*this == str);}bool operator<=(const string& str) const{return !(*this > str);}private:char* _str;size_t _capacity;size_t _size;const static size_t nops;};const size_t string::nops = -1;ostream& operator<<(ostream& out, const string& s){out << s.c_str();return out;}istream& operator>>(istream& in, string& s){s.clear();char c;char buff[128];c = in.get();size_t i = 0;while (c != ' ' && c != '\n'){if (i == 127){buff[i] = '\0';s += buff;i = 0;}buff[i++] = c;c = in.get();}if (i != 0){buff[i] = '\0';s += buff;}return in;}}