初识C++ · string的使用(1)

目录

1 STL简介

2 string类

2.1 构造 析构 拷贝

2.2 size length

2.3 [ ]的使用

2.4 迭代器

2.5 Push_Back和append

3 sort的使用


1 STL简介

STL是一个标准库,是C++标准库的一个重要部分,那么什么是STL?STL是一个模板库,包含了算法框架和数据结构

STL有不同的版本,比如原始版本,P.J 版本,R.W 版本,SGI版本,不同版本有不同的特点,比如SGI版本的可移植性好,比如P.J版本的可读性较差。

STL这个库里面有六大部分,分别是算法,容器,迭代器,仿函数,空间配置器,配接器。我们即将介绍的,是容器部分的string,可以形象的把容器理解为数据结构,里面还有链表list,树set,顺序表vector等。

这里简单说明,就进入string的正式部分了。


2 string类

string首先是一个类,是委员会发明类之前的一个“前车”,所以成员函数部分可能有点冗余,比如函数有120多个。

string类是字符数组,可以进行增删查改,但是这里的字符不一定是一个字节,通过后面的学习就知道了,比如w_char就是4字节,我们先不做了解。

2.1 构造 析构 拷贝

constructor就是构造的意思,所以这里面进入,就是构造函数的真面目了:

构造函数就有7个,这也是造成冗余的原因之一.

int main()
{string s;return 0;
}

 第一个构造函数使用如上,即什么也不干,那么s里面就是空的,什么也没有,也可以通过调试观察里面有什么,当然,里面有其他的,我们先不做深究。

int main()
{string s1("abcdefg");cout << s1 << endl;return 0;
}

第二个构造使用如上,很简单,但是为什么支持直接打印呢?因为流重载重载了string类,所以可以打印,那么这也是个验证的好方法。const string& str就是常量字符串的意思,所以我们给上常量字符串就行了。

int main()
{string s1("abcdefg");string s4(s1);return 0;
}

第四个构造使用如上,也就是给一个字符串的指针就可以了,使用很常见,也很实用。

以上3个构造函数的最常用到的,后面三个可以作为了解,毕竟有点鸡肋的。

int main()
{string s1("abcdefg");string s2(s1, 0, 3);cout << s1 << endl;cout << s2 << endl;return 0;
}

这个构造重载的参数有3个,分别是常量字符串,pos,npos,我们看文档的时候不如连蒙带猜,平时的pos使用是位置的意思,比如之前链表,顺序表的时候pos是位置的索引,即从常量字符串的pos位置开始,那么什么时候结束呢?

到npos位置的时候结束:

查看文档发现,npos的值是-1?但是是size_t类型的,并且下面写到Maximum value for size_t,结合之前介绍的char的轮盘,可以知道npos是42亿多。

那么函数的意思就是从pos位置拷贝一直到npos?什么字符串要占4个G的大小?

所以结合文档(string太短了或者len的值是npos,就会直接拷贝完)

int main()
{string s1("abcdefg");string s2(s1, 0);string s3(s1, 0,30);return 0;
}

第一个我们只给了两个参数,那么函数就使用缺省值,即npos,第二个给了三个,但是30明显超出了s1的大小,所以这俩个字符串都是拷贝完s1,实际上使用的时候不会有第二种的写法。

int main()
{string s5("Hello world",5);cout << s5 << endl;return 0;
}

第五个函数的意思就是从一个常量字符串里面拷贝多少个字节进去,我们从Hello World里面拷贝5个字节进去,那么打印出来就是Hello。

int main()
{string s7(10, 'x');cout << s7 << endl;return 0;
}

第六个函数的意思就是拷贝n个c字符到string里面去。

以上3个作为了解,实际用处不太大的。

第7个涉及到了迭代器,暂时不介绍。

destructor即析构函数,析构没什么特殊的,出了作用域,string就自己销毁了,不需要自己去销毁。

拷贝有个很舒服的地方在于可以直接使用=:

