赞
踩
string的模拟实现其实就是增删改查,只不过加入了类的概念。
为了防止与std里面的string冲突,所以这里统一用String。
目录
4.1 bool operator<(const String& s) const
4.2 bool operator==(const String& s) const
4.3 bool operator<=(const String& s) const
4.4 bool operator>(const String& s) const
4.5 bool operator>=(const String& s) const
4.6 bool operator!=(const String& s) const
6.1 ostream& operator<<(ostream& out, const String& s)
6.2 istream& operator>>(istream& in, String& s)
String operator+(const String& s2)
对于构造函数来说有有参构造和无参构造
所以直接把他们结合起来
default | string(); |
---|---|
copy | string (const string& str); |
1.string();//无参构造
2.string (const string& str);//有参构造
- String(const char* str = "") :_size(strlen(str)), _capacity(_size)
- {
- _str = new char[_capacity+1];
- strcpy(_str, str);
- }
如果把_str的初始化放在初始化列表会出问题
- private:
- char* _str;
- size_t _size;
- size_t _capacity;
- static const size_t npos = -1;
- String(const char* str = "") :_str(new char [_capacity+1]),_size(strlen(str)), _capacity(_size)
- {
- //_str = new char[_capacity+1];
- strcpy(_str, str);
- }
初始化列表是会按照成员变量的顺序去初始化,所以这里 初始化_str,_capacity没有初始化,所以在开空间的时候会出问题,当然你可以换一换位置,但是未免太繁琐,同时这里不能把_str设置为nullptr,如果设置为空,那么_size正初始化就会出问题
这里的析构函数没有那么多细节,直接释放空间,然后处理其他的成员变量就行了
- ~String()
- {
- delete[] _str;//注意这里的delete[],不是delete
- _str = nullptr;
- _size = 0;
- _capacity = 0;
- }
其实迭代器可以理解为是指针在进行,有的底层是指针有的是其他的方法,这里我们用指针去模拟实现
- //迭代器
- typedef char* iterator;
- typedef char* const_iterator;
- iterator begin()
- {
- return _str;
- }
- iterator end()
- {
- return _str + _size;
- }
- const_iterator begin()const
- {
- return _str;
- }
- const_iterator end()const
- {
- return _str + _size;
- }

迭代器也需要const类型,这样const类型的函数才能去调用,所以写两份。注意范围for就是无脑替换迭代器,本质和迭代器是一样的。
测试案例
- #define _CRT_SECURE_NO_WARNINGS 1
- #include"String.h"
- int main()
- {
- String str("Test string");
- for (String::iterator it = str.begin(); it != str.end(); ++it)
- cout << *it;
- cout << '\n';
- for (auto ch : str)
- {
- cout << ch << " ";
- }
- cout << endl;
- return 0;
- }
还有反向迭代器,这里就不一一列举了,想了解的可以参考string类的介绍
1.capacity()//表示容量大小
2.size()//有效数据大小
3.max_size()//最大有多少数据
4.empty()//是否为空
5.resize()//扩容
6.reserve()//扩容
- size_t size()const
- {
- return _size;
- }
- size_t capacity()const
- {
- return _capacity;
- }
- size_t max_size()const
- {
- return 4294967291;
- }
- bool empty()const
- {
- return _size == 0;
- }
- void reserve(size_t n)
- {
- if (n > _capacity)
- {
- char* tmp = new char[n + 1];
- strcpy(tmp, _str);
- delete[]_str;
- _str = tmp;
- }
- _capacity = n;
- }
- void resize(size_t n, char ch = '\0')
- {
- if (n < _size)
- {
- _str[n] = '\n';
- _size = n;
- }
- else
- {
- reserve(n);
- while (_size < n)
- {
- _str[_size] = ch;
- _size++;
- }
- _str[_size] = '\0';
- }
- }

1.对于empty,它是如果为空,才是真,不为空就假
2.对于resize和reserve来说,从参数列表可以看出,resize可以设置初始值,也就是可以改变_size,
但是reserve不行,同时reserve设置的n如果比capacity小的话,是不会造成任何影响或者改变的
3.这里的max_size,这里我设置了一个常量,但是并没有这么简单,因为max_size是根据你当前系统来判断该给多大的,因素很多,但是实现起来很麻烦,这里就简单的设置为初始值了
测试案例
由于其他的测试在之前的string类博客测试过了,所以这里就不一一测试了
- #define _CRT_SECURE_NO_WARNINGS 1
- #include"String.h"
- int main()
- {
- String str("Test string");
- cout << "size: " << str.size() << "\n";
- cout << "capacity: " << str.capacity() << "\n";
- cout << "max_size: " << str.max_size() << "\n";
- return 0;
- }
运算符重载就是>,<,=,>=,<=这四种,但是其实写一个大于和等于或者写一个小于和等于就行了,因为其他的都能复用
- bool operator<(const String& s) const
- {
- return strcmp(_str, s._str) < 0;
- }
- bool operator==(const String& s) const
- {
- return strcmp(_str, s._str) == 0;
- }
由于上面写了<和=的运算符重载,所以下面这几个直接复用前面的东西就行, 注意上面的写法用的是字符串函数进行比较,但是库里面用的是模板,所以这里有出入,如果用模板,就不能这样比较了
- bool operator<=(const String& s) const
- {
- return *this < s || *this == s;
- }
- bool operator>(const String& s) const
- {
- return !(*this <= s);
- }
- bool operator>=(const String& s) const
- {
- return !(*this < s);
- }
- bool operator!=(const String& s) const
- {
- return !(*this == s);
- }
String substr(size_t pos = 0, size_t len = npos)const
- String substr(size_t pos = 0, size_t len = npos)const
- {
- assert(pos >= 0 && pos < _size);
- size_t end = len + pos;//最后的位置
- String s = "";
- if (len == npos || pos + len > _size)//如果长度已经大于当前字符串长度
- {
- len = _size - pos;//新长度就等于pos到_size这么长
- end = _size;//
- }
- s.reserse(len);//开辟空间
- for (int i = pos; i < end; i++)//从pos开始到end结束
- {
- s += _str[i];
- }
- return s;
- }

