C++利剑string类(详解)

前言:大家都知道在C语言里面的有  char  类型,我接下来要讲的 string 类功能是使用 char  类型写的类,当然这个是C++官方写的,接下来我们将会学会使用它,我们会发现原来  char  这种类型是还能这么好用,授人以鱼不如授人以渔,接下来我将会讲不少干货,不仅仅是教会我们使用,还会教我们如何模拟实现一个  string  类,我也会教大家如何去读英文文档,话不多说,正文开始。

目录

一,string  类初识

1)英文文档的查找和阅读

2)string类初步使用

string 如何创建对象

string  成员函数的使用

1)size()

2)  length() 

3)  max_size() 

4)resize()

 5)  capacity()

6)    reserve() 

7)  clear() 

8)    at() 

9)  back() /front()

 10)append()

11)  push_back() 

10)    insert() 

13)erase

14)c_str()

15)find()/rfind

16)substr()

17)getline()

二,模拟实现


一,string  类初识

1)英文文档的查找和阅读

想要了解一个语言里面的一个语法,有什么比直接去它的官网看原汁原味的英文文档更加得劲呢?我现在贴出C++的官网cplusplus.com/reference/

打开之后我们会看到这个页面

因为新版本不具有搜索功能,为了我们方便使用,我们切回老版本,点击图上的这个

之后我们就能在上面的reserch进行搜索了

我们搜索  string  就会显示 string 类的提供的所有接口和功能,我们先看它对string类的描述,也就是第一大段

这上面明确说明了,string类是一串char字符,并且提供了一系列的接口,在下面是它的接口或者成员函数,让我们来看看,如何查看成员函数的功能,使用方法。

我们阅读英文文献不一定要全部明白意思,我们可以从上面的四个方面入手,就能大概理解功能和使用方法,碰到不会的单词我们可以用搜索引擎,但不建议使用翻译软件直接翻译,因为这样即不准确也不利用我们的成长,以后我们还会阅读不少的英文文献,只有自身硬才能笑到最后。

2)string类初步使用

string 如何创建对象

在使用时,我们首先可以把它定义的对象当作一个字符串,但是这个对象拥有很多C语言字符串没有的特性,比如不需要我们考虑它的空间够不够,我们可以使用运算符对它进行操作,也就是进行+,+=,=等操作,并且提供了许多接口帮助我们减少手搓的代码量

话不多说,我们先定义一个string 对象吧

string c1;      //里面只有一个\0
string c2("wzdhxhn");   //里面是"wzdxhn\0"
string c3=("wzdxhn");   //里面是"wzdxhn\0"
string c4=c3;           //里面也是"wzdxhn\0"
string c5(c4);          //里面还是"wzdxhn\0"
c1=c5+c4;              //里面可是"wzdxhnwzdxhn\0"哦
c5+=c5;                  //里面是"wzdxhnwzdxhn\0"哦
for(int i=0;i<7;i++)
c2[i]=6;                  //c2里面的内容将会全部变成6
cout<<c1;
cin>>c1;                    //支持输入输出流

没错,真的是一场酣畅淋漓的初始化和赋值,string都支持这种操作,并且拷贝都是深拷贝哦,如果在C里面我们就需要循坏进行赋值了,刚开始是不是就感受到了它的便利。编译器:最终还是我承受了一切。

string  成员函数的使用

前提知识:size_t npos = -1这个是C++库里面的,代表整形的最大值,如果它是默认参数,代表知道\0等结束标志结尾

1)size()

sizeicon-default.png?t=N7T8https://legacy.cplusplus.com/reference/string/string/size/

 没有函数参数,这个函数可以获取string里面字符串的长度,不包括\0,然后返回

string s("hello");
cout<<s.size();      //输出s的长度5
2)  length() 

string::length - C++ Referenceicon-default.png?t=N7T8https://legacy.cplusplus.com/reference/string/string/length/

 功能类似size,没有参数,也是返回字符串长度,不包括\0