当然,重载也重载了三个拷贝函数,

int main()
{string s1 = "abcdefg";string s2 = s1;cout << s1 << endl;cout << s2 << endl;return 0;
}

使用起来也是很方便,底层是怎么操作的我们就不用深究了,但是肯定是发生了隐式类型准换的,s1想要引用,就加const即可。

第三个函数就不用深究了,作用不大。


2.2 size length

在C语言中,我们计算数组的大小常常是size/size,在string中,我们直接调用size就行了:

int main()
{string s1 = "abdeef";cout << s1.size() << endl;cout << s1.length() << endl;return 0;
}

但是通过文档,我们发现size和length没有区别,都是返回string的长度,那么出现两个相同功能的函数的原因是因为string发明太早了,我们对于一个字符串可以说大小也可以说长度,顺序表也是,但是对于后面的树等结构,长度不太说的过去,所以对于string来说,length最初是专门为它服务的,大小是都能用的,length只有string可以用,所以最好后面统一使用size。


2.3 [ ]的使用

以前访问数组我们通常使用下标 + [ ]进行访问,这点在string里面都是可以使用的,但是这里实际上和数组访问有区别,这里不是指针偏移,这是调用的函数,[]重载。

int main()
{string s1 = "abcdefg";for (int i = 0; i < s1.size(); i++){cout << s1[i];}return 0;
}

可是如果到这里你觉得[]就介绍完了你就大错特错辣。

class string
{
public:char& operator[](size_t pos){assert(pos < _size);return _str[pos];}private:char* _str;size_t _size;size_t _capacity;
};

string里面的[]重载函数如上,第一个重点是引用返回,因为是引用返回,所以可以减少拷贝,第二个重点是,assert,因为使用了暴力检查,所以越界了就会直接报错:

既然是引用返回,所以我们可以修改字符串里面的内容,但是[]重载有两个版本,一个是普通版本没有const,一个是const版本,当我们不希望string被修改的时候就可以:

int main()
{const string s2("123456");s2[1] = 'a';return 0;
}


2.4 迭代器

迭代器iterator,有如上几个函数,实际上我们了解前4个就可以了,后面以c开头的其实就是const,表示迭代的元素不能被修改而已。

先看使用:


int main()
{string s1("Hello world");string::iterator it1 = s1.begin();while (it1 != s1.end()){cout << *it1 << " ";it1++;}return 0;
}

因为iterator是公有函数,所以使用的时候必须加上类名+类域访问符,使it1 = s1.begin(),就是相当于it1从字符H开始,end同理,end就是字符串的最后一个标志->'\0',那么这里看起来十分像指针,但是并不是,不如我们来看看类型。

int main()
{cout << typeid(string::iterator).name() << endl;return 0;
}

吓人吧?但是目前来说我们可以把它当作指针使用,但是我们只发挥了它的一层功力。

我们现在讨论一个问题,遍历一个字符数组有多少种方式?

遍历方式1:下标 + []

int main()
{string s1("Hello world");for (int i = 0; i < s1.size(); i++){cout << s1[i];}return 0;
}

遍历方式2:迭代器

int main()
{string s1("Hello world");string::iterator it1 = s1.begin();while (it1 != s1.end()){cout << *it1 << " ";it1++;}return 0;
}

遍历方式3:范围for

int main()
{string s1("Hello world");for (auto e : s1){cout << e;}return 0;
}

第一种方式没有什么好说的,第二种是迭代,第三种实际上底层也是调用的迭代器,来看看:

已经出现了刚才那个一长串的类型了,就不用多说了吧?

所以范围for循环底层也是通过迭代器实现的。

当我们进入到begin的文档就会大仙有两个版本,const和普通版本:

int main()
{const string s1("Hello world");string::const_iterator it1 = s1.begin();while (it1 != s1.end()){cout << *it1;it1++;}return 0;
}