测试样例:
size_t find(char c, size_t pos = 0)const
- size_t find(char c, size_t pos = 0)const
- {
- for (int i = pos;i < _size; i++)
- {
- if (_str[i] = c)
- {
- return i;
- }
- }
- return npos;
- }
查找一个字符 之间从pos位置开始遍历就行了
size_t find(const char* s, size_t pos = 0)const
- size_t find(const char* s, size_t pos = 0)const
- {
- char* p = strstr(_str + pos, s);
- if (p)
- {
- return p - _str;
- }
- else
- {
- return npos;
- }
- }
查找一个字符直接用库函数strstr就行
测试用例:
由于这里的流插入和流提取不会涉及到私有的成员变量,所以不用写成友员函数
- ostream& operator<<(ostream& out, const String& s)
- {
- for (auto ch : s)
- {
- out << ch;
- }
- return out;
- }
- //流提取
- istream& operator>> (istream& in, string& s)
- {
- s.clear();
- char ch = in.get();
- while (ch != ' ' && ch != '\n')
- {
- s += ch;
- ch = in.get();
- }
-
- return in;
- }
对于上面这段代码来说,我们首先要用一个clear去清理一下,因为不清理会导致之前的数据存在。
还有一点就是这段代码并不好,因为读字符的时候可能会导致频繁的扩容,我们电脑上面的程序可不止一个,不能一直中断其他程序,来进行这个,这样对于计算机的消耗有点大
- istream& operator>>(istream& in, String& s)
- {
- char buff[129];
- size_t i = 0;
- char ch;
- ch = in.get();
- while (ch != ' ' && ch != '\0')
- {
- buff[i++] = ch;
- if (i == 128)
- {
- buff[i] = '\0';
- s += buff;
- i = 0;
- }
- ch = in.get();
- }
- if (i > 0)
- {
- buff[i] = '\0';
- s += buff;
- }
- return in;
- }