string s("hello");
cout<<s.length();      //输出s的长度5
3)  max_size() 

 
string::max_size - C++ Referenceicon-default.png?t=N7T8https://legacy.cplusplus.com/reference/string/string/max_size/

 没有参数,返回字符串里面ASCLL码值的最大值这个可以改变字符串的大小,

4)resize()

string::resize - C++ Referenceicon-default.png?t=N7T8https://legacy.cplusplus.com/reference/string/string/resize/

 只有一个参数就是字符串调整后的大小(以\0为标注),没有返回值,可以扩大和缩小字符串长度,扩大可以指定一个参数填充,也可以选择不指定,这个参数有默认参数,但要注意这个如果指定大小小于字符串的大小则会将数据覆盖

string s("hello");
cout<<s.resize(10,'6');    //输出:hello66666
cout<<s.resize(2);         //输出:he
 5)  capacity()

string::capacity - C++ Referenceicon-default.png?t=N7T8https://legacy.cplusplus.com/reference/string/string/capacity/

没有参数,返回一个无符号整形,代表调整后储存字符串空间的大小,这个会返回string类的字符串空间的容量,要注意的是,字符串空间的容量不等于长度,可能有一些空间存在,但是我们没使用,相当于多开了空间

6)    reserve() 

string::reserve - C++ Referenceicon-default.png?t=N7T8https://legacy.cplusplus.com/reference/string/string/reserve/一个参数没有返回值,这个可以重新定义容量,但是要注意只能扩大,不能缩小容量,因为编译器会做判断,如果重定义的容量小于之前的字符串空间的容量就不会进行任何操作,也不会报错。只有一个参数,就是你再次定义的容量大小

7)  clear() 

string::clear - C++ Referenceicon-default.png?t=N7T8https://legacy.cplusplus.com/reference/string/string/clear/没有参数,没有返回值,顾名思义,清理数据,大小和长度。,但是不会改变开的空间大小,也就是字符串空间大小

8)    at() 

string::at - C++ Referenceicon-default.png?t=N7T8https://legacy.cplusplus.com/reference/string/string/at/这个相当于下标访问,只有一个参数就是你要访问的字符串位置 ,最后返回你要的下标元素的引用

string s("hello");
s.at(2);    //等价于s[2]
9)  back() /front()

 string::back - C++ Referenceicon-default.png?t=N7T8https://legacy.cplusplus.com/reference/string/string/back/

 没有参数,返回最后一个字符,front()则是返回第一个字符

string s("hello");
cout<<s.back();       //输出:o
 10)append()

 string::append - C++ Referenceicon-default.png?t=N7T8https://legacy.cplusplus.com/reference/string/string/append/

 这个有两个函数参数,一个是插入的字符串或者字符,第二个参数有默认参数0,代表插入的位置,返回类型是插入后的string类

string s("hello");
s.append(" world");
cout<<s;      //输出:hello world
11)  push_back() 

string::push_back - C++ Referenceicon-default.png?t=N7T8https://legacy.cplusplus.com/reference/string/string/push_back/这个成员函数有一个参数,没有返回值,是要注意插入的只能是字符,或者ASCLL码值而且是尾插,插入字符串请使用append

string s("nihao");
s.push_back('h');  
cout<<s;         //输出:nihaoh
10)    insert() 

string::insert - C++ Referenceicon-default.png?t=N7T8https://legacy.cplusplus.com/reference/string/string/insert/

这个函数支持的参数很多

从图什么我们能知道,返回类型是插入后的string类或者迭代器,这个insert功能强大,不仅支持插入字符,也支持字符串,支持各种各样的插入方式,即带来了遍历也变得复杂了

13)erase

string::erase - C++ Referenceicon-default.png?t=N7T8https://legacy.cplusplus.com/reference/string/string/erase/

这个函数功能很明确了,就是删除字符串,没有参数,返回值是删除后的string类或者迭代器,因此不做举例了

14)c_str()

string::c_str - C++ Referenceicon-default.png?t=N7T8https://legacy.cplusplus.com/reference/string/string/c_str/这个会将string类型 转化为C语言的char* 类型,返回类型是  const char*   ,但要注意返回类型是const类型,只读不写