const的作用不用多说,这里要注意的是为什么const_iterator,而不是const iterator?

我们类比指针,如果是const int* p ,那么修饰的是*p,指向不能变,如果是int* const p,就是修饰的p本身,那么如果是const iterator,修饰的就是迭代器本身,本身不能改变,还谈何遍历呢?

所以C++采用的方式是const_iterator。

接着就是rbegin的使用,如果说begin是正方向遍历,rbegin就是逆方向遍历,r也不难猜出来,Reverse,逆置。

使用如下:

int main()
{string s1("Hello world");string::reverse_iterator it1 = s1.rbegin();while (it1 != s1.rend()){cout << *it1;it1++;}return 0;
}

加个reverse_,同const一样的,使用了之后begin都要变成rbegin。

可能有疑问了,这里++?为什么不是--,实际上++是重载之后的--,不难想象++就是倒着回去遍历的。

2.5 Push_Back和append及+=

数据离不开插入数据:

Push_back即尾插,在字符串末尾插入一个数据,插入之后,对应的字符串长度也会增加。

int main()
{string s1("Hello world");s1.push_back('x');cout << s1 << endl;return 0;
}

push_back是插入一个字符,append是插入一个字符串,append插入的字符串可以是一个字符吗?那也是可以的,一个字符也可以是字符串:

int main()
{string s1("Hello world");s1.append("x");s1.append("abcd");cout << s1 << endl;return 0;
}

当然,这里也是有许多重载的,我们也是可以连蒙带猜的去猜使用方法的,但是实际上使用最多的是第三个,后面的其实,用处不太大;

int main()
{string s1("Hello world");string s2("123456");s1.append(s2,4,5);s1.append(s2,4);cout << s1 << endl;return 0;
}

这里就不介绍了看看文档咯。

当然类似的,有插入就有删除,比如尾删pop_back等,就不介绍了:

但是呢,还是略显麻烦了,不就是加个字符吗?string有个堪称神力的重载:

 不管是push_back还是append在这个重载面前都黯然失色了,因为这个太方便:

int main()
{string s("aaa");s += "bbb";s += "c";cout << s << endl;return 0;
}

要加什么直接加上去就行了,很方便。 


3 sort的使用

讲了这么多string内部的函数,这里就介绍一点实际应用,string是一种容器(数据结构),那么容器是存储数据的,算法是修改数据的,他们之间的联系靠迭代器完成,为什么说迭代器不是冗余的设计,因为迭代器是两者之间的桥梁,使用如下:

int main()
{string s1("Hello world");sort(s1.begin(), s1.end());cout << s1 << endl;return 0;
}

这里按照字典序排列,即ASCII码值排列字符串,sort所在的头文件是algorithm,中文意思就是算法的意思,sort的使用要注意左闭右开

左闭右开有个优点就是好计算总共排序多少元素,因为左减右就直接算出来了,这里是对整个string进行排序,如果想要进行部分排序,只需要:

int main()
{string s1("Hello world");sort(s1.begin(), s1.end() + 5);cout << s1 << endl;return 0;
}

这里是对前5个元素进行排序,可以看到离不开迭代器。


感谢阅读!

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

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

相关文章

[蓝桥杯]真题讲解:数三角(枚举+STL)

[蓝桥杯]真题讲解&#xff1a;数三角&#xff08;枚举STL&#xff09; 一、视频讲解二、正解代码1、C2、python33、Java 一、视频讲解 [蓝桥杯]真题讲解&#xff1a;数三角&#xff08;枚举STL&#xff09; 二、正解代码 1、C #include<bits/stdc.h> #define int long…

疯狂学英语

我上本科的时候&#xff0c;学校出国留学的气氛不浓厚&#xff0c;我们班只有一名同学有出国留学的倾向&#xff0c;我们宿舍八个人没有一个考虑过留学。 只有小昊&#xff0c;在本校上了研究生之后&#xff0c;不知道受到什么影响&#xff0c;想出国留学。那时候小昊利用一切…

