stl容器学习——queue,stack,list与string
简介:本文记录了对string list queue stack四个容器的学习总结,包含有四种容器常用的函数介绍和一些使用过程中碰到的细节总结,在list容器中介绍了迭代器的使用。
头文件
想要用哪一种容器,就要加上对应的头文件
比如想要使用queue , 就要加上 #include<queue>
以此类推,想要使用STL库中的容器,只要加上它们的头文件就好。
string
目录部分
1.string的定义及初始化
2.string的运算符和比较符使用
3.常用的一系列函数
1.string的定义及初始化
string str
string可以看成一种定义的字符串类型,定义的方法和基本类型(int等)是一样的。
string str = "hello world";
string能够在定义的时候直接用"="进行赋值,这样str代表的就是"hello world"这一个字符串。
str = "hello world";
当然在定义结束后再赋值也是可以的。
在这里要介绍一下assign这个函数,它是个用来对string赋值的函数。
assign的赋值是覆盖性的,会覆盖掉原来字符串的内容,相当于重置了一遍后再写入新的内容。
我们先定义两个字符串string str1,str2;
再定义一个字符串并初始化为"hello world": string str="hello world"
;
现在我们开始来介绍assign函数的几个常见用法
① 用一个字符串给另一个字符串赋值
str1.assign(str);
这里是将str的值赋给了str1,而str的值为"hello world",所以此时的str1也是"hello world";
那么如果我们给这个函数多加入两个参数呢?
str1.assign(str,int index,int size_count);
我们在函数后面多加了两个参数**index 和 size_count **
其中index代表着str这个字符串的下标,size_count代表着要被赋值的长度。
我们不妨令index=1,size_count=5,那么执行完str1.assign(str,1,5);
我们会得到这样的结果:str1="ello " (末尾有一个空格)
不难发现,这次的assign函数是从str字符串的下标1处开始,将往后的5个长度赋值给了str1,所以实际上str1就是str从 index下标 处开始,长度为 size_count 的一个字串。
那么如果只加入index参数,而不加入size_count这一个参数呢?
不妨再来执行下这个代码str1.assign(str,2);
此时的index=2,而str1="llo world";
很容易发现,如果不输入参数size_count,那么assign函数执行的就是将str字符串从index下标处开始的所有内容都赋给str1。
②用字符串常量对字符串进行赋值
用字符串常量,像"hello world"这种的给string赋值时:
如果输入的只有一个参数(字符串常量本身):str1.assign("hello world");
或者输入的是三个参数:str1.assign("hello world",1,8);
以上的两种赋值,跟①的结果是一样的。
但是!!!
如果输入的是两个参数,那么它的运行结果就跟①出现了不同。
举个栗子:
str1.assign("hello world",3);
最后str1="hel"而不会是"lo world"。
当只有两个参数的时候,输入的第二个参数实际上是size_count而不是index。
所以输入两个参数时,实际上默认index=0,也就是从字符串常量"hello world"的开头开始,然后截取前size_count个元素赋值给str1.
而在①的情况中,如果输入两个参数,默认的是从index开始(index为输入值),默认size_count是从index开始剩下的其他元素的个数。
③ 用n个相同的字符对字符串赋值
str1.assign(int n,char ch);
这个用法比较简单,我举个栗子大家就能明白了。
str1.assign(10,'a');
执行完这个语句后,str1="aaaaaaaaaa" (10个a)
2.string的运算符及比较符
string支持 = , == , += , != , + 这几种运算符的操作
= 就是赋值作用,这一点在前面的初始化部分已经说明过了,相当于c语言中的strcpy函数。
== 和 != 就是用来比较两个字符串是否相等,作用相当于c语言中的strcmp函数。
+= 和 + 则可以用来为string赋值,这种赋值是添加性的,不会覆盖掉字符串原先的值。
string str="hello world";
string str1="qaq";
str1+=str;//执行完毕后,此时的str1="qaqhello world"
str1+='w';//执行完毕后,此时的str1="qaqhello worldw"
str1+="orz";//执行完毕后,此时的str1="qaqhello worldworz";
从上面的例子可以看出,+=这个符号不仅可以用在string类型,字符串常量和字符型也是同样适用的。
3.string的一些常用函数
① size()和length()
size函数返回的是字符串的大小,length返回的是字符串的长度,但是实际上它们的返回值是一样的,包括在cpp源码中的定义也是一样的,所以实际上没啥区别,喜欢用哪个就用哪个。
string str="hello";
此时str.size()和str.length()的值都是5(字符串的长度).
② at()
at()函数的参数是at(int index),index是字符串的下标
在c语言中,我们要想遍历输出一个字符串数组,可以用到这样的代码:
for(i=0;i<len;i++)//len为字符数组str的长度
{
print("%c",str[i]);
}
那么在使用c++的string时,我们可以使用这样的代码来替换:
for(i=0;i<str.size();i++)
{
cout<<str.at(i);
}
相比较一下,我们马上就能发现,str.at(i)实际上和str[i]是一样的,只是表示的方法不同。
那么at()这个函数有什么好处呢?
at()函数是十分安全的,它会帮你检查下标是否越界,如果越界程序将无法运行,避免因为本次的越界情况导致更严重的错误,而如果用str[i]的表示方法,则没有办法保证安全性。
建议自己输出一下str.at(-1)这种肯定会越界的值,看看编译器会输出什么
③ find()
string除了find()以外,还有find_first_of这一类的函数,在此不做介绍
find() 一般用来查找子串,当然也可以用来查找单个字符是否在字符串中出现过。
如果在主串中找到了要查找的字串或者单个字符,那么会返回字串在主串中第一次出现的位置或是查找到的单个字符的位置。
如果没有找到,返回的值是 string::npos ,返回的值是 string::npos ,返回的值是 string::npos
重要的话要说三遍,这个返回值要怎么使用呢。
npos这个常量是定义为-1,但是npos的类型实际上是无符号数,所以npos实际上是这个类型正数的最大值。
说了这么多,来直接看一下例子吧:
string str="hello world";
string sub1="ell";
string sub2="wor";
string sub3="heo";
cout<<str.find(sub1)<<' '<<str.find(sub2)<<' '<<str.find(sub3);
/*
输出结果是1 6 4294967295
这里可以很明显发现,因为sub1和sub2都是可以找到的,返回的就是找到的第一个字符的下标
而sub3是找不到的,这个时候find函数的返回值是4294967295,也就是2^32-1(unsigned int 的最大值)
*/
从上面的代码中,可以很明显看出find的返回值是多少,那么如果我们用int或者long型的变量来接收find函数的这个返回值可不可行呢?
int i1,i2;
long i3;
i1=str.find(sub1);
i2=str.find(sub2);
i3=str.find(sub3);
cout<<i1<<' '<<i2<<' '<<i3;//输出的结果是 1 6 -1
我们都知道数据是依照补码的形式储存的,而2^32-1这个值储存到int和long类型的时候,代表的值都是-1,所以这个时候输出的值自然就是-1了。
看完上面两个例子,应该就知道要怎么使用find函数的返回值了,我们再举一个例子说明吧:
题目当你在str主串中寻找一个sub字串时,如果找到字串,输出yes,没有找到则输出no
string str="hello world";
string sub="hlo";//这里举一个找不到的例子
//写法1
if(str.find(sub) == string::npos)
{
cout<<"yes"<<endl;
}
else
{
cout<<"no"<<endl;
}
//写法2
int find;
find=str.find(sub);
if(find != -1)
{
cout<<"yes"<<endl;
}
else
{
cout<<"no"<<endl;
}
//写法三(错误写法!!)
if(str.find(sub) >= 0)
{
cout<<"yes"<<endl;
}
else
{
cout<<"no"<<endl;
}
在以上的三个写法中,前两个写法都是前面我们所提到的正确方法,第一个是直接与string::npos作比较,第二个则是用int类型或者long类型接收这个返回值,然后和-1作比较,这两种都是可行的。
那么我们来看看第三种写法:为什么if (str.find(sub) >= 0)
这个判断语句是错误的呢?
答案很简单,还记得我们上面提过,find函数如果没有找到,返回的值实际上是2^32-1,所以不管有没有找到字串sub,输出的都是"yes"。
那如果写成if(str.find(sub) == -1)
这个判断语句呢?
答案其实是可行的,无符号数是没有负数的,所以碰到-1这个数的时候,实际上是和-1的补码作比较,而前面也提到过了,它的补码实际上和-1的就是相同的,所以这个判断是可以的。
总结一下:千万不能把判断语句写成if (str.find(sub) >= 0)
,如果是这么写,那么if条件实际上是永远成立的。
好了,上面花了很多的篇幅来详细解释了一下find函数的返回值问题,从我的个人角度来看,find函数的返回值还是挺有意思的,而且如果不清楚的话,很有可能在这里犯下难以被察觉的错误。
那么接下来来介绍一下find函数的一些常用的参数。
我们以string str="hello world",sub;
这样的两个字符串为例,其中str是被初始化定义过的。
第一个用法就是上文一直在使用的str.find(sub)
,传入的参数是一个字符串,如果找到,那么返回的就是第一个下标的位置,如果没找到,返回值就是string::npos ,也就是-1。
当然除了传入字符串,传入单个的字符也是可以的:str.find('l')
如果找到,返回的就是第一个l的下标值,在这里面就是2,如果没有找到返回的也是string::npos
那如果我在后面加上第二个参数呢?
str.find(sub,int index)
那么这个函数要表达的意思就是:从下标index开始,搜索sub这个字串,如果搜索到该字串,返回第一个字符的下标值。
举一个例子:string str="hello world",sub="hel";
在这个时候,如果我们使用的是str.find(sub)
,那么我们得到的返回值就是0
而如果我们使用的是str.find(sub,3)
,那么我们得到的返回值就是string::npos(从下标3开始寻找,没有办法查找到sub字串)。
❗实际上,如果只输入第一个参数,第二个参数是默认为0的,也就是代表着从头开始查找
find函数是有第三个参数的,但是第三个参数的使用比较少见,这里暂时不作介绍
④ rfind()
rfind()函数实际上和find()函数是十分相似的,差别只在于它们的查找顺序不一样。
stl容器学习——queue,stack,list与string的更多相关文章
- 【STL容器学习】-关联容器与map的用法
STL提供了4个关联容器:set.multiset.map和multimap.这些容器提供了通过keyword高速存储和訪问数据元素的能力.Set和map不同意有反复keyword,而multiset ...
- STL容器分析--queue
queue,顾名思义,是指队列.满足先进先出的原则.
- STL之容器适配器queue的实现框架
说明:本文仅供学习交流,转载请标明出处,欢迎转载! 上篇文章STL之容器适配器stack的实现框架已经介绍了STL是怎样借助基础容器实现一种经常使用的数据结构stack (栈),本文介绍下第二种STL ...
- STL容器适配器 stack, queue
stack是一种后进先出(last in first out)的数据结构.它只有一个出口,如图所示.stack允许新增元素,删除元素,取得最顶端元素.但除了最顶端外,没有其他任何地方可以存储stack ...
- STL序列式容器学习总结
STL序列式容器学习总结 参考资料:<STL源码剖析> 参考网址: Vector: http://www.cnblogs.com/zhonghuasong/p/5975979.html L ...
- STL总结之queue, priority_queue, stack
之所以把这三个容器放在一起,是因为他们都是容器适配器. STL中queue就是我们常用的FIFO队列,实现是一个容器适配器,这种数据结构在网络中经常使用. queue的模板声明: templa ...
- 容器适配器(stack、 queue 、priority_queue)源码浅析与使用示例
一.容器适配器 stack queue priority_queue stack.queue.priority_queue 都不支持任一种迭代器,它们都是容器适配器类型,stack是用vector/d ...
- STL之queue&stack使用简介
queue 队列也是一个线性存储表,与后进先出的堆栈不同,元素数据的插入在表的一端进行,在另一端删除,从而构成了一个先进先出(First In First Out) 表.插入一端称为队尾,删除一 ...
- Effective STL 学习笔记: 多用 vector & string
Effective STL 学习笔记: 多用 vector & string 如果可能的话, 尽量避免自己去写动态分配的数组,转而使用 vector 和 string . 原书作者唯一想到的一 ...
随机推荐
- RTX Server SDK跨服务器
反向单点登录RTX,即通过腾讯通登录到其他的系统,登录腾讯通后其他的系统不用输入用户名和密码即可登录.可能有二种情况.腾讯通和其他系统在同一台服务器上或在不同的服务器上.要调用腾讯通的登录验证接口的系 ...
- Zookeeper使用--开源客户端
一.ZkClient ZkClient是在Zookeeper原生API接口之上进行了包装,是一个更易用的Zookeeper客户端,其内部还实现了诸如Session超时重连.Watcher反复注册等功能 ...
- [模板]KMP字符串匹配
洛谷P3375 注意:两次过程大致相同,故要熟读熟记,切勿搞混 可以看看其他的教程:http://www.cnblogs.com/c-cloud/p/3224788.html 本来就不太熟,若是在记不 ...
- Java Persistence with MyBatis 3(中文版) 第三章 使用XML配置SQL映射器
关系型数据库和SQL是经受时间考验和验证的数据存储机制.和其他的ORM 框架如Hibernate不同,MyBatis鼓励开发者可以直接使用数据库,而不是将其对开发者隐藏,因为这样可以充分发挥数据库服务 ...
- CSS实现input默认文字灰色有提示文字点击后消失鼠标移开显示
CSS实现input美化操作默认是为灰色,并且有提示 如下图 鼠标点击后文字消失,鼠标移开后文字显示 给input入下图添加代码 style="color:#cccccc; outline: ...
- QT学习之多线程
[为什么要用多线程?] 传统的图形用户界面应用程序都只有一个执行线程,并且一次只执行一个操作.如果用户从用户界面中调用一个比较耗时的操作,当该操作正在执行时,用户界面通常会冻结而不再响应.这个问题可以 ...
- smarty中用truncate来截取中英文字符串及避免中文乱码问题
smarty中用truncate来截取含有中英文的字符串,可能会出现中文乱码问题.字符串截取长度不一问题,下面是新建个扩展函数,或修改原Truncate函数方法也可以的.扩展smarty/plugin ...
- Activator不能创建包含范型参数的实例
Activator包含特定的方法,用以在本地或从远程创建对象类型,或获取对现有远程对象的引用.此类不能被继承. 具体介绍:http://msdn.microsoft.com/zh-cn/library ...
- Hadoop压缩之MapReduce中使用压缩
1.压缩和输入分片 Hadoop中文件是以块的形式存储在各个DataNode节点中,假如有一个文件A要做为输入数据,给MapReduce处理,系统要做的,首先从NameNode中找到文件A存储在哪些D ...
- freePCRF免费版体验
[摘要]遍寻网络数昼夜,未得开源PCRF,亦未得有参考价值的PCRF相关文档.所幸觅得免费体验版freePCRF软件.可窥见PCRF设计思路.方法:PCC规则定义.管理策略:遂记录安装.体验心得. f ...