15)find()/rfind

string::find - C++ Referenceicon-default.png?t=N7T8https://legacy.cplusplus.com/reference/string/string/find/

这个函数的作用就是查找字符或者字符串里面的字符,返回它在字符串里面的位置,注意找字符串的时候不是找子字符串而是找属于这个子串里面的字符

 find()是从前往后找,rfind()则是从后往前找,参数差不多

string s("hello,world");
cout<<s.find('l',5);  结果是:10,返回为world里面的l,因为的从5 o开始查找的
16)substr()

string::substr - C++ Referenceicon-default.png?t=N7T8https://legacy.cplusplus.com/reference/string/string/substr/这个函数的作用就是返回原字符串中的一个子字符串,返回参数为char* ,参数很简单,应该是子字符串的位置,一个是长度,如果不指定长度,默认到\0

string s("hello world");
cout<<s.substr(0,5);  //输出:hello
17)getline()

getline (string) - C++ Referenceicon-default.png?t=N7T8https://legacy.cplusplus.com/reference/string/string/getline/这个函数的作用就是cin的一个拓展,没有参数和没有返回值,众所周知,cin输入字符串碰到空白会暂停,但是getline要碰到\0才会停止

string s;
cin>>s;     //输入:jascsahjas jscasjbsnc,但最后只有jascsahjas成功输出了
s.getline(); //输入:jascsahjas jscasjbsnc    s里面是:jascsahjas jscasjbsnc

二,模拟实现

备注:博主想偷懒了,答应大家的模拟实现不能再给大家做详细的解释了,但我会贴出源码供大家参考,里面只有一点点的注释,如果大家有不懂的,可以评论区@我,我会给大家一一解答,大家记得先看下面的私有成员,不要直接从头看到尾哦