汇聚荣电商:做拼多多运营如何入行?

踏入电商领域&#xff0c;尤其是成为拼多多平台的运营专家&#xff0c;是许多创业者和职场新人的梦想。拼多多以其独特的团购模式在电商界迅速崛起&#xff0c;吸引了大量的商家和消费者。如果你也对拼多多运营感兴趣&#xff0c;那么以下内容将为你提供实用的指导和建议。 一、…

(undone) 什么是马尔可夫链?Markov Chain

参考视频1&#xff1a;https://www.bilibili.com/video/BV1ko4y1P7Zv/?spm_id_from333.337.search-card.all.click&vd_source7a1a0bc74158c6993c7355c5490fc600 参考视频2&#xff1a;https://www.bilibili.com/video/BV1xg4y1K7z4/?spm_id_from333.788&vd_source7a…

采用java+B/S开发的全套医院绩效考核系统源码springboot+mybaits 医院绩效考核系统优势

采用java开发的全套医院绩效考核系统源码springbootmybaits 医院绩效考核系统优势 医院绩效管理系统解决方案紧扣新医改形势下医院绩效管理的要求&#xff0c;以“工作量为基础的考核方案”为核心思想&#xff0c;结合患者满意度、服务质量、技术难度、工作效率、医德医风等管…

[数据集][图像分类]杂草分类数据集17509张9类别

数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;17509 分类类别数&#xff1a;9 类别名称:["chineseapple","lantana","negatives","parkinsonia","part…

Maven、JavaWeb基础开发

1 Maven介绍 1、标准化的项目结构 2、标准化的构建流程 3、依赖管理 4、依赖范围 2 JavaWeb基础开发 2.1 Http协议 1 Http请求数据格式 2 Http响应数据格式 2.2 Web服务器&#xff08;Tomcat&#xff09; VTS、FileServer使用Tomcat部署&#xff1b; 其他服务单元TESLA S…

GBase 8s 数据库集群切换及恢复

GBase 8s 数据库切换分为自动切换、由CM控制的按FOC规则的切换、手工切换。 自动切换 全自动切换用于HAC集群中&#xff0c;由于集群只有两个节点&#xff0c;数据库相互之前进行状态检查&#xff0c;发现异常时&#xff0c;能按DRAUTO的配置方式进行自动切换。 在HAC集群中&…

MyBatis——MyBatis查询语句

一、返回Car 当查询的结果&#xff0c;有对应的实体类&#xff0c;并且查询结果只有一条时&#xff1a; &#xff08;查询结果只有一条也可以用 List 集合接收&#xff09; package org.qiu.mybatis.mapper;import org.qiu.mybatis.pojo.Car;/*** author 秋玄* version 1.0*…

e行64位V11.17.4 安卓全局虚拟定位APP

e行最新版11.17.4 支持全局虚拟位置 小米手机 百度地图 高德地图 实测成功 其他app自测 不一定支持所有app 下载&#xff1a;https://www.123pan.com/s/HAf9-tsyCh.html

【单片机调试】mcu调试bug记录

【单片机调试】mcu调试bug记录 2023.5-2023.11待输入 2023.12-2023.22024.3-至今1.spi通信问题 2023.5-2023.11 待输入 2023.12-2023.2 辞职阶段&#xff1a;【STM32调试】寄存器调试不良问题记录持续版 2024.3-至今 1.spi通信问题 现象说明&#xff1a; mcu与afe芯片为spi通…

(车载)毫米波雷达信号处理中的恒虚警检测(CFAR)技术概述

说明 恒虚警检测(Constant False-Alarm Rate, CFAR)是雷达目标(信号)检测中很重要的一个概念&#xff0c;从事雷达相关科研或工程研发的或多或少应该都接触过。CFAR这项技术在工程实践上其实是比较简单的(至少在我了解的车载雷达领域)&#xff0c;不过这项技术也有很多可以深挖…