一、字符串类的认识
C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数, 但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。在OJ中,有关字符串的题目基本以string类的形式出现,而且在常规工作中,为了简单、方便、快捷,基本 都使用string类,很少有人去使用C库中的字符串操作函数。为了增加自己对于string的理解,自己将模仿库中string类有的方法,设计一个简单的string类。其中类成员包括以下:
class string { private: char* _str;//字符串首地址 size_t _capacity;//字符串容量 size_t _size;//有效数据的个数 public: typedef char* iterator; }
二、库中string常用的方法
我主要会实现string中经常会用到的方法,若大家想要了解更多关于string的细节,可以登录这个C++查询网站https://cplusplus.com/reference/自行查询。下面是一些常用方法以及代码片段,可能前面出现的方法会用到后面出现的方法的实现,若有疑问可以看最后面的完整代码
正向迭代器
iterator begin() { return _str; } iterator end() { return _str + _size; }
+=
string& operator+=(char c) { if (_size == _capacity) { _capacity = _capacity == 0 ? 4 : 2 * _capacity; char* tmp = new char[_capacity +1]; strcpy(tmp, _str); delete[] _str; _str = tmp; } _str[_size] = c; _str[_size + 1] = '\0'; _size++; return *this; } string& operator+=(const char* str) { append(str); return *this; }
push_back(尾插)
void push_back(char c) { *this += c; }
append(在字符串末尾追加)
void append(const char* str) { int i = 0; while (str[i]) { push_back(str[i]); i++; } }
clear(清除掉字符串的数据)
void clear() { _size = 0; _str[0] = '\0'; }
swap(交换两个字符串的内容)
void swap(string& s) { std::swap(_str,s._str); std::swap(_size, s._size); std::swap(_capacity, s._capacity); }
c_str(返回字符串的首地址)
const char* c_str()const { return _str; }
resize(将字符串设定为指定大小,字符串占满所开辟的空间)
void resize(size_t n, char c = '\0') { if (n > _capacity) { reserve(n); for (int i = _size; i < _capacity; i++) { _str[i] = c; } _size = _capacity; } else { _size = n; } }
reserve(预开辟出空间,字符串还是原来的大小(一般不缩容))
void reserve(size_t n) { if (n > _capacity) { _capacity = n; char* tmp = new char[_capacity + 1]; strcpy(tmp, _str); delete[] _str; _str = tmp; } }
find(返回字符c在string中第一次出现的位置/返回子串s在string中第一次出现的位置)
size_t find(char c, size_t pos = 0) const { for (size_t i = pos; i < _size; i++) { if (_str[i] == c) return i; } return std::string::npos; } size_t find(const char* s, size_t pos = 0) const { const char* ptr = std::strstr(_str + pos, s); if (ptr == nullptr) return std::string::npos; else { return ptr - _str; } }
insert(在pos位置上插入字符c/字符串str,并返回该字符的位置)
string& insert(size_t pos, char c) { if (_size == _capacity) { reserve(_capacity == 0 ? 4 : 2 * _capacity); } size_t end = _size - 1; while (end >= pos) { _str[end + 1] = _str[end]; end--; } _str[pos] = c; return *this; } string& insert(size_t pos, const char* str) { int len = 0; while (str[len++]); if (_size + len > _capacity) { reserve(_size + len); } memmove(_str + pos + len, _str + pos, len * sizeof(char)); for (int i = pos; i < pos + len; i++) { _str[i] = str[i - pos]; } _size += len; return *this; }
erase(删除pos位置上的元素,并返回该string)
string& erase(size_t pos, size_t len) { memmove(_str + pos, _str + pos + len, (_size - pos-len) * sizeof(char)); _size -= len; return *this; }
三、完整代码
//string.h #pragma once #define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> #include <string> //using namespace std; namespace sxb { class string { friend std::ostream& operator<<(std::ostream& _cout, const string& s); friend std::istream& operator>>(std::istream& _cin, string& s); private: char* _str; size_t _capacity; size_t _size; public: typedef char* iterator; public: string(const char* str = "") { //_str = str; int len = 0; while(str[len] != ' ' && str[len] != '\0') { len++; } _str = new char[len + 1]; for (int i = 0; i < len; i++) { _str[i] = str[i]; } _str[len] = '\0'; _capacity = len; _size = len; } string(const string& s) { _str = new char[s.size() + 1]; strcpy(_str, s.c_str()); _str[s.size()] = '\0'; _capacity = s.size(); _size = s.size(); } string& operator=(const string& s) { for (int i = 0; i < size(); i++) { _str += s[i]; } return *this; } ~string() { delete[] _str; _size = 0; _capacity = 0; } // // iterator iterator begin() { return _str; } iterator end() { return _str + _size; } // / // // modify void push_back(char c) { *this += c; } string& operator+=(char c) { if (_size == _capacity) { _capacity = _capacity == 0 ? 4 : 2 * _capacity; char* tmp = new char[_capacity +1]; strcpy(tmp, _str); delete[] _str; _str = tmp; } _str[_size] = c; _str[_size + 1] = '\0'; _size++; return *this; } void append(const char* str) { int i = 0; while (str[i]) { push_back(str[i]); i++; } } string& operator+=(const char* str) { append(str); return *this; } void clear() { _size = 0; _str[0] = '\0'; } void swap(string& s) { std::swap(_str,s._str); std::swap(_size, s._size); std::swap(_capacity, s._capacity); } const char* c_str()const { return _str; } /// capacity size_t size()const { return _size; } size_t capacity()const { return _capacity; } bool empty()const { return _str[0] == '\0'; } void resize(size_t n, char c = '\0') { if (n > _capacity) { reserve(n); for (int i = _size; i < _capacity; i++) { _str[i] = c; } _size = _capacity; } else { _size = n; } } void reserve(size_t n) { if (n > _capacity) { _capacity = n; char* tmp = new char[_capacity + 1]; strcpy(tmp, _str); delete[] _str; _str = tmp; } } /// access char& operator[](size_t index) { return _str[index]; } const char& operator[](size_t index)const { return _str[index]; } /// relational operators bool operator==(const string& s) { if (_size != s.size()) return false; for (int i = 0; i < _size; i++) { if (_str[i] != s[i]) return false; } return true; } bool operator!=(const string& s) { return !operator==(s); } 返回c在string中第一次出现的位置 size_t find(char c, size_t pos = 0) const { for (size_t i = pos; i < _size; i++) { if (_str[i] == c) return i; } return std::string::npos; } 返回子串s在string中第一次出现的位置 size_t find(const char* s, size_t pos = 0) const { const char* ptr = std::strstr(_str + pos, s); if (ptr == nullptr) return std::string::npos; else { return ptr - _str; } } 在pos位置上插入字符c/字符串str,并返回该字符的位置 string& insert(size_t pos, char c) { if (_size == _capacity) { reserve(_capacity == 0 ? 4 : 2 * _capacity); } size_t end = _size - 1; while (end >= pos) { _str[end + 1] = _str[end]; end--; } _str[pos] = c; return *this; } string& insert(size_t pos, const char* str) { int len = 0; while (str[len++]); if (_size + len > _capacity) { reserve(_size + len); } memmove(_str + pos + len, _str + pos, len * sizeof(char)); for (int i = pos; i < pos + len; i++) { _str[i] = str[i - pos]; } _size += len; return *this; } 删除pos位置上的元素,并返回该元素的下一个位置 string& erase(size_t pos, size_t len) { memmove(_str + pos, _str + pos + len, (_size - pos-len) * sizeof(char)); _size -= len; return *this; } }; std::ostream& operator<<(std::ostream& _cout, const string& s) { for (int i = 0; i < s.size(); i++) { _cout << s[i]; } return _cout; } std::istream& operator>>(std::istream& _cin, string& s) { char buffer[128]; int len = 0; char bu = _cin.get(); while (bu != ' ' && bu != '\n') { buffer[len] = bu; len++; bu = _cin.get(); } for (int i = 0; i < len; i++) { s += buffer[i]; } return _cin; } }