namespace bit     //使用命名空间,防止于库的string类型冲突{class string{public:typedef char* iterator;      //string类的迭代器可以使用这个代替public:string(const char* str = "") //当无参数时,默认只有一个\0{_size = strlen(str);_capacity = _size;_str = new char[_capacity+1];strcpy(_str, str);}string(const string& s): _str(nullptr), _size(0), _capacity(0) //初始化列表{string tmp(s._str);this->swap(tmp);}string& operator=(const string &s){if(this != &s){string temp(s);this->swap(temp);}return *this;}~string(){if (_str){delete[] _str;_str = nullptr;}}//// iteratoriterator begin(){return _str;      //通过地址可以判断迭代器的位置}iterator end(){return _str + _size;}/// modifyvoid push_back(char c){if (_size == _capacity)reserve(_capacity*2);_str[_size++] = c;_str[_size] = '\0';}string& operator+=(char c){push_back(c);            //嘻嘻,复用已有的功能,偷懒return *this;}void append(const char* str);string& operator+=(const char* str);void clear()    //清除数据,但空间不变,尽量减少开空间的频率{_size = 0;_str[_size] = '\0';}void swap(string& s){std::swap(_str, s._str);  //官方库的swap函数,又是一个偷懒小技巧std::swap(_size, s._size);std::swap(_capacity, s._capacity);}const char* C_Str()const     //哈哈,是不是很简单{return _str;}/// capacitysize_t size()const   //有手就行{return _size;}size_t capacity()const{return _capacity;}bool empty()const{return _size == 0;}void resize(size_t newSize, char c = '\0'){if (newSize > _size){// 如果newSize大于底层空间大小,则需要重新开辟空间if (newSize > _capacity){reserve(newSize);}memset(_str + _size, c, newSize - _size); //调用C官方库,初始化,不懂,参考我以前的博客}_size = newSize;_str[newSize] = '\0';}void reserve(size_t newCapacity){// 如果新容量大于旧容量,则开辟空间if (newCapacity > _capacity){char* str = new char[newCapacity + 1];strcpy(str, _str);// 释放原来旧空间,然后使用新空间delete[] _str;_str = str;_capacity = newCapacity;}}/// accesschar& operator[](size_t index)//很容易实现吧{assert(index < _size);return _str[index];}const char& operator[](size_t index)const  //要记住const类型要单独处理{assert(index < _size);return _str[index];}///relational operatorsbool operator<(const string& s)const{int res = strcmp(_str, s._str); //C官方库,以前博客有这种函数的模拟实现和讲解if(res < 0)return true;return false;}bool operator<=(const string& s)const{return !(*this > s);}bool operator>(const string& s)const{int res = strcmp(_str, s._str);if(res > 0)return true;return false;}bool operator>=(const string& s)const{return !(*this < s);}bool operator==(const string& s)const{int res = strcmp(_str, s._str);if(res == 0)return true;return false;}bool operator!=(const string& s)const{return !(*this == s);}// 返回c在string中第一次出现的位置size_t find (char c, size_t pos = 0) const   //只读不改,最好const,同时支持非const类型{for (size_t i = pos; i < _size; ++i){if (_str[i] == c)return i;//找到,返回下标}return -1;//未找到}// 返回子串s在string中第一次出现的位置size_t find (const char* s, size_t pos = 0) const{assert(s);          //断言,如果条件为假就报错,结束程序并报错assert(pos < _size);const char* src = _str + pos;while (*src){const char* match = s;//如果不匹配,返回子串起始处重新查找const char *cur = src;while (*match && *match==*cur)//结束条件{++match;++cur;}if (*match == '\0')//找到子串{return src - _str;//返回下标}else{++src;}}return -1;//未找到}// 在pos位置上插入字符c/字符串str,并返回该字符的位置string& insert(size_t pos, char c){assert(pos <= _size);if (_size > _capacity){//扩容char *newstr = new char[_capacity * 2 + 1];//开空间strcpy(newstr, _str);delete[] _str;_str = newstr;_capacity *= 2;//Expand(_capacity * 2);}//移数据for (int i = _size; i >= (int)pos; --i){_str[i + 1] = _str[i];}_str[pos] = c;_size++;return *this;}string& insert(size_t pos, const char* str){size_t len = strlen(str);if (_size + len > _capacity)//扩容{//扩容char *newstr = new char[_capacity * 2 + 1];//开空间strcpy(newstr, _str);delete[] _str;_str = newstr;_capacity *= 2;//Expand(_size + len);}//后移数据for (int i = _size; i >= (int)pos; --i){_str[len + i] = _str[i];}//拷贝字符串while (*str != '\0'){_str[pos++] = *str++;}_size += len;return *this;}// 删除pos位置上的元素,并返回该元素的下一个位置string& erase(size_t pos, size_t len){assert(pos < _size);if (pos + len >= _size)//pos位置之后全为0{_str[pos] = '\0';_size = pos;}else{strcpy(_str + pos, _str + pos + len);_size -= len;}return *this;}private:friend ostream& operator<<(ostream& _cout, const bit::string& s);friend istream& operator>>(istream& _cin, bit::string& s);private:char* _str;size_t _capacity;size_t _size;};};//输入流重载istream& bit::operator>>(istream& _cin, bit::string& s){//预分配100个空间char *str = (char *)malloc(sizeof(char)*100);char *buf = str;        //buf可以防止频繁开空间int i = 1;//预处理:跳过流里面的所有空格和回车while ((*buf = getchar()) == ' ' || (*buf == '\n'));for ( ; ; ++i){if (*buf == '\n') //回车跳出{*buf = '\0';break;}else if (*buf == ' ') //空格跳出{*buf = '\0';break;}else if (i % 100 == 0) //空间不足{i += 100; //追加100个空间str = (char *)realloc(str,i);}else  //每次getchar()一个值{buf = (str+i);//为了避免realloc返回首地址改变,不使用++buf,而是用str加上偏移.//每次读取一个字符*buf = getchar();}}//输入完成,更新ss._str = str;s._capacity = s._size = i;return _cin;}//输出流重载ostream& bit::operator<<(ostream& _cout, const bit::string& s){for (size_t i = 0; i < s.size(); ++i){_cout << s[i];}return _cout;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/208083.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数学建模-基于LightGBM和BP神经网络的互联网招聘需求分析与预测

