c++内置string库的相关函数:string - C++ Reference
目录
一·string类构造,拷贝构造和析构:
二·string内正向迭代器实现:
三·赋值运算符重载实现:
四·reserve,empty,clear实现:
五·push_back,append实现:
六·+=运算符实现:
七·swap和c_str()实现:
八·resize的实现:
九·比较关系的实现:
十·insert的实现:
十一·find的实现:
十二·erase的实现:
十三·substr的实现:
十四· cin与cout实现:
十五·内部成员变量输出:
十六·访问操作符重载的实现:
总代码汇总:
string.h:
string.cpp:
一·string类构造,拷贝构造和析构:
/// // //string 初始化://'\0'不占_capacity里的空间,但是它占空间,故开空间的时候给它开一个位置。而_capacity的大小//是有效元素占空间的大小。string(const char* str = "") {_size = strlen(str);_str = new char[_size + 1];_capacity = _size;strcpy(_str, str);}///拷贝构造: 如s1(s2)string(const string& s) {_str = new char[s._capacity + 1];strcpy(_str, s._str);_size = s._size;_capacity = s._capacity;}
//析构函数:~string() {delete[]_str;_capacity = _size = 0;}
二·string内正向迭代器实现:
在这路可以把它看成指针来对其模拟操作:
typedef char* iterator;typedef const 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;}
三·赋值运算符重载实现:
//赋值重载: 如:s1=s1 s1=s2;(要把原先的数据和空间舍弃)string& operator=(const string& s) {if (strcmp(_str, s._str) == 0) {return *this;}else {clear();delete[]_str;_str = new char[s._capacity + 1];strcpy(_str, s._str);_size = s._size;_capacity = s._capacity;return *this;}}
四·reserve,empty,clear实现:
void string::reserve(size_t n) {if (n > _capacity) {char* tmp = new char[n + 1];strcpy(tmp, _str);delete[]_str;_str = tmp;_capacity = n;}}bool empty()const {return _size == 0;}
void string::clear() {_str[0] = '\0';_size = 0;}
五·push_back,append实现:
void string::push_back(char c) {if (_size == _capacity) {reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size++] = c;_str[_size] = '\0';}void string::append(const char* str) {size_t len=strlen(str);if (_size == _capacity) {reserve(_size + len > _capacity * 2 ? _size + len : _capacity * 2);}strcpy(_str + _size, str);_size += len;}
六·+=运算符实现:
string& string::operator+=(char c) {push_back(c);return *this;}
string& string:: operator+=(const char* str) {append(str);return *this;}
七·swap和c_str()实现:
void string:: swap(string& s) {//利用运算符重载出的赋值函数完成:string tmp = s;s = *this;*this = tmp;}const char* string::c_str()const {return this->_str;}
八·resize的实现:
void string::resize(size_t n, char c) {size_t i = 0;i = _size;if (n > _size) {if (n > _capacity) {reserve(n > 2 * _capacity ? n : 2 * _capacity);}size_t gap = n - _size;while (gap--) {_str[i++] = c;}}_str[i] = '\0';_size = i;}
九·比较关系的实现:
bool string:: operator<(const string& s) {return strcmp(_str, s._str)<0;}bool string:: operator==(const string& s) {return strcmp(_str, s._str) == 0;}bool string:: operator<=(const string& s) {return *this == s || *this < s;}bool string::operator>(const string& s) {return !(*this<=s);}bool string::operator>=(const string& s) {return *this == s || *this > s;}bool string:: operator!=(const string& s) {return !(*this == s);}
十·insert的实现:
string& string::insert(size_t pos, char c) {assert(pos < _size);if (_size + 1 > _capacity) {reserve(_size + 1 > 2 * _capacity ? _size + 1 : 2 * _capacity);}//保证内存空间最小也是数量的大小size_t end = _size;//从'\0'位置被覆盖即后挪。while (end > pos) {_str[end] = _str[end - 1];end--;}_str[pos] = c;_str[_size + 1] = '\0';//最后补充末尾的'\0'_size = _size + 1;return *this;}string& string::insert(size_t pos, const char* str) {assert(pos < _size);size_t len = strlen(str);if (_size + len > _capacity) {reserve(_size + len> 2 * _capacity ? _size + len : 2 * _capacity);}size_t end = _size+len-1;while (end >pos+len-1) {_str[end] = _str[end - len];end--;}//从'\0'开始移动,但是最后当拷贝过去'\0'会覆盖最后一个被移动的字符:char re = _str[pos + len];strcpy(_str + pos, str);_str[pos + len] = re;_str[_size + len] = '\0';_size = _size + len;return *this;}
十一·find的实现:
size_t string::find(char c, size_t pos ) const {assert(pos < _size);for (size_t i = pos; i <_size; i++) {if (_str[i] == c) {return i;}}return npos;}size_t string::find(const char* s, size_t pos) const {assert(pos < _size);const char *p=strstr(_str + pos, s);if (p == nullptr) {return npos;}else {return p - _str;}}
十二·erase的实现:
string& string::erase(size_t pos, size_t len) {assert(pos < _size);//len长于pos后面的位置,直接都删。if (pos + len > _size) {_str[pos] = '\0';_size = pos;}//否则把len后面的字符串copy到pos位置。else {strcpy(_str + pos, _str +pos+ len);_size = _size - len;}return *this;}
十三·substr的实现:
string string::substr(size_t pos, size_t len) {assert(pos < _size);if (len == npos) {len = _size - pos;//实际长度}string tmp;for (size_t i = pos; len>0; i++,len--) {tmp += _str[i];}return tmp;}
十四· cin与cout实现:
由于默认第一个参数是this问题,把它定义在外部作为友好函数去访问内部成员:
ostream& operator<<(ostream& _cout, const st::string& s){for (auto ch : s){_cout << ch;}return _cout;}//istream& operator>>(istream& _cin, st::string& s);istream& operator>>(istream& _cin, st::string& s) {if (!s.empty()) {s.clear();}char buff[2024] = { 0 };//利用数组,先把输入的元素放入栈的数组里,//快满了后追加到string的数组里,方便对开空间的掌握,以及减少调用reserve函数次数char ch = _cin.get();//输入到缓冲区,只要有字符就读取,没有get()就先输入在读取int i = 0;while(ch!=' '&&ch!='\n') {buff[i++] = ch;if (i == 2023) {s += buff;i = 0;}ch = _cin.get();}if (i != 0) {s += buff;}return _cin;}
十五·内部成员变量输出:
size_t size()const {return _size;}size_t capacity()const {return _capacity;}bool empty()const {return _size == 0;}
十六·访问操作符重载的实现:
//获取指定字符:char& operator[](size_t index) {assert(index < _size);return _str[index];}const char& operator[](size_t index)const {assert(index < _size);return _str[index];}//不可修改的访问,//如:const st::string s3("xyz");//s3[1] = 1;
//定义的const对象,其成员都不能被修改,就自动调用const类的
十七·对swap,拷贝构造,赋值的现代写法:
首先它并没有多大的提高效率,而是可以这么理解:它会让我们手动自行的操作减少一部分,通过调用如实现创造好的swap。比如:这个自己写的swap与std里的swap 有所不同,大概就是库里用的模版出的类,会有空间反复开辟,而自己写的这个直接交换指针就好,那么就相当于指向的空间就也互换了。
///swap现代写法:(不用开辟对象,仅仅做到成员交换,让它们指向的空间互换即可)void swap(string& s){std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}
对拷贝构造而言:如:s1拷给s2
可以不在里面自己手写成员赋值等,调用构造+swap即可(但是这里如果一开始s1被插入过数据,扩过容,_capacity可能不一):
string(const string&s) {string tmp(s._str);swap(tmp);}
对于赋值操作,可以分为两种:如:s1=s2;第一种就是不改变s2的前提下完成:
//不改变s2情况下:string& operator =(const string& s ) {if (*this != s) {string tmp(s._str);swap(tmp);}return* this;}
第二种就是改变了s2,把s1的资源给了它:
string& operator =(string& s) {swap(s);return*this;}
总代码汇总(传统写法):
string.h:
#pragma once#include<iostream>
#include<assert.h>using namespace std;
namespace st{class string{friend ostream& operator<<(ostream& _cout, const st::string& s);friend istream& operator>>(istream& _cin, st::string& s);public:迭代器:typedef char* iterator;typedef const 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 初始化://'\0'不占_capacity里的空间,但是它占空间,故开空间的时候给它开一个位置。而_capacity的大小//是有效元素占空间的大小。string(const char* str = "") {_size = strlen(str);_str = new char[_size + 1];_capacity = _size;strcpy(_str, str);}///拷贝构造: 如s1(s2)string(const string& s) {_str = new char[s._capacity + 1];strcpy(_str, s._str);_size = s._size;_capacity = s._capacity;}//赋值重载: 如:s1=s1 s1=s2;(要把原先的数据和空间舍弃)string& operator=(const string& s) {if (strcmp(_str, s._str) == 0) {return *this;}else {clear();delete[]_str;_str = new char[s._capacity + 1];strcpy(_str, s._str);_size = s._size;_capacity = s._capacity;return *this;}}//清除数据,改size但容量不变:void clear();//析构函数:~string() {delete[]_str;_capacity = _size = 0;}void push_back(char c);string& operator+=(char c);void append(const char* str);string& operator+=(const char* str);void swap(string& s);const char* c_str()const;///capacitysize_t size()const {return _size;}size_t capacity()const {return _capacity;}bool empty()const {return _size == 0;}//增大尺寸:void resize(size_t n, char c = '\0');//预存空间/扩容:void reserve(size_t n);//////获取指定字符:char& operator[](size_t index) {assert(index < _size);return _str[index];}const char& operator[](size_t index)const {assert(index < _size);return _str[index];}///relational operators:bool operator<(const string& s);bool operator<=(const string& s);bool operator>(const string& s);bool operator>=(const string& s);bool operator==(const string& s);bool operator!=(const string& s);返回c在string中第一次出现的位置size_t find(char c, size_t pos = 0) const;返回子串s在string中第一次出现的位置size_t find(const char* s, size_t pos = 0) const;在pos位置上插入字符c/字符串str,并返回该字符的位置string& insert(size_t pos, char c);string& insert(size_t pos, const char* str);删除pos位置上的元素,并返回该元素的下一个位置string& erase(size_t pos, size_t len);//从指定位置往后找len个长度子串并返回string类型对象string substr(size_t pos, size_t len = npos);private:char* _str;size_t _capacity;size_t _size;static const size_t npos;};}
string.cpp:
#define _CRT_SECURE_NO_WARNINGS
#include"string.h"namespace st {const size_t string::npos = -1;void string::clear() {_str[0] = '\0';_size = 0;}void string::push_back(char c) {if (_size == _capacity) {reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size++] = c;_str[_size] = '\0';}void string::reserve(size_t n) {if (n > _capacity) {char* tmp = new char[n + 1];strcpy(tmp, _str);delete[]_str;_str = tmp;_capacity = n;}}string& string::operator+=(char c) {push_back(c);return *this;}void string::append(const char* str) {size_t len=strlen(str);if (_size == _capacity) {reserve(_size + len > _capacity * 2 ? _size + len : _capacity * 2);}strcpy(_str + _size, str);_size += len;}string& string:: operator+=(const char* str) {append(str);return *this;}void string:: swap(string& s) {//利用运算符重载出的赋值函数完成:string tmp = s;s = *this;*this = tmp;}const char* string::c_str()const {return this->_str;}void string::resize(size_t n, char c) {size_t i = 0;i = _size;if (n > _size) {if (n > _capacity) {reserve(n > 2 * _capacity ? n : 2 * _capacity);}size_t gap = n - _size;while (gap--) {_str[i++] = c;}}_str[i] = '\0';_size = i;}bool string:: operator<(const string& s) {return strcmp(_str, s._str)<0;}bool string:: operator==(const string& s) {return strcmp(_str, s._str) == 0;}bool string:: operator<=(const string& s) {return *this == s || *this < s;}bool string::operator>(const string& s) {return !(*this<=s);}bool string::operator>=(const string& s) {return *this == s || *this > s;}bool string:: operator!=(const string& s) {return !(*this == s);}string& string::insert(size_t pos, char c) {assert(pos < _size);if (_size + 1 > _capacity) {reserve(_size + 1 > 2 * _capacity ? _size + 1 : 2 * _capacity);}//保证内存空间最小也是数量的大小size_t end = _size;//从'\0'位置被覆盖即后挪。while (end > pos) {_str[end] = _str[end - 1];end--;}_str[pos] = c;_str[_size + 1] = '\0';//最后补充末尾的'\0'_size = _size + 1;return *this;}string& string::insert(size_t pos, const char* str) {assert(pos < _size);size_t len = strlen(str);if (_size + len > _capacity) {reserve(_size + len> 2 * _capacity ? _size + len : 2 * _capacity);}size_t end = _size+len-1;while (end >pos+len-1) {_str[end] = _str[end - len];end--;}//从'\0'开始移动,但是最后当拷贝过去'\0'会覆盖最后一个被移动的字符:char re = _str[pos + len];strcpy(_str + pos, str);_str[pos + len] = re;_str[_size + len] = '\0';_size = _size + len;return *this;}size_t string::find(char c, size_t pos ) const {assert(pos < _size);for (size_t i = pos; i <_size; i++) {if (_str[i] == c) {return i;}}return npos;}size_t string::find(const char* s, size_t pos) const {assert(pos < _size);const char *p=strstr(_str + pos, s);if (p == nullptr) {return npos;}else {return p - _str;}}string& string::erase(size_t pos, size_t len) {assert(pos < _size);//len长于pos后面的位置,直接都删。if (pos + len > _size) {_str[pos] = '\0';_size = pos;}//否则把len后面的字符串copy到pos位置。else {strcpy(_str + pos, _str +pos+ len);_size = _size - len;}return *this;}string string::substr(size_t pos, size_t len) {assert(pos < _size);if (len == npos) {len = _size - pos;//实际长度}string tmp;for (size_t i = pos; len>0; i++,len--) {tmp += _str[i];}return tmp;}ostream& operator<<(ostream& _cout, const st::string& s){for (auto ch : s){_cout << ch;}return _cout;}//istream& operator>>(istream& _cin, st::string& s);istream& operator>>(istream& _cin, st::string& s) {if (!s.empty()) {s.clear();}char buff[2024] = { 0 };//利用数组,先把输入的元素放入栈的数组里,//快满了后追加到string的数组里,方便对开空间的掌握,以及减少调用reserve函数次数char ch = _cin.get();//输入到缓冲区,只要有字符就读取,没有get()就先输入在读取int i = 0;while(ch!=' '&&ch!='\n') {buff[i++] = ch;if (i == 2023) {s += buff;i = 0;}ch = _cin.get();}if (i != 0) {s += buff;}return _cin;}}