string的兄弟String
一、前言
在实现string类之前,我们需要知道string是表示字符串的字符串类 ,string类的成员变量如下(库中存在string类,所以命名为string会造成冲突,所以我们定义一个String类去实现string类的各种功能):
class String{
private:
char* _str; //字符串指针
size_t _capacity; //容量
size_t _size; //字符串大小
};
二、初始化与清理
2.1构造函数
String(const char* str = "")
{
_size = strlen(str);
_capacity = _size;
_str = new char[_capacity + 1]; //申请连续空间
strcpy(_str, str); //拷贝字符串内容
}
2.2析构函数
~String(){
if (_str){
delete[] _str;
_str = nullptr; //空间置空
_size = _capacity = 0; //容量大小都置0
}
}
2.3拷贝构造
//1.一般写法
String(const String& s){
char *tmp = new char[s._capacity+1];
strcpy(tmp, s._str);
delete[] _str;
_str = tmp;
_size = s._size;
_capacity = s._capacity;
}
//2.现代写法
String(const String& s)
:_str(nullptr)
, _size(s._size)
, _capacity(s._capacity)
{
char* tmp(s._str);
swap(_str, tmp);
}
2.4清除
void clear(){
char *tmp = new char[_capacity + 1];
delete[] _str;
tmp[0] = '\0';
_str = tmp;
_size = 0;
}
三、运算符重载
3.1赋值运算符
//一般写法
String& operator=(const String &s){
char *tmp = new char[s._capacity+1];
strcpy(tmp, s._str);
delete[] _str;
_str = tmp;
_size = s._size;
_capacity = s._capacity;
return *this;
}
//现代写法
String& operator=(String s){
swap(_str, s._str);
_size = s._size;
_capacity = s._capacity;
return *this;
}
3.2其他运算符
//<运算符
bool operator<(const String& s){
size_t i = _size;
size_t c = s._size;
if (i == 0 && c == 0){
return false;
}
size_t num = 0;
while (i&&c){
if (_str[num] < s._str[num]){
return true;
}
else if(_str[num]>s._str[num]){
return false;
}
else{
i--;
c--;
num++;
}
}
if (i == 0&&c!=0){
return true;
}
return false;
}
//==运算符
bool operator==(const String& s){
size_t i = _size;
size_t c = s._size;
int num = 0;
while (i&&c){
if (_str[num] != s._str[num]){
return false;
}
i--;
c--;
num++;
}
if (c || i){
return false;
}
return true;
}
//<=运算符
bool operator<=(const String& s){
return *this<s || *this == s;
}
//>运算符
bool operator>(const String& s){
return !(*this <= s);
}
//>=运算符
bool operator>=(const String& s){
return !(*this < s);
}
//!=运算符
bool operator!=(const String& s){
return !(*this == s);
}
//+=字符运算符
String& operator+=(char c){
PushBack(c); //尾插
return *this;
}
//+=字符串运算符
String& operator+=(const char* str){
Append(str); //尾插字符串
return *this;
}
//[]运算符
char& operator[](size_t index){
return _str[index];
}
const char& operator[](size_t index)const{
return _str[index];
}
四、迭代器
4.1迭代器
typedef char* iterator
iterator begin(){
return &_str[0];
}
iterator end(){
return &_str[_size];
}
4.2const迭代器
typedef const char* const_iterator;
const_iterator begin()const{
return &_str[0];
}
const_iterator end()const{
return &_str[_size];
}
五、其他操作
5.1扩容
//容量扩容
void reserve(size_t newCapacity){
if (newCapacity > _capacity){
char *tmp = new char[newCapacity+1];
strcpy(tmp, _str);
swap(tmp, _str);
_capacity = newCapacity;
}
}
//大小扩容
void resize(size_t newSize, char c = '\0'){
if (newSize > _capacity){
reserve(newSize);
}
if (newSize > _size){
size_t num = _size;
while (num != newSize){
PushBack(c);
num++;
}
}
_size = newSize;
_str[_size] = '\0';
}
5.2插入,删除字符/字符串
// 在pos位置上插入字符c/字符串str,并返回该字符的位置
String& insert(size_t pos, char c){
assert(pos < _capacity);
if (_size >= _capacity){
size_t newcapacity = _capacity == 0 ? 15 : 2 * _capacity;
reserve(newcapacity); //扩容
}
size_t it =_size;
while (it != pos){
_str[it] = _str[it-1];
it--;
}
_str[pos] = c;
_size++;
_str[_size] = '\0';
return *(this+pos);
}
String& insert(size_t pos, const char* str){
assert(pos < _capacity);
if (_size + strlen(str) >= _capacity){
reserve(_size + strlen(str));
}
size_t l = strlen(str);
size_t it = _size;
while (it !=pos){
_str[it + l-1] = _str[it-1];
it--;
}
size_t p = pos;
size_t i = 0;
while (i < l){
_str[p] = str[i];
p++;
i++;
}
_size += l;
_str[_size] = '\0';
return *(this+pos);
}
//尾插一个字符
void PushBack(char c){
if (_size >= _capacity){
size_t newcapacity = _capacity == 0 ? 15 : 2 * _capacity;
reserve(newcapacity);
}
_str[_size++] = c;
_str[_size] = '\0';
}
//尾插字符串
void Append(const char* str){
if (_size + strlen(str) >=_capacity){
reserve(_size + strlen(str));
}
for (size_t i = 0; i < strlen(str); i++){
PushBack(str[i]);
}
}
//删除pos位置上的元素
String& erase(size_t pos, size_t len){
assert(pos + len < _capacity);
size_t p = pos;
while (p<_size-len){
_str[p] = _str[p+len];
p++;
}
_size-=len;
_str[_size] = '\0';
return *(this+pos);
}
5.3查找
//返回字符c在string中第一次出现的位置
size_t find(char c, size_t pos = 0) const{
while (pos<_size){
if (_str[pos] == c){
return pos;
}
pos++;
}
return -1;
}
//返回子串s在string中第一次出现的位置
size_t find(const char* s, size_t pos = 0) const{
size_t i = 0;
while (pos < _size){
size_t c_pos = pos;
while(s[i]!='\0'&&_str[pos]!='\0'&&_str[pos] == s[i]){
i++;
pos++;
}
if (s[i] == '\0'){
return c_pos;
}
if (_str[pos] == '\0'){
return -1;
}
pos = c_pos+1;
i = 0;
}
return -1;
}
5.4判空,交换以及其他接口的实现
//交换对象
void Swap(String& s){
swap(_str, s._str);
int tmp = s._size;
s._size = _size;
_size = tmp;
tmp = _capacity;
_capacity = s._capacity;
s._capacity = tmp;
}
//字符串首地址
const char* c_str()const{
return _str;
}
//大小
size_t size()const{
return _size;
}
//容量
size_t capacity()const{
return _capacity;
}
//判空
bool empty()const{
return _size == 0;
}
5.5友元函数的输入输出
class String{
friend ostream& operator<<(ostream& _cout, const String& s);
friend istream& operator>>(istream& _cin, String& s);
private:
char* _str; //字符串指针
size_t _capacity; //容量
size_t _size; //字符串大小
}
ostream& operator<<(ostream& _cout, const String& s){
_cout << s._str;
return _cout;
}
istream& operator>>(istream& _cin, String& s){
_cin >> s._str;
return _cin;
}
关于string的常用接口的实现基本结束,还有部分少见接口,读者可以自行实现。