基于LightGBM和BP神经网络的互联网招聘需求分析与预测 整体求解过程概述(摘要) 就业是民生之本&#xff0c;是发展之基&#xff0c;也是安国之策。2020 年新冠肺炎疫情的爆发&#xff0c;稳就业成为应对疫情、稳定社会的重要保障之一。随着数据新动能的发展&#xff0c;互联网…

【Linux】Ubuntu添加root用户

在Ubuntu中&#xff0c;默认情况下是禁用了root用户的登录。如果仍然想要启用root用户&#xff0c;并设置root用户的密码&#xff0c;应按照以下步骤进行操作&#xff1a; 一、输入sudo passwd root设置root用户密码 二、切换root用户 sudo -i su root 这两条命令均可却换至…

Tkinter 面向对象框架《一》

一、说明 在本教程中&#xff0c;您将学习如何在 Tkinter 中应用面向对象编程以使代码更有条理。首先介绍Tk下小部件&#xff0c;然后介绍Ttk小部件&#xff0c;即如何从ttk.Frame类继承并在根窗口中使用它。 二、定义 Tkinter 面向对象的窗口 2.1 最基本的对象 以下简单程序创…

数字媒体技术基础之:栅格图像与矢量图形

使用各种软件创建不同类型的复合图像和图稿时&#xff0c;常会遇到基本的数字图像类型&#xff1a;栅格图像和矢量图像。 ◆ ◆ ◆ 栅格图像 栅格图像是基于像素的图像&#xff0c;故又称为“像素图像”或“位图图像”&#xff0c;主要用于编辑照片或制作可在 Web 上轻松使用…

C#语言高阶开发

目录 数据结构 集合 动态数组ArrayList 习题&#xff1a;声明一个Monster类&#xff0c;有一个Attack方法,用一个ArrayList去封装Monster的对象,装10个&#xff0c;遍历monster的list让他们释放攻击方法 哈希表HashTable 创建一个武器类&#xff0c;有一个属性叫做id,每个…

循环队列的结构设计和基本操作的实现(初始化,入队,出队,判空,获取长度,清空,销毁)

目录 1.队列的定义 2.循环队列的设计图示 3.循环队列的结构设计 4.循环队列的实现 5.循环队列的总结 1.队列的定义 和栈相反,队列(queue)是一种先进先出(first in first out,缩写为FIFO)的线性表.它只允许在表的一端进行插入,而在另一端删除元素. 在队列中,允许插入的一…

数据结构与算法之美学习笔记:29 | 堆的应用:如何快速获取到Top 10最热门的搜索关键词?

目录 前言堆的应用一&#xff1a;优先级队列堆的应用二&#xff1a;利用堆求 Top K堆的应用三&#xff1a;利用堆求中位数解答开篇内容小结 前言 本节课程思维导图&#xff1a; 搜索引擎的热门搜索排行榜功能你用过吗&#xff1f;搜索引擎每天会接收大量的用户搜索请求&#x…

Shell循环:for(三)

示例&#xff1a;使用for实现批量主机root密码的修改 一、前提 已完成密钥登录配置&#xff08;ssh-keygen&#xff09;定义主机地址列表并了解远程修改密码的方法 [rootlocalhost ~]# ssh-keygen #设置免密登录[rootlocalhost ~]# ssh-copy-id 192.168.151.151 二、演示…

Linux进程详解

Linux进程详解 1、进程概述1.1并行和并发1.2 PCB1.3 进程状态1.4 进程命令 2、进程创建2.1 函数2.2 fork()解析 3、父子进程3.1 进程执行位置3.2 循环创建子进程3.3 终端显示问题3.4 进程数数 4、execl和execlp4.1 execl()4.2 execlp()4.3 函数的使用 5、进程控制5.1 结束进程5…

Oracle忘记所有密码怎么办

最近遇到一个Oracle的问题&#xff0c;密码要过期了&#xff0c;但是除了用户密码&#xff0c;其他密码都不知道了&#xff0c;修改不了密码怎么办呢&#xff1f; 试了各种方法&#xff0c;最终下面的方式生效了&#xff1a; 首先&#xff0c;使用orapwd生成新的密码文件&…

