注意

实现仿cplus官网的的string类,对部分主要功能实现

实现

头文件

#pragma once#include #include #include namespace mystring{class string{friend std::ostream& operator<<(std::ostream& os, const string& str);public://迭代器typedef char* iterator;typedef const char* cosnt_iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}cosnt_iterator begin() const{return _str;}cosnt_iterator end() const{return _str + _size;}//初始化string(const char* str = "");string(const string& obj);string& operator=(const string& obj);//增void PsuhBack(char ch);string& Append(const char* str);string& Insert(size_t pos, char ch);string& Insert(size_t pos, const char* str);string& operator+=(char ch);string& operator+=(const char* str);void Reserve(size_t capacity);void Resize(size_t capacity, char ch = '\0');//删string& Erase(size_t pos, size_t n = npos);void Clear();//查size_t Find(char ch, size_t pos = 0);size_t Find(char* str, size_t pos = 0);const char* c_str() const{return _str;}size_t size() const{return _size;}size_t capacity() const{return _capacity;}//改char& operator[](size_t pos){assert(pos < _size);return _str[pos];}const char& operator[](size_t pos) const{assert(pos < _size);return _str[pos];}void Swap(string& obj);//不修改成员变量的,最好const//比较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 strcmp(_str, s._str) < 0;}bool operator>=(const string& s) const{return *this > s || s == *this;}bool operator<=(const string& s) const{return *this < s || *this == s;}bool operator!=(const string& s) const{return !(*this == s);}//析构~string(){delete[] _str;_str = nullptr;_size = _capacity = 0;}private:char* _str;size_t _size;size_t _capacity;static size_t npos;};std::ostream& operator<<(std::ostream& os, const string& str);std::istream& operator>>(std::istream& is, string& str);}

实现

#define _CRT_SECURE_NO_WARNINGS 1#include "String.h"using namespace mystring;size_t string::npos = -1;mystring::string::string(const char* str):_size(strlen(str)){_capacity = _size == 0 ? 3 : _size + 1;_str = new char[_capacity];strcpy(_str, str);}mystring::string::string(const string& obj):_size(obj._size),_capacity(obj._capacity){_str = new char[_capacity];strcpy(_str, obj._str);}void string::PsuhBack(char ch){if (_size + 1>= _capacity){//扩容Reserve(_capacity * 2);}_str[_size] = ch;_size++;_str[_size] = '\0';//insert(_size, ch);}string& mystring::string::Append(const char* str){size_t len = strlen(str);if (_size + len >= _capacity){//扩容Reserve(_capacity + len);}strcpy(_str + _size, str);_size += len;return *this;}string& mystring::string::Insert(size_t pos, char ch){assert(pos <= _size);if (_size + 1>= _capacity){//扩容Reserve(_capacity * 2);}int end = _size + 1;while (end > pos){_str[end] = _str[end - 1];end--;}_str[pos] = ch;_size++;return *this;}string& mystring::string::Insert(size_t pos, const char* str){assert(pos <= _size);size_t len = strlen(str);if (_size + len >= _capacity){//扩容Reserve(_capacity + len);}size_t end = _size + len;while (end - len + 1> pos){_str[end] = _str[end - len];end--;}strncpy(_str + pos, str, len);_size += len;return *this;}string& mystring::string::operator+=(char ch){PsuhBack(ch);return *this;}string& mystring::string::operator+=(const char* str){Append(str);return *this;}void mystring::string::Reserve(size_t capacity){//比原空间小,不扩容,防止单独调用if (capacity > _capacity){char* tmp = new char[capacity];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = capacity;}}void mystring::string::Resize(size_t capacity, char ch){//比元空间小,不缩容if (capacity > _capacity){Reserve(capacity + 1);memset(_str + _size, ch, capacity - _size);_size = capacity;_str[_size] = '\0';}else{_str[capacity] = '\0';_size = capacity;}}string& mystring::string::Erase(size_t pos, size_t n){assert(pos < _size);//分三种情况,n全删和部分size_t end = pos;if (n == npos || pos + n >= _size){_str[pos] = '\0';//长度改为pos_size = pos;}else{/*while (end < _size - n){_str[end] = _str[end + n];end++;}_str[_size - n] = '\0';*/strcpy(_str + pos, _str + pos + n);_size -= n;}return *this;}void mystring::string::Clear(){_size = 0;_str[_size] = '\0';}size_t mystring::string::Find(char ch, size_t pos){assert(pos < _size);for (size_t i = pos; i < _size; i++){if (_str[i] == ch){return i;}}return npos;}size_t mystring::string::Find(char* str, size_t pos){assert(pos < _size);char* p = strstr(_str + pos, str);if (p == nullptr){return npos;}else{return p - _str;}}void mystring::string::Swap(string& obj){std::swap(_str, obj._str);std::swap(_size, obj._size);std::swap(_capacity, obj._capacity);}string& mystring::string::operator=(const string& obj){if (this != &obj){char* tmp = new char[obj._capacity];strcpy(tmp, obj._str);delete[] _str;_str = tmp;_size = obj._size;_capacity = obj._capacity;}return *this;}std::ostream& mystring::operator<<(std::ostream& os, const string& str){for (auto ch : str){os << ch;}return os;}std::istream& mystring::operator>>(std::istream& is, string& str){//cin遇到空格会退出str.Clear();char ch = is.get();//先存入临时数组,减少扩容次数char buff[128];size_t i = 0;while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == 127){buff[127] = '\0';str += buff;i = 0;}ch = is.get();}//没有放入的if (i != 0){buff[i] = '\0';str += buff;}return is;/*str.Clear();char ch = is.get();char buff[128];size_t i = 0;while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == 127){buff[127] = '\0';str += buff;i = 0;}ch = is.get();}if (i != 0){buff[i] = '\0';str += buff;}return is;*/}