这段代码就是对之前的一个改良,设置一个数组去存, 当存到128个字符的时候再一起把它放进字符串里面去,最后还有判断一下如果i!=128的情况即可
这里用成员函数来写,库里面用的是非成员函数
- String operator+(const String& s2)
- {
- String ret;
- ret._size = _size + s2._size;
- ret._str = new char[_capacity + s2._capacity];
- strcpy(ret._str, _str);
- strcpy(ret._str + _size, s2._str);
- return ret;
- }
先开空间,然后把两个字符串放进去就行。
- #pragma once
- #include<iostream>
- #include<assert.h>
- using namespace std;
- class String
- {
- public:
-
- //迭代器
- typedef char* iterator;
- typedef char* const_iterator;
- iterator begin()
- {
- return _str;
- }
- iterator end()
- {
- return _str + _size;
- }
- const_iterator begin()const
- {
- return _str;
- }
- const_iterator end()const
- {
- return _str + _size;
- }
- //构造函数
- String(const char* str = "") :_size(strlen(str)), _capacity(_size)
- {
- _str = new char[_capacity+1];
- strcpy(_str, str);
- }
- //析构函数
- ~String()
- {
- delete[] _str;
- _str = nullptr;
- _size = 0;
- _capacity = 0;
- }
- //拷贝构造
- String(const String& s):_str(nullptr),_size(s._size), _capacity(s._capacity)
- {
- _str = new char[_capacity + 1];
- strcpy(_str, s._str);
- _size = s._size;
- _capacity = s._capacity;
- }
- //下表访问
- char& operator[](size_t pos)
- {
- assert(pos < _size||pos>=0);
- return _str[pos];
- }
- void swap(String& s)
- {
- std::swap(_str, s._str);
- std::swap(_size, s._size);
- std::swap(_capacity, s._capacity);
- }
- //赋值运算符重载
- String&operator=(String tmp)
- {
- swap(tmp);
- return *this;
- }
- //Capacity
- size_t size()const
- {
- return _size;
- }
- size_t capacity()const
- {
- return _capacity;
- }
- size_t max_size()const
- {
- return 4294967291;
- }
- bool empty()const
- {
- return _size == 0;
- }
- void reserse(size_t n)
- {
- if (n > _capacity)
- {
- char* tmp = new char[n + 1];
- strcpy(tmp, _str);
- delete[]_str;
- _str = tmp;
- }
- _capacity = n;
- }
- void resize(size_t n, char ch = '\0')
- {
- if (n < _size)
- {
- _str[n] = '\n';
- _size = n;
- }
- else
- {
- reserse(n);
- while (_size < n)
- {
- _str[_size] = ch;
- _size++;
- }
- _str[_size] = '\0';
- }
- }
- //Element access
- char& back()
- {
- return _str[_size - 1];
- }
- const char& back()const
- {
- return _str[_size - 1];
- }
- char& front()
- {
- return _str[0];
- }
- const char& front()const
- {
- return _str[0];
- }
- //Modifiers
- void append(const char* str)
- {
- size_t n = _size + strlen(str);
- if (n > _capacity)
- {
- reserse(n);
- _capacity = n;
- }
- strcat(_str, str);
- _size += strlen(str);
- }
- void push_back(char ch)
- {
- if (_size == _capacity)
- {
- reserse(_capacity == 0 ? 4 : 2 * _capacity);
- }
- _str[_size] = ch;
- _size++;
- _str[_size] = '\0';
- }
- String& operator+=(const String& s)
- {
- append(s._str);
- return *this;
- }
- String& operator+=(const char* str)
- {
- append(str);
- return *this;
- }
-
- String& operator+=(char ch)
- {
- push_back(ch);
- return *this;
- }
- void insert(size_t pos, char ch)
- {
- assert(pos <= _size && pos >= 0);
- if (_size == _capacity)
- {
- reserse(_capacity == 0 ? 4 : _capacity * 2);
- }
- size_t end = _size + 1;
- while (end > pos)
- {
- _str[end] = _str[end-1];
- end--;
- }
- _str[pos] = ch;
- _size++;
- }
- void insert(size_t pos, const char* str)
- {
- assert(pos <= _size && pos >= 0);
- int len = strlen(str);
- if (_size + len > _capacity)
- {
- reserse(_size + len);
- }
- size_t end = _size+1;
- while (end > pos)
- {
- _str[end + len] = _str[end-1];
- end--;
- }
- strncpy(_str + pos, str, len);
- _size += len;
- }
- void erase(size_t pos = 0, size_t len = npos)
- {
- assert(pos >= 0 && pos < _size);
- if (len == npos||pos+len>_size)
- {
- _str[pos] = '\0';
- _size = pos;
- }
- else
- {
- size_t end = pos + len;
- while (end <= _size)
- {
- _str[end - len] = _str[end];
- end++;
- }
- _size -= len;
- }
- }
- //String operations:
- const char* c_str()const
- {
- return _str;
- }
- const char* data()const
- {
- return _str;
- }
- size_t find(char c, size_t pos = 0)const
- {
- for (int i = pos;i < _size; i++)
- {
- if (_str[i] == c)
- {
- return i;
- }
- }
- return npos;
- }
- size_t find(const char* s, size_t pos = 0)const
- {
- char* p = strstr(_str + pos, s);
- if (p)
- {
- return p - _str;
- }
- else
- {
- return npos;
- }
- }
- String substr(size_t pos = 0, size_t len = npos)const
- {
- assert(pos >= 0 && pos < _size);
- size_t end = len + pos;
- String s = "";
- if (len == npos || pos + len > _size)
- {
- len = _size - pos;
- end = _size;
- }
- s.reserse(len);
- for (int i = pos; i < end; i++)
- {
- s += _str[i];
- }
- return s;
- }
- String operator+(const String& s2)
- {
- String ret;
- ret._size = _size + s2._size;
- ret._str = new char[_capacity + s2._capacity];
- strcpy(ret._str, _str);
- strcpy(ret._str + _size, s2._str);
- return ret;
- }
- bool operator<(const String& s) const
- {
- return strcmp(_str, s._str) < 0;
- }
-
- bool operator==(const String& s) const
- {
- return strcmp(_str, s._str) == 0;
- }
-
- bool operator<=(const String& s) const
- {
- return *this < s || *this == s;
- }
-
- bool operator>(const String& s) const
- {
- return !(*this <= s);
- }
-
- bool operator>=(const String& s) const
- {
- return !(*this < s);
- }
-
- bool operator!=(const String& s) const
- {
- return !(*this == s);
- }
- private:
- char* _str;
- size_t _size;
- size_t _capacity;
- static const size_t npos = -1;
- };
- //non_member constants
- ostream& operator<<(ostream& out, const String& s)
- {
- for (auto ch : s)
- {
- out << ch;
- }
- return out;
- }
- istream& operator>>(istream& in, String& s)
- {
- char buff[129];
- size_t i = 0;
- char ch;
- ch = in.get();
- while (ch != ' ' && ch != '\0')
- {
- buff[i++] = ch;
- if (i == 128)
- {
- buff[i] = '\0';
- s += buff;
- i = 0;
- }
- ch = in.get();
- }
- if (i > 0)
- {
- buff[i] = '\0';
- s += buff;
- }
- return in;
- }

以上就是string的全部内容了,
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。