selenium 工具 的基本使用

公司每天要做工作汇报&#xff0c;汇报使用的网页版&#xff0c; 所以又想起 selenium 这个老朋友了。 再次上手&#xff0c;发现很多接口都变了&#xff0c; 怎么说呢&#xff0c; 应该是易用性更强了&#xff0c; 不过还是得重新看看&#xff0c; 我这里是python3。 pip安装…

有文件实体的后门无文件实体的后门rootkit后门

有文件实体后门和无文件实体后门&RootKit后门 什么是有文件的实体后门&#xff1a; 在传统的webshell当中&#xff0c;后门代码都是可以精确定位到某一个文件上去的&#xff0c;你可以rm删除它&#xff0c;可以鼠标右键操作它&#xff0c;它是有一个文件实体对象存在的。…

熬夜会秃头——beta冲刺Day4

这个作业属于哪个课程2301-计算机学院-软件工程社区-CSDN社区云这个作业要求在哪里团队作业—beta冲刺事后诸葛亮-CSDN社区这个作业的目标记录beta冲刺Day4团队名称熬夜会秃头团队置顶集合随笔链接熬夜会秃头——Beta冲刺置顶随笔-CSDN社区 一、团队成员会议总结 1、成员工作进…

(详细教程)笔记本电脑安装Ubuntu系统

1.前言 老的小米笔记本淘汰了&#xff0c;装一下linux系统玩一下。 使用工具如下&#xff1a;一台小米笔记本pro15.6一个惠普32G U盘一个台式机用于下载镜像等资源 2.下载Ubuntu桌面版 cn.ubuntu.com/download/de… 这里我下载的是 22.04.3 LTS 3.下载烧录工具&#xff0c…

Lattice-Based Blind Signatures: Short, Efficient, and Round-Optimal

目录 摘要引言 Lattice-Based Blind Signatures: Short, Efficient, and Round-Optimal CCS 2023 摘要 我们提出了一种基于随机预言机启发式和标准格问题&#xff08;环/模块SIS/LWE和NTRU&#xff09;的2轮盲签名协议&#xff0c;签名大小为22KB。该协议是全面优化的&#xf…

如何做接口测试?接口测试工具有哪些?

回想入职测试已经10年时间了&#xff0c;初入职场的我对于接口测试茫然不知。后来因为业务需要&#xff0c;开始慢慢接触接口测试。从最开始使用工具进行接口测试到编写代码实现接口自动化&#xff0c;到最后的测试平台开发。回想这一路走来感触颇深&#xff0c;因此为了避免打…

分享82个节日PPT,总有一款适合您

分享82个节日PPT&#xff0c;总有一款适合您 82个节日PPT下载链接&#xff1a;https://pan.baidu.com/s/1boDTl3PiHFXLJ890CoUfJA?pwd8888 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易。…

MathType 7.5.2中文版软件使用期到了怎么办?

MathType 7.5.2中文版作为一款专业的公式编辑器&#xff0c;MathType受到很多人的青睐&#xff0c;它可以将编辑好的公式保存成多种图片格式或透明图片模式&#xff0c;可以很方便的添加或移除符号、表达式等模板&#xff08;只需要简单地用鼠标拖进拖出即可)&#xff0c;也可以…

39.从0到上线三天搭建个人网站(第三天)

点赞收藏加关注&#xff0c;你也能住大别墅&#xff01; 一、第三天主要工作 1.完成detail页面的开发 2.将所有数据以及部分静态资源存在uniCloud&#xff0c;为以后做管理后台做准备 3.创建云对象getData&#xff0c;在beforecreate&#xff08;&#xff09;中获取数据 4.…

详解原生Spring框架下的类切入点表达式与切入点函数

&#x1f609;&#x1f609; 学习交流群&#xff1a; ✅✅1&#xff1a;这是孙哥suns给大家的福利&#xff01; ✨✨2&#xff1a;我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 &#x1f96d;&#x1f96d;3&#xff1a;QQ群&#xff1a;583783…