如果调试一个程序让你很苦恼,千万不要放弃,成功永远在拐角之后,除非你走到拐角,否则你永远不知道你离他多远,所以,请记住,坚持不懈,直到成功。

目录
前言
1.string类的常用接口
1.1string类对象的常见构造:
1.2string类对象的访问及遍历操作
1.3string类对象的容量操作
1.4string类对象的修改操作:
2.string类的模拟实现
3.string类的习题
STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。学会使用STL,许多底层的数据结构以及算法都不需要自己重新造轮子,站在前人的肩膀上,健步如飞的快速开发。
本篇文章介绍string类,学习string类我们大致分两个方面进行,首先是学习如何使用库中string接口,然后再通过学习string底层源代码的进行模拟实现接口
在介绍string接口前,首先介绍一个网站可以用来查询C++中的库函数以及STL,后续的学习当中会经常在这个文档上查阅各种接口——https://legacy.cplusplus.com/
string类包含许多接口,在这里我们主要重点介绍string类的常用接口,对于常用的接口我们需要做到不用查阅文档就可以熟练的使用,对于其它接口,只需要做到知道有这种接口,查阅文档会使用即可
函数名称 功能说明 string() 构造空的string类对象,即空字符串 string(const char* s) 用C-string来构造string类对象 string(const string&s) 拷贝构造函数 string(size_t n, char c) string类对象中包含n个字符c
函数名称 功能说明 operator[] 返回pos位置的字符,const string类对象调用 范围for C++11支持的更简洁的范围for遍历方式 begin + end begin获取第一个字符的迭代器 , end获取最后一个字符下一个位置的迭
代器rebing + rend rbegin获取最后一个字符下一个位置的迭代器,rend获取第一个字符的迭代器
operator[]:
范围for:
上面是两种string类对象常规的遍历方式,下面介绍一种STL中通用的遍历方式就是迭代器
迭代器在行为上像指针一样的类型
正向遍历:begin + end
反向遍历:rebegin + rend
以上是关于迭代器正向遍历和反向遍历的两种方式,除此之外,库中还有const修饰的函数
如:
为什么会存在const修饰的函数呢?通过下面的代码来说明:
这段代码中我们只是想打印这个字符串,并不做任何的修改,因此可以使用引用,这样做就减少了一次拷贝构造,提高程序的效率,所以在库中也定义了const修饰的函数
下面来介绍一个在编写代码时的小技巧:
上面两行代码是等价的,在使用熟练之后,如果在编写代码的过程中如果觉得定义rit这个变量时类型过长,可以使用auto这个关键字,因为auto可以自动推导变量类型
size和length函数是等价的:
函数名称 功能说明 size 返回字符串有效长度 length 返回字符串有效长度 capacity 返回空间总大小 clear 清空有效字符 reserve 为字符串预留空间 resize 将有效字符的个数该成n个,多出的空间用字符c填充
capacity函数:
clear函数:
reserve函数:
关于reserve这个函数的好处是什么呢?
string这个类在构造对象的时候,底层是使用动态增长的方式来按需申请和释放内存的,如果在构造之前就知道大概需要多大的空间,就不用频繁的申请内存,有效避免在堆上频繁申请内存,造成内存碎片的问题
resize函数:
功能:将有效字符改成n个,多出的空间用字符c来填充
因此会存在三种情况:
n < size :删除数据
size < n <= capacity :插入数据
n > capacity :扩容 + 插入数据
第一种情况:
第二种情况:
第三种情况:
函数名称 功能说明 push_back 在字符串后面尾插字符c append 在字符串后面追加一个字符串 operator+= 在字符串后面追加字符串 c_str 返回c格式字符串 find 从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置 rfind 从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置 substr 在str中从pos位置开始,截取n个字符,然后将其返回
insert 在pos位置插入字符 erase 删除pos位置处的n个字符 assign 将一个字符串拷贝到一个对象中去 replace 从pos位置开始,将n个字符改成n个字符 push_back函数:
append函数:
operator+=:
c_str函数:返回一个指向该字符串首字符的指针
find函数:
rfind函数:
注:find函数和rfind如果找不到就返回npos
-1是size_t类型转换后就是最大的整型:
substr函数:从pos位置开始,截取n个字符,返回截取字符第一个字符的地址
insert函数:
erase函数:
assign函数:
repalce函数:

1.定义一个string类:为了和库里的区分将类名定义为String
class String { public://成员函数 private://成员变量 };接口1:
构造函数:
//无参构造:String(){char* _str = new char[1];_str[0] = '\0';_capacity = _size = 0;}//带参构造:String(const char* str = ""){_size = strlen(str);_capacity = _size;_str = new char[_capacity + 1];strcpy(_str, str);}接口2:
拷贝构造函数:
//传统写法:String(const String& s){_str = new char[s._capacity + 1];_capacity = s._capacity;_size = s._size;strcpy(_str, s._str);}//现代写法String(const String& s):_str(nullptr),_size(0),_capacity(0){String tmp(s._str);std::swap(_str, tmp._str);std::swap(_size, tmp._size);std::swap(_capacity, tmp._capacity);}//现代写法的优化:void swap(String& s){std::swap(_str, s._str);//内置类型调用算法库里面的std::swap(_size, s._size);std::swap(_capacity, s._capacity);}String(const String& s):_str(nullptr), _size(0), _capacity(0){String tmp(s._str);//this->swap(tmp);swap(tmp);//自定义类型使用自己的swap,避免了使用算法库里面的产生三次深拷贝}接口3
析构函数:
~String(){delete[] _str;_str = nullptr;_capacity = _size = 0;}接口4
赋值重载函数:
//传统写法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;}//现代写法:String& operator=(const String& s){if (this != &s){String tmp(s);swap(tmp);}return *this;}//现代写法的优化String& operator=(String s){if (this != &s){swap(s);}return *this;}接口5
operator[]:
char& operator[](size_t pos){return _str[pos];}接口6
size():
size_t size(){return _size;}接口7
capacity():
size_t capacity() {return _capacity; }接口8:
c_str():
char* c_str() {return _str; }接口9:
begin和end
typedef char* iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}接口10
reserve():
void reserve(int n){if (n > _capacity){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}接口11
push_back():
void push_back(char ch){if (_size == _capacity){int newCapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newCapacity);}_str[_size] = ch;++_size;_str[_size] = '\0';}接口12
append():
void append(const char* str){size_t len = strlen(str);if (_size+len > _capacity){reserve(_size + len);}strcat(_str, str);_size += len;}接口13
operator+=():
//+=字符String& operator+=(const char ch){push_back(ch);return *this;}//+=字符串String& operator+=(const char* str){append(str);return *this;}接口14
insert():
//插入字符String& insert(size_t pos, const char ch){assert(pos < _size);if (_size == _capacity){int newCapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newCapacity);}//写法1:/* int end = _size;while (end >= (int)pos){_str[end + 1] = _str[end];--end;}*///写法2:int end = _size + 1;while (end > pos){_str[end] = _str[end - 1];--end;}_str[pos] = ch;_size++;return *this;}//插入字符串:String& insert(size_t pos, const char* str){size_t len = strlen(str);if (_size + len > _capacity){reserve(_size + len);}//写法1:/* int end = _size;while (end >= (int)pos){_str[end + len] = _str[end];--end;}*///写法2:int end = _size + len;while (end >= pos + len){_str[end] = _str[end - len];--end;}strncpy(_str + pos, str, len);_size += len;return *this;}接口15
erase():
String& erase(size_t pos, size_t len = npos){assert(pos < _size);if (len == npos || len >= _size - pos){_str[pos] = '\0';_size = pos;}else{strcpy(_str + pos, _str + pos + len);_size -= len;}return *this;}接口16
find():
//查找字符size_t find(char ch, size_t pos = 0){assert(pos < _size);int i = pos;while (_size--){if (_str[i] == ch){return i;}i++;}return npos;}//查找字符串:size_t find(const char* str, size_t pos = 0){assert(pos < _size);char* ptr = strstr(_str + pos, str);if (ptr == nullptr){return npos;}else{return ptr - _str;}}接口17
clear():
void clear() {_str[0] = '\0';_size = 0; }接口18
resize():
void resize(size_t n, char ch = '\0'){if (n > _capacity){reserve(n);for (int i = _size; i < n; i++){_str[i] = ch;}_size = n;_str[_size] = '\0';}else{_str[_size] = '\0';_size = n;}}流提取:oparetor<<()
ostream& operator<<(ostream& out, String& s) {for (int i = 0; i < s.size(); i++){out << s[i];}return out; }流插入:oparetor>>()
istream& operator>>(istream& in, String& s) {s.clear();//第一种写法//char ch = in.get();等于空格或者换行就就结束了!//while (ch != ' ' && ch != '\n')//{// s += ch;// ch = in.get();//}// 第一种写法的优化//减少频繁扩容char buf[128] = { 0 };int i = 0;char ch = in.get();while (ch != ' ' && ch != '\n'){if (i == 127){s += buf;i = 0;}buf[i++] = ch;ch = in.get();}//不足128或者剩下的:if (i > 0){buf[i] = '\0';s += buf;}return in; }

习题1:字符串转换成整数oj链接
class Solution { public:int StrToInt(string str) {int sum = 0;int flag = 1;for(int i = 0; i= '0' && str[i] <= '9')){return 0;}else{sum = sum*10 + str[i] - '0';}}return sum*flag;} }; 习题2:字符串相加oj链接
class Solution { public:string addStrings(string num1, string num2) {int end1 = num1.size()-1;int end2 = num2.size()-1;int carry = 0;string retStr;retStr.reserve(max(num1.size(),num2.size()+1));while(end1 >= 0 || end2 >= 0){int val1 = end1 >= 0 ? num1[end1] - '0' : 0;int val2 = end2 >= 0 ? num2[end2] - '0' : 0;int ret = val1 + val2 + carry;carry = ret / 10;ret %= 10;retStr += '0' + ret;end1--;end2--;}if(carry == 1)retStr += '1';reverse(retStr.begin(),retStr.end());return retStr;} };习题4:仅仅反转字母oj链接
class Solution { public:string reverseOnlyLetters(string s) {int begin = 0;int end = s.size()- 1;while(begin < end){while(begin < end && !isalpha(s[begin])){++begin;}while(begin < end && !isalpha(s[end])){--end;}swap(s[begin],s[end]);++begin;--end;}return s;} };习题5:字符串中只出现一次的字符oj链接
class Solution { public:int firstUniqChar(string s) {int str[26] = { 0 };for(auto& ch : s){str[ch - 'a']++;}for(int i = 0; i < s.size(); i++){if(str[s[i]-'a'] == 1)return i;}return -1;} };习题6:字符串中最后一个单词的长度oj链接
#include#include using namespace std; int main() {string s;getline(cin,s);size_t pos = s.rfind(' ');cout< 习题7:验证字符串是否回文oj链接
class Solution { public:bool isCharacter(char ch){return ((ch >= '0' && ch <= '9')||(ch >= 'a' && ch <= 'z')||(ch >= 'A' && ch <= 'Z'));}bool isPalindrome(string s) {for(auto& ch : s){if(ch >= 'A' && ch <= 'Z'){ch +=32;}}int begin = 0;int end = s.size()-1;while(begin < end){while(begin < end && !isCharacter(s[begin])){++begin;}while(begin < end && !isCharacter(s[end])){--end;}if(s[begin] != s[end])return false;else{++begin;--end;}}return true;} };习题8:反转字符串(区间部分反转)oj链接
class Solution { public:string reverseStr(string s, int k) {int n = s.size();for(int i = 0; i习题9:反转字符串中的单词oj链接
class Solution { public:string reverseWords(string s) {int len = s.size();int begin = 0;int end = 0;while(begin < len){while(s[end] != ' ' && s[end] != '\0'){++end;}int end1 = end+1;while(begin < end){swap(s[begin],s[end-1]);++begin;--end;}begin = end1;end = end1;}return s;} };
上一篇:少年行,唐,第一,意(简单)
下一篇:关于成长的一句名言