测试

#define _CRT_SECURE_NO_WARNINGS 1#include #include #include "String.h"using namespace mystring;//void printstring(const string& s)//{//string::cosnt_iterator it = s.begin();//while (it != s.end())//{//printf("%c", *it);//it++;//}//}int main(){string s1("abcd");std::string s2("abcd");//string s2("hello nih");//string::iterator it = s1.begin();/*for (size_t i = 0; i < s1.size(); i++){printf("%c",s1[i]);}*//*while (it != s1.end()){printf("%c", *it);it++;}*///s1 += 'a';//s1 += 'b';// += 'c';/*s1.Insert(0, 'y');s1.Insert(0, 'x');s1.Insert(2, "hello");*///s1.Insert(2, "hello");//s1.reserve();//s1.Erase(2,1);//s1.resize(10, 'x');//printf("%zd\n", s1.Find('b'));//printf("%zd\n", s2.find('b'));/*s2 += '\0';s2 += " www.nihao";s2.clear();*///s1 += '\0';//s1 += " www.he";std::cin >> s1;//std::cin >> s2;//string s2("world");//s2 = s1;//printf("size = %d\n capacity = %d\n%s\n", s1.size(), s1.capacity(), s1.c_str());//printf("s1 = s2 %d", s1 >= s2);//printstring(s1);std::cout << s1;return 0;}

注意事项

容量默认比长度多一个,存储的\0
构造函数采用缺省构造,如果无参,默认为空字符串,如果为空指针,strlen计算长度会报错。因为容量依赖于长度,所以初始化列表先对size初始化。长度0时容量初始化为3,存储\0
插入功能注意0位置的插入,从size处开始会出错,因为size_t不会小于0的问题.所以选择从\0下一个位置开始挪
resize和reserve不会缩小容量,只会改变长度,resize判断两种情况,容量小于和大于目前的容量
erase如果长度是npos,就从pos位置全部删除,也需要分全删和部分删的情况
为了适应const对象调用下标,重载一个[]运算符,常成员函数返回常对象
swap比std的函数好的地方在于不需要构造,只需要交换三个成员变量
<<输出和c_str的区别,遇到\0c_str会停下来,<<按照长度打印
>>功能里cin遇到空格和换行会自动停下来,不会获取这个字符,导致while无限循环.所以改用io的get函数,空格和换行也会读取,用一个临时数组存够后一起放入对象里,避免多次扩容的浪费

vs的容量是默认15,如果超出则1.5倍扩容。而g++2倍扩容

写时拷贝

在浅拷贝的基础上增加了引用计数的方式
写时拷贝
写时拷贝的缺陷

扩展

测试时string的正确写法
STL的string类怎么了