- namespace simulate_string
- {
-
-
-
-
-
- class string
- {
- private:
- char* _str;
- size_t _size;
- size_t _capacity;
- const static int npos = -1;//类型说明+作用域变量;
- public:
- typedef char* iterator;
- typedef const char* const_iterator;
-
- //迭代器相当于直接调用该类型的指针
- iterator begin()//指向首元素地址
- {
- return _str;
- }
-
- const_iterator begin() const
- {
- return _str;
- }
-
- iterator end()//指向末尾元素的下一个地址,在string类中该地址存放的是‘\0’
- {
- return _str+_size;
- }
-
- const_iterator end()const
- {
- return _str + _size;
- }
-
- //构造函数
- string(const char* str="")
- :_size(strlen(str))
- {
- _capacity = _size;//防止_size和_capacity声明顺序与初始化列表顺序相反;
-
- //开空间(_capacity是有效容量不包括'\0')
- _str = new char[_capacity+1];
- strcpy(_str,str);
- }
-
- //拷贝构造
- string(const string& s)
- :_size(s._size)
- {
- _capacity = s._capacity;
- _str = new char[_capacity + 1];//多一个空间存放'\0'
- strcpy(_str,s._str);//会拷贝‘\0’;
- std::cout << "string(const string& s)" << std::endl;
-
- }
-
- //移动拷贝构造(移动语义)
- string(string&& s)//这里右值引用为什么不需要加const?因为要对右值进行资源转移。
- {
- swap(s);
- std::cout << "string(string&& s)" << std::endl;
- }
-
- void swap(string& s)
- {
- std::swap(_str, s._str);
- std::swap(_size, s._size);
- std::swap(_capacity, s._capacity);
- }
-
- ~string()
- {
- delete[] _str;
- _str = nullptr;
- _capacity = _size = 0;
- }
-
- size_t size() const
- {
- return _size;
- }
-
-
- char& operator[](size_t pos)
- {
- assert(pos<_size);
- return _str[pos];
- }
-
- const char& operator[](size_t pos) const
- {
- assert(pos < _size);
- return _str[pos];
- }
-
- const char* c_str()
- {
- return _str;
- }
-
- //赋值运算符重载
- string& operator=(const string& s)
- {
- if (this != &s)
- {
- char* tmp = new char[s._capacity + 1];
- strcpy(tmp, s._str);
- delete[] _str;
- _str = tmp;
-
- _size = s._size;
- _capacity = s._capacity;
- }
- return *this;
- }
-
- // 不修改成员变量数据的函数,最好都加上const
-
- //strcmp会返回0,-1,1;分别代表相等,小于,大于;
- 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);
- }
-
-
-
-
-
- void push_back(char& ch)
- {
- insert(_size,ch);
- }
-
- void append(const char* str)
- {
- insert(_size,str);
- }
-
- //如果出现s1+=s1的情况,阁下该如何应对?
- string& operator+=(const string& s)
- {
- if (this!= &s)
- {
- append(s._str);
- }
- else
- {
-
- //创建临时对象;
- string news(s);
- append(news._str);
- }
-
- return *this;
- }
-
- string& operator+=(char& ch)
- {
- push_back(ch);
- return *this;
- }
-
- string& operator+=(const char* str)
- {
- append(str);
- return *this;
- }
-
- void reserve(size_t n)//不能缩容
- {
- if (n > _capacity)//需要的空间大于当前容量才进行扩容!
- {
- char* tmp = new char[n + 1];
- strcpy(tmp, _str);
- delete[] _str;
- _str = tmp;
- _capacity = n;//有效容量不包括\0;
- }
- }
- void resize(size_t n,char ch='\0')//开空间加初始化
- {
-
- if (n <= _size)
- {
- _size = n;
- _str[_size] = '\0';
- }
-
- else
- {
- if (n>_capacity)
- {
- reserve(n);
- }
-
- int i = _size;
-
- while (i < n)
- {
- _str[i] = ch;//初始化为传递的字符,没有就使用默认缺省;
- ++i;
- }
-
- _size = n;
- _str[_size] = '\0';
-
- }
-
- }
-
- string& insert(size_t pos,char ch)
- {
- assert(pos<=_size);
- if (_size + 1 > _capacity)//需要扩容
- {
- reserve(_capacity * 2);
- }
-
- size_t end = _size+1;
- while (end>pos)//当pos为0这种情况时,无符号整数0再减1是无符号整数的最大值而不是-1,所以当end从0再减1时,会继续循环,访问_str[max],程序会崩;
- {
- //_str[end+1] = _str[end];不可以程序会崩;
-
- _str[end] = _str[end-1];
- --end;
- }
- _str[pos] = ch;
- ++_size;
- return *this;
-
- }
-
-
- string& insert(size_t pos, const char* str)
- {
- assert(pos <= _size);
- size_t len = strlen(str);//计算要插入字符的长度;
-
- if (_size + len > _capacity)
- {
- reserve(len + _size);//需要开辟的有效空间,不包括'\0'
- }
-
- size_t end =_size;
-
- while (end>pos)//当end最小为1;
- {
- _str[end+len-1]=_str[end-1];
- --end;
- }
-
- strncpy(_str+pos,str,len);//strcpy会把默认字符串的'\0'也加在后面,会覆盖原字符串的后面第一个字符;
-
- _size += len;
- _str[_size] = '\0';
- return *this;
-
- }
-
-
- string& erase(size_t pos=0,size_t len=npos)//如果不说明删除多少个,默认从当前位置删到完;
- {
- assert(pos<_size);
- if (len==npos||pos+len>=_size)//如果前面不判断len==npos,后面pos+len会溢出,size_t无符号正整数最大就是-1的补码,因为是无符号;
- {
- _size = pos;
- _str[_size] = '\0';
- }
- else
- {
- //连‘\0’都拷贝,把_str+pos+len以后的所有字符都拷贝过来;
- strcpy(_str+pos,_str+pos+len);
- _size -= len;
- }
- return *this;
- }
-
-
-
- //返回一个字符在_str中第一次出现的位置;
- size_t find(char ch,size_t pos=0)
- {
- assert(pos<_size);
- int i = 0;
- while (i<_size)
- {
- if (_str[i]==ch)
- {
- return i;
- }
- ++i;
- }
- return npos;
-
- }
-
- //返回一个字符在_str中最后一次出现的位置;
- //实质是在_str中从后往前找与ch相等的下标索引;
- size_t rfind(char ch,size_t pos=npos)//size_t类型的pos被赋予size_t类型的npos=-1,则npos等于max int;
- {
- assert(pos>=0);
- if (pos == npos||pos>=_size)
- pos = _size-1;
- int i =pos;
- while (i>=0)
- {
- if (_str[i]==ch)
- {
- return i;
- }
- --i;
- }
- return npos;
- }
-
-
- //按顺序找_str中在str中第一次出现的位置,返回一个指针,指向这个字符;
- size_t find(const char* str,size_t pos=0)
- {
- assert(pos<_size);
- //解释strstr();实际上就是找字符串str在_str中第一次出现的位置;
- //Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1.
-
- char* p = strstr(_str+pos,str);
- //库里面的,按顺序找字符串2在字符串1中第一次出现的位置;
-
- if (p==nullptr)
- {
- return npos;
-
- }
- else
- {
- return p-_str;
- }
- }
-
-
- };
-
-
-
- //************* 类外 ***************
- //流插入(写到类外保证cout<
- std::ostream& operator<<(std::ostream& out,const string& s)
- {
- for (int i=0;i
size();++i) - {
- out << s[i] <<' ';
- }
-
- return out;
- }
-
- //cout和cin分别是输入输出头文件下的一个ostream类对象和istream类对象;
-
-
- //流提取
- std::istream& operator>>(std::istream& in,string& s)
- {
- char ch=in.get();//输入流中的函数,每次取一个字符;相当于连空格都可以取到的cin;
-
- while (ch!=' '&&ch != '\n')//只要不读到enter也就是换行符,就一直提取;
- {
- s += ch;
- ch = in.get();
- }
-
- return in;//支持连续提取;
- }