书名:C/C++函数与算法速查宝典
ISBN:978-7-115-58835-7
本书由人民邮电出版社发行数字版。版权所有,侵权必究。
您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。
我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。
如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。
著 陈 锐 孙玉胜 梁 辉
责任编辑 蒋 艳
人民邮电出版社出版发行 北京市丰台区成寿寺路11号
邮编 100164 电子邮件 315@ptpress.com.cn
网址 http://www.ptpress.com.cn
读者服务热线:(010)81055410
反盗版热线:(010)81055315
读者服务:
微信扫码关注【异步社区】微信公众号,回复“e58835”获取本书配套资源以及异步社区15天VIP会员卡,近千本电子书免费畅读。
本书全面、系统地讲解了C和C++中的常用函数及算法,其内容分为3篇,共29章,包括近300个常用函数和九大类算法,还以实例形式讲解了Visual Studio调试技术。其中,在C语言函数篇,对每一个函数的讲解都包含了函数原型、功能、参数、返回值、范例、解析等内容,部分函数会通过综合实例来辅助理解。在算法篇,每个算法采用相应实例进行讲解,包含问题、分析、实现、说明等内容。在C++输入/输出流与容器篇,针对每个类库选取了最常用的函数,按构造类函数、存取类函数、操作类函数等类别从函数原型、函数功能、函数参数、函数返回值、函数范例、函数解析等方面进行了介绍。
本书适合学习C/C++函数和算法的初、中级开发人员,爱好者和大、中专院校学生使用。对于经常使用C/C++进行开发的程序员,本书更是一本不可多得的案头常备工具书。
C/C++作为目前最为流行的编程语言之一,是高等院校计算机类相关专业学生的必修课程,也是计算机科学研究和软件开发的重要基础。熟练掌握C/C++编程语言和相关的开发工具对于今后深入学习和理解数据结构、算法设计与分析、操作系统、计算机网络、数据库原理、编译原理等专业课程意义重大。C/C++定义了编写程序的语法规则,其中的算法则告诉如何利用这两门语言编写出高质量的程序。本书主要介绍C语言常用的函数、C++常见类库和函数、常用算法及范例,旨在帮助读者掌握C/C++中的常用函数和算法,理解如何使用这些函数,并熟谙算法思想。
本书分为3篇:C语言函数篇、算法篇、C++输入/输出流与容器篇。其中,C/C++函数、容器主要介绍每个函数的原型、参数含义、返回值及使用方法。相对来说,这两部分内容比较容易掌握。算法这一篇分11章(第8~18章)进行介绍,其中第18章是以范例的形式介绍程序调试技术。我们学习计算机软件开发的过程往往是从掌握编程语言的语法开始,但在学完编程语言后,只是了解了这些语言的语法,会编写简单的程序,如果遇到一些稍有难度的程序(如蛇形方阵、螺旋矩阵)时,仍然会感到吃力。而导致这种结果的其中一个原因是看的程序太少,阅读的程序设计类书籍太少,另一个原因是没有学过数据结构和算法方面的知识。在读完一本C语言的书后,虽然了解了它的语法规则,但是可能还不怎么会用,这就需要多看一些范例,并上机实践。除此之外,还需要学习并掌握一些常见的算法。算法是程序设计的思想和灵魂,而C/C++只是实现算法的工具。这就像做一道菜,语言工具就是食材和作料,算法就是烧菜的方法,至于菜烧得好吃不好吃,则取决于厨师的手艺。在编程中,算法决定了编写出的程序是不是有效,因此,熟练掌握算法至关重要。
为了让读者快速地掌握函数的使用方法,除了介绍函数的功能、参数、返回值外,本书还提供了极具代表性、趣味性和实用性的范例,以开拓读者思路,使其理解算法设计的奥妙。例如,第12章的“求n个数中的最大者”“和式分解”“大牛生小牛问题”都巧妙地利用了递归来实现。第16章矩阵算法中的“打印螺旋矩阵”“将矩阵旋转90度”虽然代码不长,却充分体现出程序员的程序设计思想和实际编程技术。考虑到算法的实用性,本书尽量将范例与实际工作和生活相结合,比如加油站问题、找零钱问题、大小写金额转换、求算术表达式的值。本书的算法部分可以被看作对前面基础知识的一种升华。
本书作为一本工具书,对每一个函数和算法范例的关键知识点都进行了说明,并列出了注意事项,以帮助读者快速上手。
本书的内容不仅包括C函数库、C++函数库,还包括常用的算法。本书精选了C语言中的7个常用函数库,其中包含了100多个常用函数,还精选了多个常用算法,比如排序算法、查找算法、递推算法、枚举算法、递归算法、贪心算法、回溯算法等。此外,还精选了C++中的11个常用类库,其中包含了近200个常用函数。这些函数涵盖了C/C++的各个领域,基本满足读者的各项需求,算法也比较全面,所选用的范例也都是比较经典的范例。
本书层次分明、结构清晰,便于读者阅读和掌握。本书用篇、章、节和小节划分知识点,其中第1篇C语言函数篇中每一小节都以【函数原型】【函数功能】【函数参数】【函数的返回值】【函数范例】【函数解析】的形式分别进行讲解。
本书对每个函数都结合了具体的范例进行讲解,旨在通过具体运用,让读者明白函数的用法。而本书的算法则除了有具体的范例外,还用比较直观的图表来表示抽象的概念,以便读者掌握。在叙述上,本书普遍采用短句或易于理解的语言,让读者阅读起来更轻松。
针对每个函数和算法,本书均提供了具体的应用范例。此外,还选取了一些比较大的综合范例以说明多个函数的综合应用效果。另外,除了对算法原理的讲解,本书还筛选了典型范例,并提供了完整的实现代码,方便读者掌握算法思想,提高读者的实践能力。
第1篇主要讲解C语言的常用函数,包括ctype.h、stdio.h、string.h、stdlib.h、math.h、stdarg.h、time.h库函数,如字符处理函数、标准控制台输入/输出函数、字符串和字符数组、字符串转换函数、内存分配函数、过程控制函数、数学函数、可变参数函数、日期和时间函数的应用。
第2篇主要讲解常用算法,包括插入排序、交换排序、选择排序、归并排序和基数排序算法、基于线性表/树的查找算法,以及哈希查找算法、顺推法和逆推法、枚举算法、递归算法、贪心算法、回溯算法、分治算法、矩阵算法、实用算法等。
第3篇主要讲解C++输入/输出的基类ios_base类、iostream类、文件流类、string类、vector类、deque类、list类、stack类、queue类、set类、map类的使用。
在教学研究和实践过程中,经常有学生在上机实践时会犯这样或那样的错误,那么如何能快速找出错误程序的位置和原因,以便让程序正常运行呢?方法如下。
为了解决程序调试问题,首先要选择一个比较趁手的开发工具,比如Visual C++或Visual Studio。
● 对于语法错误,编译器会直接定位错误行,并给出相应的错误提示。
● 对于逻辑错误和运行时的错误,则需要为可能出问题的代码段设置断点,以跟踪查看变量在程序运行过程中的变化情况。通过对输入的数据进行分析,就能很快找出问题所在。
虽然本书为所有的范例都提供了完整的代码,但还是建议读者亲自在计算机上运行一下代码,在编写代码和运行代码的过程中体会算法的设计思想。这个过程中,你也许会不小心输入错误,也许会为一个小错误苦恼半天,但在经过多次检查和艰难调试后,你最终会找到代码错误的原因并且成功将其解决。当你看到代码正确地运行出结果时,你可能会激动不已,甚至喜极而泣。这个过程也是每个成功者的必经之路,只有经历无数次的痛苦、挣扎,你才有可能成长为一名经验丰富的C/C++程序员,或一名合格的软件工程师。计算机是一门学科,也是一门技术,算法思想固然很重要,但再伟大的算法也需要对其进行验证。正所谓实践是检验真理的唯一标准,这个亘古不变的道理在这里同样成立。
如果有读者看完本书后感觉有所收获,那么编者长时间的辛苦与付出就是值得的,也就达到了编写本书的目的。
本书范例的运行结果(如图1-1)中显示的路径仅为作者本地运行路径,读者运行的路径略有不同。
本书由陈锐、孙玉胜、梁辉主编,戎璐、徐洁、蔡增玉、陈明、李昊、崔建涛参与编写。
由于时间仓促,加上编者水平有限,书中难免会存在一些不足和疏漏,希望读者不吝赐教,通过邮箱235668080@qq.com与编者联系,或通过QQ群(1059130240)与编者沟通交流。
本书的编写参阅了大量相关文献、著作、网络资源,在此向各位原著者致谢!
另外,本书的出版得到了郑州轻工业大学和人民邮电出版社的大力支持与帮助,在此向其表示感谢。尤其要感谢人民邮电出版社的蒋艳编辑和王旭丹编辑,她们十分看重本书的实用价值,在她们的努力下,本书才得以顺利出版。
最后,还要感谢所有编者的家人,正是他们的默默付出与鼓励才使我们顺利完成本书的编写。
陈锐
本书由异步社区出品,社区(https://www.epubit.com/)为您提供相关资源和后续服务。
本书提供如下资源:
● 本书配套源代码;
● C++输入/输出流与容器篇对应PDF电子资源。
要获得以上配套资源,请在异步社区本书页面中点击,跳转到下载界面,按提示进行操作即可。注意:为保证购书读者的权益,该操作会给出相关提示,要求输入提取码进行验证。
如果您是教师,希望获得教学配套资源,请在社区本书页面中直接联系本书的责任编辑。
作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。
当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,点击“提交勘误”,输入勘误信息,单击“提交”按钮即可。本书的作者和编辑会对您提交的勘误进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。
扫描下方二维码,您将会在异步社区微信服务号中看到本书信息及相关的服务提示。
我们的联系邮箱是contact@epubit.com.cn。
如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。
如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们;有意出版图书的作者也可以到异步社区在线提交投稿(直接访问www.epubit.com/ contribute即可)。
如果您是学校、培训机构或企业用户,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。
如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接发邮件给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。
“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT技术图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT技术图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。
“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社近40年的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、AI、测试、前端、网络技术等。
异步社区
微信服务号
由ANSI制定的C标准库虽然不是C语言本身的构成部分,但是它支持标准C语言的实现,还提供该函数库中的函数声明、类型及宏定义。标准库中的函数及宏定义如下表所示。
标准库中的函数及宏定义
函数 |
宏定义 |
alloc.h |
动态地址分配函数 |
assert.h |
诊断函数 |
float.h |
定义从属于环境工具的浮点值 |
math.h |
数学函数 |
stdarg.h |
变长参数表 |
stdlib.h |
常用函数(动态内存分配、类型转换等) |
ctype.h |
字符操作函数 |
limits.h |
定义从属于环境工具的各种限定 |
setjmp.h |
非局部跳转函数 |
stddef.h |
常用函数 |
string.h |
字符串函数 |
errno.h |
定义出错代码 |
local.h |
地区函数 |
signal.h |
信号函数 |
stdio.h |
标准的输入/输出函数 |
time.h |
日期与时间函数 |
如果要使用标准库中的函数,则需要用以下的方式包含库函数。
#include<库函数>
虽然库函数的包含顺序是任意的,但是库函数必须被包含在任何外部声明或定义之外。
注意:C++标准库也同样包含C标准库,但是所有C语言函数库的库函数之前都被冠以“c”,例如,C标准库中的库函数stdio.h在C++中则变为cstdio。
ctype.h库函数包含了C语言中的字符测试函数、字符转换函数等函数。字符测试函数的作用是判断字符的类型,如数字字符、英文字母、空白字符等。字符转换函数主要有大写英文字母转换为小写英文字母的函数、小写英文字母转换为大写英文字母的函数、字符转换为ASCII码的函数。
ctype.h库函数在C++中通用,使用时,需要以下文件包含命令。
#include <cctype>
C语言中的字符测试函数可以判断字符属于哪种类型,比如是属于英文字母、数字字符、控制字符、可打印字符、小写英文字母、标点符号、空白符,还是属于十六进制字符。另外,还可以判断字符属于ASCII码的范围等。
int isalnum(int ch);
isalnum函数的功能是判断字符是否是英文字母或数字字符。
参数ch:可以是字符,也可以是整型数字。
如果ch是英文字母或数字字符,则返回非0值;否则返回0。
/********************************************
*范例编号:01_01
*范例说明:判断字符是否是英文字母或数字字符
*********************************************/
01 #include <stdio.h>
02 #include <ctype.h>
03 void main()
04 {
05 char ch1=’*’;
06 char ch2=’2’;
07 if(isalnum(ch1)!=0)
08 printf(“’%c’是英文字母或数字字符\n”,ch1);
09 else
10 printf(“’%c’不是英文字母也不是数字字符\n”,ch1);
11 if(isalnum(ch2)!=0)
12 printf(“’%c’是英文字母或数字字符\n”,ch2);
13 else
14 printf(“’%c’不是英文字母或数字字符\n”,ch2);
15 } system(“pause”);
该函数范例的运行结果如图1-1所示。
图1-1 函数范例的运行结果
(1)参数 ch 必须是用单引号括起来的字符,或者是整型数字。例如,’a’’2’’5’’%’都是合法的。
(2)如果 ch 是’0’~’9’的数字,或者是’A’~’Z’和’a’~’z’的字符时,则返回非0值;否则返回0。
isalnum函数是宏定义,非真正函数。
int isalpha(int ch);
isalpha函数的功能是判断ch是否是英文字母。
参数ch:可以是带单引号的英文字母,也可以是带单引号的数字,或其他字符。
如果ch是英文字母(‘A’~’Z’或’a’~’z’),则返回非0值;否则返回0。
/********************************************
*范例编号:01_02
*范例说明:判断字符是否是英文字母
*********************************************/
01 #include <stdio.h>
02 #include <ctype.h>
03 #include <stdlib.h>
04 void main()
05 {
06 int c;
07 c=’x’;
08 printf(“%c:%s\n”,c,isalpha(c)?”是英文字母”:”不是英文字母”);
09 c=’6’;
10 printf(“%c:%s\n”,c,isalpha(c)?”是英文字母”:”不是英文字母”);
11 c=’&’;
12 printf(“%c:%s\n”,c,isalpha(c)?”是英文字母”:”不是英文字母”);
13 system(“pause”);
14 }
该函数范例的运行结果如图1-2所示。
图1-2 函数范例的运行结果
(1)参数 ch必须是带单引号的字符,或者是整型数字。与isalnum函数的参数取值相同。
(2)如果ch是小写英文字母或大写英文字母,即’A’~’Z’或’a’~’z’,则函数返回非0值;否则返回0。
int isascii(int ch);
isascii函数的功能是判断ch的ASCII码是否位于0~127,也就是判断ch是否为ASCII码字符。
参数ch:可以是带单引号的字符,也可以是整型数字。
如果ch的ASCII码位于0~127,则函数返回非0值;否则返回0。ASCII的全称为美国信息交换标准代码,是一种标准的单字节字符编码方案,用来表示常用的英文字母、数字等字符与二进制数的对应关系。
/********************************************
*范例编号:01_03
*范例说明:判断字符的ASCII码是否位于0~127
*********************************************/
01 #include <stdio.h>
02 #include <ctype.h>
03 #include <stdlib.h>
04 void main()
05 {
06 int i,n;
07 char str[]={‘B’,0x80,’a’,’y’};
08 n=sizeof(str)/sizeof(char);
09 for(i=0;i<n;i++)
10 {
11 printf(“%c%s是一个ASCII字符\n”, str[i],(isascii(str[i]))?””:”不”);
12 }
13 system(“pause”);
14 }
该函数范例的运行结果如图1-3所示。
图1-3 函数范例的运行结果
(1)参数ch的取值合法性与isalpha函数的参数取值相同。
(2)主要判断ch的ASCII码是否位于0~127。
int iscntrl(int ch);
iscntrl函数的功能是判断ch是否是控制字符,即ASCII码是否位于0x00(NOL)~0x1f(VS)或等于0x7f(Delete键的ASCII码)。
参数ch:可以是带单引号的字符,也可以是整型数字。
如果ch是控制字符,则函数返回非0值;否则返回0。
/********************************************
*范例编号:01_04
*范例说明:判断字符是否是控制字符
*********************************************/
01 #include <stdio.h>
02 #include <ctype.h>
03 #include <stdlib.h>
03 void main()
04 {
05 int c;
06 c=’a’;
07 printf(“’%c’%s\n”,c,iscntrl(c)?”是控制字符”:”不是控制字符”);
08 c=13;
09 printf(“ASCII码为%x的字符%s\n”,c,iscntrl(c)?
10 “是控制字符”:”不是控制字符”);
11 c=0x7f;
12 printf(“ASCII码为%x的字符%s\n”,c,iscntrl(c)?
13 “是控制字符”:”不是控制字符”);
14 system(“pause”);
15 }
该函数范例的运行结果如图1-4所示。
图1-4 函数范例的运行结果
(1)参数ch的取值合法性与isalpha函数的参数取值相同。
(2)控制字符的ASCII码是0x00~0x1f和0x7f。
int isdigit(int ch);
isdigit函数的功能是判断ch是否是数字字符,即是否是’0’~’9’的字符。
参数ch:可以是带单引号的字符,也可以是整型数字。
如果ch的取值在’0’~’9’,则函数返回非0值;否则返回0。
/********************************************
*范例编号:01_05
*范例说明:判断字符是否是数字字符
*********************************************/
01 #include <stdio.h>
02 #include <ctype.h>
03 #include <stdlib.h>
04 void main()
05 {
06 char str[]=”2%3a5S”;
07 int i;
08 for(i=0;str[i]!=’\0’;i++)
09 printf(“%c%s数字字符.\n”,str[i],isdigit(str[i])?”是”:”不是”);
10 system(“pause”);
11 }
该函数范例的运行结果如图1-5所示。
图1-5 函数范例的运行结果
(1)参数ch的取值合法性与isalpha函数的参数取值相同。
(2)数字字符分别是’0’’1’…’9’,对应的ASCII码分别是48、49、…、57。
注意:不要将数字字符与数字0、1、…、9混淆。
int isgraph(int ch);
isgraph函数的功能是判断ch是否是可打印字符(不包括空格)。
参数ch:可以是带单引号的字符,也可以是整型数字。
如果ch是可打印字符(不包括空格),则返回非0值;否则返回0。
/********************************************
*范例编号:01_06
*范例说明:判断字符是否是可打印字符(不包括空格)
*********************************************/
01 #include <stdio.h>
02 #include <ctype.h>
03 #include <stdlib.h>
04 void main ()
05 {
06 char ch;
07 while(1)
08 {
09 printf(“请输入一个字符(退出请输入’q’):”);
10 ch=getchar();
11 getchar();
12 if(isgraph(ch))
13 printf(“’%c’是可打印字符.\n”,ch);
14 else
15 printf(“’%c’不是可打印字符.\n”,ch);
16 if(ch==’q’)
17 break;
18 }
19 system(“pause”);
20 }
该函数范例的运行结果如图1-6所示。
图1-6 函数范例的运行结果
(1)参数ch的取值合法性与isalpha函数的参数取值相同。
(2)可打印字符指的是可显示字符,英文字母、数字字符、标点符号都是可打印字符,可打印字符的ASCII码在33~127。换行符、回车符、空格符、Tab键对应的字符都是不可打印字符。
int islower(int ch);
islower函数的功能是判断ch是否是小写英文字母。
参数ch:可以是带单引号的字符,也可以是整型数字。
如果ch是小写英文字母,则返回非0值;否则返回0。
/********************************************
*范例编号:01_07
*范例说明:判断字符是否是小写英文字母
*********************************************/
01 #include <stdio.h>
02 #include <ctype.h>
03 #include <stdlib.h> void main()
04 {
05 int i=0,low_count=0,upper_count=0,other=0;
06 char str[]=”Test String.”;
07 char ch;
08 while(str[i])
09 {
10 ch=str[i];
11 if(islower(ch))
12 {
13 printf(“’%c’是小写英文字母.\n”,ch);
14 low_count++;
15 }
16 else if(isupper(ch))
17 {
18 printf(“’%c’是大写英文字母.\n”,ch);
19 upper_count++;
20 }
21 else
22 {
23 printf(“’%c’是其他字符.\n”,ch);
24 other++;
25 }
26 i++;
27 }
28 printf(“小写字母有%d个,大写字母有%d个,其他字符有%d个.\n”,
29 low_count,upper_count,other);
30 system(“pause”);
31 }
该函数范例的运行结果如图1-7所示。
图1-7 函数范例的运行结果
(1)参数ch的取值合法性与isalpha函数的参数取值相同。
(2)小写英文字母是’a’~’z’的字母,共26个,对应的ASCII码为97~122。
int isprint(int ch);
isprint函数的功能是判断ch是否是可打印字符(包括空格)。
参数ch:可以是带单引号的字符,也可以是整型数字。
如果ch是可打印字符(包括空格),则返回非0值;否则返回0。
/********************************************
*范例编号:01_08
*范例说明:判断字符是否是可打印字符(包括空格)
*********************************************/
01 #include <stdio.h>
02 #include <ctype.h>
03 #include <stdlib.h> void main()
04 {
05 int i=0;
06 char str[]=”Welcome to you!\nWelcome to Beijing!\n”;
07 while(isprint(str[i]))
08 {
09 putchar(str[i]);
10 i++;
11 }
12 system(“pause”);
13 }
该函数范例的运行结果如图1-8所示。
图1-8 函数范例的运行结果
(1)参数ch的取值合法性与isalpha函数的参数取值相同。
(2)isprint函数与isgraph函数都是判断字符是否是可打印字符的函数,区别在于前者将空格符作为不可打印字符,而后者则将空格符作为可打印字符。
(3)在范例程序中,因为有不可打印字符’\n’,所以只输出了第1个’\n’之前的字符。
(4)putchar函数的作用是将一个字符输出。
int ispunct(int ch);
ispunct函数的功能是判断ch是否是标点符号。
参数ch:可以是带单引号的字符,也可以是整型数字。
如果ch是标点符号,则返回非0值;否则返回0。
/********************************************
*范例编号:01_09
*范例说明:判断字符是否是标点符号
*********************************************/
01 #include <stdio.h>
02 #include <ctype.h>
03 #include <stdlib.h> void main()
04 {
05 char str1[]=”How are you,Mr Liu!”;
06 char str2[]=”Mobile interface development,system analyst,algorithm design!”;
07 int i=0,count=0;
08 char *p;
09 while(str1[i]!=’\0’)
10 {
11 if(ispunct(str1[i]))
12 count++;
13 i++;
14 }
15 printf (“字符串%s包含%d个标点符号.\n”,str1,count);
16 p=str2;
17 count=0;
18 while(*p!=’\0’)
19 {
20 if(ispunct(*p))
21 count++;
22 p++;
23 }
24 printf (“字符串%s包含%d个标点符号.\n”,str2,count);
25 system(“pause”);
26 }
该函数范例的运行结果如图1-9所示。
图1-9 函数范例的运行结果
(1)参数ch的取值合法性与isalpha函数的参数取值相同。
(2)在范例程序中,count是计数器,表示标点符号的个数。
int isspace(int ch);
isspace函数的功能是判断ch是否是空白符,空白符包括空格符、水平制表符、回车符等,如表1-1所示。
表1-1 空白符与ASCII码的对应关系
空白符 |
ASCII码 |
说明 |
‘ ’ |
32 |
空格符 |
‘\t’ |
9 |
水平制表符 |
‘\n’ |
10 |
换行符 |
‘\v’ |
11 |
垂直制表符 |
‘\f’ |
12 |
换页符 |
‘\r’ |
13 |
回车符 |
参数ch:可以是带单引号的字符,也可以是整型数字。
如果ch是空白符,则返回非0值;否则返回0。
/********************************************
*范例编号:01_10
*范例说明:判断字符是否是空白符
*********************************************/
01 #include <stdio.h>
02 #include <ctype.h>
03 #include <stdlib.h>
04 void main()
05 {
06 char str[]=”Huge come from Beijing!\n”;
07 char *p;
08 int count=0,alpha_count=0,black_count=0,other_count=0;
09 for(p=str;*p!=’\0’;p++)
10 {
11 if(isspace(*p))
12 black_count++;
13 else if(isalpha(*p))
14 alpha_count++;
15 else
16 other_count++;
17 count++;
18 putchar(*p);
19 }
20 printf(“字符个数为%d,英文字母个数为%d,空白符个数为%d,其他字符个数为%d\n”,
21 count,alpha_count,black_count,other_count);
22 system(“pause”);
23 }
该函数范例的运行结果如图1-10所示。
图1-10 函数范例的运行结果
(1)参数ch的取值合法性与isalpha函数的参数取值相同。
(2)在范例程序中,逐个判断字符串中的字符,如果是空白符,则将’\n’赋值给c,然后输出c;否则,直接输出c。
int isxdigit(int ch);
isxdigit函数的功能是判断ch是否是十六进制数字0~9和A~F(a~f)。
参数ch:可以是带单引号的字符,也可以是整型数字。
如果ch是十六进制数字对应字符,则返回非0值;否则返回0。
/********************************************
*范例编号:01_11
*范例说明:判断字符是否是十六进制数字
*********************************************/
01 #include <stdio.h>
02 #include <ctype.h>
03 #include <string.h> void main()
04 {
05 char str[3][10]={“2FE9H”,”3EC7”,”X48A”};
06 int i,k,len;
07 for(k=0;k<3;k++)
08 {
09 len=strlen(str[k]);
10 for(i=0;str[i]!=’\0’;)
11 if(isxdigit(str[k][i]))
12 i++;
13 else
14 break;
15 if(i>=len)
16 printf(“%s是十六进制对应的字符\n”,str[k]);
17 else
18 printf(“%s不是十六进制对应的字符\n”,str[k]);
19 }
20 }
该函数范例的运行结果如图1-11所示。
图1-11 函数范例的运行结果
(1)参数ch的取值合法性与isalpha函数的参数取值相同。
(2)在范例程序中,因为字符串”2FE9H”中含有字符’H’,”X48A”中含有’X’,所以两者都不是十六进制数字对应的字符串。
(3)isxdigit函数的作用是判断ch是否是十六进制数字对应的字符,而不是判断ch是否是十六进制数。’0’’1’’C’是十六进制数对应的字符,0、1、C是十六进制数中的数字。
字符转换函数包括将大写英文字母转换为小写英文字母的函数、将小写英文字母转换为大写英文字母的函数、将字符转换为ASCII码的函数。
int tolower(int ch);
如果ch是’A’~’Z’的大写英文字母,则tolower函数会将ch转换为’a’~’z’的小写英文字母。
参数ch:可以是带单引号的字符,也可以是整型数字。
如果ch是大写英文字母,则返回小写英文字母;如果ch不是大写英文字母,则返回ch。
/********************************************
*范例编号:01_12
*范例说明:将大写英文字母转换为小写英文字母
*********************************************/
01 #include <stdio.h>
02 #include <ctype.h>
03 #include <stdlib.h>
04 #define MAXSIZE 100
05 void main()
06 {
07 char str[]=”Artificial Intelligence and Big Data are the most popular direction for
08 computer majors.\n”,str2[MAXSIZE];
09 int i,j;
10 for(i=0,j=0;str[i]!=’\0’;i++)
11 {
12 if(isalpha(str[i]))
13 {
14 if(isupper(str[i]))
15 {
16 str2[j++]=tolower(str[i]);
17 }
18 else
19 {
20 str2[j++]=str[i];
21 }
22 }
23 else
24 {
25 str2[j++]=str[i];
26 }
27
28 }
29 str2[j]=’\0’;
30 printf(“源字符串:%s”,str);
31 printf(“转换后的字符串:%s”,str2);
32 system(“pause”);
33 }
该函数范例的运行结果如图1-12所示。
图1-12 函数范例的运行结果
(1)参数ch的取值合法性与isalph函数的参数取值相同。
(2)如果ch是大写英文字母,则tolower函数的返回值是小写英文字母;否则,不进行转换,直接将原字符返回。因此,该函数可以直接作为putchar函数的参数。
int toupper(int ch);
toupper函数的功能是将小写英文字母’a’~’z’转换为大写英文字母’A’~’Z’。
参数ch:可以是带单引号的字符,也可以是整型数字。
如果ch是小写英文字母,则返回大写英文字母;如果ch不是小写英文字母,则返回ch。
/********************************************
*范例编号:01_13
*范例说明:将小写英文字母转换为大写英文字母
*********************************************/
01 #include <stdio.h>
02 #include <ctype.h>
03 #include <stdlib.h>
04 #define MAXSIZE 100
05 void main()
06 {
07 char str[]=”Hello,C Program Language.\n”
08 “Welcome to C Language World!\n”,str2[MAXSIZE];
09 int i,j;
10 for(i=0,j=0;str[i]!=’\0’;)
11 {
12 if(isalpha(str[i]))
13 {
14 if(isupper(str[i]))
15 str2[j++]=str[i++];
16 else if(islower(str[i]))
17 str2[j++]=toupper(str[i++]);
18 }
19 else
20 str2[j++]=str[i++];
21 }
22 str2[j]=’\0’;
23 printf(“源字符串:%s”,str);
24 printf(“转换后的字符串:%s”,str2);
25 system(“pause”);
26 }
该函数范例的运行结果如图1-13所示。
图1-13 函数范例的运行结果
(1)参数ch的取值合法性与isalpha函数的参数取值相同。
(2)与tolower函数一样,因为toupper函数具有返回值,所以也可以作为putchar函数的参数。
int toascii(int ch);
toascii函数的功能是将字符转换为相应的ASCII码。
参数ch:是字符数据。
返回值是字符ch的ASCII码。转换后的ASCII码的范围是0~127,低7位以外的数位将被清除。
/********************************************
*范例编号:01_14
*范例说明:将字符转换为对应的ASCII码
*********************************************/
01 #include <stdio.h>
02 #include <ctype.h>
03 void main()
04 {
05 char ch;
06 while(1)
07 {
08 printf(“请输入一个字符:”);
09 ch=getchar();
10 if(ch==’q’)
11 break;
12 if(ch!=10)
13 printf(“ASCII码为%d\n”,toascii(ch));
14 getchar();
15 }
16 }
该函数范例的运行结果如图1-14所示。
图1-14 函数范例的运行结果
(1)参数ch只能是单个字符数据,如’A’’a’等。如果输入多个字符,则只将第一个字符转换为对应的ASCII码。
(2)范例程序中第2个getchar函数的作用是忽略输入的回车符。
C++标准库不仅包含了标准的C库,还包含输入/输出流(I/O)、字符串类(string)、标准容器和算法。
● 输入/输出流。ANSI C++定义了标准输入/输出流,支持原来的输入/输出流技术,还支持流缓冲区、格式化标识符、操作运输符、文件流,并支持cin、cout、cerr等对象。
● 字符串类。字符串类的引入主要用来消除对char*指针的使用,支持字符串的各种运算,如两个字符串的连接操作、字符串的交换,并自动进行内存管理。字符串类带来了比使用char*指针更好的性能。
● 标准容器。标准C++封装了组织数据更为通用的方法,在程序设计过程中不需要自己编写基本的操作代码。标准容器包括vector、list、queue、stack、deque、map、set等。
● 算法。C++标准库提供了一些常用的操作,其将标准容器作为操作的对象,利用模板函数实现了通用操作。比较常见的标准算法有for_each、find、count_if、equal、min、merge、sort等。
标准库中,容器和算法一般被称为标准模板库(Standard Template Library,STL)。迭代器(iterator)类似于指针,也是STL的一部分,可将容器和算法粘合在一起进行工作。
常用的流层次架构如右图所示。其中,底色为阴影的方框表示类,底色为白色的方框表示对象。
本篇主要讲解C++中最为常用的iostream类、fstream类及其基类——ios_base类、ios类。
流层次架构
标准容器是利用类模板组织并存储数据的集合,它管理着各种元素存储的空间并提供存取元素的各项操作,既可以直接存取元素也可以利用迭代器存取元素。标准容器分为3类:顺序容器、关联容器和容器适配器。其中,顺序容器包括vector类、deque类和list类;关联容器包括set类、map类、bitset类、multiset类、multimap类;容器适配器包括stack类、queue类、priority_queue类。
标准算法用来操作集合中的元素,如排序、查找、归并等。这些算法与具体的容器分离,利用迭代器对容器中的元素进行操作。这样做的好处就是不用为每一个容器都提供类似的服务,只用写一次代码就可以作用于所有的容器类型,减少了代码量,增强了灵活性。
迭代器是一种类似于指针的东西,标准库为每一种标准容器都定义了一种迭代器类型。所有的标准库容器都定义了相应的迭代器类型,而只有少数的容器支持下标操作。因为迭代器对所有的容器都适用,所以在C++程序中,更倾向于使用迭代器,而不是下标操作来访问容器元素。
C++标准模板库的分类如下图所示。
C++标准模板库的分类
ios_base类是C++中所有流类的基类,它描述了流的大多数基本属性和操作,并且对所有流对象来说都是通用的。但是,ios_base类不用做定义对象。
本章主要讲解ios_base类的最为常用的功能:输入/输出的形式,如靠左端显示还是靠右端显示、以十进制形式还是以十六进制形式输出、域宽、精度。
使用本章类中的相关函数时,需要使用以下文件包含命令。
#include< ios_base.h>
或
#include< ios_base>
using namespace std;
注意:C++的扩展名为cpp。
ios_base类的层次架构如图19-1所示。
图19-1 ios_base类的层次架构
01 ios_base (const ios_base&);
02 virtual ~ios_base();
03 fmtflags flags() const;
04 fmtflags flags(fmtflags fmtfl);
05 fmtflags setf(fmtflags fmtfl);
06 fmtflags setf(fmtflags fmtflags fmtfl,fmtflags mask);
07 void unsetf(fmtflags mask);
08 streamsize precision() const;
09 streamsize precision(streamsize prec);
10 streamsize width() const;
11 streamsize width(streamsize wide);
ios_base类的声明在xiosbase.h文件中。
fmtflags flags() const;
fmtflags flags(fmtflags fmtfl);
(1)第1个函数返回当前流的格式标志。
(2)第2个函数将流的格式标志设置为fmtfl。
参数fmtfl:要设置的流格式标志。fmtfl的类型为fmtflags。fmtflags的类别及含义如表19-1所示。
表19-1 fmtflags的类别及含义
常量 |
类别 |
含义 |
dec |
进制 |
读/写十进制整数 |
hex |
读/写十六进制整数 |
|
oct |
读/写八进制整数 |
|
fixed |
浮点数格式 |
用定点格式输出浮点数 |
scientific |
用科学计数法输出浮点数 |
|
internal |
对齐 |
在指定的位置利用插入符填充域宽 |
left |
在生成域的尾部插入填充字符填充域宽 |
|
right |
在生成域的头部插入填充字符填充域宽 |
|
boolalpha |
其他格式 |
读/写true或false作为bool对象的值 |
showbase |
插入一个前缀,作为整数域的基 |
|
showpoint |
输出带小数点的浮点数 |
|
showpos |
在非负数前插入一个加号 |
|
skipws |
输入时跳过前导空白符 |
|
unitbuf |
在每次进行插入操作之后都刷新输出 |
|
uppercase |
在插入操作中将小写字母转换为大写字母 |
以上这些常量可以是任何有效的组合,如ios_base::hex、ios_base::basefield。
函数返回调用前的流的格式标志。
/********************************************
*范例编号:19_01
*范例说明:设置输出格式后输出数字
*********************************************/
01 #include< iostream>
02 using namespace std;
03 void main ()
04 {
05 cout.flags(ios_base::left|ios_base::dec|ios_base::showbase);
06 cout.width(10);
07 cout< < 60< < endl;
08 cout.flags(ios_base::right|ios_base::oct|ios_base::showbase);
09 cout.width(10);
10 cout< < 60< < endl;
11 cout.flags(ios_base::right|ios_base::scientific|ios_base::showpos);
12 cout.width(16);
13 cout< < 1234.567< < endl;
14 system(“pause”);
15 }
该函数范例的运行结果如图19-2所示。
图19-2 函数范例的运行结果
(1)fmtflags类型可以用在成员函数flags、setf和unsetf中。
(2)fmtflags类型常量都是定义在ios_base类中的公共成员。因此,它们可以直接使用类名引用其成员,如ios_base::hex;也可以使用派生类或实例对象引用各个成员,如ios::left,cout.fixed。
(3)在标准C++中,类库中的所有类都在空间std中定义,因此可以将传统头文件的引用格式
#include < iostream.h>
写成如下形式。
#include < iostream>
using namespace std;
以上两种写法是等价的。引出名字空间只是为了避免不同类中太多的函数出现同名的情况。
fmtflags setf(fmtflags fmtfl);
fmtflags setf(fmtflags fmtfl, fmtflags mask);
void unsetf(fmtflags mask);
(1)第1个成员函数将流的格式标志设置为fmtfl。
(2)第2个成员函数用fmtfl和mask设置流的格式标志,并清除在mask设置而未在fmtfl中设置的格式标志,相当于调用函数flags((fmtfl&mask)|(flags()~mask))。
(3)第3个成员函数用来清除mask设置的流格式标志。
(1)参数fmtfl:要设置的流格式标志。
(2)参数mask:要设置的掩码。mask的取值及等价值如表19-2所示。
表19-2 mask的取值及等价值
mask值 |
等价值 |
adjustfield |
left|right|internal |
basefield |
dec|oct|hex |
floatfield |
scientific|fixed |
函数返回调用前的流的格式标志。
/********************************************
*范例编号:19_02
*范例说明:控制流的输出格式
*********************************************/
01 #include < iostream>
02 #include < stdlib.h>
03 using namespace std;
04 void main()
05 {
06 ios_base::fmtflags ff;
07 cout.setf(ios_base::right,ios_base::adjustfield);
08 cout.width(10);
09 cout < < ‘a’< < endl;
10 ff = cout.flags();
11 ff &= ~cout.basefield;
12 ff |= cout.hex;
13 ff |= cout.showbase;
14 cout.flags(ff);
15 cout < < 100< < endl;
16 cout.unsetf(ios_base::showbase);
17 cout < < 100< < endl;
18 system(“pause”);
19 }
该函数范例的运行结果如图19-3所示。
图19-3 函数范例的运行结果
setf(fmtflags fmtfl)函数的作用相当于调用函数flags (fmtfl|flags()),setf(fmtflags, fmtflags mask)函数的作用相当于调用flags((fmtfl&mask)|(flags() &~mask)),unsetf(fmtflags mask)的类型fmtflags可以用在成员函数flags、setf和unsetf中。
streamsize precision() const;
streamsize precision(streamsize prec);
(1)第1个成员函数返回浮点数的精度。
(2)第2个成员函数用来设置浮点数的精度。在C++中,streamsize的类型定义如下。
typedef int streamsize;
参数prec:要设置的浮点数的精度。
两个函数都返回原来存储的精度值。
/********************************************
*范例编号:19_03
*范例说明:利用设置的精度输出浮点数
*********************************************/
01 #include < iostream>
02 #include < stdlib.h>
03 using namespace std;
04 void main ()
05 {
06 double f=3.1415926;
07 cout.precision(6);
08 cout< < f< < endl;
09 cout.precision(10);
10 cout< < f< < endl;
11 cout.setf(ios::fixed);
12 cout< < f< < endl;
13 system(“pause”);
14 }
该函数范例的运行结果如图19-4所示。
图19-4 函数范例的运行结果
在默认情况下,精度表示输出小数点前后的所有数字的最大位数。在定点和科学计数法的情况下,精度表示输出小数点后的数字位数。
streamsize width() const;
streamsize width(streamsize wide);
(1)第1个成员函数返回当前的域宽。
(2)第2个成员函数设置新的域宽。
参数wide:新的域宽。
函数返回调用wide函数前的域宽。
/********************************************
*范例编号:19_04
*范例说明:按照设置的域宽输出数据
*********************************************/
01 #include < iostream>
02 #include < iomanip>
03 #include < stdlib.h>
04 using namespace std;
05 void main ()
06 {
07 cout< < 345< < endl;
08 cout.width(12);
09 cout< < 345< < endl;
10 cout.width(12);
11 cout.fill(‘A’);
12 cout< < right< < 345< < endl;
13 cout.width(12);
14 cout.fill(‘B’);
15 cout< < left< < 345< < endl;
16 cout< < setw(12)< < left< < 345< < cout.fill(‘B’)< < endl;
17 system(“pause”);
18 }
该函数范例的运行结果如图19-5所示。
图19-5 函数范例的运行结果
(1)域宽表示输出的最小字符个数。如果字符的宽度小于域宽,则根据格式标志(靠左、靠右)填充字符。要填充字符,需要调用ios类的fill函数。
(2)设置域宽也可以使用操作算子setw。例如,代码
cout.width(10);
cout< < 345< < endl;
与代码
cout< < setw(10)< < endl;
等价。使用setw流操作算子时,要包含头文件iomanip.h。
iostream类派生自istream(输入流)类和ostream(输出流)类,因此iostream类的对象可以执行输入/输出操作。
本章主要讲解派生出iostream类的istream类、ostream类、ios类。其中,ios类主要讲解最为常用的函数:get函数、getline函数、ignore函数、peek函数、read函数、putback函数、put函数、fill函数。
使用本章类中的相关函数时,需要使用以下文件包含命令。
#include< iostream.h>
或:
#include< iostream>
using namespace std;
iostream类的层次架构如图20-1所示。
图20-1 iostream类的层次架构
iostream类的成员函数可以分为4个部分,分别是由istream类派生的函数、由ostream类派生的函数、由ios类派生的函数和由ios_base类派生的函数。
(1)由istream类派生的函数如下。
istream&operator>>(bool&val );
istream&operator>>(short&val );
istream&operator>>(unsigned short&val );
istream&operator>>(int&val );
istream&operator>>(unsigned int&val );
istream&operator>>(long&val );
istream&operator>>(unsigned long&val );
istream&operator>>(float&val );
istream&operator>>(double&val );
streamsize gcount () const;
int get();
istream&get ( char& c );
istream&get ( char*s, streamsize n );
istream&get ( char*s, streamsize n, char delim );
istream&get ( streambuf&sb);
istream&get ( streambuf&sb, char delim );
istream&getline (char*s, streamsize n );
istream&getline (char*s, streamsize n, char delim );
istream&ignore ( streamsize n=1, int delim=EOF );
int peek ();
istream& read ( char*s, streamsize n );
streamsize readsome ( char*s, streamsize n );
streamsize gcount () const;
istream&putback ( char c );
istream&unget ();
streampostellg ();
istream&seekg ( streampos pos );
istream&seekg ( streamoff off, ios_base::seekdir dir );
(2)由ostream类派生的函数如下。
ostream&operator< < (bool&val );
ostream&operator< < (short&val );
ostream&operator< < (unsigned short&val );
ostream&operator< < (int&val );
ostream&operator< < (unsigned int&val );
ostream&operator< < (long&val );
ostream&operator< < (unsigned long&val );
ostream&operator< < (float&val );
ostream&operator< < (double&val );
ostream&operator< < (long double&val );
ostream&operator< < (const void*val );
ostream&operator< < (streambuf*sb );
ostream&put ( char c );
ostream&write ( const char*s , streamsize n );
streampos tellp ();
ostream&seekp ( streampos pos );
ostream&seekp ( streamoff off, ios_base::seekdir dir );
ostream&flush ();
(3)由ios类派生的函数如下。
bool good () const;
bool eof () const;
bool fail () const;
bool bad () const;
bool operator ! () const;
operator void * () const;
iostate rdstate () const;
void setstate ( iostate state );
void clear ( iostate state=goodbit );
ios©fmt ( const ios& rhs );
char fill () const;
char fill ( char fillch );
locale imbue ( const locale& loc );
(4)由ios_base类派生的函数如下。
fmtflags flags () const;
fmtflags flags ( fmtflags fmtfl );
fmtflags setf ( fmtflags fmtfl );
fmtflags setf ( fmtflags fmtfl, fmtflags mask );
void unsetf ( fmtflags mask );
streamsize precision () const;
streamsize precision ( streamsize prec );
streamsize width () const;
streamsize width ( streamsize wide );
ios_base类的声明在xiosbase.h文件中。
int get();
istream&get ( char&c );
istream&get ( char*s, streamsize n );
istream&get ( char*s, streamsize n, char delim );
istream&get ( streambuf&sb);
istream&get ( streambuf&sb, char delim );
这些函数的功能都是执行输入操作。其中,各个函数的功能如下。
(1)第1个函数从流中接受一个字符并返回该字符对应的整型值。
(2)第2个函数从流中接受一个字符并存放到c中。
(3)第3个函数从流中接受字符串并存放到数组s中。当输入n−1个字符或遇到定界符’\n’时,这些字符将被流接受。空字符’\0’被自动添加到字符串的末尾。
(4)第4个函数从流中接受字符串并存放到数组s中,并用delim代替’\n’作为输入结束的定界符。
(5)第5个函数从流中接受字符串并存放到sb中。
(6)第6个函数从流中接受字符串并存放到sb中,并用indelim代替’\n’作为定界符。
(1)参数c:存放接受的字符。
(2)参数s:字符数组,存放接受的字符串。
(3)参数n:要接受的最大字符个数(包括终结符’\0’)。
(4)参数delim:替换字符。
(5)参数sb:输出流缓冲区。
第1个函数返回读入的字符,其他函数返回流对象。
/********************************************
*范例编号:20_01
*范例说明:读取文件中的内容并输出
*********************************************/
01 #include < iostream>
02 #include < fstream>
03 using namespace std;
04 void main ()
05 {
06 char ch,str[256];
07 ifstream infile;
08 cout < < “请输入文件名(‘\\n’作为结束符):\n”;
09 cin.get(str,256,’\n’);
10 infile.open(str);
11 cout< < “文件”< < str< < “的内容如下:”< < endl;
12 while(infile.good())
13 {
14 ch=infile.get();
15 cout< < ch;
16 }
17 cout< < endl;
18 infile.close();
19 system(“pause”);
20 }
该函数范例的运行结果如图20-2所示。
图20-2 函数范例的运行结果
(1)get函数是派生自istream类的函数,用来执行流的输入操作(标准读入、读取文件)。
(2)为了通过streambuf执行输入操作,需要利用rdbuf函数返回指向streambuf对象的指针。这样就可以通过流对象与rdbuf函数输出流中的内容。
istream&getline (char*s, streamsize n );
istream&getline (char*s, streamsize n, char delim );
(1)第1个函数从输入流中析取字符串并存放到字符数组s中。
(2)第2个函数也是从输入流中析取字符串并存放到字符数组s中,与第1个成员函数的区别在于第1个成员函数以’\n’作为限定符,而第2个成员函数则指定了限定符delim。
(1)参数s:字符数组,存放从输入流中析取的字符串。
(2)参数n:接受的最长字符个数(包括最后的空字符’\0’)。
(3)参数delim:限定符,遇到限定符时,停止从流中接受字符。
函数返回输入流的对象。
/********************************************
*范例编号:20_02
*范例说明:接受输入的字符串并输出
*********************************************/
01 #include < iostream>
02 #include < stdlib.h>
03 using namespace std;
04 void main()
05 {
06 char name[20],addr[50];
07 cout< < “请输入你的姓名:”< < endl;
08 cin.getline(name,20);
09 cout< < “请输入你的网址:”< < endl;
10 cin.getline(addr,20);
11 cout< < “姓名:”< < name< < endl< < “网址:”< < addr< < endl;
12 system(“pause”);
13 }
该函数范例的运行结果如图20-3所示。
图20-3 函数范例的运行结果
(1)当输入限定符(‘\n’或delim)或输入的字符个数为n−1时,停止从输入流中接受字符。
(2)getline函数是派生自istream类的函数。
istream&ignore( streamsize n=1, int delim=EOF );
ignore函数的功能是忽略指定的字符delim前面的字符。
(1)参数n:丢弃的最大字符个数。
(2)参数delim:指定丢弃的字符。
函数返回输入流的对象。
/********************************************
*范例编号:20_03
*范例说明:忽略指定字符前面的字符
*********************************************/
01 #include < iostream>
02 #include< stdlib.h>
03 using namespace std;
04 void main()
05 {
06 char str[80];
07 cout< < “请输入一个字符串:”< < endl;
08 cin.ignore(256,’,’);
09 cin.getline(str,80);
10 cout< < “忽略字符’,’前的字符后剩余的字符串:”< < endl< < str< < endl;
11 system(“pause”);
12 }
该函数范例的运行结果如图20-4所示。
图20-4 函数范例的运行结果
当接受了n个字符并将其丢弃或指定的delim字符出现后,ignore函数会将后面的字符存放在缓冲区,这些缓冲区的字符等待被存储到指定数组中。
int peek ();
peek是未格式化的输入函数,它的功能是检查输入的字符并将其提供给输入流。
该函数没有参数。
函数返回输入的字符。
/********************************************
*范例编号:20_04
*范例说明:从流中接受输入的字符
*********************************************/
01 #include < iostream>
02 #include < stdlib.h>
03 using namespace std;
04 void main ()
05 {
06 char ch,str[80];
07 int n;
08 cout< < “请输入一个数字或字符串: “;
09 ch=cin.peek();
10 if((ch>=’0’)&&(ch< =’9’))
11 {
12 cin>>n;
13 cout< < “你输入的数字是:” < < n< < endl;
14 }
15 else
16 {
17 cin>>str;
18 cout< < “你输入的字符串是:”< < str< < endl;
19 }
20 system(“pause”);
21 }
该函数范例的运行结果如图20-5所示。
图20-5 函数范例的运行结果
(1)peek函数与get函数都可以用来接受流中的字符,不同的是peek函数还将流中的字符提供给下一个输入流,而get函数只是接受流中的字符。
(2)peek函数是派生自istream类的函数。
istream&read ( char*s, streamsize n );
read函数从流中读取n个字符并将其存放到字符数组s中。
(1)参数s:存放接受的字符。
(2)参数n:读取字符的最大个数。
函数返回流对象。
/********************************************
*范例编号:20_05
*范例说明:从输入流中接受字符块
*********************************************/
01 #include < iostream>
02 #include < stdlib.h>
03 using namespace std;
04 void main ()
05 {
06 char buf[80];
07 cout< < “请输入姓名:”< < endl;
08 cin.read(buf,8);
09 buf[8]=’\0’;
10 cout< < “你的姓名:”< < buf< < endl;
11 system(“pause”);
12 }
该函数范例的运行结果如图20-6所示。
图20-6 函数范例的运行结果
(1)read函数用来接受输入的字符块,它属于非格式输入函数,字符存放到字符数组s中后,并不会自动添加’\0’为结束标志。因此,为了正确输出字符,需要手动添加’\0’。
(2)read函数是派生自istream类的函数。
istream&putback ( char ch );
putback函数将前面用get函数或getline函数从输入流中读取的字符ch返回给输入流,并插入当前指针的位置,供后面读取。
参数ch:返回给输入流的字符。
函数返回流对象。
/********************************************
*范例编号:20_06
*范例说明:将get函数接受的字符返回给输入流
*********************************************/
01 #include < iostream>
02 #include < stdlib>
03 using namespace std;
04 void main ()
05 {
06 char ch;
07 int n;
08 char str[256];
09 cout< < “请输入数字或字符:”;
10 ch=cin.get();
11 if((ch>=’0’)&&(ch< =’9’))
12 {
13 cin.putback (ch);
14 cin >> n;
15 cout< < “你输入的数字是:”< < n < < endl;
16 }
17 else
18 {
19 cin.putback(ch);
20 cin>>str;
21 cout< < “你输入的字符串是:”< < str< < endl;
22 }
23 system(“pause”);
24 }
该函数范例的运行结果如图20-7所示。
图20-7 函数范例的运行结果
putback函数是派生自istream类的函数。
ostream&put ( char ch );
put函数将字符ch输出到输出流缓冲区流指针指向的位置,并使流指针指向下一个位置,以便接受下一个字符。
参数ch:输出到流中的字符。
函数返回流对象。
/********************************************
*范例编号:20_07
*范例说明:从输出流中接受输出的字符
*********************************************/
01 #include < iostream>
02 #include < stdlib.h>
03 using namespace std;
04 void main()
05 {
06 char ch;
07 cout< < “请输入字符(以’\n’作为结束):”< < endl;
08 do
09 {
10 ch=cin.get();
11 cout.put(ch);
12 } while(ch!=’\n’);
13 system(“pause”);
14 }
该函数范例的运行结果如图20-8所示。
(1)put函数是派生自ostream类的函数。
图20-8 函数范例的运行结果
(2)get函数与put函数类似于C语言中的fgetc函数与fputc函数,不仅可以作为标准输入与输出,还可以对文件进行读/写操作。
char fill () const;
char fill ( char fillch );
(1)第1个成员函数返回填充字符。
(2)第2个成员函数将fillch设置为新的填充字符并返回之前的填充字符。
参数fillch:用于填充的字符。
函数返回先前的填充字符。
/********************************************
*范例编号:20_08
*范例说明:在输出流中填充字符
*********************************************/
01 #include < iostream>
02 #include < stdlib.h>
03 using namespace std;
04 void main ()
05 {
06 char prev;
07 cout.width(12);
08 cout< < 60< < endl;
09 prev=cout.fill(‘x’);
10 cout< < “先前的填充字符:”< < prev< < endl;
11 cout.width(12);
12 cout < < 60< < endl;
13 prev=cout.fill(‘X’);
14 cout< < “先前的填充字符:”< < prev< < endl;
15 cout.width(12);
16 cout < < 60< < endl;
17 system(“pause”);
18 }
该函数范例的运行结果如图20-9所示。
图20-9 函数范例的运行结果
fill函数是派生自ios类的函数。
ifstream类、ofstream类和fstream类都是对文件进行读/写操作的类,我们将这些类统称为文件流类。
在C++中,要对文件进行读/写操作,需要将文件流类与文件关联起来(一般采用open的方式或构造函数的方式),然后利用文件流对文件进行操作。
如果要对文件进行读/写操作,需要使用以下文件包含命令。
#include< fstream>
using namespace std;
注意:ifstream类、ofstream类和fstream类的定义都包含在fstream.h文件中。
ifstream类、ofstream类和fstream类的层次架构如图21-1所示。
图21-1 文件流类的层次架构
ifstream类、ofstream类和fstream类的成员函数可以分为两大部分:自身定义的函数和派生的函数。派生的函数主要来自istream类、ostream类、ios_base类和ios类。自身定义的函数除了构造函数外,还包括以下几个函数。
filebuf* rdbuf () const;
bool is_open ();
void open(const char*filename,ios_base::openmode mode=ios_ base::out );
void open(const string&filename,ios_base::openmode mode=ios_ base::out );
(1)ifstream类、ofstream类和fstream类的构造函数原型基本相同,区别在于打开文件的方式不同。
(2)文件流类的大多数成员函数都派生自基类istream类、ostream类、ios类和ios_base类。
ifstream ();
ifstream ( const char * filename, ios_base::openmode mode=ios_base::in );
这两个函数的功能都是用来构造ifstream类对象。调用第2个函数时,流与文件相关联,与调用成员函数open的效果一样。
(1)参数filename:字符串,表示要打开的文件。
(2)参数mode:标识打开文件的模式,是ios_base::openmode类型的对象,由表21-1所示的一个或多个常量构成。
表21-1 mode的常量及含义
mode的常量 |
含义 |
app |
从文件尾添加数据 |
ate |
打开文件输出,文件位置指针处于文件尾部 |
binary |
以二进制的方式打开文件(默认打开方式为文本模式) |
in |
为输入打开文件,是istream流和fstream流的默认打开方式 |
out |
为输出打开文件,是ostream流的默认打开方式 |
trunc |
如果文件存在,则清除文件内容 |
该函数没有返回值。
/********************************************
*范例编号:21_01
*范例说明:读取文件中的内容并输出
*********************************************/
01 #include < iostream>
02 #include < fstream>
03 using namespace std;
04 void main ()
05 {
06 ifstream ifs(“test.txt”,ifstream::in);
07 cout< < “读取test.txt文件中的内容:”< < endl;
08 while(ifs.good())
09 cout < < (char)ifs.get();
10 ifs.close();
11 system(“pause”);
12 }
该函数范例的运行结果如图21-2所示。
图21-2 函数范例的运行结果
带参数的ifstream构造函数使流对象直接与物理文件相关联,在以后的使用过程中可以直接利用流对象对该文件进行操作。
filebuf *rdbuf () const;
函数实现将一个流对象指向的内容输出到另一个流对象指向的文件中。
该函数没有参数。
函数返回指向与流相关的filebuf对象的指针。
/********************************************
*范例编号:21_02
*范例说明:读取文件中的内容并输出
*********************************************/
01 #include < iostream>
02 #include < fstream>
03 using namespace std;
04 void main()
05 {
06 filebuf *p;
07 ifstream fin;
08 char *buf;
09 long n;
10 fin.open(“read.txt”);
11 if(!fin.is_open())
12 {
13 cout < < “打开文件失败” < < endl;
14 return;
15 }
16 fstream fout(“write.txt”,ios::out|ios::binary);
17 if(! fout.is_open())
18 {
19 cout < < “目标文件打开失败!” < < endl;
20 return;
21 }
22 fout< < fin.rdbuf();
23 p=fin.rdbuf();
24 n=p->pubseekoff(0,ios::end,ios::in);/*得到文件的大小*/
25 buf=new char[n];
26 p->pubseekpos(0,ios::in);/*设置位置指针的绝对位置*/
27 p->sgetn(buf,n);/*从输入序列中得到n个字符存入buf中*/
28 cout.write(buf,n);/*在屏幕上输出buf中的字符*/
29 free(buf);
30 fin.close();
31 fout.close();
32 system(“pause”);
33 }
该函数范例的运行结果如图21-3所示。
图21-3 函数范例的运行结果
(1)filebuf类是由streambuf类派生出的。streambuf类负责对字符序列进行读/写,streambuf对象通常与特定的字符序列相关联,通过streambuf对象可以将数据读/写入内存缓冲区,这个内存缓冲区可以与字符序列相关联。由于filebuf类派生自streambuf类,因此filebuf类具有对字符序列读/写的功能,主要负责对文件进行读/写操作。
(2)需要注意的是,对于ifstream流对象来说,即使没有文件被打开,与流相关的filebuf指针也不是空指针。
bool is_open ();
is_open函数的功能是检测与流相关的文件是否被打开。
该函数没有参数。
如果与流相关的文件被打开,则返回true;否则,返回false。
/********************************************
*范例编号:21_03
*范例说明:如果文件被打开,则输出文件中的内容
*********************************************/
01 #include < iostream>
02 #include < fstream>
03 using namespace std;
04 void main ()
05 {
06 ifstream fin;
07 ofstream fout;
08 int i;
09 char ch,str[]=”There are 46323 students, including 21141
10 undergraduates and 25182 postgraduates. There are 90
11 undergraduate majors, 32 first-class disciplines”;
12 fout.open(“test.txt”,ios::app);
13 if (fout.is_open())
14 {
15 cout < < “File is open.The content is:\n”;
16 for(i=0;i< strlen(str);i++)
17 fout< < str[i];
18 fout.close();
19 }
20 else
21 cout< < “File is not open as writing”< < endl;
22 fin.open(“test.txt”,ios::in);
23 if(fin.is_open())
24 {
25 while (fin.good())
26 {
27 ch=fin.get();
28 if (fin.good())
29 cout< < ch;
30 }
31 cout< < endl;
32 fin.close();
33 }
34 else
35 cout< < “File is not open as reading.\n”;
36 system(“pause”);
37 }
该函数范例的运行结果如图21-4所示。
图21-4 函数范例的运行结果
如果利用ifstream类的成员函数open成功打开了文件或使用带参数的构造函数创建了对象,则ifstream流就与文件关联了起来。
void open(const char * filename, ios_base::openmode mode=ios_base::in );
void close( );
open函数的功能是打开文件filename,使文件与流对象相关联并对该文件执行输入/输出操作。具体操作的类型取决于参数mode,在默认情况下(省略第2个参数),在流上执行输入操作。
close函数关闭与流对象相关的文件,使文件与流对象不相关。
这两个函数都是ifstream类中的成员函数。
(1)参数filename:指向字符串的指针,表示要打开的文件名。
(2)参数mode:标识打开文件的模式,是ios_base::openmode类型的对象。mode的常量及含义见表21-1。
两个函数都没有返回值。
/********************************************
*范例编号:21_04
*范例说明:从文件中读取字符并输出
*********************************************/
01 #include < iostream>
02 #include < fstream>
03 using namespace std;
04 void main ()
05 {
06 fstream file;
07 char str[100],ch;
08 int i=0;
09 file.open(“test.txt”,fstream::in|fstream::out);
10 if (!file.is_open())
11 {
12 cout < < “源文件打开失败...” < < endl;
13 return;
14 }
15 cout< < “请输入要保存的字符串(以回车键结束):”< < endl;
16 while((ch=cin.get())!=’\n’)
17 str[i++]=ch;
18 str[i]=’\0’;
19 for(i=0;i< strlen(str);i++)
20 file< < str[i];
21 file.close();
22 file.open(“test.txt”,fstream::in|fstream::out|fstream::app);
23 file.seekg(0,ios::beg);
24 cout< < “从文件中读取的字符为:”< < endl;
25 while(file.good())
26 cout< < (char)file.get();
27 file.close();
28 system(“pause”);
29 }
该函数范例的运行结果如图21-5所示。
图21-5 该函数范例的运行结果
(1)open(file,open)函数实际上调用了rdbuf()->open(file,mode)。如果流对象已经与文件相关,则调用open函数失败。
(2)如果流没有与文件相关联,则调用close函数失败。
(3)ifstream类、ofstream类和fstream类都有open成员函数和close成员函数。其中,它们的close成员函数原型相同,ofstream类的open成员函数原型如下。
void open(const char*filename,ios_base::openmode mode = ios_base::out );
默认的打开方式是out。fstream类的open成员函数原型如下。
void open ( const char * filename,ios_base::openmode mode = ios_base::in | ios_base::out );
默认的打开方式是in和out的组合,既可以用于输入也可以用于输出。
istream&read ( char*s, streamsize n );
ostream&write ( const char*s , streamsize n );
ifstream类的成员函数read和ofstream类的成员函数write分别派生自istream类和ostream类。read函数从流中读取n个字符并存放到字符数组s中。write函数将长度为n的字符串s写入输出流中。
(1)参数s:字符数组。
(2)参数n:读取/写入文件流字符的最大个数。
函数返回流对象。
/********************************************
*范例编号:21_05
*范例说明:从文件in.txt中读取数据存放到文件out.txt中
*********************************************/
01 #include < iostream>
02 #include < fstream>
03 using namespace std;
04 void main()
05 {
06 int length;
07 char buf[٤٠٩٦];
08 ifstream infile;
09 ofstream outfile;
10 infile.open (“in.txt”,ios::in|ios::binary);
11 outfile.open(“out.txt”,ios::out|ios::binary);
12 while (!infile.eof()) /*文件不结束,继续循环*/
13 {
14 infile.read(buf,4096); /*一次读4096个字节*/
15 length=infile.gcount(); /*取实际读的字节数*/
16 outfile.write(buf,length); /*按实际读的字节数写入文件*/
17 cout.write(buf,length); /*在屏幕上输出文件中的内容*/
18 }
19 infile.close();
20 outfile.close();
21 system(“pause”);
22 }
该函数范例的运行结果如图21-6所示。
图21-6 函数范例的运行结果
ifstream类中的read函数用来从文件中读取数据,ofstream类中的write函数用来向文件中写入数据。
istream&seekg ( streampos pos );
istream&seekg ( streamoff off, ios_base::seekdir dir );
streampos tellg ();
(1)seekg函数用来设置流的位置指针的位置。其中,pos表示位置指针的位置,off表示基于dir的相对位移量。
(2)tellg函数返回流的位置指针的绝对位置。
(1)参数pos:在输入流中的新位置,是一个整型值。
(2)参数off:位置指针的绝对位置,是文件的开始检索点。
(3)参数dir的取值及含义如表21-2所示。
表21-2 dir的取值及含义
dir的取值 |
含义 |
ios_base::beg |
流缓冲区的开始位置 |
ios_base::cur |
流缓冲区的当前位置 |
ios_base::end |
流缓冲区的结束位置 |
seekg函数返回流对象,tellg函数返回位置指针所在的位置。
/********************************************
*范例编号:21_06
*范例说明:从文件中读取字符并输出
*********************************************/
01 #include < iostream>
02 #include < fstream>
03 using namespace std;
04 void main ()
05 {
06 int length;
07 char *buf;
08 ifstream infile;
09 infile.open(“test.txt”,ios::binary);
10 infile.seekg (0,ios::end);
11 length=infile.tellg();
12 infile.seekg (0, ios::beg);
13 buf=new char [length];
14 infile.read (buf,length);
15 cout.write(buf,length);
16 infile.close();
17 system(“pause”);
18 }
该函数范例的运行结果如图21-7所示。
图21-7 函数范例的运行结果
(1)tellg函数的返回值是输入流中从开始位置到当前位置指针所在位置之间的字符个数。
(2)seekg函数和tellg函数都是派生自istream类的函数。
第9行:以二进制方式打开test.txt文件。
第10~11行:将文件位置指针定位在文件末尾,求出文件的长度。
第12~15行:从文件中读取数据到buf中,并输出到屏幕。
ostream&seekp ( streampos pos );
ostream&seekp ( streamoff off, ios_base::seekdir dir );
streampos tellp ();
(1)seekp函数在文件输出流中设置位置指针的位置,参数pos、off和dir的含义与seekg函数的相同。
(2)tellp函数获得文件输出流中的位置指针位置。
(1)参数pos:流缓冲区的位置指针所在的位置。
(2)参数off:相对于参数dir的偏移值。
(3)参数dir:检索方向,取值范围是ios_base::beg、ios_base::cur和ios_base::end,含义与seekg函数中参数dir的含义相同。
seekp函数返回流对象,tellp函数返回文件位置指针的位置。
/********************************************
*范例编号:21_07
*范例说明:向文件中写入字符并读取
*********************************************/
01 #include < fstream>
02 #include < iostream>
03 using namespace std;
04 void main ()
05 {
06 fstream file;
07 int pos,length;
08 char *buf;
09 file.open(“test.txt”,ios::in|ios::out);
10 file.write(“Microsoft Visual Studio 2013”,26);
11 pos=file.tellp();
12 file.seekp (pos-2);
13 file.write (“2018”,5);
14 file.seekg(0,ios::end);
15 length=file.tellg();
16 file.seekg(0,ios::beg);
17 buf=new char[length];
18 file.read(buf,length);
19 cout< < “test.txt文件中的内容如下:\n”;
20 cout.write(buf,length);
21 file.close();
22 cout< < endl;
23 system(“pause”);
24 }
该函数范例的运行结果如图21-8所示。
图21-8 函数范例的运行结果
seekp函数与tellp函数都是派生自ostream类的函数,它们都是ofstream类和fstream类的成员函数。
第9~10行:以读、写的方式打开test.txt文件,并向文件中写入”Microsoft Visual Studio 2013”中的前26个字符。
第11~13行:得到位置指针在文件中的当前位置,并向指定位置写入字符”2018”。
第14~15行:将位置指针定位到文件末尾,并求出文件的长度。
第16~18行:将位置指针定位到文件的开始位置,并将文件中的内容读取到buf中。
第19~20行:在屏幕上输出buf中的内容。
第21行:关闭文件。
ostream& flush ();
flush函数使输出流与相关联的缓冲区保持同步,实际上是将缓冲区的字符写入输出流中。
该函数没有参数。
函数返回流对象。
/********************************************
*范例编号:21_08
*范例说明:将101~200的整数写入文件并显示出来
*********************************************/
01 #include < fstream>
02 #include < iostream>
03 using namespace std;
04 void main ()
05 {
06 ofstream outfile(“test.txt”);
07 for (int i=101; i< =200; i++)
08 {
09 outfile < < “ “< < i;
10 if((i-100)%10==0)
11 outfile< < “\n”;
12 outfile.flush();
13 }
14 system("type test.txt");
15 outfile.close();
16 system(“pause”);
17 }
该函数范例的运行结果如图21-9所示。
图21-9 函数范例的运行结果
flush函数的作用类似于endl控制符,都是将缓冲区的字符输出到流中。另外,endl控制符还有换行的作用。
string类主要用于消除对char*的使用,以保持与现有代码的兼容性,它还会自动进行内存管理,方便对字符进行操作,带来比使用char*更佳的性能。字符串的用途非常广泛,特别是在处理大整数问题时。当整数类型无法满足大整数的存储需求时,就可用string类存储。
如果要使用string类中的函数,需要使用以下文件包含命令。
#include< string>
using namespace std;
string类中的函数可以分为四大类,分别是字符串运算符函数、字符串迭代器函数、字符串长度函数、字符串操作函数。
string类的构造函数用来创建字符串对象。
string ();
string ( const string&str );
string ( const string&str, size_t pos, size_t n=npos );
string ( const char*s, size_t n );
string ( const char*s );
string ( size_t n, char c );
template< class InputIterator> string (InputIterator begin, InputIterator end);
在C++中,字符串构造函数有7个:第1个函数创建一个空的字符串对象;第2个函数创建一个str副本;第3个函数创建str中从pos开始长度为npos的子对象;第4个函数创建str中前n个字符的子序列;第5个函数创建一个字符串对象,其值为s指向的字符串;第6个函数创建一个长度为n、字符为c的子序列;第7个函数创建一个由start和end迭代器指定的字符集的字符串对象。
(1)参数str:字符串对象,用来初始化当前要构造的string对象。
(2)参数pos:子串在str中的开始位置。
(3)参数n:子串中字符的个数。第3个函数string的默认值是npos,它是size_t类型的最大值。
(4)参数s:字符串数组。
(5)参数c:字符,用来初始化string对象。对于第6个函数来说,n表示c重复的次数。
(6)参数begin:字符串的开始位置,它可以是一个整数,也可以是一个迭代器。
(7)参数end:字符串的结束位置,它可以是一个整数,也可以是一个迭代器。
所有的构造函数都没有返回值。
/********************************************
*范例编号:22_01
*范例说明:利用各种构造函数创建字符串对象
*********************************************/
01 #include < iostream>
02 #include < string>
03 using namespace std;
04 void main ()
05 {
06 string s1 (“Standard Template Library”);
07 string s2 (“Sequence Container”, 8);
08 string s3 (“Another character sequence”);
09 string s4 (s1,9,8);
10 string s5 (s1.begin(), s1.begin()+8);
11 string s6 (s1);
12 string s7 (s2);
13 string s8 (10, ‘Q’);
14 cout< < “字符串1:”< < s1< < “\n字符串2:”< < s2< < “\n字符串3:”< < s3< < endl;
15 cout< < “字符串4:”< < s4< < endl< < “字符串5:”< < s5< < endl< < “字符串6:”;
16 cout< < s6< < endl< < “字符串7:”< < s7< < endl< < “字符串8:”< < s8< < endl;
17 system(“pause”);
18 }
该函数范例的运行结果如图22-1所示。
图22-1 函数范例的运行结果
string类的构造函数有多个,在创建string对象时,可以有多种形式。例如,可以利用对象创建string对象,也可以利用字符串创建string对象。
string& operator=( const string& str );
string& operator=( const char*s );
string& operator=( char c );
在C++中,赋值运算符(=)函数的作用是将右端的字符串值赋值给左端的字符串对象。
(1)参数str:字符串对象,str的内容作为新字符串对象的内容。
(2)参数s:字符串,作为新字符串对象的内容。
(3)参数c:单个字符,作为新字符串对象的内容。
函数返回string的引用。
/********************************************
*范例编号:22_02
*范例说明:将源字符串复制给目标字符串
*********************************************/
01 #include < iostream>
02 #include < string>
03 using namespace std;
04 void main ()
05 {
06 string str1, str2, str3, str4;
07 str1=”Welcome to Northwest University!”;
08 str2=str1;
09 str3=’A’;
10 str4=”Hello MFC!”;
11 cout< < “str1:”< < str1< < endl;
12 cout< < “str2:”< < str2< < endl;
13 cout< < “str3:”< < str3< < endl;
14 cout< < “str4:”< < str4< < endl;
15 system(“pause”);
16 }
该函数范例的运行结果如图22-2所示。
图22-2 函数范例的运行结果
(1)string类的=运算符的作用与成员函数assign的作用类似,都是将右端的字符或字符串赋值给左端的string类对象。
(2)在C++中,因为定义了以下赋值运算符函数
const string &operator=(const string &str);
所以当编译器遇到像string1=string2这样的表达式时,就会产生如下的函数调用。
string1.operator=(string2);
(3)在C++中定义函数时,通过在运算符前使用关键字operator来表示运算符重载函数。赋值运算符函数operator是C++中string类的成员函数。
string operator+(const string&lhs, const string&rhs);
string operator+(const char*lhs, const string&rhs);
string operator+(char lhs, const string&rhs);
string operator+(const string&lhs, const char*rhs);
string operator+(const string&lhs, char rhs);
string& operator+=( const string& str );
string& operator+=( const char*s );
string& operator+=( char c );
+运算符函数的主要功能是将rhs连接在lhs之后,使其构成新的字符串对象。
+=运算符函数的主要功能是将右端的字符串与左端的字符串连接到一起,并赋值给左端的字符串对象。
(1)参数lhs:字符串对象、字符串或字符,它作为新字符串对象的开始部分。
(2)参数rhs:字符串对象、字符串或字符,它作为新字符串对象的后半部分。
(3)参数 str:字符串对象,被追加到运算符左端字符串对象的末尾,从而构成新的字符串对象。
(4)参数s:包含空字符的字符串,被添加到字符串对象的末尾。
(5)参数c:字符,被添加到字符串对象的末尾。
(1)第1种运算符函数返回组合后的字符串对象。
(2)第2种运算符函数返回组合后的字符串对象的引用。
/********************************************
*范例编号:22_03
*范例说明:连接字符串
*********************************************/
01 #include < iostream>
02 #include < string>
03 using namespace std;
04 void main ()
05 {
06 string s1,s2,s3,s4,IP;
07 string str1(“2021 “);
08 string str2(“Olympic “);
09 string str3(“Games”);
10 s1=”211.”;
11 s2=”156.”;
12 s3=”26.”;
13 s4=”115”;
14 IP=s1+s2+s3+s4;
15 cout< < “连接后的字符串:”< < IP< < endl;
16 str1+=str2;
17 str1+=str3;
18 cout < < “连接后的字符串:”< < str١< < endl;
19 system(“pause”);
20 }
该函数范例的运行结果如图22-3所示。
图22-3 函数范例的运行结果
+运算符函数和+=运算符函数都是运算符重载函数,+运算符函数返回字符串对象,+=运算符函数返回字符串对象的引用。这两种运算符函数类似于简单运算符和复合运算符的操作。
bool operator==(const string& c1, const string& c2);
bool operator!=(const string& c1, const string& c2);
bool operator< (const string& c1, const string& c2);
bool operator>(const string& c1, const string& c2);
bool operator< =(const string& c1, const string& c2);
bool operator>=(const string& c1, const string& c2);
==、!=、<、>、<=、>=运算符函数的主要功能分别是判断一个字符串对象是否等于、不等于、小于、大于、小于等于、大于等于另一个字符串对象。
(1)当c1小于c2时,函数operator<返回true;否则返回false。
(2)当c1大于c2时,函数operator>返回true;否则返回false。
(3)当c1小于等于c2时,函数operator<=返回true;否则返回false。
(4)当c1大于等于c2时,函数operator>=返回true;否则返回false。
(1)参数c1:字符串对象,它作为新字符串对象的开始部分。
(2)参数c2:字符串对象,它作为新字符串对象的后半部分。
(1)当c1与c2相等时,函数operator==返回true;否则返回false。
(2)当c1与c2不相等时,函数operator!=返回true;否则返回false。
/********************************************
*范例编号:22_04
*范例说明:比较两个字符串
*********************************************/
01 #include < string>
02 #include < iostream>
03 using namespace std;
04 void main()
05 {
06 string s1=”Welcome to China!”;
07 string s2=”Welcome to Beijing!”;
08 string s3=”Welcome to Xi’an”;
09 cout< < “s1:”< < s1< < endl;
10 cout< < “s2:”< < s2< < endl;
11 cout< < “s3:”< < s3< < endl;
12 if(s1==s2)
13 cout< < “s1与s2相等!”< < endl;
14 else
15 cout< < “s1与s2不相等!”< < endl;
16 if(s1< s2)
17 cout< < “s1小于s2!”< < endl;
18 else
19 cout< < “s1不小于s2!”< < endl;
20 if(s3>=s1)
21 cout< < “s3大于等于s1!”< < endl;
22 else
23 cout< < “s3不大于等于s1!”< < endl;
24 system(“pause”);
25 }
该函数范例的运行结果如图22-4所示。
图22-4 函数范例的运行结果
在C++中,string类提供了两个字符串之间比较运算符重载的实现,这对于字符串的操作是非常方便的。在C++的其他类(对象)操作中,如果要比较两个对象的关系,就需要用户对运算符进行重载。
const char&operator[] ( size_t pos ) const;
char&operator[] ( size_t pos );
[]运算符函数的主要功能是返回string对象中下标为pos的字符。
参数pos:要存取string中字符的下标。
函数返回string中pos位置对应的字符。
/********************************************
*范例编号:22_05
*范例说明:输出字符串中的每个字符
*********************************************/
01 #include < iostream>
02 #include < string>
03 using namespace std;
04 void main()
05 {
06 string s=”Hello World!”;
07 size_t i=0;
08 cout< < “s中的字符分别是:”< < endl;
09 while(i< s.length())
10 {
11 cout< < s[i];
12 i++;
13 }
14 cout< < endl;
15 system(“pause”);
16 }
该函数范例的运行结果如图22-5所示。
图22-5 函数范例的运行结果
(1)[]运算符函数的作用与string的成员函数at的作用类似,区别在于at函数还会对下标的范围进行检测。
(2)size_t在C++中被定义为无符号整型,即unsigned int。
(3)在利用[]运算符函数存取string中的字符时,第一个字符的下标是从0开始的,而不是从1开始。
λconst char&at ( size_t pos ) const;
λchar&at ( size_t pos );
at函数的功能与[]运算符函数的类似,也是返回string对象中下标为pos的字符。
参数pos:要存取string中字符的下标。
函数返回string中pos位置对应的字符。
/********************************************
*范例编号:22_06
*范例说明:输出字符串中的每个字符
*********************************************/
01 #include < iostream>
02 #include < string>
03 using namespace std;
04 void main()
05 {
06 string s(“Hello World!”);
07 size_t i=0;
08 char str[100];
09 cout< < “s中的字符分别是:”< < endl;
10 while(i< s.length())
11 {
12 str[i]=s.at(i);
13 cout< < s.at(i);
14 i++;
15 }
16 str[i]=’\0’;
17 cout< < endl;
18 cout< < “str:”< < str< < endl;
19 system(“pause”);
20 }
该函数范例的运行结果如图22-6所示。
图22-6 函数范例的运行结果
如果at函数中的参数取值超出了string范围,则会抛出一个越界异常。
迭代器类似于指针,提供存取string中各个字符的方法。
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
begin函数返回与string中第一个字符相关的迭代器。end函数返回与string中最后一个字符相关的迭代器。
该函数没有参数。
(1)begin函数返回string的开始位置。
(2)end函数返回string的最后一个元素后第一个位置的迭代器。
/********************************************
*范例编号:22_07
*范例说明:利用迭代器输出字符串中的所有字符
*********************************************/
01 #include < iostream>
02 #include < string>
03 using namespace std;
04 void main ()
05 {
06 string str1=”Xiamen University!”;
07 string::iterator it;
08 char str2[200];
09 int i=0;
10 it=str1.begin();
11 cout< < “字符串str1:”< < endl;
12 while(it< str1.end())
13 {
14 str2[i++]=*it;
15 cout< < *it;
16 it++;
17 }
18 str2[i]=’\0’;
19 cout< < endl;
20 cout< < “str2:”< < str2< < endl;
21 system(“pause”);
22 }
该函数范例的运行结果如图22-7所示。
图22-7 函数范例的运行结果
在string中,begin函数和end函数分别都有两个版本:一种是非const string迭代器的iterator,另一种是const string迭代器的iterator。其中,const string迭代器并不能修改所迭代的容器string。
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
rbegin函数返回与string中最后一个字符相关的迭代器,它是反向的开始位置。
该函数没有参数。
(1)rbegin函数返回string的反向的开始位置。
(2)rend函数返回string的反向的结束位置的反向迭代器(迭代器指向的是第一个字符之前的元素)。
/********************************************
*范例编号:22_08
*范例说明:利用迭代器逆向输出字符串中的所有字符
*********************************************/
01 #include < iostream>
02 #include < string>
03 using namespace std;
04 void main ()
05 {
06 string str(“International Olympiad in Informatics”);
07 string::reverse_iterator rit=str.rbegin();
08 string str2(str.length(),’x’);
09 string::reverse_iterator it=str2.rbegin();
10 cout< < “str1:”;
11 while(rit< str.rend())
12 {
13 *it=*rit;
14 cout< < *rit;
15 rit++;
16 it++;
17 }
18 cout< < endl;
19 cout< < “str2:”< < str2< < endl;
20 system(“pause”);
21 }
该函数范例的运行结果如图22-8所示。
图22-8 函数范例的运行结果
(1)与begin函数和end函数一样,rbegin函数和rend函数也分别有两个版本:一种是非const string迭代器的iterator,另一种是const string迭代器的iterator。
(2)rbegin迭代器指向的字符与end迭代器指向的前一个字符相等,rend迭代器与begin迭代器指向的字符相等。
在string类中,与字符串长度有关的函数主要有length函数、size函数、max_size函数、capacity函数、resize函数、reserve函数、empty函数等。
size_t length() const;
size_t size() const;
length函数与size函数功能等价,都是返回string中字符的个数。
该函数没有参数。
两个函数都返回string中字符的个数。
/********************************************
*范例编号:22_09
*范例说明:求字符串的长度
*********************************************/
01 #include < iostream>
02 #include < string>
03 using namespace std;
04 void main ()
05 {
06 string str=”Hello World!”;
07 cout< < “字符串”< < str< < “的长度length()是:”< < str.length() < < endl;
08 cout< < “字符串”< < str< < “的长度size()是:”< < str.size() < < endl;
09 system(“pause”);
10 }
该函数范例的运行结果如图22-9所示。
图22-9 函数范例的运行结果
length函数和size函数的作用相同,都是返回string中字符的个数。
size_t max_size () const;
max_size函数返回string对象能容纳的最大字符个数。
该函数没有参数。
函数返回string对象能容纳的最大字符个数。
/********************************************
*范例编号:22_10
*范例说明:求string的长度及所能容纳的最大字符个数
*********************************************/
01 #include < iostream>
02 #include < string>
03 using namespace std;
04 void main ()
05 {
06 string str1(“Nanjing University!”),str2(“Hunan University!”),str3;
07 cout< < str1< < “的长度str()是:”< < str1.size()< < endl;
08 cout< < str1< < “的长度length():”< < str1.length()< < endl;
09 str3=str1+str2;
10 cout< < “连接后”< < str3< < “的长度str()是:”< < str3.size()< < endl;
11 cout< < “连接后”< < str3< < “的长度length():”< < str3.length()< < endl;
12 str3+=str1+str2;
13 cout< < “连接后”< < str3< < “的长度str()是:”< < str3.size()< < endl;
14 cout< < “连接后”< < str3< < “的长度length():”< < str3.length()< < endl;
15 cout< < “字符串能容纳的最大长度是:”< < str3.max_size()< < endl;
16 system(“pause”);
17 }
该函数范例的运行结果如图22-10所示。
图22-10 函数范例的运行结果
size_t capacity () const;
capacity函数返回分配给string对象的存储空间大小。
该函数没有参数。
函数返回string对象的存储空间大小。
/********************************************
*范例编号:22_11
*范例说明:求string的长度、分配的存储空间大小及所能容纳的最大字符个数
*********************************************/
01 #include < iostream>
02 #include < string>
03 #include < vector>
04 using namespace std;
05 void main ()
06 {
07 string str(“Nanjing University is a famous University!”);
08 int i;
09 cout < < “Capacity of “< < str< < “:”< < str.capacity()< < endl;
10 cout < < “Max_size of “< < str< < “:”< < str.max_size()< < endl;
11 vector< char> v;
12 cout< < “capacity:”< < v.capacity()< < “ size:”< < v.size()< < endl;
13 for(i = 0; i < ٨; i++)//插入8个元素
14 {
15 v.push_back(i+’a’);
16 cout< < “capacity:”< < v.capacity()< < “ size:”< < v.size()< < endl;
17 }
18 while(v.size() != v.capacity())//当容量还未用完
19 v.push_back(10+’a’);
20 cout< < “size = =capacity. Then insert one element\n”;
21 cout< < “Now capacity is “< < v.capacity()< < “, size is “< < v.size()< < endl;
22 cout< < “Then insert one element\n”;
23 v.push_back(20+’A’);//再插入1个元素
24 cout< < “capacity is “< < v.capacity()< < “, size is “< < v.size()< < endl;
25 system(“pause”);
26 }
该函数范例的运行结果如图22-11所示。
图22-11 函数范例的运行结果
对于string来说,系统分配的存储空间不一定刚好等于字符串长度,它可能大于或等于字符串的长度。
void resize ( size_t n, char c );
void resize ( size_t n );
resize函数的功能是重新将string的长度设置为n。
(1)参数n:新的string的字符个数。
(2)参数c:用于填充string剩余的空间。
函数返回string对象的存储空间大小。
/********************************************
*范例编号:22_12
*范例说明:设置string的长度
*********************************************/
01 #include < iostream>
02 #include < string>
03 using namespace std;
04 void main ()
05 {
06 string str=”Deep Learning”;
07 size_t size;
08 cout < < “字符串:”< < str< < endl;
09 size=str.size();
10 cout< < str< < “的长度是:”< < size< < endl;
11 str.resize(10);
12 cout< < “当前的长度是:”< < size< < endl;
13 str.resize (11,’!’);
14 cout< < “当前的字符串:”< < str< < endl;
15 system(“pause”);
16 }
该函数范例的运行结果如图22-12所示。
图22-12 函数范例的运行结果
如果n小于当前string的长度,则后续的字符将被抛弃;如果n大于当前string的长度,则字符c的实例将被添加到末尾,直到字符个数达到n为止。
void reserve ( size_t res_arg=0 );
reserve函数的功能是请求为string对象预留大小为res_arg的内存空间。
参数res_arg:为string对象分配的最小内存空间。
该函数没有返回值。
/********************************************
*范例编号:22_13
*范例说明:为字符串预留内存空间
*********************************************/
01 #include < iostream>
02 #include < string>
03 using namespace std;
04 void main ()
05 {
06 string str;
07 int i;
08 str.reserve(26);
09 for(i=0;i< 26;i++)
10 str.append(1,’a’+i);
11 cout< < “字符串:”< < str< < endl;
12 cout< < str< < “的容量为:”< < str.capacity()< < endl;
13 cout< < str< < “的长度为:”< < str.length()< < endl;
14 system(“pause”);
15 }
该函数范例的运行结果如图22-13所示。
图22-13 函数范例的运行结果
reserve函数可能会增加或减少string对象的内存空间。
void empty();
empty函数的功能是判断string是否为空,即string的大小是否为0。
该函数没有参数。
如果string的大小为0,则返回true;否则,返回false。
/********************************************
*范例编号:22_14
*范例说明:判断string是否为空
*********************************************/
01 #include < iostream>
02 #include < string>
03 using namespace std;
04 void main ()
05 {
06 string str1=”Made in China”;
07 string str2=””;
08 if(str1.empty())
09 cout< < “字符串\””< < str1< < “\”为空”< < endl;
10 else
11 cout< < “字符串\””< < str1< < “\”不为空”< < endl;
12 if(str2.empty())
13 cout< < “字符串\””< < str2< < “\”为空”< < endl;
14 else
15 cout< < “字符串\””< < str2< < “\”不为空”< < endl;
16 system(“pause”);
17 }
该函数范例的运行结果如图22-14所示。
图22-14 函数范例的运行结果
empty函数并不能以任何方式修改string中的内容。
字符串操作函数主要包括insert函数、erase函数、replace函数、swap函数、c_str函数、copy函数、find函数、find_first_of函数、find_last_of函数、substr函数。
string&insert ( size_t pos1, const string&str );
string&insert ( size_t pos1, const string&str, size_t pos2, size_t n );
string&insert ( size_t pos1, const char*s, size_t n);
string&insert ( size_t pos1, const char*s );
string&insert ( size_t pos1, size_t n, char c );
iterator insert ( iterator p, char c );
void insert ( iterator p, size_t n, char c );
template< class InputIterator>
void insert ( iterator p, InputIterator first, InputIterator last );
以上重载函数的功能都是在一个字符串中插入另一个字符串。其中,各个函数的功能如下。
(1)第1个函数的功能是在当前字符串对象的第pos1个位置插入字符串str。
(2)第2个函数的功能是在当前字符串对象的第pos1个位置插入字符串str的一部分,插入的部分为从str的第pos2个位置开始的n个字符。
(3)第3个函数的功能是在当前字符串对象的第pos1个位置插入字符串s的前n个字符。
(4)第4个函数的功能是在当前字符串对象的第pos1个位置插入字符串s。
(5)第5个函数的功能是在当前字符串对象的第pos1个位置插入n个字符c。
(6)第6个函数的功能是在当前字符串对象的迭代器p指向的位置插入字符c。
(7)第7个函数的功能是在当前字符串对象的迭代器p指向的位置插入n个字符c。
(8)第8个函数的功能是在当前字符串对象的迭代器p指向的位置插入部分字符,这些字符从迭代器first开始到迭代器last结束。
(1)参数pos1:要在当前字符串对象中插入字符串或字符的位置。
(2)参数pos2:要插入的子串在str中的起始位置。
(3)参数str:要插入的字符串对象。
(4)参数s:要插入的字符串或字符数组。
(5)参数n:要插入字符串的字符个数。
(6)参数c:要插入的字符。
(7)参数p:当前字符串对象的迭代器,表示要插入的位置。
(8)参数first:待插入字符序列在字符串中的起始位置。
(9)参数last:待插入字符序列在字符串中的终止位置。
这些函数的返回值都是字符串对象的引用或字符串的迭代器。
/********************************************
*范例编号:22_15
*范例说明:判断string是否为空
*********************************************/
01 #include < iostream>
02 #include < string>
03 using namespace std;
04 void main ()
05 {
06 string str=”Software Engineering.”;
07 string sub1=”Learning “;
08 string sub2=”or”;
09 string sub3=”Computer Science”;
10 string::iterator it;
11 str.resize(100);
12 str.insert(0,sub1);
13 cout< < str< < endl;
14 str.insert(sub1.length(),sub2);
15 cout< < str< < endl;
16 str.insert(sub1.length()+sub2.length(),sub3);
17 cout< < str< < endl;
18 str.insert(sub1.length()+sub2.length()+sub3.length(),1,’,’);
19 cout< < str< < endl;
20 str.insert(0,”This is a good idea”);
21 it=str.insert(str.begin(),’ ‘);
22 str.insert (it,sub3.begin(),sub3.begin()+6);
23 cout< < str< < endl;
24 system(“pause”);
25 }
该函数范例的运行结果如图22-15所示。
图22-15 函数范例的运行结果
(1)如果插入的是字符串,则字符串对象以’\0’结束。
(2)插入字符串或字符时,其第1个字符的下标以0开始,而不是以1开始。
(3)如果要插入的位置超过了当前字符串的范围,则抛出一个异常。
string&erase ( size_t pos=0, size_t n=npos );
iterator erase ( iterator position );
iterator erase ( iterator first, iterator last );
erase函数的功能是清除string中的字符,并缩短string的长度。其中,各个函数的功能如下。
(1)第1个函数的功能是清除pos开始的n个字符。其中,参数pos和n都是可选的。如果只有一个参数pos,则清除pos起的所有字符;如果没有参数,则清除string中的所有字符。
(2)第2个函数的功能是清除string中迭代器position指示的字符。
(3)第3个函数的功能是清除迭代器first和last之间的字符。
(1)参数pos:要清除string中字符序列的起始位置。
(2)参数n:要清除字符的个数。
(3)参数position:迭代器指示的位置,指向要清除的字符。
(4)参数first:要清除字符序列的起始位置。
(5)参数last:要清除字符序列的结束位置。
(1)第1个函数返回字符串的引用。
(2)第2个函数返回字符串对象中指向第1个被清除字符的迭代器。
/********************************************
*范例编号:22_16
*范例说明:清除string中的字符
*********************************************/
01 #include < iostream>
02 #include < string>
03 using namespace std;
04 void main ()
05 {
06 string str=”She graduated from Tsinghua University.”;
07 string sub=”Northwest “;
08 string sub2=” in 2021”;
09 string::iterator it;
10 str.erase(19,8);
11 cout< < str< < endl;
12 it=str.begin()+19;
13 it=str.erase(it);
14 cout< < str< < endl;
15 str.insert(it,sub.begin(),sub.end());
16 cout< < str< < endl;
17 it=str.end()-1;
18 str.insert(it,sub2.begin(),sub2.end());
19 cout< < str< < endl;
20 system(“pause”);
21 }
该函数范例的运行结果如图22-16所示。
图22-16 函数范例的运行结果
对于第2个erase函数来说,仅仅清除string中的一个字符。
string&replace ( size_t pos1, size_t n1, const string&str );
string&replace ( iterator i1, iterator i2, const string&str );
string&replace (size_t pos1,size_t n1,const string&str,size_t pos2,size_t n2);
string&replace ( size_t pos1, size_t n1, const char*s, size_t n2 );
string&replace ( iterator i1, iterator i2, const char*s, size_t n2 );
string&replace ( size_t pos1, size_t n1, const char*s );
string&replace ( iterator i1, iterator i2, const char*s );
string&replace ( size_t pos1, size_t n1, size_t n2, char c );
string&replace ( iterator i1, iterator i2, size_t n2, char c );
template< class InputIterator>
string&replace ( iterator i1, iterator i2, InputIterator j1, InputIterator j2 );
replace函数的功能是用参数中的字符或字符串取代当前字符串对象中的字符序列。其中,各个函数的功能如下。
(1)第1个函数的功能是用字符串对象str替换当前字符串对象从第pos1个字符开始的n1个字符。
(2)第2个函数的功能是用字符串对象str替换当前字符串对象的迭代器i1和迭代器i2之间的字符。
(3)第3个函数的功能是用字符串对象str的一部分(从第pos2个字符开始的n2个字符)替换当前字符串对象中从第pos1个字符开始的n1个字符。
(4)第4个函数的功能是用字符串s中前n2个字符替换当前字符串中从第pos1个字符开始的n1个字符。
(5)第5个函数的功能是用字符串s中的前n2个字符替换当前字符串对象中迭代器i1和迭代器i2之间的字符。
(6)第6个函数的功能是用字符串s替换当前字符串对象中从第pos1个字符开始的n1个字符。
(7)第7个函数的功能是用字符串s替换当前字符串对象中迭代器i1和迭代器i2之间的字符。
(8)第8个函数的功能是用n2个字符c替换当前字符串对象中从第pos1个字符开始的n1个字符。
(9)第9个函数的功能是用n2个字符c替换当前字符串对象中迭代器i1和迭代器i2之间的字符。
(10)第10个函数的功能是用迭代器j1和迭代器j2之间的字符替换当前字符串对象中迭代器i1和迭代器i2之间的字符。
(1)参数pos1:当前字符串对象中要替换的开始字符的位置。
(2)参数i1:迭代器,被替换字符串对象中的开始位置。
(3)参数i2:迭代器,被替换字符串对象中的结束位置。
(4)参数j1:迭代器,替换字符串对象中的开始字符的位置。
(5)参数j2:迭代器,替换字符串对象中的结束字符的位置。
(6)参数n1:被替换字符的个数。
(7)参数n2:用来替换的字符个数。
(8)参数str:字符串对象,用来替换当前字符串对象中指定的字符。
(9)参数s:字符数组,用来替换当前字符串对象中指定的字符。
(10)参数c:字符,用来替换当前字符串对象中指定的字符。
函数返回字符串对象的引用。
/********************************************
*范例编号:22_17
*范例说明:输出置换后的字符串
*********************************************/
01 #include < iostream>
02 #include < string>
03 using namespace std;
04 void main ()
05 {
06 string str1=”Nanjing is a beautiful city.I like Nanjing!”;
07 string str2=”Machine Learning is a very interesting course!”;
08 string str3=”I like Basic Program language!”;
09 string::size_type pos;
10 str1.replace(0,str1.length(),str2);
11 cout< < str1< < endl;
12 pos=str1.find(“is”);
13 str1.replace(pos-1,str1.length()-pos,”and Data Analysis are interesting course”);
14 cout< < str1< < endl;
15 string::iterator it=str1.begin();
16 str1.replace(it+pos+3,it+pos+16,”Java”);
17 cout< < str1< < endl;
18 str1.replace(str1.end()-8,str1.end()-1,4,’!’);
19 cout< < str1< < endl;
20 system(“pause”);
21 }
该函数范例的运行结果如图22-17所示。
图22-17 函数范例的运行结果
(1)在replace函数中,字符串中的下标是从0开始的,而不是从1开始。
(2)如果n1大于当前字符串的实际长度,则从pos1开始的整个字符串都将被替换。
(3)如果n2小于实际的字符串长度,则用最后一个字符之前的字符来替换当前字符串。
void swap ( string&str );
swap函数的功能是将当前string对象与str对象中的内容交换。交换后,当前字符串的内容是str中的内容,str中的内容是当前字符串的内容。
参数str:字符串对象,用来与当前字符串对象中的内容进行交换。
该函数没有返回值。
/********************************************
*范例编号:22_18
*范例说明:交换两个字符串的内容
*********************************************/
01 #include < iostream>
02 #include < string>
03 using namespace std;
04 void main()
05 {
06 string str1=”Visual C++”;
07 string str2=”Visual Basic”;
08 cout < < “交换前:”< < endl;
09 cout< < “str1:”< < str1< < endl;
10 cout< < “str2:”< < str2< < endl;
11 str1.swap(str2);
12 cout < < “交换后:”< < endl;
13 cout< < “str1:”< < str1< < endl;
14 cout< < “str2:”< < str2< < endl;
15 }
该函数范例的运行结果如图22-18所示。
图22-18 函数范例的运行结果
const char* c_str ( ) const;
c_str函数的功能是利用string对象中的内容生成C字符串,并返回指向该字符串的指针。
该函数没有参数。
函数返回指向与string对象等效的C字符串的指针。
/********************************************
*范例编号:22_19
*范例说明:将string对象转换为C字符串,并分割字符串
*********************************************/
01 #include < iostream>
02 #include < cstring>
03 #include < string>
04 using namespace std;
05 void main()
06 {
07 char *s,*p;
08 char i=1;
09 string str(“Computer & software engineer”);
10 s=new char[str.size()+1];
11 strcpy(s,str.c_str());
12 cout< < “字符串:”< < s< < endl;
13 printf(“字符数组地址:%p\n”,&s[0]);
14 p=strtok(s,” “);
15 printf(“地址%d:%p\n”,i++,p);
16 while(p!=’\0’)
17 {
18 cout< < p< < endl;
19 p=strtok(‘\0’,” “);
20 printf(“地址%d:%p\n”,i++,p);
21 }
22 delete[] s;
23 system(“pause”);
24 }
该函数范例的运行结果如图22-19所示。
图22-19 函数范例的运行结果
调用c_str函数后,转换后的C字符串末尾自动被增加一个’\0’结束符。
size_t copy ( char* s, size_t n, size_t pos = 0) const;
copy函数的功能是从string对象中取出若干个字符存放到数组s中。其中,s是字符数组,n表示要取出字符的个数,pos表示要取出字符的开始位置。
(1)参数s:字符数组,用来存放从string对象中取出的字符。
(2)参数n:取出的字符个数。
(3)参数pos:要取出的字符在string对象中的开始位置。
函数返回取出字符的个数。
/********************************************
*范例编号:22_20
*范例说明:取出string对象中的指定字符
*********************************************/
01 #include < iostream>
02 #include < string>
03 using namespace std;
04 void main ()
05 {
06 char buf[60];
07 int len;
08 string::size_type n;
09 string str=”Deep Leaning & Artifical Intelligence”;
10 cout< < “字符串str对象:”< < str< < endl;
11 n=str.find_first_of(‘ ‘);
12 len=str.copy(buf,n,0);
13 buf[len]=’\0’;
14 cout < < “数组buf中的内容:”< < buf< < endl;
15 n=str.find_first_of(‘&’);
16 len=str.copy(buf,str.length()-n,n+1);
17 buf[len]=’\0’;
18 cout < < “数组buf中的内容:”< < buf< < endl;
19 system(“pause”);
20 }
该函数范例的运行结果如图22-20所示。
图22-20 函数范例的运行结果
(1)在调用copy函数时,应先为s分配内存空间使其能容纳n个字符。
(2)如果n大于pos到string末尾字符的个数,则仅取出从pos到string末尾的字符。
size_t find ( const string&str, size_t pos=0 ) const;
size_t find ( const char*s, size_t pos, size_t n ) const;
size_t find ( const char*s, size_t pos=0 ) const;
size_t find ( char c, size_t pos=0 ) const;
find函数的功能是在当前string对象中查找指定的字符c或字符串s或字符串对象str。其中,各个函数的功能如下。
(1)第1个函数的功能是从当前string对象的第1个字符开始查找字符串对象str。
(2)第2个函数的功能是从当前string对象的第pos个字符开始查找字符串s(仅在当前的string对象中查找前n个字符)。
(3)第3个函数的功能是从当前string对象的第pos个字符开始查找字符串s。
(4)第4个函数的功能是从当前string对象的第pos个字符开始查找字符c。
(1)参数str:要查找的字符串对象。
(2)参数pos:在当前string对象中查找指定字符串或字符的起始位置。
(3)参数s:字符数组,要查找的字符串。
(4)参数n:要查找的字符串的前n个字符。
如果查找成功,则返回字符串或字符在当前string对象中第一次出现的位置;否则,返回string的数据成员npos,即−1。
/********************************************
*范例编号:22_21
*范例说明:在string对象中查找字符串
*********************************************/
01 #include < iostream>
02 #include < string>
03 using namespace std;
04 void main ()
05 {
06 string str(“TCP functions at the OSI transport layer or layer 4.\
07 There are 4 layers.”);
08 string str2(“layer”);
09 int pos,i=1;
10 cout< < “字符串:”< < str< < endl;
11 pos=str.find(str2);
12 while(pos!=string::npos)
13 {
14 cout< < “’layer’第”< < i++< < “次出现的位置:” < < pos< < endl;
15 pos=str.find(str2,pos+1);
16 }
17 system(“pause”);
18 }
该函数范例的运行结果如图22-21所示。
图22-21 函数范例的运行结果
size_t find_first_of ( const string& str, size_t pos=0 ) const;
size_t find_first_of ( const char*s, size_t pos, size_t n ) const;
size_t find_first_of ( const char*s, size_t pos=0 ) const;
size_t find_first_of ( char c, size_t pos=0 ) const;
size_t find_last_of ( const string& str, size_t pos=npos ) const;
size_t find_last_of ( const char*s, size_t pos, size_t n ) const;
size_t find_last_of ( const char*s, size_t pos=npos ) const;
size_t find_last_of ( char c, size_t pos=npos ) const;
find_first_of函数和find_last_of函数的功能都是在当前string中查找与str、s、c部分匹配的字符或字符串。二者的区别在于find_first_of函数是从前往后查找,而find_last_of函数则是从后往前查找。
(1)参数str:要查找的字符串对象。
(2)参数s:要查找的字符串。
(3)参数c:要查找的字符。
(4)参数pos:在string对象中查找的起始位置。
(5)参数n:表示只查找字符串s的前n个字符。
如果查找成功,则返回str、s、c中的任意字符在当前string对象中的位置;否则,返回npos,即−1。
/********************************************
*范例编号:22_22
*范例说明:在string中查找字符串(部分匹配)
*********************************************/
01 #include < iostream>
02 #include < string>
03 using namespace std;
04 void main()
05 {
06 string str1(“Welcome to my hometown.”);
07 string str2(“Posts & telecom press.”);
08 int pos,i=1;
09 cout< < “字符串str1:”< < str1< < endl;
10 pos=str1.find_first_of(“cet”);
11 while(pos!=string::npos)
12 {
13 cout< < “第”< < i++< < “次找到:”< < str1[pos]< < endl;
14 str1[pos]=’#’;
15 pos=str1.find_first_of(“cet”,pos+1);
16 }
17 cout< < “字符串str1:”< < str1< < endl;
18 cout< < “字符串str2:”< < str2< < endl;
19 pos=str2.find_last_of(“s”);
20 while(pos!=string::npos)
21 {
22 cout< < “’s’出现的位置:”< < pos< < endl;
23 pos=str2.find_last_of(“s”,pos-1);
24 }
25 system(“pause”);
26 }
该函数范例的运行结果如图22-22所示。
图22-22 函数范例的运行结果
find_first_of函数与find函数的区别:对于find_first_of函数来说,如果指定字符串中某个字符与当前string对象中的字符相等,则返回该字符在string中的位置;而find函数则要求两个字符串完全匹配,而不仅仅要求某个字符相等。
string substr ( size_t pos=0, size_t n=npos ) const;
substr函数的功能是由当前string对象生成子串并返回。
(1)参数pos:子串在string对象中的起始位置。
(2)参数n:子串的长度。
函数返回string对象的子串。
/********************************************
*范例编号:22_23
*范例说明:生成string的子串
*********************************************/
01 #include < iostream>
02 #include < string>
03 using namespace std;
04 void main()
05 {
06 string str1(“C:\\Ghost\\ghostxp.exe”);
07 string str2(“Data Structure is an important professional core course!”);
08 string substr1,substr2, substr3,substr4;
09 int pos;
10 pos=str1.find_last_of(“\\”);
11 cout< < “完整路径:”< < str1< < endl;
12 cout< < “文件夹:”< < str1.substr(0,pos)< < endl;
13 cout< < “文件名:”< < str1.substr(pos+1)< < endl;
14 cout < < “初始字符串:” < < str٢< < endl;
15 substr1 = str2.substr(5, 10);
16 cout < < “子字符串substr1:” < < substr1 < < endl;
17 substr2= str2.substr();
18 cout < < “默认的子字符串substr2:” < < endl;
19 cout < < substr2 < < endl;
20 substr3=str2.substr(5);
21 cout < < “子字符串substr3:” < < endl;
22 cout < < substr3 < < endl;
23 substr4=str2.substr(str2.length()-7);
24 cout < < “子字符串substr4:” < < endl;
25 cout < < substr4 < < endl;
26 system(“pause”);
27 }
该函数范例的运行结果如图22-23所示。
图22-23 函数范例的运行结果
(1)若不指定参数,则substr函数返回的是从字符串第1个位置开始的字符串,即整个字符串。
(2)如果pos超出了string的范围,则出现越界错误。如果n超出了string的最大范围,则将pos之后的所有字符都作为子串返回。
(3)若只指定一个参数,则substr函数返回的是从该指定位置开始到字符串末尾的字符串。
(4)substr函数其实是basic_string类中的函数,但是可以被其子类string使用。
int stoi (const string& str, size_t* idx = 0, int base = 10);
int stoi (const wstring& str, size_t* idx = 0, int base = 10);
stoi函数的功能是将string转换为整数。
(1)参数str:以string对象表示的整数字符串。
(2)参数idx:指向无符号整型的指针,其值为指向当前整数的下一个字符。通常被设置为空指针,表示不使用该参数。
(3)参数base:整数的基,即要转换为十进制数,还是十六进制、八进制、二进制数。
函数返回转换后的整数。
/********************************************
*范例编号:22_24
*范例说明:将字符串中的数字转换为整数
*********************************************/
01 #include < iostream>
02 #include < string>
03 using namespace std;
04 void main ()
05 {
06 int i_str,i;
07 size_t *n=new size_t;
08 float f;
09 string str[]={“2021Mobile”,”158”,”0xf”};
10 string str2=”13.5”;
11 for(i=0;i< sizeof(str)/sizeof(str[0]);i++)
12 {
13 cout< < “str”< < i< < “:”< < str[i]< < endl;
14 i_str=stoi(str[i],0,0);
15 cout< < “转换后:”< < i_str< < endl;
16 }
17 i_str=stoi(str[0],n,0);
18 cout< < “数字字符后的下一个字符是:”< < str[0].at(*n)< < endl;
19 f=stof(str2,0);
20 cout< < “字符串”< < str2< < “转换后为:”< < f< < endl;
21 system(“pause”);
22 }
该函数范例的运行结果如图22-24所示。
图22-24 函数范例的运行结果
(1)默认情况下,stoi函数中的参数base默认为10。
(2)stoi函数和stof函数中的参数idx均为数字字符的下一个字符位置,如在”2021Mobile”中,若idx不设置为NULL,则将返回数字字符”2021”的下一个字符’M’的位置。
vector类是一种顺序容器,也就是说,集合中的元素是严格按照线性序列存放的。vector容器可以看做是动态数组,容器中的元素存放在连续的存储区域。因此,vector容器中的元素不仅可以使用迭代器存取,也可以使用下标运算符进行访问。
vector容器自动地分配存储区和释放存储区,不需要使用new和delete关键字对内存进行操作。vector容器还可以根据需要自动对内存区域进行扩展和收缩。
vector容器最擅长的工作如下。
(1)利用位置索引存取容器中的单个元素。
(2)以任何顺序迭代容器中的元素。
(3)在容器的末尾追加和删除元素。
如果要使用vector类中的函数,则需要使用以下文件包含命令。
#include< vector>
using namespace std;
vector类中的函数可以分为五大类,分别是构造类函数、迭代器函数、容量类函数、存取类函数、操作类函数。
vector容器的构造类函数包括构造函数和析构函数。
vector(const Allocator&=Allocator());
vector(size_type n,const T&value=T(),const Allocator&=Allocator());
template< class InputIterator>
vector(InputIterator first, InputIterator last, const Allocator&=Allocator());
vector(const vector< T,Allocator>&x );
~vector ();
在C++中,字符串构造函数有4个。其中,各个函数的功能如下。
第1个函数是默认的构造函数,它的功能是创建一个空的vector对象。
第2个函数是重复序列构造函数,它的功能是创建多个相同的vector对象副本。
第3个函数是迭代构造函数,它的功能是利用迭代器创建vector对象。
第4个函数是拷贝构造函数,它的功能是创建一个与x相同的vector对象。
(1)参数n:构造新对象的个数。
(2)参数value:新对象的值。
(3)参数first:迭代器的开始位置,通过[first,last)表示对象中从first到last之间的元素。
(4)参数last:迭代器的结束位置,通过[first,last)表示对象中从first到last之间的元素。
(5)参数x:一个vector对象,用来初始化新的vector对象。
所有的构造函数都没有返回值。
/********************************************
*范例编号:23_01
*范例说明:利用各种构造函数创建字符串对象
*********************************************/
01 #include < iostream>
02 #include < vector>
03 using namespace std;
04 void main()
05 {
06 int i;
07 vector< int> v1(3,20);
08 char str[]={‘a’,’b’,’c’,’d’,’e’};
09 vector< char> v2(str,str+sizeof(str)/sizeof(str[0]));
10 vector< char> v3(v2.begin(),v2.end());
11 vector< char> v4(v3);
12 cout < < “容器v1的值是:”;
13 for (i=0;i< v1.size();i++)
14 cout < < “ “< < v1[i];
15 cout< < endl;
16 cout < < “容器v2的值是:”;
17 for (i=0;i< v2.size();i++)
18 cout< < “ “< < v2[i];
19 cout< < endl;
20 cout < < “容器v3的值是:”;
21 for (i=0;i< v3.size();i++)
22 cout< < “ “< < v3[i];
23 cout< < endl;
24 cout< < “容器v4的值是:”;
25 for (i=0;i< v4.size();i++)
26 cout< < “ “< < v4[i];
27 cout< < endl;
28 system(“pause”);
29 }
该函数范例的运行结果如图23-1所示。
图23-1 函数范例的运行结果
在使用迭代器构造vector对象时,当前vector容器的内容是[first,last)之间的元素。
注意:包括first指向的元素,而不包括last指向的元素。
析构函数~vector()在程序结束时由系统自动调用。
vector< T,Allocator>&operator=(const vector< T,Allocator>&x);
operator=函数的功能是将vector对象x中的内容拷贝到当前的vector对象中。
参数x:一个vector对象,用来初始化当前的vector对象。
函数返回当前对象的引用。
/********************************************
*范例编号:23_02
*范例说明:拷贝vector中的内容
*********************************************/
01 #include < iostream>
02 #include < vector>
03 using namespace std;
04 void main()
05 {
06 vector< int> v1(5,20);
07 vector< int> v2(10,50);
08 vector< int>::iterator it;
09 v2=v1;
10 cout< < “容器v1的大小: “< < v1.size()< < endl;
11 for(vector< int>::iterator it=v1.begin();it< v1.end();it++)
12 cout< < “ “< < *it;
13 cout< < endl;
14 cout < < “容器v2的大小: “< < v2.size()< < endl;
15 for(it=v2.begin();it< v2.end();it++)
16 cout< < “ “< < *it;
17 cout< < endl;
18 system(“pause”);
19 }
该函数范例的运行结果如图23-2所示。
图23-2 函数范例的运行结果
迭代器类似于C/C++中的指针,指向容器中的元素,利用迭代器可以很方便地存取容器中的元素。
iterator begin ();
const_iterator begin () const;
iterator end ();
const_iterator end () const;
(1)begin函数的功能是返回vector容器中第一个元素的位置。
(2)end函数的功能是返回vector容器中最后一个元素的后一个位置。
该函数没有参数。
(1)begin函数返回vector容器中第一个元素的位置。
(2)end函数返回vector容器中最后一个元素的后一个位置。
/********************************************
*范例编号:23_03
*范例说明:利用迭代器依次输出vector中的元素
*********************************************/
01 #include < iostream>
02 #include < vector>
03 using namespace std;
04 void main ()
05 {
06 vector< char> v(5,’A’);
07 vector< char>::iterator it;
08 cout< < “容器中的元素:”;
09 for (it=v.begin();it< v.end();it++)
10 cout< < *it< < “ “;
11 for (int i=0; i< =5; i++)
12 v.push_back(‘Z’-i);
13 cout< < “\n容器中的元素:”;
14 for (it=v.begin();it< v.end();it++)
15 cout< < *it< < “ “;
16 cout< < endl;
17 system(“pause”);
18 }
该函数范例的运行结果如图23-3所示。
图23-3 函数范例的运行结果
迭代器begin指向vector容器中的第一个元素,迭代器end指向vector容器中最后一个元素之后的位置,而不是指向最后一个元素。
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
(1)rbegin函数的功能是返回与vector中最后一个元素相关的迭代器。
(2)rend函数的功能是返回与vector中第一个元素之前元素相关的迭代器。
该函数没有参数。
(1)rbegin函数返回vector的反向的开始位置。
(2)rend函数返回vector的反向的结束位置(迭代器指向的是第一个元素之前的元素)。
/********************************************
*范例编号:23_04
*范例说明:利用反向迭代器逆向输出vector中的元素
*********************************************/
01 #include < iostream>
02 #include < vector>
03 using namespace std;
04 struct student
05 {
06 char no[20];
07 char name[20];
08 float score;
09 }stu[]={{“2019002”,”Wang”,90},{“2020001”,”Liu”,89},{“2020101”,”Hua”,92}};
10 void main()
11 {
12 vector< student> s;
13 vector< student>::iterator it;
14 vector< student>::reverse_iterator rit;
15 for (int i=0; i< 3; i++)
16 {
17 s.push_back(stu[i]);
18 }
19 cout < < “容器中的元素(正向迭代):”< < endl;
20 for(it=s.begin();it< s.end();it++)
21 cout< < “ “< < (*it).no< < “ “< < (*it).name< < “ “< < (*it).score< < endl;
22 cout < < “容器中的元素(反向迭代):”< < endl;
23 for(rit=s.rbegin();rit< s.rend();rit++)
24 cout< < “ “< < (*rit).no< < “ “< < (*rit).name< < “ “< < (*rit).score< < endl;
25 system(“pause”);
26 }
该函数范例的运行结果如图23-4所示。
图23-4 函数范例的运行结果
rbegin函数和rend函数与begin函数和end函数作用一样,区别仅在于它们的迭代方向不同:rbegin函数与rend函数是从右往左进行迭代,而begin函数与end函数是从左往右进行迭代。
在vector容器中,容量类函数主要指的是与容器的大小有关的函数,这些函数主要包括size函数、max_size函数、capaticy函数、empty函数、resize函数、reserve函数。
size_type size() const;
size_type max_size () const;
size_type capacity () const;
(1)size函数的功能是求vector容器中元素的个数。
(2)max_size函数的功能是求vector容器能容纳的最大元素个数。
(3)capacity函数的功能是求为vector容器分配的存储空间大小。
这几个函数都没有参数。
(1)size函数返回vector容器中实际的元素个数。
(2)max_size函数返回vector容器中所能容纳的最大元素个数。
(3)capacity函数返回为vector容器分配的存储空间大小。
/********************************************
*范例编号:23_05
*范例说明:输出vector容器中的实际元素个数、存储空间大小和所能容纳的最大元素个数
*********************************************/
01 #include < iostream>
02 #include < vector>
03 using namespace std;
04 void main ()
05 {
06 vector< char> v;
07 for(int i=0;i< 20;i++)
08 {
09 v.push_back(i+’a’);
10 cout< < “ “< < v.at(i);
11 }
12 cout< < “\n容器的实际元素个数: “< < v.size()< < endl;
13 cout< < “容器的存储空间大小: “< < v.capacity()< < endl;
14 cout< < “容器所能容纳的最大元素个数: “< < v.max_size()< < endl;
15 system(“pause”);
16 }
该函数范例的运行结果如图23-5所示。
图23-5 函数范例的运行结果
size函数返回vector容器的实际元素个数,max_size函数返回vector容器所能容纳的最大元素个数,capacity函数返回实际分配的存储空间大小。
bool empty () const;
empty函数的功能是判断vector容器是否为空,即vector容器的元素个数是否为0。
该函数没有参数。
如果vector容器中的元素个数为0,则返回true;否则,返回false。
/********************************************
*范例编号:23_06
*范例说明:求vector容器中元素的和
*********************************************/
01 #include < iostream>
02 #include < vector>
03 using namespace std;
04 void main ()
05 {
06 vector< int> v;
07 vector< int>::iterator it;
08 float s=0;
09 int i;
10 for (i=2;i< =30;i+=5)
11 v.push_back(i);
12 if(v.empty())
13 {
14 cout< < “容器为空!”< < endl;
15 return;
16 }
17 else
18 {
19 cout< < “容器中元素: “;
20 for(it=v.begin();it< v.end();it++)
21 {
22 cout< < “ “< < *it;
23 s+=*it;
24 }
25 cout< < endl;
26 }
27 cout< < “容器中元素的和: “< < s< < endl;
28 cout< < “容器中元素的平均值: “< < s/v.size()< < endl;
29 system(“pause”);
30 }
该函数范例的运行结果如图23-6所示。
图23-6 函数范例的运行结果
empty函数并不会修改vector容器中的元素,如果要清除vector容器中的元素,则需要调用clear函数。
void resize (size_type sz, T c=T());
resize函数的功能是重新调整vector容器的大小使之包含sz个元素。
(1)参数sz:vector容器中元素的个数。
(2)参数c:要插入vector容器中的元素值。
该函数没有返回值。
/********************************************
*范例编号:23_07
*范例说明:输出调整vector容器大小后的元素
*********************************************/
01 #include < iostream>
02 #include < vector>
03 using namespace std;
04 void DispVector(vector< int> v);
05 void main()
06 {
07 vector< int> v(5,20);
08 vector< int>::iterator it;
09 int i;
10 for (i=1;i< 8;i++)
11 v.push_back(i);
12 DispVector(v);
13 v.resize(5);
14 DispVector(v);
15 v.resize(10,8);
16 DispVector(v);
17 v.resize(15);
18 DispVector(v);
19 system(“pause”);
20 }
21 void DispVector(vector< int> v)
22 {
23 cout< < “容器中的元素:”< < endl;
24 vector< int>::iterator it;
25 for(it=v.begin();it< v.end();it++)
26 cout< < *it< < “ “;
27 cout< < endl;
28 }
该函数范例的运行结果如图23-7所示。
图23-7 函数范例的运行结果
(1)如果sz小于原来vector容器的大小,则容器前面的元素被保留,后面的元素被抛弃。如果sz大于原来vector容器的大小,则在容器的末尾插入元素c,使容器的大小达到sz。
(2)这里所说的vector容器的大小指的是元素的实际个数,而不是vector容器的存储空间大小。
(3)size_type是一个无符号整型。
void reserve ( size_type n );
reserve函数的功能是重新为vector容器分配内存空间使其至少能容纳n个元素。
参数n:请求分配存储空间的大小,表示分配的空间至少能容纳n个元素。
该函数没有返回值。
/********************************************
*范例编号:23_08
*范例说明:输出重新为vector容器分配的内存空间的大小
*********************************************/
01 #include < iostream>
02 #include < vector>
03 using namespace std;
04 void main()
05 {
06 vector< int> v;
07 v.push_back(25);
08 cout< < “重新分配存储空间前:”< < endl;
09 cout< < “容器的存储空间大小:”< < v.capacity()< < endl;
10 cout< < “容器的实际元素个数:”< < v.size()< < endl;
11 cout< < “容器所能容纳的元素个数:”< < v.max_size()< < endl;
12 v.reserve(100);
13 cout< < “重新分配存储空间后:”< < endl;
14 cout< < “容器的存储空间大小:”< < v.capacity()< < endl;
15 cout< < “容器的实际元素个数:”< < v.size()< < endl;
16 cout< < “容器所能容纳的元素个数:”< < v.max_size()< < endl;
17 system(“pause”);
18 }
该函数范例的运行结果如图23-8所示。
图23-8 函数范例的运行结果
reserve函数中的参数n表示为vector容器分配的最小的内存空间。调用reserve函数后,原来vector容器中的元素不会受到影响,并且不会改变容器中的实际元素个数和容器所能容纳的最大元素个数。
vector存取类函数主要包括operator[]函数、at函数、front函数、back函数。
reference operator[] ( size_type n );
const_reference operator[] ( size_type n ) const;
operator[]函数是运算符重载函数,它的功能是存取vector容器中的元素。
参数n:vector容器中第n个元素的下标。
函数的返回值是vector容器中下标为n的元素的引用。
/********************************************
*范例编号:23_09
*范例说明:输出排序前后vector容器中的元素
*********************************************/
01 #include < iostream>
02 #include < vector>
03 #include < stdlib.h>
04 #include < time.h>
05 using namespace std;
06 void main()
07 {
08 vector< char> v;
09 int i,t,j,k;
10 v.resize(12);
11 vector< char>::size_type n=v.size();
12 srand((unsigned)time(NULL));
13 for(i=0;i< n;i++)
14 v[i]=rand()%26+’a’;
15 cout< < “容器中的元素:”< < endl;
16 for(i=0;i< n;i++)
17 cout< < “ “< < v[i];
18 cout< < endl;
19 cout< < “排序后容器中的元素:”< < endl;
20 for(i=0; i< n; i++)
21 {
22 k=i;
23 for(j=i+1;j< n;j++)
24 {
25 if(v[j]< v[k])
26 k=j;
27 }
28 if(k!=i)
29 {
30 t=v[i];
31 v[i]=v[k];
32 v[k]=t;
33 }
34 }
35 for(i=0;i< n;i++)
36 cout< < “ “< < v[i];
37 cout< < endl;
38 system(“pause”);
39 }
该函数范例的运行结果如图23-9所示。
图23-9 函数范例的运行结果
(1)类型reference和const_reference都是vector容器中元素的引用类型,通常被分别定义为T&和const T&。
(2)operator[]函数的作用与at函数的类似,它们都用来存取vector容器中的元素,区别仅在于at函数自动进行越界检查。
const_reference at ( size_type n ) const;
reference at ( size_type n );
at函数的功能与operator[]函数的一样,也是用来存取vector容器中的元素。
参数n:vector容器中第n个元素的位置。
函数返回vector容器中元素的引用。
/********************************************
*范例编号:23_10
*范例说明:输出排序前和排序后vector容器中的元素
*********************************************/
01 #include < iostream>
02 #include < vector>
03 #include < time.h>
04 #include < stdlib.h>
05 using namespace std;
06 void main()
07 {
08 vector< int> v(12);
09 int i,t,j,k;
10 vector< int>::size_type n=v.size();
11 srand((unsigned)time(NULL));
12 for(i=0;i< n;i++)
13 v.at(i)=rand()%100;
14 cout< < “容器中的元素:”< < endl;
15 for(i=0;i< n;i++)
16 cout< < “ “< < v.at(i);
17 cout< < endl;
18 cout< < “排序后容器中的元素:”< < endl;
19 for(i=0; i< n; i++)
20 {
21 k=i;
22 for(j=i+1;j< n;j++)
23 {
24 if(v[j]< v[k])
25 k=j;
26 }
27 if(k!=i)
28 {
29 t=v[i];
30 v[i]=v[k];
31 v[k]=t;
32 }
33 }
34 for(i=0;i< n;i++)
35 cout< < “ “< < v.at(i);
36 cout< < endl;
37 system(“pause”);
38 }
该函数范例的运行结果如图23-10所示。
图23-10 函数范例的运行结果
如果参数n大于或等于vector容器的实际大小,则抛出一个越界异常。
reference front ();
const_reference front () const;
reference back ();
const_reference back () const;
(1)front函数的功能是返回vector容器中的第一个元素。
(2)back函数的功能是返回vector容器中的最后一个元素。
该函数没有参数。
函数返回vector容器中的第一个元素和最后一个元素。
/********************************************
*范例编号:23_11
*范例说明:输出vector容器中的第一个元素和最后一个元素
*********************************************/
01 #include < iostream>
02 #include < vector>
03 using namespace std;
04 void main()
05 {
06 vector< int> v(5);
07 int i;
08 for(i=0;i< v.size();i++)
09 v[i]=i+1;
10 cout< < “容器中的元素:”< < endl;
11 for(i=0;i< v.size();i++)
12 cout< < “ “< < v[i];
13 cout< < endl;
14 cout< < “第一个元素是:”< < v.front()< < endl;
15 cout< < “最后一个元素是:”< < v.back()< < endl;
16 system(“pause”);
17 }
该函数范例的运行结果如图23-11所示。
图23-11 函数范例的运行结果
begin函数和end函数分别返回vector容器中元素的迭代器,而front函数和back函数则直接返回元素。
vector操作类函数主要包括assign函数、push_back函数、pop_back函数、insert函数、erase函数、clear函数、swap函数。
void assign ( InputIterator first, InputIterator last );
void assign ( size_type n, const T&u );
assign函数的功能是利用迭代器或指定的值为当前vector容器中的元素赋值。其中,各个函数的功能如下。
(1)第1个函数是利用迭代器first和last为当前vector容器中的元素赋值。
(2)第2个函数是将重复的n个元素值u赋值给当前vector容器中的元素。
(1)参数first:输入对象的迭代器,指向输入对象的第一个元素。
(2)参数last:输入对象的迭代器,指向输入对象最后一个元素之后的位置。
(3)参数n:u的重复次数。
(4)参数u:vector容器的新元素值。
函数返回指向与string对象等效的C字符串指针。
/********************************************
*范例编号:23_12
*范例说明:利用assign函数为vector容器中的元素赋值
*********************************************/
01 #include < iostream>
02 #include < vector>
03 #include < time.h>
04 #include < stdlib.h>
05 using namespace std;
06 void DispVec(vector< int> v);
07 void main ()
08 {
09 vector< int> v1,v2,v3;
10 int a[10];
11 int i;
12 srand((unsigned)time(NULL));
13 for(i=0;i< sizeof(a)/sizeof(a[0]);i++)
14 a[i]=rand()%100;
15 v1.assign(8,100);
16 cout< < “容器v1的大小: “< < v1.size()< < endl;
17 cout< < “容器v1中的元素: “< < endl;
18 DispVec(v1);
19 v2.assign(v1.begin(),v1.end()-1);
20 cout< < “容器v2的大小: “< < v2.size()< < endl;
21 cout< < “容器v2中的元素: “< < endl;
22 DispVec(v2);
23 v3.assign(a,a+sizeof(a)/sizeof(a[0]));
24 cout< < “容器v3的大小: “< < v3.size()< < endl;
25 cout< < “容器v3中的元素: “< < endl;
26 DispVec(v3);
27 system(“pause”);
28 }
29 void DispVec(vector< int> v)
30 {
31 int i;
32 for(i=0;i< v.size();i++)
33 cout< < “ “< < v.at(i);
34 cout< < endl;
35 }
该函数范例的运行结果如图23-12所示。
图23-12 函数范例的运行结果
在利用迭代器first和last为当前的vector容器赋值时,要赋值的元素范围是[first,last),即包括first指向的元素,而不包括last指向的元素。
void push_back ( const T&x );
push_back函数的功能是在vector容器的最后一个元素后添加元素x。
参数x:要追加到vector末尾的元素。
该函数没有返回值。
/********************************************
*范例编号:23_13
*范例说明:在vector容器末尾追加字符
*********************************************/
01 #include < iostream>
02 #include < vector>
03 using namespace std;
04 void main()
05 {
06 vector< char> v;
07 char ch;
08 cout< < “请输入要存储的字符(‘q’或’Q’表示结束):\n”;
09 cin>>ch;
10 while(ch!=’q’&&ch!=’Q’)
11 {
12 cin>>ch;
13 v.push_back(ch);
14 }
15 cout< < “容器中的元素个数是:”< < v.size()< < endl;
16 cout< < “容器中的元素:”< < endl;
17 for(int i=0;i< v.size();i++)
18 cout< < “ “< < v[i];
19 cout< < endl;
20 system(“pause”);
21 }
该函数范例的运行结果如图23-13所示。
图23-13 函数范例的运行结果
当调用push_back函数后,vector容器的实际元素个数增1。当实际元素个数等于vector容器的存储空间大小时,系统会自动为该容器分配内存空间。
void pop_back ();
pop_back函数的功能是删除vector容器中的最后一个元素。
该函数没有参数。
该函数没有返回值。
/********************************************
*范例编号:23_14
*范例说明:输出删除前后vector容器中的元素
*********************************************/
01 #include < iostream>
02 #include < vector>
03 using namespace std;
04 void main ()
05 {
06 vector< int> v;
07 int sum=0;
08 for(int i=1;i< =5;i++)
09 v.push_back(i*10);
10 cout< < “容器中的元素:”< < endl;
11 vector< int>::iterator it;
12 for(it=v.begin();it< v.end();it++)
13 cout< < “ “< < *it;
14 cout< < endl;
15 v.pop_back();
16 cout< < “删除一个元素后容器中的元素:”< < endl;
17 for(it=v.begin();it< v.end();it++)
18 cout< < “ “< < *it;
19 cout< < endl;
20 system(“pause”);
21 }
该函数范例的运行结果如图23-14所示。
图23-14 函数范例的运行结果
iterator insert ( iterator position, const T&x );
void insert ( iterator position, size_type n, const T&x );
void insert ( iterator position, InputIterator first, InputIterator last );
insert函数的功能是在vector容器中插入元素。其中,各个函数的功能如下。
(1)第1个函数的功能是将x插入vector容器中第position个元素之前。
(2)第2个函数的功能是将n个x插入vector容器中第position个元素之前。
(3)第3个函数的功能是将输入对象中[first,last)之间的元素插入第position个元素之前。
(1)参数position:元素要插入的位置。
(2)参数x:要插入的元素。
(3)参数n:要插入的元素个数。
(4)参数first:迭代器,指向输入对象的开始元素。
(5)参数last:迭代器,指向输入对象末尾元素之后的位置。
第1个函数返回新插入元素的迭代器。其他函数没有返回值。
/********************************************
*范例编号:23_15
*范例说明:在vector容器中插入元素
*********************************************/
01 #include < iostream>
02 #include < vector>
03 using namespace std;
04 void main()
05 {
06 vector< int> v(5,50);
07 int a[]={1,2,3,4,5};
08 vector< int>::iterator it;
09 it=v.begin();
10 for(int i=0;i< sizeof(a)/sizeof(a[0]);i++)
11 it=v.insert(it,a[i]);
12 cout< < “容器中的元素:”;
13 for(it=v.begin();it< v.end();it++)
14 cout< < “ “< < *it;
15 it=v.insert(it,20);
16 cout< < “\n插入的元素是:”< < *it< < endl;
17 v.insert(it,2,10);
18 it=v.begin();
19 vector< int> v2(2,6);
20 v.insert(it+1,v2.begin(),v2.end());
21 v.insert(v.begin(),a,a+3);
22 cout< < “容器中的元素:”;
23 for(it=v.begin();it< v.end();it++)
24 cout< < “ “< < *it;
25 cout< < endl;
26 system(“pause”);
27 }
该函数范例的运行结果如图23-15所示。
图23-15 函数范例的运行结果
(1)第3个函数不仅可以接受vector容器的迭代器作为参数,也可以接受数组的指针作为参数。
(2)对于第3个函数来说,输入对象[first,last)之间的元素都将插入vector容器中,包括first指向的元素,但不包括last指向的元素。
iterator erase ( iterator position );
iterator erase ( iterator first, iterator last );
erase函数的功能是删除vector容器中指定的元素。其中,各个函数的功能如下。
(1)第1个函数的功能是删除vector容器中第position个元素。
(2)第2个函数的功能是删除vector容器中[first,last]之间的元素。
(1)参数position:迭代器,指向要删除的元素。
(2)参数first:迭代器,指向要删除[first,last]之间元素中的第一个元素。
(3)参数last:迭代器,指向要删除[first,last]之间元素中的最后一个元素。
函数返回vector容器中最后被删除元素的后一个位置。
/********************************************
*范例编号:23_16
*范例说明:输出删除前后vector容器中的元素
*********************************************/
01 #include < iostream>
02 #include < vector>
03 #include < time.h>
04 #include < stdlib.h>
05 using namespace std;
06 void main()
07 {
08 vector< int> v(10,5);
09 vector< int>::iterator it;
10 int i;
11 srand((unsigned)time(NULL));
12 for(i=1;i< =5;i++)
13 v.push_back(rand()%100);
14 cout< < “容器中的元素:”< < endl;
15 for(it=v.begin();it< v.end();it++)
16 cout< < “ “< < *it;
17 cout< < endl;
18 v.erase(v.begin()+3);
19 v.erase(v.end()-3);
20 v.erase(v.begin()+1,v.begin()+3);
21 cout< < “删除部分元素后,容器中的元素:”< < endl;
22 for(i=0; i< v.size();i++)
23 cout< < “ “< < v[i];
24 cout< < endl;
25 system(“pause”);
26 }
该函数范例的运行结果如图23-16所示。
图23-16 函数范例的运行结果
erase函数返回删除指定元素的后一个位置。
void clear ();
clear函数的功能是清除vector容器中的所有元素。
该函数没有参数。
该函数没有返回值。
/********************************************
*范例编号:23_17
*范例说明:输出清除前后vector容器中的元素
*********************************************/
01 #include < iostream>
02 #include < vector>
03 using namespace std;
04 void main()
05 {
06 vector< int> v;
07 int i;
08 vector< int>::iterator it;
09 v.resize(10);
10 for(i=1;i< =5;i++)
11 v[i]=i*10;
12 cout< < “容器中的元素:”< < endl;
13 for(it=v.begin();it< v.end();it++)
14 cout< < “ “< < *it;
15 cout< < endl;
16 v.clear();
17 it=v.end();
18 v.insert(it,500);
19 v.push_back(100);
20 v.push_back(200);
21 v.insert(it,500);
22 cout < < “容器中的元素:”;
23 for(i=0; i< v.size(); i++)
24 cout < < “ “< < v[i];
25 cout< < endl;
26 system(“pause”);
27 }
该函数范例的运行结果如图23-17所示。
图23-17 函数范例的运行结果
调用clear函数后,当前vector容器中的元素个数为0。
void swap ( vector< T,Allocator>&vec );
swap函数的功能是将当前vector容器中的内容与vec容器中的内容互换。
参数vec:一个vector类型的对象,用来与当前vector容器中的内容进行交换。
该函数没有返回值。
/********************************************
*范例编号:23_18
*范例说明:将当前vector容器中的内容与vec容器中的内容交换
*********************************************/
01 #include < iostream>
02 #include < vector>
03 #include < time.h>
04 #include < stdlib.h>
05 using namespace std;
06 void InitVec(vector< int> *v);
07 void DispVec(vector< int> v);
08 void main ()
09 {
10 vector< int> v1(5);
11 vector< int> v2(8);
12 InitVec(&v1);
13 InitVec(&v2);
14 cout< < “交换前,v1中的元素:”;
15 DispVec(v1);
16 cout< < “\n交换前,v2中的元素:”;
17 DispVec(v2);
18 v1.swap(v2);
19 cout< < “\n交换后,v1中的元素:”;
20 DispVec(v1);
21 cout< < “\n交换后,v2中的元素:”;
22 DispVec(v2);
23 cout< < endl;
24 system(“pause”);
25 }
26 void InitVec(vector< int> *v)
27 {
28 int i;
29 srand((unsigned)time(NULL));
30 for(i=0;i< (*v).size();i++)
31 (*v)[i]=rand()%100;
32 }
33 void DispVec(vector< int> v)
34 {
35 int i;
36 vector< int>::iterator it;
37 for(it=v.begin();it< v.end();it++)
38 cout< < “ “< < *it;
39 }
该函数范例的运行结果如图23-18所示。
图23-18 函数范例的运行结果
(1)调用swap函数后,当前vector容器中的元素成为vec容器中的元素,vec容器中的元素成为当前vector容器中的元素。
(2)要交换的两个容器的大小不一定相同。
deque被称为双端队列,它也是一种顺序容器。deque容器具有以下性质。
(1)利用位置索引可以存取容器中的单个元素。
(2)可以通过任何顺序迭代容器中的元素。
(3)可以在容器的开始和末尾插入/删除元素。
deque容器与vector容器提供类似的功能,但与vector容器不同的是,deque容器不仅可以在容器的末尾插入/删除元素,还可以在容器的开始位置插入/删除元素。
在C++的标准模板库中,deque容器有以下两个模板参数。
template< class T, class Allocator=allocator< T> >
class deque;
其中,T是元素的类型;Allocator用来提供类型化的内存分配及撤销。
如果要使用deque类(容器)中的函数,需要使用以下文件包含命令。
#include< deque>
using namespace std;
deque类中的函数可以分为五大类,分别是构造类函数、迭代器函数、容量类函数、存取类函数、操作类函数。
deque容器的构造类函数包括构造函数和析构函数。
deque ( const Allocator&=Allocator() );
deque ( size_type n, const T&value=T(), const Allocator&=Allocator() );
deque ( InputIterator first, InputIterator last, const Allocator&=Allocator() );
deque ( const deque< T,Allocator>&x );
~deque ();
deque构造函数的功能是创建deque容器并初始化容器中的元素。其中,各个函数的功能如下。
(1)第1个函数是deque默认的构造函数,它的功能是构造一个空的deque容器,该容器的内容为空,即容器的大小为0。
(2)第2个函数是deque的重复序列函数,它的功能是将value的值重复n次并存放到容器中。
(3)第3个函数是deque的迭代构造函数,它的功能是将输入对象中迭代器first和last之间的元素存放到容器中。
(4)第4个函数是deque的拷贝构造函数,它的功能是用另一个双端队列x初始化deque容器。
deque析构函数的功能是撤销deque容器的对象,并释放元素所占的存储区。
(1)参数n:value值重复的次数。
(2)参数value:容器对象的值。
(3)参数first:迭代器,输入对象的元素的开始位置。
(4)参数last:迭代器,输入对象的元素的结束位置。
(5)参数x:deque对象,用来填充当前deque对象的内容。
(6)参数Allocator:C++模板类,用来为新对象分配内存和撤销对象的内存。
构造函数和析构函数都没有返回值。
/********************************************
*范例编号:24_01
*范例说明:利用deque构造函数创建双端队列
*********************************************/
01 #include < iostream>
02 #include < deque>
03 using namespace std;
04 void main()
05 {
06 unsigned int i;
07 deque< int> d1;
08 deque< int> d2(6,10);
09 deque< int> d3(d2.begin()+1,d2.end());
10 deque< int> d4(d2);
11 if(d1.empty())
12 cout < < “容器d1为空:”< < endl;
13 cout< < “容器d2的元素:”;
14 for (i=0;i< d2.size();i++)
15 cout < < “ “ < < d2[i];
16 cout< < “\n容器d3的元素:”;
17 for (i=0;i< d3.size();i++)
18 cout < < “ “ < < d3[i];
19 cout< < “\n容器d4的元素:”;
20 for (i=0;i< d4.size();i++)
21 cout < < “ “ < < d4[i];
22 cout< < endl;
23 system(“pause”);
24 }
该函数范例的运行结果如图24-1所示。
图24-1 函数范例的运行结果
(1)在使用迭代器first和last构造deque对象时,当前deque容器中包含first指向的元素,而不包含last指向的元素。
(2)析构函数~deque()在程序结束时由系统自动调用。
deque< T,Allocator>&operator=( const deque< T,Allocator>&x );
operator=函数的功能是将deque对象x中的内容拷贝到当前的deque对象中。
参数x:一个deque对象,用来初始化当前的deque对象。
函数返回当前的deque对象。
/********************************************
*范例编号:24_02
*范例说明:利用一个deque对象构造另一个deque对象
*********************************************/
01 #include < iostream>
02 #include < deque>
03 using namespace std;
04 void main()
05 {
06 deque< int> d1(10);
07 deque< int> d2(20);
08 deque< int> d3(30,5);
09 cout< < “赋值前:”< < endl;
10 cout< < “d1的大小:”< < d1.size()< < endl;
11 cout< < “d2的大小:”< < d2.size()< < endl;
12 cout< < “d3的大小:”< < d3.size()< < endl;
13 d2=d1;
14 cout< < “赋值后:”< < endl;
15 cout< < “d1的大小:”< < d1.size()< < endl;
16 cout< < “d2的大小:”< < d2.size()< < endl;
17 d1=d3;
18 cout< < “重新赋值后:”< < endl;
19 cout< < “d1的大小:”< < d1.size()< < endl;
20 cout< < “d3的大小:”< < d3.size()< < endl;
21 system(“pause”);
22 }
该函数范例的运行结果如图24-2所示。
图24-2 函数范例的运行结果
当调用opertor=函数后,当前deque容器中的内容被x中的内容替换掉,x容器的大小与当前容器的大小相同。
deque容器包括4个迭代器:begin、end、rbegin和rend,利用这些迭代器可以很方便地存取容器中的元素。
iterator begin ();
const_iterator begin () const;
iterator end ();
const_iterator end () const;
(1)begin函数的功能是返回deque容器中第一个元素的位置。
(2)end函数的功能是返回deque容器中最后一个元素的后一个位置。
该函数没有参数。
(1)begin函数返回deque容器中第一个元素的位置。
(2)end函数返回deque容器中最后一个元素的后一个位置。
/********************************************
*范例编号:24_03
*范例说明:利用迭代器依次输出deque中的元素
*********************************************/
01 #include < iostream>
02 #include < deque>
03 using namespace std;
04 void main()
05 {
06 deque< char> d;
07 deque< char>::iterator it;
08 for (int i=0; i< =5; i++)
09 d.push_back(i+’A’);
10 cout< < “容器d中的元素:”;
11 it=d.end()-1;
12 for(;it!=d.begin();it--)
13 cout< < “ “< < *it;
14 cout< < “ “< < *it< < endl;
15 system(“pause”);
16 }
该函数范例的运行结果如图24-3所示。
图24-3 函数范例的运行结果
(1)迭代器begin指向deque容器中的第一个元素,迭代器end指向deque容器中最后一个元素之后的位置,而不是指向最后一个元素。
(2)注意将begin函数与front函数、end函数与back函数区别开。begin函数返回第1个元素的位置,front函数返回第1个元素;end函数返回最后一个元素的后一个位置,back函数返回最后一个元素。
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
(1)rbegin函数的功能是返回与deque中最后一个元素相关的迭代器。
(2)rend函数的功能是返回与deque中第一个元素之前的元素相关的迭代器。
该函数没有参数。
(1)rbegin函数返回deque的反向的开始位置,即最后一个元素所在的位置。
(2)rend函数返回deque的反向的结束位置(迭代器指向的是第一个元素前面的一个元素)。
/********************************************
*范例编号:24_04
*范例说明:利用反向迭代器逆向输出deque中的元素
*********************************************/
01 #include < iostream>
02 #include < deque>
03 using namespace std;
04 void main ()
05 {
06 deque< char> d;
07 deque< char>::iterator it1;
08 deque< char>::reverse_iterator it2;
09 for (int i=0; i< =5; i++)
10 d.push_back(i+’A’);
11 cout< < “容器d中的元素(顺序):”< < endl;
12 for(it1=d.begin();it1!=d.end();it1++)
13 cout< < “ “< < *it1;
14 cout< < endl;
15 cout< < “容器d中的元素(逆序):”< < endl;
16 for(it2=d.rbegin();it2< d.rend();it2++)
17 cout< < “ “< < *it2;
18 cout< < endl;
19 system(“pause”);
20 }
该函数范例的运行结果如图24-4所示。
图24-4 函数范例的运行结果
rbegin函数与begin函数、rend函数与end函数都指向迭代的元素,区别仅在于它们的迭代方向不同:rbegin函数与rend函数是从右往左进行迭代,而begin函数与end函数是从左往右进行迭代。
在deque容器中,容量类函数主要是指与容器的大小有关的函数,这些函数主要包括size函数、max_size函数、empty函数、resize函数。
size_type size() const;
size_type max_size () const;
(1)size函数的功能是返回deque容器中的元素个数。
(2)max_size函数的功能是返回deque容器能容纳的最大元素个数。
该函数没有参数。
(1)size函数返回deque容器中实际的元素个数。
(2)max_size函数返回deque容器中所能容纳的最大元素个数。
/********************************************
*范例编号:24_05
*范例说明:输出deque容器中的实际元素个数和所能容纳的最大元素个数
*********************************************/
01 #include < iostream>
02 #include < deque>
03 using namespace std;
04 void DispDeque(deque< int> d);
05 void main()
06 {
07 deque< int> d;
08 deque< int>::iterator it;
09 int i=1;
10 cout< < “容器d的大小:”< < d.size()< < “,”;
11 cout< < “能容纳的最大元素个数:”< < d.max_size()< < endl;
12 d.resize(5);
13 for(it=d.begin();it!=d.end();it++)
14 *it=i++*5;
15 DispDeque(d);
16 cout< < “容器d的大小:”< < d.size()< < “,”;
17 cout< < “容器d能容纳的最大元素个数:”< < d.max_size()< < endl;
18 d.insert(d.begin(),5,20);
19 DispDeque(d);
20 cout< < “容器d的大小:”< < d.size()< < “,”;
21 cout< < “容器d能容纳的最大元素个数:”< < d.max_size()< < endl;
22 d.pop_back();
23 DispDeque(d);
24 cout < < “容器d的大小:”< < d.size()< < “,”;
25 cout< < “容器d能容纳的最大元素个数:”< < d.max_size()< < endl;
26 system(“pause”);
27 }
28 void DispDeque(deque< int> d)
29 {
30 int i;
31 for(i=0;i< d.size();i++)
32 cout< < “ “< < d[i];
33 cout< < endl;
34 }
该函数范例的运行结果如图24-5所示。
size函数返回deque容器的实际元素个数,max_size函数返回deque容器中所能容纳的最大元素个数。
图24-5 函数范例的运行结果
bool empty () const;
empty函数的功能是判断deque容器是否为空,即deque容器的元素个数是否为0。
该函数没有参数。
如果deque容器中的元素个数为0,则返回true;否则,返回false。
/********************************************
*范例编号:24_06
*范例说明:求deque容器中元素的和及平均值
*********************************************/
01 #include < iostream>
02 #include < deque>
03 using namespace std;
04 void DispDeque(deque< int> d);
05 void main()
06 {
07 deque< int> d;
08 deque< int>::iterator it;
09 int i,n;
10 float sum=0;
11 d.resize(10);
12 for(it=d.begin(),i=1;it!=d.end(); it++,i++)
13 *it=i*2;
14 n=d.size();
15 DispDeque(d);
16 while(!d.empty())
17 {
18 sum+=d.front();
19 d.pop_front();
20 DispDeque(d);
21 }
22 cout< < “容器中元素之和: “< < sum< < endl;
23 cout< < “容器中元素的平均值: “< < sum/n< < endl;
24 system(“pause”);
25 }
26 void DispDeque(deque< int> d)
27 {
28 deque< int>::iterator it;
29 for(it=d.begin();it!=d.end();it++)
30 cout< < “ “< < *it;
31 cout< < endl;
32 }
该函数范例的运行结果如图24-6所示。
图24-6 函数范例的运行结果
与vector容器中的empty函数一样,deque中的empty函数也不会修改容器中的元素。
void resize ( size_type sz, T c=T() );
resize函数的功能是重新调整deque容器的大小使其包含sz个元素。
(1)参数sz:deque容器中元素的个数。
(2)参数c:如果sz大于当前容器中元素的个数,则将c添加到deque容器中。
该函数没有返回值。
/********************************************
*范例编号:24_07
*范例说明:输出调整后deque容器中的元素
*********************************************/
01 #include < iostream>
02 #include < deque>
03 using namespace std;
04 void DispDeque(deque< int> d);
05 void main ()
06 {
07 deque< int> d(5,10);
08 int i=0;
09 DispDeque(d);
10 for(i=0;i< d.size();i++)
11 d[i]=i;
12 DispDeque(d);
13 d.resize(3);//将容器的大小缩小到3个元素
14 DispDeque(d);
15 d.resize(15,20);//将容器的大小扩展到15个元素
16 DispDeque(d);
17 d.resize(10);//将容器的大小扩展到10个元素,如果原容器大小大于10,则保留前10个元素,否则,扩展的元素是0
18 cout< < “容器中的元素:”< < endl;
19 DispDeque(d);
20 system(“pause”);
21 }
22 void DispDeque(deque< int> d)
23 {
24 deque< int>::iterator it;
25 for (it=d.begin();it< d.end();it++)
26 cout< < “ “< < *it;
27 cout< < endl;
28 }
该函数范例的运行结果如图24-7所示。
图24-7 函数范例的运行结果
(1)如果sz小于原来deque容器的大小,则sz之后的元素将被抛弃,前面的元素仍被保留。如果sz大于原来deque容器的大小,则容器的大小扩展到sz个元素,并在末尾追加元素c。如果省略了参数c,则插入的元素值为0。
(2)这里所说的容器的大小指的是deque容器中的实际元素个数,而不是deque容器的存储空间大小。
deque存取类函数主要包括operator[]函数、at函数、front函数、back函数。
reference operator[] ( size_type n );
const_reference operator[] ( size_type n ) const;
operator[]函数是运算符重载函数,它的功能是存取deque容器中的元素。
参数n:元素在deque容器中的位置。
函数的返回值是deque容器中下标为n的元素。
/********************************************
*范例编号:24_08
*范例说明:输出deque容器中的元素之和
*********************************************/
01 #include < iostream>
02 #include < deque>
03 using namespace std;
04 void main()
05 {
06 deque< int> d;
07 deque< int>::iterator it;
08 int i=0,s=0;
09 d.resize(8);
10 for(it=d.begin();it!=d.end();it++)
11 *it=i++;
12 cout< < “容器中的元素:”< < endl;
13 for(i=0;i< d.size();i++)
14 cout< < “ “< < d[i];
15 cout< < endl;
16 for(i=0; i< d.size(); i++)
17 s+=d[i];
18 cout< < “容器中的元素之和:”< < s< < endl;
19 system(“pause”);
20 }
该函数范例的运行结果如图24-8所示。
图24-8 函数范例的运行结果
(1)类型reference和const_reference都是deque容器中元素的引用类型,通常被分别定义为T&和const T&。
(2)operator[]函数与at函数作用类似,它们都用来存取deque容器中的元素,区别仅在于at函数会自动进行越界检查。
const_reference at ( size_type n ) const;
reference at ( size_type n );
at函数的功能与operator[]函数的一样,也是用来存取deque容器中的元素。
参数n:deque容器中第n个元素所在的位置。
函数返回deque容器中指定位置的元素。
/********************************************
*范例编号:24_09
*范例说明:利用at函数输出逆置前和逆置后deque容器中的元素
*********************************************/
01 #include < iostream>
02 #include < deque>
03 using namespace std;
04 void main()
05 {
06 deque< char> d(10);
07 int i,n,t;
08 for (i=0; i< d.size(); i++)
09 d.at(i)=i+’A’;
10 cout< < “容器中的元素:”;
11 //输出容器中的元素,正确!
12 for (i=0; i< d.size(); i++)
13 cout< < “ “< < d.at(i);
14 cout< < endl;
15 //利用at()逆置容器中的元素
16 n=d.size();
17 for (i=0; i< n/2; i++)
18 {
19 t=d.at(i);
20 d.at(i)=d.at(n-i-1);
21 d.at(n-i-1)=t;
22 }
23 cout< < “逆置后容器中的元素:”;
24 //利用[]输出容器中的元素
25 for (i=0; i< d.size(); i++)
26 cout< < “ “< < d.at(i);
27 cout< < endl;
28 //利用at函数输出容器中的元素,越界时产生一个异常错误!
29 for (i=0; i< =d.size(); i++)
30 cout< < “ “< < d.at(i);
31 cout< < endl;
32 system(“pause”);
33 }
该函数范例的运行结果如图24-9所示。
图24-9 函数范例的运行结果
在引用deque容器中的元素时,如果参数n大于或等于deque容器的实际大小,则抛出一个越界异常,如图24-10所示。
图24-10 越界异常
需要注意的是,deque容器中第1个元素的下标是从0开始的,而不是从1开始。
reference front ();
const_reference front () const;
reference back ();
const_reference back () const;
(1)front函数的功能是返回deque容器中的第一个元素。
(2)back函数的功能是返回deque容器中的最后一个元素。
该函数没有参数。
函数返回deque容器中元素的引用。
/********************************************
*范例编号:24_10
*范例说明:输出deque容器中的第一个元素和最后一个元素
*********************************************/
01 #include < iostream>
02 #include < vector>
03 using namespace std;
04 void main()
05 {
06 vector< char> d(5);
07 int i;
08 for(i=0;i< d.size();i++)
09 d[i]=i+’a’;
10 cout< < “容器中的元素:”;
11 for(i=0;i< d.size();i++)
12 cout< < “ “< < d[i];
13 cout< < endl;
14 cout< < “第一个元素是:”< < d.front()< < endl;
15 cout< < “最后一个元素是:”< < d.back()< < endl;
16 system(“pause”);
17 }
该函数范例的运行结果如图24-11所示。
图24-11 函数范例的运行结果
begin函数和end函数分别返回deque容器中元素的迭代器,而front函数和back函数则直接返回容器中的元素。
deque操作类函数主要包括assign函数、push_back函数、push_front函数、pop_back函数、pop_front函数、insert函数、erase函数、clear函数、swap函数。
void assign ( InputIterator first, InputIterator last );
void assign ( size_type n, const T&u );
assign函数的功能是将元素赋值给当前的deque容器,之前存放在deque容器中的内容被覆盖掉。其中,各个函数的功能如下。
(1)第1个函数是利用迭代器将first和last之间的元素赋值给当前的deque容器。
(2)第2个函数是将重复的n个元素值u赋值给当前的deque容器。
(1)参数first:输入对象的迭代器,指向输入对象的第一个元素。
(2)参数last:输入对象的迭代器,指向输入对象最后一个元素之后的位置。
(3)参数n:元素u的个数。
(4)参数u:deque容器的新元素值。
该函数没有返回值。
/********************************************
*范例编号:24_11
*范例说明:利用assign函数为deque容器中的元素赋值
*********************************************/
01 #include < iostream>
02 #include < deque>
03 using namespace std;
04 void main ()
05 {
06 deque< int> d1;
07 deque< int> d2;
08 int i;
09 d1.assign(6,10);
10 cout< < “容器d1的大小: “< < d1.size()< < endl;
11 cout< < “容器d1中的元素: “< < endl;
12 for(i=0;i< d1.size();i++)
13 cout< < “ “< < d1.at(i);
14 cout< < endl;
15 d2.assign(d1.begin()+2,d1.end()-1);
16 cout< < “容器d2的大小: “< < d2.size()< < endl;
17 cout< < “容器d2中的元素: “< < endl;
18 for(i=0;i< d2.size();i++)
19 cout< < “ “< < d2.at(i);
20 cout< < endl;
21 d2.assign(5,20);
22 cout< < “容器d2中的元素: “< < endl;
23 for(i=0;i< d2.size();i++)
24 cout< < “ “< < d2.at(i);
25 cout< < endl;
26 system(“pause”);
27 }
该函数范例的运行结果如图24-12所示。
图24-12 函数范例的运行结果
在利用迭代器first和last为deque容器赋值时,赋值的元素范围是[first,last),即包括first指向的元素,而不包括last指向的元素。
void push_back ( const T&x );
push_back函数的功能是在deque容器的最后一个元素后添加元素x。
参数x:要追加到deque末尾的元素。
该函数没有返回值。
/********************************************
*范例编号:24_12
*范例说明:在deque容器末尾追加字符
*********************************************/
01 #include < iostream>
02 #include < deque>
03 using namespace std;
04 void main()
05 {
06 deque< char> d;
07 deque< char>::iterator p;
08 for(int i=0;i< 5;i++)
09 d.push_back(i+’A’);
10 cout< < “容器中的元素个数是:”< < d.size()< < endl;
11 cout< < “容器中的元素:”< < endl;
12 for(p=d.begin();p!=d.end();p++)
13 cout< < “ “< < *p;
14 cout< < endl;
15 }
该函数范例的运行结果如图24-13所示。
图24-13 函数范例的运行结果
调用push_back函数后,deque容器的实际元素个数增1,并将新元素追加在容器的最后,但并不会影响deque中的其他元素。
void push_front ( const T&x );
push_front函数的功能是在deque容器中的第1个元素前插入新元素x。
参数x:要插入deque中的最前面的元素。
该函数没有返回值。
/********************************************
*范例编号:24_13
*范例说明:在deque容器中的最前面插入新元素
*********************************************/
01 #include < iostream>
02 #include < deque>
03 using namespace std;
04 void DispDeque(deque< int> d);
05 void main ()
06 {
07 deque< int> d(3,10);
08 int i;
09 cout < < “容器中的元素:”;
10 DispDeque(d);
11 for(i=1;i< 5;i++)
12 d.push_back(i);
13 cout < < “容器中的元素:”;
14 DispDeque(d);
15 d.push_front(20);
16 d.push_front(30);
17 cout < < “容器中的元素:”;
18 DispDeque(d);
19 system(“pause”);
20 }
21 void DispDeque(deque< int> d)
22 {
23 deque< int>::iterator it=d.begin();
24 while(it!=d.end())
25 {
26 cout< < “ “< < *it;
27 it++;
28 }
29 cout< < endl;
30 }
该函数范例的运行结果如图24-14所示。
图24-14 函数范例的运行结果
与push_back函数一样,调用push_front函数也会使deque容器的实际大小自动增1,并在最前面增加一个元素值x。
void pop_back ();
pop_back函数的功能是移除deque容器中的最后一个元素。
该函数没有参数。
该函数没有返回值。
/********************************************
*范例编号:24_14
*范例说明:输出移除最后一个元素前后deque容器中的元素之和
*********************************************/
01 #include < iostream>
02 #include < deque>
03 using namespace std;
04 int Sum(deque< int> d);
05 void main ()
06 {
07 deque< int> d;
08 int s=0;
09 for(int i=1;i< 6;i++)
10 d.push_back(i*10);
11 cout< < “容器中的元素:”;
12 s=Sum(d);
13 cout< < “\n容器中元素之和:”< < s< < endl;
14 d.pop_back();
15 cout < < “容器中的元素:”;
16 s=Sum(d);
17 cout< < “\n移除最后一个元素后,容器中元素之和:”< < s< < endl;
18 system(“pause”);
19 }
20 int Sum(deque< int> d)
21 {
22 deque< int>::iterator p;
23 int s=0;
24 p=d.begin();
25 while(p!=d.end())
26 {
27 cout< < “ “< < *p;
28 s+=*p;
29 p++;
30 }
31 return s;
32 }
该函数范例的运行结果如图24-15所示。
图24-15 函数范例的运行结果
调用pop_back函数之后,deque容器的实际大小自动减1。
void pop_front ();
pop_front函数的功能是移除deque容器中的第一个元素。
该函数没有参数。
该函数没有返回值。
/********************************************
*范例编号:24_15
*范例说明:输出移除前后deque容器中的元素之和
*********************************************/
01 #include < iostream>
02 #include < deque>
03 using namespace std;
04 int Sum(deque< int> d);
05 void main ()
06 {
07 deque< int> d;
08 int s=0;
09 for(int i=1;i< 6;i++)
10 d.push_back(i*10);
11 cout< < “容器中的元素:”;
12 s=Sum(d);
13 cout< < “\n容器中元素之和:”< < s< < endl;
14 d.pop_front();
15 cout< < “容器中的元素:”;
16 s=Sum(d);
17 cout< < “\n移除第一个元素后,容器中元素之和:”< < s< < endl;
18 system(“pause”);
19 }
20 int Sum(deque< int> d)
21 {
22 deque< int>::iterator p;
23 int s=0;
24 p=d.begin();
25 while(p!=d.end())
26 {
27 cout< < “ “< < *p;
28 s+=*p;
29 p++;
30 }
31 return s;
32 }
该函数范例的运行结果如图24-16所示。
调用pop_front函数之后,deque容器的实际大小自动减1。
图24-16 函数范例的运行结果
iterator insert ( iterator position, const T&x );
void insert ( iterator position, size_type n, const T&x );
void insert ( iterator position, InputIterator first, InputIterator last );
insert函数的功能是在deque容器中的指定位置插入元素x。其中,各个函数的功能如下。
(1)第1个函数的功能是将x插入deque容器中第position个元素之前。
(2)第2个函数的功能是将n个x插入deque容器中第position个元素之前。
(3)第3个函数的功能是将输入对象中[first,last)之间的元素插入第position个元素之前。
(1)参数position:要插入当前deque中的元素的位置。
(2)参数x:要插入的元素。
(3)参数n:要插入的元素个数。
(4)参数first:迭代器,指向输入对象的开始元素。
(5)参数last:迭代器,指向输入对象末尾元素之后的位置。
第1个函数返回新插入元素的迭代器,其他函数没有返回值。
/********************************************
*范例编号:24_16
*范例说明:在deque容器中插入元素
*********************************************/
01 #include < iostream>
02 #include < deque>
03 using namespace std;
04 void DispDeque(deque< int> d);
05 void main ()
06 {
07 deque< int> d;
08 deque< int> d2(3,20);
09 deque< int>::iterator it;
10 int a[]={10,20,30,40,50},i;
11 for (i=1; i< =5; i++)
12 d.push_back(i);
13 cout< < “容器中的元素:”;
14 DispDeque(d);
15 it=d.begin();
16 for(i=0;i< sizeof(a)/sizeof(a[0]);i++)
17 it=d.insert (it,a[i]);
18 cout< < “容器中的元素:”;
19 DispDeque(d);
20 it=d.begin()+3;
21 d.insert (it,d2.begin(),d2.end());
22 d.insert(d.begin()+2,3,50);
23 cout< < “容器中的元素:”;
24 DispDeque(d);;
25 system(“pause”);
26 }
27 void DispDeque(deque< int> d)
28 {
29 deque< int>::iterator it;
30 for(it=d.begin();it!=d.end();it++)
31 cout< < “ “< < *it;
32 cout< < endl;
33 }
该函数范例的运行结果如图24-17所示。
图24-17 函数范例的运行结果
双端队列deque的insert函数可以在deque容器的最前面和最后面插入元素,也可以在deque容器的任意位置插入元素。
iterator erase ( iterator position );
iterator erase ( iterator first, iterator last );
erase函数的功能是删除deque容器中的指定元素。其中,各个函数的功能如下。
(1)第1个函数的功能是删除deque容器中的第position个元素。
(2)第2个函数的功能是删除deque容器中[first,last]之间的元素。
(1)参数position:迭代器,指向要删除的元素。
(2)参数first:迭代器,指向要删除[first,last]之间元素中的第一个元素。
(3)参数last:迭代器,指向要删除[first,last]之间元素中的最后一个元素。
函数返回deque容器中最后被删除元素的后一个位置。
/********************************************
*范例编号:24_17
*范例说明:输出删除前后deque容器中的元素,并求其元素之和
*********************************************/
01 #include < iostream>
02 #include < deque>
03 using namespace std;
04 void PrintContents(deque< int> d);
05 int GetSum(deque< int> d);
06 void main()
07 {
08 deque< int> d;
09 for(int i=0;i< 5;i++)
10 d.push_front(i+1);
11 PrintContents(d);
12 cout< < “容器中元素之和:”< < GetSum(d)< < endl;
13 //删除第2个元素
14 d.erase(d.begin()+1);
15 PrintContents(d);
16 cout< < “容器中元素之和:”< < GetSum(d)< < endl;
17 //删除最后2个元素
18 d.erase(d.end()-2,d.end());
19 PrintContents(d);
20 cout< < “容器中元素之和:”< < GetSum(d)< < endl;
21 system(“pause”);
22 }
23 void PrintContents(deque< int> d)
24 {
25 deque< int>::iterator p;
26 cout< < “容器中的元素:”< < endl;
27 for(p=d.begin();p< d.end();p++)
28 cout< < “ “< < *p;
29 cout< < endl;
30 }
31 int GetSum(deque< int> d)
32 {
33 deque< int>::iterator it;
34 int s=0;
35 for(it=d.begin();it!=d.end();it++)
36 s+=*it;
37 return s;
38 }
该函数范例的运行结果如图24-18所示。
图24-18 函数范例的运行结果
erase函数不仅可以删除deque容器中最前面的元素和最后面的元素,还可以删除其他位置的元素,但是在删除其他位置的元素时的执行效率不如list容器。
void clear ();
clear函数的功能是清除deque容器中的所有元素。
该函数没有参数。
该函数没有返回值。
/********************************************
*范例编号:24_18
*范例说明:输出清除deque容器后的元素
*********************************************/
01 #include < iostream>
02 #include < deque>
03 using namespace std;
04 void main()
05 {
06 deque< int> d;
07 deque< int>::iterator it;
08 int a[]={10,20,30,40,50},i=0;
09 d.resize(sizeof(a)/sizeof(a[0]));
10 for(it=d.begin();it< d.end();it++)
11 *it=a[i++];
12 cout < < “容器中的元素:”;
13 for (int i=0; i< d.size(); i++)
14 cout< < “ “ < < d[i];
15 d.clear();
16 if(d.empty())
17 cout< < “\n容器为空”< < endl;
18 cout< < “容器大小:”< < d.size()< < endl;
19 d.insert(d.begin(),3,6);
20 d.push_back (16);
21 cout < < “容器中的元素:”;
22 for (i=0; i< d.size(); i++)
23 cout< < “ “ < < d[i];
24 cout< < endl;
25 system(“pause”);
26 }
该函数范例的运行结果如图24-19所示。
图24-19 函数范例的运行结果
调用clear函数后,当前deque容器中的元素个数为0。
void swap ( deque&dqe );
swap函数的功能是将当前deque容器中的内容与dqe容器中的内容互换。
参数dqe:deque类型的对象,用来与当前deque容器中的内容进行交换。
该函数没有返回值。
/********************************************
*范例编号:24_19
*范例说明:将两个deque容器中的内容交换
*********************************************/
01 #include < iostream>
02 #include < deque>
03 using namespace std;
04 struct student
05 {
06 int no;
07 char name[20];
08 char sex;
09 double score;
10 }stu1[]={{101,”王欢”,’F’,95},{103,”周亚夫”,’M’,99},{108,”卫子夫”,’F’,92}},
11 stu2[]={{206,”张良”,’M’,100},{203,”郝昭”,’M’,98},{207,”秦可卿”,’F’,89},{209,”颜良”,’M’,
12 78}};
13 void DispDeque(deque< struct student> s);
14 void main ()
15 {
16 deque< struct student> student1;
17 deque< struct student> student2;
18 int i;
19 for(i=0;i< sizeof(stu1)/sizeof(stu1[0]);i++)
20 student1.push_back(stu1[i]);
21 cout< < “交换前,容器student1:”< < endl;
22 DispDeque(student1);
23 for(i=0;i< sizeof(stu2)/sizeof(stu2[0]);i++)
24 student2.push_back(stu2[i]);
25 cout< < “容器student2:”< < endl;
26 DispDeque(student2);
27 student1.swap(student2);
28 cout< < “\n交换后,容器student1:”< < endl;
29 DispDeque(student1);
30 cout< < “容器student2:”< < endl;
31 DispDeque(student2);
32 system(“pause”);
33 }
34 void DispDeque(deque< struct student> s)
35 {
36 int i;
37 for(i=0; i< s.size(); i++)
38 cout< < “ “< < s[i].no< < “ “< < s[i].name< < “ “< < s[i].sex< < “ “< < s[i].score< < endl;
39 }
该函数范例的运行结果如图24-20所示。
图24-20 函数范例的运行结果
(1)调用swap函数后,两个deque容器中的内容互相交换。两个deque容器的大小不一定相同。
(2)使用swap函数交换的两个容器中的数据类型必须一致,否则交换会出现语法错误。
list类是一种以双向链表方式实现的一种顺序容器。在list容器中,存放元素的存储单元可以是连续的,也可以是不连续的。list容器的特点是可以对list中的每一个元素进行插入、删除、查找操作。与vector容器和deque容器相比,在list容器中插入、删除、移动元素更加方便,效率更高。由于list中的元素是通过指针链接在一起构成的链表,因此不能通过下标的方式存取元素。在list中访问元素的效率比在vector容器中访问的效率低,这是因为元素之间的指针占用了额外的内存空间。
在C++的标准模板库中,list容器有以下两个模板参数。
template< class T, class Allocator = allocator< T> >
class list;
其中,T是元素的类型;Allocator用来提供类型化的内存分配及撤销。
如果要使用list类(容器)中的函数,需要使用以下文件包含命令。
#include< list>
using namespace std;
list容器中的函数可以分为五大类,分别是构造类函数、迭代器函数、容量类函数、存取类函数、操作类函数。
list容器的构造类函数包括构造函数和析构函数。
list ( const Allocator&=Allocator() );
list ( size_type n, const T&value=T(), const Allocator&=Allocator() );
list ( InputIterator first, InputIterator last, const Allocator&=Allocator() );
list ( const list< T,Allocator>&x );
~list ();
list构造函数的功能是创建list容器并初始化容器中的元素。其中,各个函数的功能如下。
(1)第1个函数是list默认的构造函数,它的功能是构造一个空的list容器,该容器的内容为空,即容器大小为0。
(2)第2个函数是list的重复序列构造器,它的功能是将n个值为value的元素存放在当前的list容器中。
(3)第3个函数是list的迭代构造函数,它的功能是将输入对象中迭代器first和last之间的元素存放到容器中。
(4)第4个函数是list的拷贝构造函数,它的功能是用另一个双向链表x初始化list容器。
list析构函数的功能是撤销list容器的对象,并释放元素所占的存储区。
(1)参数n:元素value的个数。
(2)参数value:容器对象的值。
(3)参数first:迭代器,输入对象的元素的开始位置。
(4)参数last:迭代器,输入对象的元素的结束位置。
(5)参数x:list对象,用来填充当前list对象的内容。
(6)参数Allocator:C++模板类,用来为新对象分配内存和撤销对象的内存。
构造函数和析构函数都没有返回值。
/********************************************
*范例编号:25_01
*范例说明:利用list构造函数创建双向链表
*********************************************/
01 #include < iostream>
02 #include < list>
03 using namespace std;
04 void PrintList(list< int> L,char *str);
05 void main ()
06 {
07 list< int> L1; //空链表
08 L1.push_back(100);
09 L1.push_back(200);
10 list< int> L2(L1.begin(),L1.end());//用L1的迭代器构造链表L2
11 int a[]={22,67,39,11,91};
12 list< int> L3(a, a + sizeof(a) / sizeof(int) );//利用数组a构造链表L3
13 list< int> L4(L3); //用L3构造链表L4
14 L3.pop_front();
15 list< int> L5(5,10); //链表L5中包含5个值为10的元素
16 PrintList(L1,”L1”);
17 PrintList(L2,”L2”);
18 PrintList(L3,”L3”);
19 PrintList(L4,”L4”);
20 PrintList(L5,”L5”);
21 system(“pause”);
22 }
23 void PrintList(list< int> L,char *str)
24 {
25 list< int>::iterator it;
26 cout< < “链表”< < str< < “的元素: “;
27 for (it=L.begin(); it != L.end(); it++)
28 cout < < *it < < “ “;
29 cout< < endl;
30 }
该函数范例的运行结果如图25-1所示。
图25-1 函数范例的运行结果
(1)在使用迭代器first和last构造list对象时,当前list容器中包含first指向的元素,而不包含last指向的元素。另外,构造list对象时,不能对迭代器first和last进行加减运算。例如,不能以如下方式构造list对象。
//错误!试图由L2的第2个元素开始构造链表L3
list< int> L3(L2.begin()+1,L2.end());
(2)析构函数~list()在程序结束时由系统自动调用。
list< T,Allocator>& operator=( const list< T,Allocator>&x );
operator=函数的功能是将list对象x中的内容拷贝到当前的list对象中。
参数x:一个list对象,用来初始化当前的list对象。
函数返回当前的list对象。
/********************************************
*范例编号:25_02
*范例说明:利用一个list对象构造另一个list对象
*********************************************/
01 #include < iostream>
02 #include < list>
03 using namespace std;
04 void DispList(list< int> L);
05 void main ()
06 {
07 list< int> L1 (8,10);
08 list< int> L2 (5,20);
09 cout< < “复制前:”< < endl;
10 cout< < “容器L1的大小:”< < L1.size()< < “,容器L1中的元素:”< < endl;
11 DispList(L1);
12 cout< < “容器L2的大小:”< < L2.size()< < “,容器L2中的元素:”< < endl;
13 DispList(L2);
14 L2=L1;
15 cout< < “将L1赋值给L2后:”< < endl;
16 cout< < “容器L1的大小:”< < L1.size()< < “,容器L1中的元素:”< < endl;
17 DispList(L1);
18 cout< < “容器L2的大小:”< < L2.size()< < “,容器L2中的元素:”< < endl;
19 DispList(L2);
20 system(“pause”);
21 }
22 void DispList(list< int> L)
23 {
24 list< int>::iterator it;
25 for(it=L.begin();it!=L.end();it++)
26 cout< < “ “< < *it;
27 cout< < endl;
28 }
该函数范例的运行结果如图25-2所示。
图25-2 函数范例的运行结果
当调用operator=函数后,当前list容器中的内容被x中的内容替换掉,并且两个list容器的大小相等。
list容器也包括begin、end、rbegin和rend 4个迭代器,利用这些迭代器可以很方便地存取容器中的元素。
iterator begin ();
const_iterator begin () const;
iterator end ();
const_iterator end () const;
(1)begin函数返回list容器中第一个元素的位置。
(2)end函数返回list容器中最后一个元素的后一个位置。
该函数没有参数。
(1)begin函数返回list容器中第一个元素的位置。
(2)end函数返回list容器中最后一个元素的后一个位置。
/********************************************
*范例编号:25_03
*范例说明:利用迭代器依次输出list中的元素
*********************************************/
01 #include < iostream>
02 #include < list>
03 using namespace std;
04 void main ()
05 {
06 char a[]=”Hello World!”;
07 int i,len=strlen(a);
08 list< char> L;
09 list< char>::iterator it;
10 for(i=0;i< len;i++)
11 L.push_back(a[i]);
12 cout< < “容器中的元素:”;
13 for (it=L.begin();it!=L.end();it++)
14 cout< < *it;
15 cout< < endl;
16 system(“pause”);
17 }
该函数范例的运行结果如图25-3所示。
图25-3 函数范例的运行结果
(1)迭代器begin指向list容器中的第一个元素,迭代器end指向list容器中最后一个元素的后一个位置,并不是指向最后一个元素。
(2)与vector容器一样,list容器也可以将数组地址(指针)作为参数。
(3)在使用迭代器存取list中的元素时,循环的结束条件不可以写做以下形式:
for (it=L.begin();it< L.end();it++)
而应该写做以下形式:
for (it=L.begin();it!=L.end();it++)
这是因为list是一个链表,地址并不一定是连续的,因此不能用大于或小于来判断循环是否结束。
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
(1)rbegin函数返回与list中最后一个元素相关的反向迭代器。
(2)rend函数返回与list中第一个元素的前一个位置相关的反向迭代器。
该函数没有参数。
(1)rbegin函数返回list的反向的开始位置,即最后一个元素所在的位置。
(2)rend函数返回list的反向的结束位置(迭代器指向的是第一个元素前面一个元素的位置)。
/********************************************
*范例编号:25_04
*范例说明:利用反向迭代器逆向输出list中的元素
*********************************************/
01 #include < iostream>
02 #include < list>
03 using namespace std;
04 int IsPalindRecomic(list< char> L);
05 void DispList(list< char> L);
06 void main ()
07 {
08 list< char> L1,L2;
09 char str1[]=”xyzabcbazyx”;
10 char str2[]=”xyzabcbaxyz”;
11 int i,flag;
12 list< char>::iterator it;
13 list< char>::reverse_iterator rit;
14 for (i=0; i< strlen(str1); i++)
15 L1.push_back(str1[i]);
16 for (i=0; i< strlen(str1); i++)
17 L2.push_back(str2[i]);
18 DispList(L1);
19 flag=IsPalindRecomic(L1);
20 if(flag==true)
21 cout< < “是回文”< < endl;
22 else
23 cout< < “不是回文”< < endl;
24 DispList(L2);
25 flag=IsPalindRecomic(L2);
26 if(flag==true)
27 cout< < “是回文”< < endl;
28 else
29 cout< < “不是回文”< < endl;
30 system(“pause”);
31 }
32 int IsPalindRecomic(list< char> L)
33 {
34 list< char>::iterator it;
35 list< char>::reverse_iterator rit;
36 int flag=true;
37 for(it=L.begin(),rit=L.rbegin();it!=L.end();it++,rit++)
38 if(*it!=*rit)
39 flag=false;
40 return flag;
41 }
42 void DispList(list< char> L)
43 {
44 list< char>::iterator it;
45 list< char>::reverse_iterator rit;
46 cout< < “容器中的元素(正向):”;
47 for(it=L.begin();it!=L.end();it++)
48 cout< < *it;
49 cout< < endl;
50 cout< < “容器中的元素(反向):”;
51 for (rit=L.rbegin();rit!=L.rend();rit++)
52 cout< < *rit;
53 cout< < endl;
54 }
该函数范例的运行结果如图25-4所示。
图25-4 函数范例的运行结果
利用rbegin函数与rend函数输出list容器中的元素时,需要使用反向迭代器控制元素的输出,即将迭代器定义为如下形式,其中,rit被定义为reverse_iterator。
list< int>::reverse_iterator rit;
在list容器中,容量类函数主要指的是与容器的大小有关的函数,这些函数主要包括size函数、max_size函数、empty函数、resize函数。
size_type size() const;
size_type max_size () const;
(1)size函数返回list容器中元素的个数。
(2)max_size函数返回list容器能容纳的最大元素个数。
该函数没有参数。
(1)size函数返回list容器中实际的元素个数。
(2)max_size函数返回list容器中所能容纳的最大元素个数。
/********************************************
*范例编号:25_05
*范例说明:输出list容器中的实际元素个数和所能容纳的最大元素个数
*********************************************/
01 #include < iostream>
02 #include < list>
03 using namespace std;
04 void main()
05 {
06 list< int> L(5,10);
07 int a[]={60,70,80,90,100},i;
08 list< int>::iterator it;
09 cout< < “容器L的实际大小:”< < L.size()< < “,”;
10 cout< < “能容纳的最大元素个数:”< < L.max_size()< < endl;
11 for (i=1;i< =5;i++)
12 L.push_back(i);
13 cout< < “容器L的实际大小:”< < L.size()< < “,”;
14 cout< < “能容纳的最大元素个数:”< < L.max_size()< < endl;
15 for(i=0;i< sizeof(a)/sizeof(a[0]);i++)
16 L.push_back(a[i]);
17 cout< < “容器L的实际大小:”< < L.size()< < “,”;
18 cout< < “能容纳的最大元素个数:”< < L.max_size()< < endl;
19 L.pop_back();
20 L.pop_front();
21 cout < < “容器L的实际大小:”< < L.size()< < “,”;
22 cout< < “能容纳的最大元素个数:”< < L.max_size()< < endl;
23 cout< < “容器中的元素:”< < endl;
24 for(it=L.begin();it!=L.end();it++)
25 cout< < “ “< < *it;
26 cout< < endl;
27 system(“pause”);
28 }
该函数范例的运行结果如图25-5所示。
图25-5 函数范例的运行结果
与vector容器一样,list容器中的size函数返回实际元素个数,max_size函数返回容器所能容纳的最大元素个数。
bool empty () const;
empty函数的功能是判断list容器是否为空,即list容器中的元素个数是否为0。
该函数没有参数。
如果list容器中的元素个数为0,则返回true;否则,返回false。
/********************************************
*范例编号:25_06
*范例说明:当list容器不为空时,输出list中的元素
*********************************************/
01 #include < iostream>
02 #include < list>
03 using namespace std;
04 void DispList(list< int> L);
05 void main ()
06 {
07 list< int> L;
08 list< int>::iterator it;
09 int a[]={55,22,33,12,89,56,85,21};
10 int i;
11 for (i=0;i< sizeof(a)/sizeof(a[0]);i++)
12 L.push_back(a[i]);
13 cout< < “容器中的元素:”< < endl;
14 DispList(L);
15 for(;!L.empty();L.pop_front())
16 DispList(L);
17 system(“pause”);
18 }
19 void DispList(list< int> L)
20 {
21 list< int>::iterator it;
22 for(it=L.begin();it!=L.end();it++)
23 cout< < “ “< < *it;
24 cout< < endl;
25 }
该函数范例的运行结果如图25-6所示。
图25-6 函数范例的运行结果
与vector容器中的empty函数一样,list容器中的empty函数只是判断容器是否为空,并不会修改容器中的元素。
void resize ( size_type sz, T c=T() );
resize函数的功能是调整list容器的大小使其包含sz个元素。
(1)参数sz:list容器中元素的个数。
(2)参数c:如果sz大于当前容器中元素的个数,则将c添加到list容器中。
该函数没有返回值。
/********************************************
*范例编号:25_07
*范例说明:输出调整后list容器中的元素
*********************************************/
01 #include < iostream>
02 #include < list>
03 using namespace std;
04 void DispList(list< char> L);
05 void main ()
06 {
07 list< char> L(6,’G’);
08 list< char>::iterator it;
09 int i;
10 DispList(L);
11 L.resize(3);//将容器中的大小缩小到3
12 DispList(L);
13 for(i=1;i< =5;i++) //将’b’’c’’d’’e’’f’插入容器L
14 L.push_back(i+’a’);
15 DispList(L);
16 L.resize(10,’Q’);//将容器的大小扩展到10个元素
17 DispList(L);
18 L.resize(12,’Z’);//将容器的大小扩展到12个元素,扩展的元素是’Z’
19 cout< < “容器中的元素个数:”< < L.size()< < endl;
20 DispList(L);
21 system(“pause”);
22 }
23 void DispList(list< char> L)
24 {
25 list< char>::iterator it;
26 cout < < “容器中的元素:”< < endl;
27 for(it=L.begin();it!=L.end();it++)
28 cout< < “ “< < *it;
29 cout< < endl;
30 }
该函数范例的运行结果如图25-7所示。
图25-7 函数范例的运行结果
(1)如果sz小于原来list容器的大小,则前面的sz个元素被保留,后面的元素被抛弃;如果sz大于原来list容器的大小,则容器的大小扩展到sz个元素,并将元素c追加在list末尾;如果省略了参数c,则将0追加在list末尾,若数据类型为char,则输出时不显示。
(2)这里所说的容器大小指的是list容器中的实际元素个数,而不是list容器的存储空间大小。
list存取类函数主要包括front函数和back函数。因为list容器实质上是一种双向链表,所以不存在operator[]函数和at函数。
reference front ();
const_reference front () const;
front函数的功能是得到list容器中的第一个元素。
该函数没有参数。
函数返回list容器中的第一个元素。
/********************************************
*范例编号:25_08
*范例说明:输出list容器中的第一个元素
*********************************************/
01 #include < iostream>
02 #include < list>
03 using namespace std;
04 void main ()
05 {
06 list< int> L;
07 for(int i=0;i< 5;i++)
08 L.push_back(i+50);
09 cout< < “容器中有”< < L.size()< < “个元素”< < endl;
10 cout< < “容器中的第一个元素:”< < L.front()< < endl;
11 system(“pause”);
12 }
该函数范例的运行结果如图25-8所示。
图25-8 函数范例的运行结果
begin函数返回list容器中第一个元素的迭代器,而front函数则直接返回list容器中的第一个元素。
reference back ();
const_reference back () const;
back函数的功能是得到list容器中的最后一个元素。
该函数没有参数。
函数返回list容器中的最后一个元素。
/********************************************
*范例编号:25_09
*范例说明:输出list容器中的最后一个元素
*********************************************/
01 #include < iostream>
02 #include < list>
03 using namespace std;
04 void main ()
05 {
06 list< int> L;
07 list< int>::iterator it;
08 for(int i=0;i< 5;i++)
09 L.push_back(i+50);
10 cout< < “容器中的元素:”;
11 for(it=L.begin();it!=L.end();it++)
12 cout< < “ “< < *it;
13 cout< < endl;
14 cout< < “容器中的第一个元素:”< < L.front()< < endl;
15 cout< < “容器中的最后一个元素:”< < L.back()< < endl;
16 L.push_back(100);
17 cout< < “容器中的最后一个元素:”< < L.back()< < endl;
18 system(“pause”);
19 }
该函数范例的运行结果如图25-9所示。
图25-9 函数范例的运行结果
end函数返回list容器中最后一个元素的迭代器,而back函数则直接返回容器中的最后一个元素。
list操作类函数主要包括assign函数、push_back函数、push_front函数、pop_back函数、pop_front函数、insert函数、erase函数、clear函数、swap函数等。
void assign ( InputIterator first, InputIterator last );
void assign ( size_type n, const T&u );
assign函数的功能是将元素赋值给当前的list容器,之前存放在list容器中的内容将被覆盖掉。其中,各个函数的功能如下。
(1)第1个函数是利用迭代器将first和last之间的元素赋值给当前的list容器。
(2)第2个函数是将n个值为u的元素赋给当前的list容器。
(1)参数first:输入对象的迭代器,指向输入对象的第一个元素。
(2)参数last:输入对象的迭代器,指向输入对象最后一个元素之后的位置。
(3)参数n:元素u的个数。
(4)参数u:list容器的新元素值。
该函数没有返回值。
/********************************************
*范例编号:25_10
*范例说明:利用assign函数为list容器中的元素赋值
*********************************************/
01 #include < iostream>
02 #include < list>
03 using namespace std;
04 void main ()
05 {
06 list< int> L1(5,10);
07 list< int> L2;
08 list< int>::iterator it;
09 L1.assign(3,100);
10 cout< < “容器L1的大小: “< < L1.size()< < endl;
11 cout< < “容器L1中的元素: “< < endl;
12 for(it=L1.begin();it!=L1.end();it++)
13 cout< < “ “< < *it;
14 cout< < endl;
15 L2.assign(L1.begin(),L1.end());
16 cout< < “容器L2的大小: “< < L2.size()< < endl;
17 cout< < “容器L2中的元素: “< < endl;
18 for(it=L2.begin();it!=L2.end();it++)
19 cout< < “ “< < *it;
20 cout< < endl;
21 system(“pause”);
22 }
该函数范例的运行结果如图25-10所示。
图25-10 函数范例的运行结果
在利用迭代器first和last为list容器赋值时,赋值的元素范围是[first,last),即包含first指向的元素,而不包含last指向的元素。
void push_back ( const T&x );
push_back函数的功能是在list容器末尾添加元素x。
参数x:要追加到list末尾的元素。
该函数没有返回值。
/********************************************
*范例编号:25_11
*范例说明:在list容器末尾追加元素
*********************************************/
01 #include < iostream>
02 #include < list>
03 using namespace std;
04 void main()
05 {
06 list< char> L(5,’S’);
07 list< char>::iterator it;
08 for(int i=0;i< 5;i++)
09 L.push_back(i+’A’);
10 cout< < “容器中的元素个数是:”< < L.size()< < endl;
11 cout< < “容器中的元素:”< < endl;
12 for(it=L.begin();it!=L.end();it++)
13 cout< < “ “< < *it;
14 cout< < endl;
15 system(“pause”);
16 }
该函数范例的运行结果如图25-11所示。
图25-11 函数范例的运行结果
每调用一次push_back函数,list容器的实际元素个数就会增1,并将新元素追加在容器的最后。
void push_front ( const T&x );
push_front函数的功能是将元素x插入list容器中的第一个元素前。
参数x:要插入list容器最前面的元素。
该函数没有返回值。
/********************************************
*范例编号:25_12
*范例说明:在list容器最前面插入新元素
*********************************************/
01 #include < iostream>
02 #include < list>
03 using namespace std;
04 void main()
05 {
06 list< int> L;
07 list< int>::iterator it;
08 for(int i=1;i< =5;i++)
09 L.push_front(i);
10 L.push_front (200);
11 L.push_front (300);
12 cout< < “容器中的元素:”;
13 for (it=L.begin(); it!=L.end(); it++)
14 cout< < “ “< < *it;
15 cout< < endl;
16 for(int i=1;i< =5;i++)
17 L.push_back(i*20);
18 cout< < “容器中的元素:”;
19 for (it=L.begin(); it!=L.end(); it++)
20 cout< < “ “< < *it;
21 cout< < endl;
22 system(“pause”);
23 }
该函数范例的运行结果如图25-12所示。
图25-12 函数范例的运行结果
与push_back函数一样,调用push_front函数也会使list容器的实际大小自动增1,并将元素x插入list的第一个位置。区别在于push_back函数是在list容器的末尾添加元素,而push_front函数则是在list容器的开始位置添加元素。
void pop_back ();
pop_back函数的功能是移除list容器中的最后一个元素。
该函数没有参数。
该函数没有返回值。
/********************************************
*范例编号:25_13
*范例说明:输出list容器中的元素并求各元素的阶乘
*********************************************/
01 #include < iostream>
02 #include < list>
03 using namespace std;
04 int GetFact(list< int> d);
05 void main ()
06 {
07 list< int> L;
08 long f=1;
09 for(int i=1;i< =5;i++)
10 L.push_back(i);
11 f=GetFact(L);
12 cout< < “\n容器中元素的阶乘:”< < f< < endl;
13 L.pop_back();
14 f=GetFact(L);
15 cout< < “\n容器中元素的阶乘:”< < f< < endl;
16 system(“pause”);
17 }
18 int GetFact(list< int> L)
19 {
20 list< int>::iterator p;
21 long f=1;
22 cout< < “容器中的元素:”;
23 p=L.begin();
24 while(p!=L.end())
25 {
26 cout< < “ “< < *p;
27 f*=*p;
28 p++;
29 }
30 return f;
31 }
该函数范例的运行结果如图25-13所示。
图25-13 函数范例的运行结果
调用pop_back函数之后,list容器的实际大小自动减1。
void pop_front ();
pop_front函数的功能是移除list容器中的第一个元素。
该函数没有参数。
该函数没有返回值。
/********************************************
*范例编号:25_14
*范例说明:输出list容器中元素的平均值
*********************************************/
01 #include < iostream>
02 #include < list>
03 using namespace std;
04 double GetAverage(list< int> d);
05 void main ()
06 {
07 list< int> L;
08 double s=0;
09 for(int i=1;i< 6;i++)
10 L.push_back(i*10);
11 s=GetAverage(L);
12 cout< < “\n容器中元素的平均值:”< < s< < endl;
13 L.pop_front();
14 L.pop_front();
15 s=GetAverage(L);
16 cout< < “\n容器中元素的平均值:”< < s< < endl;
17 system(“pause”);
18 }
19 double GetAverage(list< int> L)
20 {
21 list< int>::iterator it;
22 double s=0;
23 cout < < “容器中的元素:”;
24 it=L.begin();
25 while(it!=L.end())
26 {
27 cout< < “ “< < *it;
28 s+=*it;
29 it++;
30 }
31 return s/L.size();
32 }
该函数范例的运行结果如图25-14所示。
图25-14 函数范例的运行结果
调用pop_front函数之后,list容器的实际大小自动减1。
iterator insert ( iterator position, const T&x );
void insert ( iterator position, size_type n, const T&x );
void insert ( iterator position, InputIterator first, InputIterator last );
insert函数的功能是在list容器中的指定位置插入元素x。其中,各个函数的功能如下。
(1)第1个函数的功能是在list容器的第position个元素之前插入元素x。
(2)第2个函数的功能是在list容器的第position个元素之前插入n个值为x的元素。
(3)第3个函数的功能是在list容器中的第position个元素之前插入输入对象 [first,last)之间的元素。
(1)参数position:要插入当前list中的元素的位置。
(2)参数x:要插入的元素。
(3)参数n:要插入的元素个数。
(4)参数first:迭代器,指向输入对象的开始元素。
(5)参数last:迭代器,指向输入对象末尾元素的后一个位置。
第1个函数返回新插入元素的迭代器,其他函数没有返回值。
/********************************************
*范例编号:25_15
*范例说明:在list容器中插入元素
*********************************************/
01 #include < iostream>
02 #include < list>
03 using namespace std;
04 void main ()
05 {
06 list< int> L;
07 list< int> L2(3,50);
08 list< int>::iterator it;
09 for (int i=1; i< =5; i++)
10 L.push_back(i);
11 cout< < “容器中的元素:”;
12 for(it = L.begin();it!=L.end();it++)
13 cout< < “ “< < *it;
14 cout< < endl;
15 it=L.insert (L.begin(),10); //返回插入元素的位置
16 it++;//将迭代器向后移动一个位置
17 L.insert (it,L2.begin(),L2.end());
18 cout< < “容器中的元素:”;
19 for (it=L.begin(); it!=L.end(); it++)
20 cout< < “ “< < *it;
21 cout< < endl;
22 system(“pause”);
23 }
该函数范例的运行结果如图25-15所示。
图25-15 函数范例的运行结果
list容器是一种双向链表,可以在任意位置插入和删除元素。在顺序容器中,list的插入和删除操作的效率是最高的。
iterator erase ( iterator position );
iterator erase ( iterator first, iterator last );
erase函数的功能是删除list容器中的指定元素。其中,各个函数的功能如下。
(1)第1个函数的功能是删除list容器中的第position个元素。
(2)第2个函数的功能是删除list容器中[first,last]之间的元素。
(1)参数position:迭代器,指向要删除的元素。
(2)参数first:迭代器,指向要删除[first,last]之间元素中的第一个元素。
(3)参数last:迭代器,指向要删除[first,last]之间元素中的最后一个元素。
函数返回list容器中最后被删除元素的后一个位置。
/********************************************
*范例编号:25_16
*范例说明:输出删除后list容器中的元素
*********************************************/
01 #include < iostream>
02 #include < list>
03 using namespace std;
04 void PrintContents(list< int> L);
05 void main()
06 {
07 list< int> L;
08 list< int>::iterator it;
09 for(int i=0;i< 5;i++)
10 L.push_back(i+1);
11 PrintContents(L);
12 //删除第2个元素
13 it=L.begin();
14 it++;
15 L.erase(it);
16 PrintContents(L);
17 //删除最后2个元素
18 it=L.end();
19 it--;
20 it--;
21 L.erase(it,L.end());
22 PrintContents(L);
23 system(“pause”);
24 }
25 void PrintContents(list< int> L)
26 {
27 list< int>::iterator it;
28 cout< < “容器中的元素:”< < endl;
29 for(it=L.begin();it!=L.end();it++)
30 cout< < “ “< < *it;
31 cout< < endl;
32 }
该函数范例的运行结果如图25-16所示。
图25-16 函数范例的运行结果
在利用迭代器作为参数的erase函数移除中间的某个元素时,不能使用如下的方式。
L.erase(L.begin()+1);//错误!试图移除L中的第2个元素
正确的方式如下。
it=L.begin();
it++;
L.erase(it);
void clear ();
clear函数的功能是清除list容器中的所有元素。
该函数没有参数。
该函数没有返回值。
/********************************************
*范例编号:25_17
*范例说明:输出清除list容器后的元素
*********************************************/
01 #include < iostream>
02 #include < list>
03 using namespace std;
04 void main()
05 {
06 list< int> L;
07 list< int>::iterator it;
08 for(int i=5;i< =50;i+=10)
09 L.push_back(i);
10 cout < < “容器中的元素:”;
11 for (it=L.begin(); it!=L.end(); it++)
12 cout< < “ “< < *it;
13 cout < < “\n清空容器中的元素:”;
14 L.clear();//清除L中的元素
15 if(L.empty())
16 cout< < “\n容器为空!”< < endl;
17 else
18 cout< < “\n容器不为空!”< < endl;
19 L.push_back (501);
20 L.push_back (502);
21 cout< < “容器中的元素:”;
22 for (it=L.begin();it!=L.end(); it++)
23 cout< < “ “< < *it;
24 cout< < endl;
25 system(“pause”);
26 }
该函数范例的运行结果如图25-17所示。
图25-17 函数范例的运行结果
调用clear函数后,当前list容器的实际大小为0。
void swap ( list< T,Allocator>&lst );
swap函数的功能是将当前list容器与lst容器中的元素互换。
参数lst:list类型的对象,用来与当前list容器中的内容进行交换。
该函数没有返回值。
/********************************************
*范例编号:25_18
*范例说明:交换两个list容器中的内容
*********************************************/
01 #include < iostream>
02 #include < list>
03 #include < string>
04 using namespace std;
05 list< char> InitList(list< char> L,char str[], int len);
06 void main ()
07 {
08 list< char> L1;
09 list< char> L2;
10 list< char>::iterator it;
11 char str[80];
12 cout< < “请输入要存入的字符串(< 80):”< < endl;
13 gets(str);
14 L1=InitList(L1,str,strlen(str));
15 cout< < “容器L1:”;
16 for (it=L1.begin(); it!=L1.end(); it++)
17 cout< < “ “< < *it;
18 cout< < “\n请输入要存入的字符串(< 80):”< < endl;
19 gets(str);
20 L2=InitList(L2,str,strlen(str));
21 cout< < “容器L2:”;
22 for (it=L2.begin(); it!=L2.end(); it++)
23 cout < < “ “ < < *it;
24 cout< < endl;
25 L1.swap(L2);
26 cout< < “交换后:”< < endl;
27 cout< < “容器L1:”;
28 for (it=L1.begin(); it!=L1.end(); it++)
29 cout < < “ “ < < *it;
30 cout< < “\n容器L2:”;
31 for (it=L2.begin(); it!=L2.end(); it++)
32 cout< < “ “< < *it;
33 cout< < endl;
34 system(“pause”);
35 }
36 list< char> InitList(list< char> L,char str[],int len)
37 {
38 list< char>::iterator it;
39 for(int i=0;i< len;i++)
40 L.push_back(str[i]);
41 return L;
42 }
该函数范例的运行结果如图25-18所示。
图25-18 函数范例的运行结果
要交换的两个list容器的大小不一定相同。
void splice ( iterator position, list< T,Allocator>&x );
void splice ( iterator position, list< T,Allocator>&x, iterator i );
void splice ( iterator position, list< T,Allocator>&x, iterator first, iterator last );
splice函数的功能是将x中的元素移动到当前list容器的第position个位置上,并将x中的元素删除。其中,各个函数的功能如下。
(1)第1个函数的功能是将x中的元素移动到list容器的第position个位置上,并将x中的元素删除。
(2)第2个函数的功能是将x中迭代器i指向的元素移动到当前list容器的第position个位置上。
(3)第3个函数的功能是将x中[first,last]之间的元素移动到当前list容器的第position个位置上。
(1)参数position:要插入当前list容器中的元素的位置。
(2)参数x:一个list容器,也可以是当前list容器。
(3)参数i:x容器的迭代器,表示当前位置上的元素将被移动。
(4)参数first:迭代器,指向从x容器中移动元素的开始位置。
(5)参数last:迭代器,指向从x容器中移动元素的结束位置。
该函数没有返回值。
/********************************************
*范例编号:25_19
*范例说明:将一个list容器中的元素移动到另一个list容器
*********************************************/
01 #include < iostream>
02 #include < list>
03 using namespace std;
04 void main ()
05 {
06 list< int> L1, L2;
07 list< int>::iterator it,it2;
08 int i;
09 for (i=1; i< =50; i+=10)
10 L1.push_back(i);
11 for (i=1; i< =30; i*=5)
12 L2.push_back(i*10);
13 cout< < “容器L1:”;
14 for(it=L1.begin();it!=L1.end();it++)
15 cout< < “ “< < *it;
16 cout< < endl;
17 cout< < “容器L2:”;
18 for(it=L2.begin();it!=L2.end();it++)
19 cout< < “ “< < *it;
20 cout< < endl;
21 it = L1.end();
22 it--; //指向倒数第2个元素
23 it--; //指向倒数第3个元素
24 L1.splice (it, L2); //L1:1 11 21 10 50 250 41
25 cout< < *it< < endl;
26 it2=it;
27 cout< < “容器L1:”;
28 for (it=L1.begin(); it!=L1.end(); it++)
29 cout< < “ “< < *it;
30 L٢.splice (L٢.begin(),L١, it٢); //把it2指向的元素移动到L2
31 cout< < “\n容器L2:”;
32 for (it=L2.begin(); it!=L2.end(); it++)
33 cout < < “ “ < < *it;
34 cout< < endl;
35 system(“pause”);
36 }
该函数范例的运行结果如图25-19所示。
图25-19 函数范例的运行结果
将x容器中的元素移动到当前的list容器后,x容器中的该元素被删除。参数x也可以是当前的容器对象。
void remove ( const T&value );
remove函数的功能是将当前list容器中值为value的元素移除。
参数value:要移除的元素。
该函数没有返回值。
/********************************************
*范例编号:25_20
*范例说明:输出移除list容器中指定元素后的内容
*********************************************/
01 #include < iostream>
02 #include < list>
03 using namespace std;
04 void main ()
05 {
06 list< int>::iterator it;
07 list< int> L;
08 int i;
09 for(i=1;i< 8;i++)
10 L.push_back(i);
11 cout< < “容器中的元素:”;
12 for(it=L.begin();it!=L.end();it++)
13 cout< < “ “< < *it;
14 cout< < endl;
15 L.remove(٥);//移除值为5的元素
16 L.remove(١);//移除值为1的元素
17 cout < < “容器中的元素:”;
18 for (it=L.begin(); it!=L.end(); it++)
19 cout< < “ “< < *it;
20 cout< < endl;
21 system(“pause”);
22 }
该函数范例的运行结果如图25-20所示。
图25-20 函数范例的运行结果
erase函数移除list中指定位置的元素,remove函数移除list中指定值的元素。
void remove_if ( binder2nd< not_equal_to< T> > pr );
remove_if函数的功能是将值不等于pr(*P)的元素从list容器中删除。其中,P表示迭代器。
参数pr:binder2nd类型的对象,用来表示不等于迭代器指向的元素。
该函数没有返回值。
/********************************************
*范例编号:25_21
*范例说明:删除list中不等于迭代器指向的元素
*********************************************/
01 #include < iostream>
02 #include < list>
03 #include < string>
04 using namespace std;
05 typedef list< string, allocator< string> > LISTSTR; //定义类型LISTSTR
06 void main()
07 {
08 LISTSTR program;
09 LISTSTR::iterator it;
10 //初始化test
11 program.push_back(“Python”);
12 program.push_back(“C++”);
13 program.push_back(“Java”);
14 program.push_back(“Visual Basic”);
15 //输出program中的元素
16 cout< < “容器中的元素:”;
17 for (it = program.begin(); it != program.end(); it++)
18 cout < < *it < < “; “;
19 cout < < endl;
20 program.remove(“C++”);//移除C++
21 //输出移除后的元素
22 cout< < “容器中的元素:”;
23 for (it = program.begin(); it != program.end(); it++)
24 cout< < *it< < “; “;
25 cout< < endl;
26 //移除不等于Visual Basic的元素
27 program.remove_if(binder2nd< not_equal_to< string> >
28 (not_equal_to< string>(), “Visual Basic”));
29 //输出program中的元素
30 cout< < “容器中的元素:”;
31 for (it=program.begin(); it != program.end(); it++)
32 cout< < *it< < “; “;
33 cout< < endl;
34 system(“pause”);
35 }
该函数范例的运行结果如图25-21所示。
图25-21 函数范例的运行结果
binder2nd是C++的一个模板类,它的定义如下。
template< class Pred>
class binder2nd: public unary_function< Pred::first_argument_type,
Pred::result_type>
{
public:
binder2nd(const Pred& pr, const Pred::second_argument_type y); op(x), value(y){}
result_type operator()(const argument_type& x) const{return op(x, value);}
protected:
Pred op;
Pred::second_argument_type value;
};
模板类binder2nd对象Pr必须是由一对函数对象op和y构成。其中,成员函数operator()将当前元素x与y比较后返回bool值。
void unique ();
void unique ( not_equal_to< T> pr );
unique函数的功能是移除list容器中相邻的重复元素(只保留一个)。其中,各个函数的功能如下。
(1)第1个函数从控制序列中删除那些与前一个元素相等的元素。
(2)第2个函数删除满足条件i+1==j&&pr(*pi,*pj)的所有元素。其中,迭代器pi和pj分别指向位置为i和j的元素。
参数pr:not_equal_to类型的对象,用来比较两个元素的值。
该函数没有返回值。
/********************************************
*范例编号:25_22
*范例说明:删除list容器中相邻的重复元素
*********************************************/
01 #include < list>
02 #include < iostream>
03 using namespace std;
04 void main()
05 {
06 list< int> L;
07 not_equal_to< int> mypred;
08 list< int>::iterator it;
09 int a[]={12,5,5,5,9,8,23,5,12,55,9,9,38,76};
10 int sz=sizeof(a)/sizeof(a[0]);
11 for(int i=0;i< sz;i++)
12 L.push_back(a[i]);
13 cout< < “容器中的元素:”< < endl;
14 for (it=L.begin(); it!=L.end(); it++)
15 cout < < *it < < “ “;
16 cout< < endl;
17 L.unique();
18 cout< < “容器中的元素:”< < endl;
19 for (it=L.begin(); it!=L.end(); it++)
20 cout < < *it < < “ “;
21 cout < < endl;
22 L.unique(mypred);
23 cout< < “容器中的元素:”< < endl;
24 for (it=L.begin(); it!=L.end(); it++)
25 cout< < *it< < “ “;
26 cout< < endl;
27 system(“pause”);
28 }
该函数范例的运行结果如图25-22所示。
图25-22 函数范例的运行结果
第1个unique函数(不带参数)的功能是删除相邻元素中相等的元素,这些相等的元素只保留其中一个。第2个unique函数的功能是删除所有与第1个元素不等的元素。
void merge ( list< T,Allocator>&x );
void merge ( list< T,Allocator>&x, greater< T> pr );
merge函数的功能是将两个list容器中的元素合并。其中,各个函数的功能如下。
(1)第1个函数是将链表x合并到当前的list容器中。
(2)第2个函数利用模板类判断两个元素的大小并返回结果,保证当i<j时,有*pi>*pj,即使list容器中的元素降序排列。
(1)参数x:list容器对象,用来插入当前的list容器中。
(2)参数pr:模板类对象,定义了一个成员函数返回x>y的值。
该函数没有返回值。
/********************************************
*范例编号:25_23
*范例说明:合并list容器中的元素
*********************************************/
01 #include < iostream>
02 #include < list>
03 using namespace std;
04 void InitList(list< int> &L,int a[],int n);
05 void main ()
06 {
07 list< int> L1, L2;
08 list< int>::iterator it;
09 int a1[]={5,2,7,10,6};
10 int a2[]={8,12,9,20,15,44};
11 //初始化L1和L2
12 InitList(L1,a1,sizeof(a1)/sizeof(a1[0]));
13 InitList(L2,a2,sizeof(a2)/sizeof(a2[0]));
14 L1.sort();
15 L2.sort();
16 L1.merge(L2);
17 cout< < “合并后容器中的元素(升序):”< < endl;
18 for (it=L1.begin(); it!=L1.end(); it++)
19 cout< < “ “< < *it;
20 cout< < endl;
21 //重新初始化L1和L2
22 L1.clear();
23 InitList(L1,a1,sizeof(a1)/sizeof(a1[0]));
24 InitList(L2,a2,sizeof(a1)/sizeof(a1[0]));
25 L2.push_back(4.6);
26 L1.sort(greater< int>());
27 L2.sort(greater< int>());
28 L1.merge(L2,greater< int>());
29 cout < < “合并后容器中的元素(降序):”< < endl;
30 for (it=L1.begin(); it!=L1.end(); it++)
31 cout< < “ “< < *it;
32 cout< < endl;
33 system(“pause”);
34 }
35 void InitList(list< int> &L,int a[],int n)
36 {
37 int i;
38 for(i=0;i< n;i++)
39 L.push_back(a[i]);
40 }
该函数范例的运行结果如图25-23所示。
图25-23 函数范例的运行结果
(1)将容器x中的元素插入当前的list容器中后,容器x为空。
(2)为了使合并后容器中的元素有序,需要在合并前对容器中的元素进行排序。
void sort ();
void sort ( greater< T> pr );
sort函数的功能是将list容器中的元素进行排序。其中,各个函数的功能如下。
(1)第1个函数将list容器中的元素按照从小到大的顺序排列。
(2)第2个函数将list容器中的元素按照从大到小的顺序排列。其中,greater的功能同merge函数的功能,都是对两个元素进行比较并返回结果,根据比较的结果对元素进行排序。
参数pr:模板类对象,定义了一个成员函数返回x>y的值。
该函数没有返回值。
/********************************************
*范例编号:25_24
*范例说明:对list容器中的元素排序
*********************************************/
01 #include < iostream>
02 #include < list>
03 #include < string>
04 using namespace std;
05 void main ()
06 {
07 list< string> L;
08 list< string>::iterator it;
09 string s[]={“Visual C++”,”Java”,”Visual Foxpro”,”Python”};
10 for(int i=0;i< sizeof(s)/sizeof(s[0]);i++)
11 L.push_back(s[i]);
12 L.sort();
13 cout< < “容器中的元素(升序):”< < endl;
14 for (it=L.begin(); it!=L.end(); ++it)
15 cout < < “【“< < *it< < “】 “;
16 cout < < endl;
17 L.sort(greater< string>());
18 cout < < “容器中的元素(降序):”< < endl;
19 for (it=L.begin(); it!=L.end(); ++it)
20 cout< < “【“< < *it< < “】 “;
21 cout< < endl;
22 system(“pause”);
23 }
该函数范例的运行结果如图25-24所示。
调用不带参数的sort函数时,将对list容器中的元素进行升序排列;调用带参数的sort函数时,将对list容器中的元素进行降序排列。
图25-24 函数范例的运行结果
void reverse ();
reverse函数的功能是将list容器中的元素逆置。
该函数没有参数。
该函数没有返回值。
/********************************************
*范例编号:25_25
*范例说明:将list容器中的元素逆置并输出
*********************************************/
01 #include < iostream>
02 #include < list>
03 #include < string>
04 using namespace std;
05 template < typename T>
06 void DispList(list< T> L);
07 void main ()
08 {
09 list< int> L;
10 list< int>::iterator it;
11 list< char> L2;
12 list< char>::iterator it2;
13 int a[]={55,22,33,99,11,77,66,88},i;
14 char ch[]={‘a’,’b’,’c’,’s’,’t’,’y’};
15 for (i=0; i< sizeof(a)/sizeof(a[0]); i++)
16 L.push_back(a[i]);
17 for(i=0;i< sizeof(ch)/sizeof(ch[0]);i++)
18 L2.push_back(ch[i]);
19 cout< < “容器1中的元素:”< < endl;
20 DispList(L);
21 L.reverse();
22 cout< < “逆置后容器1中的元素:”< < endl;
23 DispList(L);
24 cout< < “容器2中的元素:”< < endl;
25 DispList(L2);
26 L2.reverse();
27 cout< < “逆置后容器2中的元素:”< < endl;
28 DispList(L2);
29 system(“pause”);
30 }
31 template < typename T>
32 void DispList(list< T> L)
33 {
34 list< T>::iterator it;
35 for (it=L.begin(); it!=L.end(); it++)
36 cout< < “ “< < *it;
37 cout< < endl;
38 }
该函数范例的运行结果如图25-25所示。
图25-25 函数范例的运行结果
逆置后,list容器中的元素以相反的顺序存放。
stack是一种后进先出的容器适配器,它只允许在容器的末端进行插入和删除操作。其中,输出元素和输入元素的一端被称为栈顶。
实质上,stack是利用类模板vector、deque或list实现的适配器,基本操作如下。
(1)back():用来实现从栈顶取出栈顶元素,对应的是top()函数。
(2)push_back():用来实现将元素压入栈顶,对应的是push()函数。
(3)pop_back():用来将栈顶元素退栈,对应的是pop()函数。
在默认情况下,stack使用deque实现。在C++的标准模板库中,stack容器有如下两个模板参数。
template< class T, class Container=deque< T> >
class stack;
其中,T是元素的类型;Container 是实现堆栈的容器类型(vector、deque或list),用来存取元素。
如果要使用stack类(容器)中的函数,则需要使用以下文件包含命令。
#include< stack>
using namespace std;
stack类中的函数可以分为四大类,分别是构造类函数、容量类函数、存取类函数、操作类函数。
stack容器的构造类函数包括构造函数。
stack的构造函数主要用来创建stack对象。
stack ();
stack ( const stack& );
stack&operator=( const stack& );
stack构造函数的功能是创建stack容器并初始化容器中的元素。其中,各个函数的功能如下。
(1)第1个函数是stack默认的构造函数,它的功能是构造一个空的堆栈。
(2)第2个函数是stack拷贝构造函数,它的功能是利用参数stack创建一个堆栈。
(3)第3个函数是stack运算符构造函数,它的功能是将运算符=右边的stack对象赋值给左边的stack对象。
参数stack:堆栈对象,用来初始化当前的stack对象。
该函数没有返回值。
/********************************************
*范例编号:26_01
*范例说明:利用stack构造函数创建堆栈
*********************************************/
01 #include < iostream>
02 #include < stack>
03 using namespace std;
04 void main ()
05 {
06 stack< int> s;
07 deque< int> d(3,20);
08 stack< int> s2(d);
09 s.push(3);
10 s.push(5);
11 s.push(8);
12 cout < < “栈中元素个数:”< < s.size()< < endl;
13 cout< < “栈顶元素:”< < s.top()< < endl;
14 cout < < “栈2中的元素个数:”< < s2.size()< < endl;
15 cout< < “栈2中的栈顶元素:”< < s2.top()< < endl;
16 system(“pause”);
17 }
该函数范例的运行结果如图26-1所示。
图26-1 函数范例的运行结果
在更高版本的C++标准库中,stack的构造函数还可通过deque、vector等容器进行构造,代码如下。
01 deque< int> d (5,10);
02 vector< int> v (3,20);
03 stack< int> s1 (d); //用deque初始化stack
04 stack< int,vector< int> > s2(v);//用vector初始化stack
在stack容器中,容量类函数主要包括empty函数和size函数。
bool empty () const;
empty函数的功能是判断stack容器是否为空。
该函数没有参数。
如果stack为空,则返回true;否则,返回false。
/********************************************
*范例编号:26_02
*范例说明:当stack不为空时,输出栈中元素
*********************************************/
01 #include < iostream>
02 #include < stack>
03 using namespace std;
04 void main ()
05 {
06 stack< char> s;
07 int i;
08 for (i=0;i< 8;i++)
09 s.push(i+’a’);
10 cout < < “容器中的元素: “ < < endl;;
11 while (!s.empty())
12 {
13 cout < < s.top()< < “ “;
14 s.pop();
15 }
16 cout< < endl;
17 system(“pause”);
18 }
该函数范例的运行结果如图26-2所示。
图26-2 函数范例的运行结果
size_type size () const;
size函数的功能是返回stack容器中的实际元素个数。
该函数没有参数。
函数返回stack容器中的实际元素个数。
/********************************************
*范例编号:26_03
*范例说明:求stack容器中的实际元素个数
*********************************************/
01 #include < iostream>
02 #include < stack>
03 #include < deque>
04 using namespace std;
05 void main ()
06 {
07 deque< int> d(2,10);
08 stack< int> s(d);
09 int i,sum=0;
10 cout< < “栈中的元素个数: “< < s.size()< < endl;
11 for (i=1; i< =10; i++)
12 s.push(i);
13 cout< < “栈中的元素个数:”< < s.size()< < endl;
14 while(!s.empty())
15 {
16 sum+=s.top();
17 s.pop();
18 }
19 cout < < “栈中元素之和:”< < sum< < endl;
20 cout< < “栈中元素个数:”< < s.size()< < endl;
21 system(“pause”);
22 }
该函数范例的运行结果如图26-3所示。
图26-3 函数范例的运行结果
stack的存取类函数主要是top函数。
value_type& top ();
const value_type& top () const;
top函数的功能是返回stack容器中的栈顶元素。
该函数没有参数。
函数的返回值是stack中的栈顶元素。
/********************************************
*范例编号:26_04
*范例说明:输出stack的栈顶元素
*********************************************/
01 #include < iostream>
02 #include < stack>
03 using namespace std;
04 void main ()
05 {
06 stack< int> s;
07 int a[]={1,2,3,4,5};
08 cout< < “将以下元素依次入栈:”< < endl;
09 for(int i=0;i< 5;i++)
10 {
11 cout< < a[i]< < “ “;
12 s.push(a[i]);
13 }
14 cout< < “ \n栈顶元素: “< < s.top()< < endl;
15 system(“pause”);
16 }
该函数范例的运行结果如图26-4所示。
图26-4 函数范例的运行结果
stack中top函数是通过调用顺序容器的back函数实现的。
stack的操作类函数主要有两个,分别是push函数和pop函数。
void push ( const T&x );
push函数的功能是将元素x入栈,即把元素x插入stack的栈顶位置。例如,s是一个栈,将字符’a’’b’’c’’d’依次入栈的情况如图26-5所示。
初始时,栈s为空栈,即栈s中没有元素。top是栈顶指针,指向栈顶元素的下一个位置。当一个元素入栈后,即成为栈顶元素。
图26-5 字符’a’’b’’c’’d’依次入栈的情况
参数x:将要入栈的元素。
该函数没有返回值。
/********************************************
*范例编号:26_05
*范例说明:利用出栈和入栈操作实现进制转换
*********************************************/
01 #include < iostream>
02 #include < stack>
03 using namespace std;
04 void main ()
05 {
06 stack< int> s;
07 int n,k,m;
08 cout< < “请输入要转换的数字:”< < endl;
09 cin>>n;
10 cout< < “请选择要转换的进制数(只能转换为十进制以内,如二进制,则输入2):”< < endl;
11 cin>>k;
12 m=n;
13 while(n)
14 {
15 s.push(n%k);
16 n=n/k;
17 }
18 cout< < “十进制数”< < m< < “转换为”< < k< < “进制后为:”;
19 while(!s.empty())
20 {
21 cout< < s.top();
22 s.pop();
23 }
24 cout< < endl;
25 system(“pause”);
26 }
该函数范例的运行结果如图26-6所示。
图26-6 函数范例的运行结果
stack的push函数是利用顺序容器的push_back函数实现的。
void pop ();
pop函数的功能是移除stack容器的栈顶元素。
该函数没有参数。
该函数没有返回值。
/********************************************
*范例编号:26_06
*范例说明:在deque容器末尾追加字符
*********************************************/
01 #include < iostream>
02 #include < stack>
03 using namespace std;
04 void main ()
05 {
06 stack< int> s;
07 int sum=0,i;
08 for (i=1; i< =5; i++)
09 s.push(i*10);
10 cout< < “栈顶元素:”< < s.top()< < endl;
11 cout< < “依次出栈的元素是:”;
12 while (!s.empty())
13 {
14 cout< < “ “< < s.top();
15 sum+=s.top();
16 s.pop();
17 }
18 cout< < “\n栈中元素的和:”< < sum< < endl;
19 system(“pause”);
20 }
该函数范例的运行结果如图26-7所示。
图26-7 函数范例的运行结果
调用pop函数后,stack容器的大小减1。stack容器的pop函数是通过调用顺序容器的pop_back函数实现的。
queue被称为队列,是一种先进先出(FIFO)的容器适配器。它只允许在一端进行插入操作,在另一端进行删除操作。其中,插入元素的一端被称为队尾,删除元素的一端被称为队头。
queue实现了队列的基本操作,其主要功能如下。
(1)front():用来取出queue中的队头元素。
(2)back():用来取出queue中的队尾元素。
(3)push_back():用来向queue的队尾插入元素。
(4)pop_back():用来将queue的队头元素删除。
通常情况下,queue通过调用deque容器的函数来实现。在C++的标准模板库中,queue容器有以下两个模板参数。
template< class T, class Container=deque< T> >
class queue;
其中,T是元素的类型;Container是顺序容器,用来存取队列中的元素。
如果要使用queue类(容器)中的函数,则需要使用以下文件包含命令。
#include< queue>
using namespace std;
queue类中的函数可以分为四大类,分别是构造类函数、容量类函数、存取类函数、操作类函数。
queue容器的构造类函数主要用来创建queue对象。
queue ();
queue ( const queue&);
queue&operator=(const queue&);
queue构造函数的功能是创建queue容器并初始化容器中的元素。其中,各个函数的功能如下。
(1)第1个函数是queue默认的构造函数,它的功能是构造一个空的队列。
(2)第2个函数是queue拷贝构造函数,它的功能是利用参数queue对象构造一个queue对象。
(3)第3个函数是queue运算符构造函数,它的功能是将运算符=右边的对象赋值给左边,从而构造一个新的queue对象。
参数queue:队列对象,用来初始化当前的queue容器。
该函数没有返回值。
/********************************************
*范例编号:27_01
*范例说明:构造queue对象
*********************************************/
01 #include < iostream>
02 #include < queue>
03 using namespace std;
04 void main ()
05 {
06 queue< int> q;
07 deque< int> d(3,20);
08 queue< int> q2(d);
09 q.push(10);
10 q.push(20);
11 q.push(30);
12 cout< < “q的队头元素:”< < q.front()< < endl;
13 cout< < “q的队尾元素:”< < q.back()< < endl;
14 cout< < “q2的队头元素:”< < q2.front()< < endl;
15 cout< < “q2的队尾元素:”< < q2.back()< < endl;
16 system(“pause”);
17 }
该函数范例的运行结果如图27-1所示。
图27-1 函数范例的运行结果
在新版本的C++标准库中,queue构造函数的定义如下。
queue ( const Container&ctnr=Container() );
它可以利用顺序容器Container构造queue对象,使用方法与stack中的构造函数相同。
在queue容器中,容量类函数主要包括empty函数和size函数。
bool empty () const;
empty函数的功能是判断queue是否为空。
该函数没有参数。
如果queue容器为空,则返回true;否则,返回false。
/********************************************
*范例编号:27_02
*范例说明:输出queue容器中的元素
*********************************************/
01 #include < iostream>
02 #include < queue>
03 using namespace std;
04 void main ()
05 {
06 queue< char> Q;
07 int i;
08 for (i=0;i< 10;i++)
09 Q.push(i+’a’);
10 cout< < “队列中的元素:”< < endl;
11 while (!Q.empty())
12 {
13 cout< < “ “< < Q.front();
14 Q.pop();
15 }
16 cout< < endl;
17 system(“pause”);
18 }
该函数范例的运行结果如图27-2所示。
图27-2 函数范例的运行结果
size_type size () const;
size函数的功能是返回queue容器的大小,即实际元素个数。
该函数没有参数。
函数返回queue容器中的实际元素个数。
/********************************************
*范例编号:27_03
*范例说明:求deque容器中元素的和
*********************************************/
01 #include < iostream>
02 #include < queue>
03 using namespace std;
04 void main ()
05 {
06 deque< int> d(3,50);
07 queue< int> Q(d);
08 cout< < “队列中的元素个数: “< < Q.size()< < endl;
09 for (int i=0; i< 8; i++)
10 Q.push(i);
11 cout< < “队列中的元素个数: “< < Q.size()< < endl;
12 system(“pause”);
13 }
该函数范例的运行结果如图27-3所示。
图27-3 函数范例的运行结果
queue的存取类函数主要包括front函数和back函数。
value_type& front ();
const value_type& front () const;
front函数的功能是返回queue容器中的队头元素,即最早进入队列中的元素。所谓队列,就是只能在一端进行插入操作,在另一端进行删除操作的线性表。其中,插入元素被称为入队列,删除元素被称为出队列。插入的一端被称为队尾,删除的一端被称为队头。例如,元素’a’’b’’c’’d’’e’的插入和删除过程如图27-4、图27-5和图27-6所示。
图27-4 元素’a’入队列
图27-5 元素’a’’b’’c’’d’’e’依次入队列
在图27-4中,队列中只有一个元素’a’,它既是队头元素,也是队尾元素。在图27-5中,队头元素为’a’,队尾元素为’e’。在图27-6中,队头元素’a’出队列,后一个元素’b’成为队头元素。
图27-6 删除队头元素’a’
该函数没有参数。
函数返回queue容器中的队头元素。
/********************************************
*范例编号:27_04
*范例说明:输出queue容器中的队头元素
*********************************************/
01 #include < iostream>
02 #include < queue>
03 using namespace std;
04 void main ()
05 {
06 queue< char> Q;
07 for(int i=0;i< =5;i++)
08 Q.push(i+’A’);
09 cout< < “队列中元素个数:”< < Q.size()< < endl;
10 cout< < “队头元素:”< < Q.front()< < endl;
11 Q.pop();
12 cout< < “队列中元素个数:”< < Q.size()< < endl;
13 cout< < “队头元素:”< < Q.front()< < endl;
14 system(“pause”);
15 }
该函数范例的运行结果如图27-7所示。
图27-7 函数范例的运行结果
value_type&back ();
const value_type& back () const;
back函数的功能是返回queue容器中的队尾元素,即最后进入队列中的元素。
该函数没有参数。
函数返回queue容器中的队尾元素。
/********************************************
*范例编号:27_05
*范例说明:输出queue容器中的队尾元素
*********************************************/
01 #include < iostream>
02 #include < queue>
03 using namespace std;
04 void main ()
05 {
06 queue< char> Q;
07 for(int i=0;i< =5;i++)
08 Q.push(i+’A’);
09 cout< < “队列中元素个数:”< < Q.size()< < endl;
10 cout< < “队尾元素:”< < Q.back()< < endl;
11 Q.push(‘M’);
12 cout< < “队列中元素个数:”< < Q.size()< < endl;
13 cout< < “队尾元素:”< < Q.back()< < endl;
14 system(“pause”);
15 }
该函数范例的运行结果如图27-8所示。
图27-8 函数范例的运行结果
queue的操作类函数主要包括push函数和pop函数。
void push ( const T&x );
push函数的功能是在queue容器的末尾追加一个新元素x。此时,队尾元素为x。
参数x:要追加到queue末尾的元素。
该函数没有返回值。
/********************************************
*范例编号:27_06
*范例说明:利用queue容器打印杨辉三角
*********************************************/
01 #include < iostream>
02 #include < queue>
03 using namespace std;
04 #define MAXSIZE 100
05 void PrintArray(int a[],int n,int N);
06 void YangHuiTriangle(int n);
07 void main()
08 {
09 int n;
10 cout< < “请输入要打印的行数:n=”;
11 cin>>n;
12 YangHuiTriangle(n);
13 system(“pause”);
14 }
15 void YangHuiTriangle(int n)
16 /*利用queue打印杨辉三角*/
17 {
18 int i,k,t,e,m,temp[MAXSIZE];
19 queue< int> Q;
20 k=0;
21 Q.push(1); //第一行元素入队
22 for(m=2;m< =n;m++) //产生第m行元素并入队,同时将第m-1行的元素保存在临时数组中
23 {
24 k=0;
25 Q.push(1); //第m行的第一个元素入队
26 for(i=1;i< =m-2;i++) //利用队列中第m-1行元素产生第i行的中间m-2个元素并入队
27 {
28 t=Q.front();
29 Q.pop();
30 temp[k++]=t; //将第m-1行的元素存入临时数组
31 e=Q.front(); //取队头元素
32 t=t+e; //利用队中第m-1行元素产生第i行元素
33 Q.push(t);
34 }
35 t=Q.front();
36 Q.pop();
37 temp[k++]=t; //将第m-1行的最后一个元素存入临时数组
38 PrintArray(temp,k,n);
39 Q.push(1); //将第m行的最后一个元素入队
40 }
41 k=0; //将最后一行元素存入数组之前,要将下标k置为0
42 while(!Q.empty()) //将最后一行元素存入临时数组*/
43 {
44 t=Q.front();
45 Q.pop();
46 temp[k++]=t;
47 if(Q.empty())
48 PrintArray(temp,k,n);
49 }
50 }
51 void PrintArray(int a[],int k,int n)
52 /*打印数组中的元素,使其能够以正确的形式输出*/
53 {
54 int i;
55 static int count=0; //记录输出的行
56 for(i=0;i< n-count;i++) //打印空格
57 printf(“ “);
58 count++;
59 for(i=0;i< k;i++) //打印数组中的元素
60 printf(“%6d”,a[i]);
61 printf(“\n”);
62 }
该函数范例的运行结果如图27-9所示。
图27-9 函数范例的运行结果
调用push函数之后,queue容器的实际大小自动增1。
void pop ();
pop函数的功能是移除queue容器中的队头元素,即最先进入队列中的元素。
该函数没有参数。
该函数没有返回值。
/********************************************
*范例编号:27_07
*范例说明:输出queue容器中的元素及元素之和
*********************************************/
01 #include < iostream>
02 #include < queue>
03 using namespace std;
04 template< typename T>
05 T DispQueue(queue< T> Q);
06 void main ()
07 {
08 queue< float> Q;
09 queue< int> Q2;
10 float a[]={2.5 ,5.5, 1.5, 2.0};
11 int i;
12 for(i=0;i< 4;i++)
13 Q.push(a[i]);
14 for(i=١;i< =5;i++)//队列中的元素:10 20 30 40 50
15 Q2.push(i*10);
16 Q.pop();//٢.٥出队列
17 Q.push(٦.٥);//٦.٥入队列
18 cout< < “队列Q中的元素:”< < endl;
19 cout< < “其和为”< < DispQueue(Q)< < endl;
20 cout< < “队列Q2中的元素:”< < endl;
21 cout< < “其和为”< < DispQueue(Q2)< < endl;
22 system(“pause”);
23 }
24 template< typename T>
25 T DispQueue(queue< T> Q)
26 {
27 T sum=0;
28 while(!Q.empty())
29 {
30 cout< < Q.front()< < “ “;
31 sum+=Q.front();
32 Q.pop();
33 }
34 cout< < endl;
35 return sum;
36 }
该函数范例的运行结果如图27-10所示。
图27-10 函数范例的运行结果
调用pop函数之后,queue容器的实际大小自动减1。
set(集合)和map(映射)都属于关联容器,它们都支持查询一个元素是否存在,并能有效地获取元素。
set中的元素总是从小到大排列,set通过二分查找树实现,其具有以下两个特点。
(1)独一无二的元素:在set类(容器)中,不存在两个值相等的元素。
(2)元素值就是关键字本身。
如果要使用set类中的函数,则需要使用以下文件包含命令。
#include< set>
using namespace std;
set类中的函数可以分为四大类,分别是构造类函数、迭代器类函数、容量类函数、操作类函数。
set容器的构造类函数包括构造函数和析构函数。
set(const Pred&comp=Pred(),const Allocator&=Allocator());
set(const set&x);
set(const value_type*first,const value_type*last,const Pred&comp=Pred(),const Allocator&=Allocator());
~set ();
set构造函数的功能是创建set容器并将容器初始化。其中,各个函数的功能如下。
(1)第1个函数是set默认的构造函数,它的功能是构造一个空的集合,集合中的元素个数为0。
(2)第2个函数是set拷贝构造函数,它的功能是利用参数x构造一个set集合。
(3)第3个函数是set迭代器构造函数,它的功能是利用输入对象[first,last)之间的元素初始化当前的set对象。
set析构函数的功能是在使用完集合后,释放set集合中元素占用的存储空间。
(1)参数comp:Pred的对象,通过调用key_comp函数返回元素关键字排序的结果。对于序列中任何在元素y之前的元素x,key_comp(y,x)都返回false。
(2)参数Allocator:分配器对象,所有的标准容器都利用Allocator分配空间并初始化对象。
(3)参数x:另一个set集合的对象,用来初始化当前的set集合。
(4)参数first:指针对象,指向输入对象的第一个元素。
(5)参数last:指针对象,指向输入对象最后一个元素的下一个位置。
该函数没有返回值。
/********************************************
*范例编号:28_01
*范例说明:构造set对象
*********************************************/
01 #include < iostream>
02 #include < set>
03 using namespace std;
04 template< class T>
05 void DispSet(set< T> S);
06 void main()
07 {
08 set< char> s1; //空set集合
09 set< char>::iterator it;
10 char a[]= {‘C’,’O’,’M’,’P’,’U’,’T’,’E’,’R’};
11 int b[]={2020,2021,2022,2023,2024,2025};
12 set< char> s2 (a+2,a+sizeof(a)/sizeof(a[0])); //利用数组对象初始化set集合
13 set< char> s3 (s2); //利用拷贝构造函数初始化set集合
14 set< int> s4(b,b+sizeof(b)/sizeof(b[0]));
15 cout< < “集合s1中的元素:”< < endl;
16 DispSet(s1);
17 cout< < “集合s2中的元素:”< < endl;
18 DispSet(s2);
19 cout< < “集合s3中的元素:”< < endl;
20 DispSet(s3);
21 cout< < “集合s4中的元素:”< < endl;
22 DispSet(s4);
23 system(“pause”);
24 }
25 template< class T>
26 void DispSet(set< T> myset)
27 {
28 set< T>::iterator it;
29 if(myset.empty())
30 cout< < “集合中元素为空!”< < endl;
31 else
32 {
33 for(it=myset.begin();it!=myset.end();it++)
34 cout< < “ “< < *it;
35 cout< < endl;
36 }
37 }
该函数范例的运行结果如图28-1所示。
图28-1 函数范例的运行结果
与前面的标准容器类似,在新版本的C++标准库中,set容器可以使用迭代器构造当前的set对象;而在旧版本的C++标准库中,set容器只允许利用指针对象初始化set对象。
在set容器中,迭代器类函数主要包括begin函数、end函数、rbegin函数及rend函数。
iterator begin ();
const_iterator begin () const;
iterator end ();
const_iterator end () const;
(1)begin函数的功能是返回set容器中第一个元素的迭代器。
(2)end函数的功能是返回set容器中最后一个元素的迭代器。实际上返回的是最后一个元素的后一个位置。
该函数没有参数。
begin函数返回set容器中第一个元素的位置,end函数返回set容器中最后一个元素的后一个位置。
/********************************************
*范例编号:28_02
*范例说明:输出set中的元素
*********************************************/
01 #include < iostream>
02 #include < set>
03 using namespace std;
04 void main()
05 {
06 int a[] = {10,20,30,40,50,60},sum=0;
07 set< int> s(a,a+sizeof(a)/sizeof(a[0]));
08 set< int>::iterator it;
09 cout< < “集合中的元素:”;
10 for (it=s.begin();it!=s.end();it++)
11 {
12 cout < < “ “< < *it;
13 sum+=*it;
14 }
15 cout< < endl;
16 cout< < “集合中元素之和:”< < sum< < endl;
17 system(“pause”);
18 }
该函数范例的运行结果如图28-2所示。
图28-2 函数范例的运行结果
begin函数返回set容器中第一个元素的位置,end函数返回set容器中最后一个元素的后一个位置。这样在for循环中,从it=s.begin()到it<s.end()就可以利用*it存取set中的每一个元素。
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
(1)rbegin函数的功能是返回与最后一个元素相关的反向迭代器。
(2)rend函数的功能是返回第一个元素相关的反向迭代器。
该函数没有参数。
rbegin函数返回set中与最后一个元素相关的反向迭代器,rend函数返回set中与第一个元素相关的迭代器。
/********************************************
*范例编号:28_03
*范例说明:正向和反向输出set中的元素
*********************************************/
01 #include < iostream>
02 #include < set>
03 using namespace std;
04 void main ()
05 {
06 int a[] = {2018,2019,2020,2021,2022};
07 set< int> myset (a,a+sizeof(a)/sizeof(a[0]));
08 set< int>::iterator it;
09 set< int>::reverse_iterator rit;
10 cout< < “容器中的元素(正向):”;
11 for ( it=myset.begin() ; it!=myset.end();it++ )
12 cout< < “ “< < *it;
13 cout< < endl;
14 cout< < “容器中的元素(反向):”;
15 for ( rit=myset.rbegin() ; rit!=myset.rend(); rit++ )
16 cout< < “ “< < *rit;
17 cout< < endl;
18 system(“pause”);
19 }
该函数范例的运行结果如图28-3所示。
图28-3 函数范例的运行结果
因为在set容器中,元素都是按照从小到大的顺序排列,所以rbegin函数返回最大元素的位置,rend函数返回最小元素的前一个位置。
在set容器中,容量类函数主要包括empty函数、size函数、max_size函数。
bool empty () const;
empty函数的功能是判断set是否为空。
该函数没有参数。
如果set容器为空,则返回true;否则,返回false。
/********************************************
*范例编号:28_04
*范例说明:判断set是否为空
*********************************************/
01 #include < iostream>
02 #include < set>
03 using namespace std;
04 void main()
05 {
06 set< int> s;
07 s.insert(10);
08 s.insert(20);
09 s.insert(30);
10 cout< < “集合s中有”< < s.size()< < “个元素.”< < endl;
11 if (s.empty())
12 cout< < “集合s是空的!”< < endl;
13 else
14 cout< < “集合s不为空!”< < endl;
15 system(“pause”);
16 }
该函数范例的运行结果如图28-4所示。
图28-4 函数范例的运行结果
size_type size() const;
size函数的功能是返回set中的实际元素个数。
该函数没有参数。
函数返回set中的元素个数。
/********************************************
*范例编号:28_05
*范例说明:求set容器中的元素及元素个数
*********************************************/
01 #include < iostream>
02 #include < set>
03 using namespace std;
04 template< typename T>
05 void DispSet(set< T> myset);
06 void main ()
07 {
08 set< int> myset;
09 set< int>::iterator it;
10 cout< < “集合的元素个数: “ < < myset.size()< < endl;
11 for (int i=1; i< =6; i++)
12 myset.insert(i*10);
13 DispSet(myset);
14 myset.insert(12);
15 DispSet(myset);
16 system(“pause”);
17 }
18 template< typename T>
19 void DispSet(set< T> myset)
20 {
21 set< T>::iterator it;
22 cout< < “集合的元素个数: “ < < myset.size();
23 cout< < “,元素分别是:”;
24 for( it=myset.begin();it!=myset.end();it++)
25 cout< < “ “< < *it;
26 cout< < endl;
27 }
该函数范例的运行结果如图28-5所示。
图28-5 函数范例的运行结果
size_type max_size () const;
max_size函数的功能是返回set能容纳的最大元素个数。
该函数没有参数。
函数返回set能容纳的最大元素个数。
/********************************************
*范例编号:28_06
*范例说明:返回set能容纳的最大元素个数
*********************************************/
01 #include < iostream>
02 #include < string>
03 #include < set>
04 using namespace std;
05 void main ()
06 {
07 typedef set< string> films;
08 string name;
09 films film;
10 int i,n;
11 cout< < “请输入观影人数:”;
12 cin>>n;
13 cout< < “输入每个人的姓名:”< < endl;
14 for(i=0; i< n; i++)
15 {
16 cin>> name;
17 film.insert(name); //将姓名插入集合
18 }
19 cout< < “\n观影人数:”< < film.size();
20 cout< < “\n观影人员姓名列表:\n”;
21 films::iterator it;
22 for(it=film.begin(); it!=film.end(); it++)
23 cout< < *it< < endl;
24 cout< < “\n电影院能容纳的观影总人口数: “< < film.max_size()< < endl;
25 system(“pause”);
26 }
该函数范例的运行结果如图28-6所示。
图28-6 函数范例的运行结果
max_size函数通常用于往set容器中插入元素之前的判定,当插入大量元素时,先利用max_size函数判定一下是否能插入这么多元素,然后再进行插入操作。
set的操作类函数主要包括insert函数、swap函数、erase函数、clear函数、find函数、count函数、lower_bound函数、upper_bound函数、equal_range函数。
pair< iterator,bool> insert ( const value_type&x );
iterator insert (iterator it, const value_type&x );
void insert(const value_type*first, const value_type*last);
insert函数的功能是将一个元素或一系列元素插入set容器中。其中,各个函数的功能如下。
(1)第1个函数先判断set中是否存在一个元素y与x相等,如果存在,则将x插入相应的位置;否则,不进行插入操作。
(2)第2个函数从it开始寻找插入点,选择有效的插入方法插入元素x。
(3)第3个函数是将指定的元素序列[first,last)插入set容器中。
(1)参数x:用来插入set容器中的元素值。
(2)参数it:迭代器,在set中寻找插入位置的起始查找位置。
(3)参数first:指示要插入元素序列[first,last)的第一个元素。
(4)参数last:指示要插入元素序列[first,last)最后一个元素的下一个位置。
对于第1个函数来说,如果插入成功,则返回pair(it,true);否则,返回pair(it,false)。其中,it是迭代器。
对于第2个函数来说,函数返回新元素插入的位置或者已经存在相同元素的位置。
/********************************************
*范例编号:28_07
*范例说明:在set容器中插入元素
*********************************************/
01 #include < iostream>
02 #include < string>
03 #include < set>
04 using namespace std;
05 struct Staff
06 {
07 string name;
08 double salary;
09 bool operator < (const Staff &a) const //重载”< “操作符
10 {
11 return a.salary < salary; //按salary由大到小的顺序排序
12 }
13 };
14 void main()
15 {
16 set< Staff> s;
17 set< Staff>::iterator it;
18 Staff staff;
19 staff.name = “徐克”;
20 staff.salary = 6800;
21 s.insert(staff);
22 staff.name = “柳丝丝”;
23 staff.salary = 9300;
24 s.insert(staff);
25 staff.name = “马超”;
26 staff.salary = 11586;
27 s.insert(staff);
28 cout < < “共有员工” < < s.size()< < “人,员工及收入如下:”< < endl;
29 for(it = s.begin(); it != s.end(); it++)
30 cout < < (*it).name < < “ , “ < < (*it).salary < < endl;
31 system(“pause”);
32 }
该函数范例的运行结果如图28-7所示。
图28-7 函数范例的运行结果
对于第1个insert函数来说,如果返回值为r,则r.first表示当前迭代器指向的元素位置,r.second的值只有两个:true和false,true表示插入成功,false表示插入失败。
void swap (set &str );
swap函数的功能是将当前set容器中的内容与str中的内容交换。
参数str:一个set对象,用来与当前set容器中的内容交换。
该函数没有返回值。
/********************************************
*范例编号:28_08
*范例说明:输出交换前后set容器中的元素
*********************************************/
01 #include < iostream>
02 #include < set>
03 using namespace std;
04 void DispSet(set< int> s,char *str);
05 void main ()
06 {
07 set< int> s1;
08 set< int> s2;
09 for(int i=1;i< =3;i++)
10 s1.insert(i*10);
11 for(i=4;i< =6;i++)
12 s2.insert(i*10);
13 cout< < “交换前:”< < endl;
14 DispSet(s1,”s1”);
15 DispSet(s2,”s2”);
16 s1.swap(s2);
17 cout< < “交换后:”< < endl;
18 DispSet(s1,”s1”);
19 DispSet(s2,”s2”);
20 system(“pause”);
21 }
22 void DispSet(set< int> s,char *str)
23 {
24 set< int>::iterator it;
25 cout< < “集合”< < str< < “中的元素:”;
26 for(it=s.begin();it!=s.end();it++)
27 cout< < *it< < “ “;
28 cout< < endl;
29 }
该函数范例的运行结果如图28-8所示。
如果allocator==str.allocator,则函数的执行时间是常数;否则,将需要执行大量的元素赋值和构造函数的操作。
图28-8 函数范例的运行结果
void erase ( iterator it );
size_type erase ( const key_type& x );
void erase ( iterator first, iterator last );
erase函数的功能是删除set中的元素。其中,各个函数的功能如下。
(1)第1个函数的功能是删除迭代器it指向的元素。
(2)第2个函数的功能是删除关键字为x的元素。
(3)第3个函数的功能是删除[first,last)中的元素。
(1)参数it:迭代器,指向要删除的元素。
(2)参数x:要删除的值为x的元素。
(3)参数first:指向要删除的[first,last)中的起始元素。
(4)参数last:指向要删除的[first,last)中最后一个元素的下一个位置。
第2个函数返回删除元素的个数。如果要删除的元素存在,则返回1;否则,返回0。其他函数均没有返回值。
/********************************************
*范例编号:28_09
*范例说明:输出删除指定元素后set中的元素
*********************************************/
01 #include < iostream>
02 #include < set>
03 using namespace std;
04 template< typename T>
05 void DispSet(set< T> s);
06 void main ()
07 {
08 set< int> s;
09 set< int>::iterator it,it2;
10 int f,i;
11 //插入元素:10 20 30 40 50 60 70 80 90 100
12 for (i=1; i< =10; i++)
13 s.insert(i*10);
14 cout< < “集合中的元素:”;
15 DispSet(s);
16 it=s.begin();
17 it++; //指向值为20的元素
18 s.erase (it);//删除20
19 f=s.erase (٦٠);//删除60
20 if(f==1)
21 cout< < “删除元素60成功!”< < endl;
22 else
23 cout< < “删除60不成功!”< < endl;
24 cout< < “集合中的元素:”;
25 DispSet(s);
26 it=s.find(70);
27 it2=s.find(70);
28 it2++;
29 it2++;
30 s.erase ( it, it٢ );//删除70 80
31 cout< < “集合中的元素:”;
32 DispSet(s);
33 system(“pause”);
34 }
35 template< typename T>
36 void DispSet(set< T> s)
37 {
38 set< T>::iterator it;
39 for (it=s.begin(); it!=s.end(); it++)
40 cout< < “ “< < *it;
41 cout< < endl;
42 }
该函数范例的运行结果如图28-9所示。
图28-9 函数范例的运行结果
删除元素后,set中的元素个数自动递减。
void clear ();
clear函数将当前set容器中的元素清空。
该函数没有参数。
该函数没有返回值。
/********************************************
*范例编号:28_10
*范例说明:输出清空set容器后的元素
*********************************************/
01 #include < iostream>
02 #include < set>
03 using namespace std;
04 void main ()
05 {
06 set< char> s;
07 set< char>::iterator it;
08 s.insert (‘A’);
09 s.insert (‘B’);
10 s.insert (‘C’);
11 cout< < “集合中的元素:”;
12 for (it=s.begin(); it!=s.end(); it++)
13 cout< < “ “< < *it;
14 s.clear();
15 cout< < “\n集合中的元素个数:”< < s.size()< < endl;
16 s.insert (‘X’);
17 s.insert (‘Y’);
18 cout< < “集合中的元素个数:”< < s.size()< < endl;
19 cout< < “集合中的元素:”;
20 for (it=s.begin(); it!=s.end(); it++)
21 cout< < “ “< < *it;
22 cout< < endl;
23 system(“pause”);
24 }
该函数范例的运行结果如图28-10所示。
图28-10 函数范例的运行结果
clear函数通过调用erase(begin(),end())实现清空set中的元素。
iterator find ( const key_type&x ) const;
find函数的功能是返回set容器中元素x的迭代器。
参数x:set容器中的元素。
如果在set中找到元素x,则返回x的迭代器;否则,返回成员函数end的值。
/********************************************
*范例编号:28_11
*范例说明:查找指定的元素并删除
*********************************************/
01 #include < iostream>
02 #include < set>
03 using namespace std;
04 void main ()
05 {
06 set< char> s;
07 set< char>::iterator it;
08 char ch;
09 for (int i=0; i< 10; i++)
10 s.insert(i+’A’);
11 cout< < “集合中的元素:”;
12 for (it=s.begin(); it!=s.end(); it++)
13 cout < < “ “ < < *it;
14 cout < < endl;
15 while(1)
16 {
17 cout< < “请输入要查找的字符(‘0’表示退出):”;
18 cin>>ch;
19 if(ch==’0’)
20 break;
21 if(s.find(ch)!=s.end())
22 cout< < “集合中存在字符”< < ch< < endl;
23 else
24 cout< < “集合中不存在字符”< < ch< < endl;
25 }
26 system(“pause”);
27 }
该函数范例的运行结果如图28-11所示。
图28-11 函数范例的运行结果
size_type count ( cont key_type&x ) const;
count函数的功能是在set容器中查找值为x的元素,并返回它在容器中出现的次数。
参数x:要查找的元素。
如果在set中找到元素x,则返回1;否则,返回0。
/********************************************
*范例编号:28_12
*范例说明:输出属于和不属于set中的元素
*********************************************/
01 #include < iostream>
02 #include < set>
03 using namespace std;
04 int IsElem(set< char> s,char,char);
05 int NotElem(set< char>,char,char);
06 void main ()
07 {
08 set< char> s;
09 set< char>::iterator it;
10 int i,num;
11 for (i=0; i< 8; i+=2)
12 s.insert(i+’A’);
13 cout< < “集合中的元素:”;
14 for(it=s.begin();it!=s.end();it++)
15 cout< < “ “< < *it;
16 cout< < endl;
17 cout< < “属于集合中的元素:”;
18 num=IsElem(s,’A’,’H’);
19 cout< < “共”< < num< < “个”< < endl;
20 cout< < “不属于集合中的元素:”;
21 num=NotElem(s,’A’,’H’);
22 cout< < “共”< < num< < “个”< < endl;
23 system(“pause”);
24 }
25 int IsElem(set< char> s,char start,char end)
26 //输出属于集合中的元素
27 {
28 char ch;
29 int num=0;
30 for(ch=start;ch< =end;ch++)
31 if(s.count(ch)>0)
32 {
33 cout< < “ “< < ch;
34 num++;
35 }
36 cout< < endl;
37 return num;
38 }
39 int NotElem(set< char> s,char start,char end)
40 //输出不属于集合中的元素
41 {
42 char ch;
43 int num=0;
44 for(ch=start;ch< =end;ch++)
45 if(s.count(ch)==0)
46 {
47 cout< < “ “< < ch;
48 num++;
49 }
50 cout< < endl;
51 return num;
52 }
该函数范例的运行结果如图28-12所示。
图28-12 函数范例的运行结果
在set容器中,因为不允许出现两个值相等的元素,所以如果要查找的元素存在,则返回的值都是1;否则,返回的值为0。
iterator lower_bound ( const key_type&x ) const;
iterator upper_bound ( const key_type&x ) const;
lower_bound函数返回第一个不小于元素x的迭代器。upper_bound函数返回第一个大于元素x的迭代器。
参数x:要比较的元素值。
lower_bound函数返回第一个不小于元素x的迭代器。upper_bound函数返回第一个大于元素x的迭代器。
/********************************************
*范例编号:28_13
*范例说明:输出[low_bound,upper_bound〕之间的元素
*********************************************/
01 #include < iostream>
02 #include < set>
03 using namespace std;
04 void main ()
05 {
06 set< int> myset;
07 set< int>::iterator it,low,high;
08 double average=0.0;
09 int i,count=0;
10 //初始化集合:10 20 30 40 50 60 70 80 90 100
11 for (i=1; i< =10; i++)
12 myset.insert(i*10);
13 cout< < “集合中的元素:”;
14 for (it=myset.begin(); it!=myset.end(); it++)
15 cout< < “ “< < *it;
16 cout< < endl;
17 low=myset.lower_bound (٤٠); //low指向40
18 high=myset.upper_bound (٨٠); //high指向90
19 for(it=low;it!=high;it++)
20 {
21 count++;
22 average+=*it;
23 }
24 average/=count;
25 cout< < “[“< < *low< < “,”< < *high< < “)范围中的元素个数:”< < count< < endl;
26 for (it=low; it!=high; it++)
27 cout< < “ “< < *it;
28 cout< < “\n平均值为”< < average< < endl;
29 system(“pause”);
30 }
该函数范例的运行结果如图28-13所示。
图28-13 函数范例的运行结果
假设first和last分别是set的迭代器,若要在[first last)区间中查找元素x,则lower_bound(x)表示在set中查找大于或等于x的元素,upper_bound(x)表示在set中查到大于x的元素。例如,如果set容器中的元素为10、20、30、40、50、60,则lower_bound(30)指向的元素是30,upper_bound(40)指向的元素是50。
pair< iterator,iterator> equal_range ( const key_type&x ) const;
equal_range函数的功能是返回一对迭代器(元素x的下边界和上边界)。
参数x:要比较的元素值。
函数返回一个pair对象。其中,pair::first相当于调用s.lower_range(x),pair::second相当于调用s.upper_range(x)。
/********************************************
*范例编号:28_14
*范例说明:输出pair指向的两个元素
*********************************************/
01 #include < iostream>
02 #include < set>
03 using namespace std;
04 void main ()
05 {
06 set< int> s;
07 int i,a[]={30,20,5,10,50,25,35,23,36};
08 pair< set< int>::iterator,set< int>::iterator> ret;
09 set< int>::iterator it;
10 for (i=0; i< sizeof(a)/sizeof(a[0]); i++)
11 s.insert(a[i]);
12 for(it=s.begin();it!=s.end();it++)
13 cout< < “ “< < *it;
14 cout< < endl;
15 ret=s.equal_range(20);
16 cout< < “first指向的元素: “< < *ret.first< < endl;
17 cout< < “second指向的元素: “< < *ret.second< < endl;
18 ret=s.equal_range(36);
19 cout< < “first指向的元素: “< < *ret.first< < endl;
20 cout< < “second指向的元素: “< < *ret.second< < endl;
21 system(“pause”);
22 }
该函数范例的运行结果如图28-14所示。
图28-14 函数范例的运行结果
equal_range函数返回set容器中元素x的上、下边界,x的上边界由pair::first表示,x的下边界由pair::second表示。
map也是一种关联容器,它也是用来存取数据的,数据的组成包括两个部分:数据值和关键字。其中,关键字是用来唯一标识数据元素的,通常利用关键字对数据进行排序。数据值与关键字对应,类型可以不同。
map容器通过关键字存取元素,而不是像顺序容器那样利用相对位置存取元素。map容器主要具有以下特征。
(1)它是一个相关联的容器,它的大小可以改变,能根据关键字提高读取数据的能力。
(2)利用双向的定位器读取数据。
(3)独一无二的关键字,容器中的元素按照关键字非递减的顺序排列。
(4)每个元素都由关键字和数据值构成。
在C++的标准模板库中,map容器有以下4个模板参数。
template < class Key, class T, class Compare=less< Key>,
class Allocator=allocator< pair< const Key,T> > >
class map;
其中,各个参数的含义如下。
(1)Key:关键字类型,每一个元素都被关键字Key独一无二地标识。
(2)T:元素的类型,每一个元素都可以存放一些数据。
(3)Compare:比较类:一个带有两个关键字类型的参数和返回一个布尔值(bool),其取值决定它们在map中的相对位置。这是一个可选参数。
(4)Allocator:表示存储管理设备。
如果要使用map类(容器)中的函数,则需要使用以下文件包含命令。
#include< map>
using namespace std;
map类中的函数可以分为五大类,分别是构造类函数、迭代器类函数、容量类函数、存取类函数、操作类函数。
map容器的构造类函数包括构造函数、析构函数、赋值构造函数。
map ( const Compare& comp=Compare(),const Allocator&=Allocator() );
template < class InputIterator>
map ( InputIterator first, InputIterator last,
const Compare& comp=Compare(), const Allocator&=Allocator() );
map ( const map< Key,T,Compare,Allocator>& x );
~map ();
map构造函数的功能是创建map容器对象并初始化容器中的元素。其中,各个函数的功能如下。
(1)第1个函数是map默认的构造函数,它的功能是构造一个空的map容器,大小为0。
(2)第2个函数是map的迭代器构造函数,利用first和last设置每一个元素序列作为容器对象的内容。
(3)第3个函数是map的拷贝构造函数,利用x对象初始化容器对象。
~map()是析构函数,自动被系统调用。它的功能是销毁对象,并释放map容器占用的存储空间。
(1)参数first:输入迭代器,输入序列的初始位置。
(2)参数last:输入迭代器,输入序列的结束位置,范围为[first,last),输入序列包括first和last之间的所有元素(除了last指向的元素)。
(3)参数x:一个map对象。
(4)参数comp:比较两个对象,以从小到大的顺序排列元素。
构造函数与析构函数都没有返回值。
/********************************************
*范例编号:29_01
*范例说明:构造map对象
*********************************************/
01 #include < iostream>
02 #include < map>
03 #include < string>
04 using namespace std;
05 void main ()
06 {
07 map< string,int>::iterator it;
08 map< string,int> p1;
09 p1[“zhang”]=21;
10 p1[“yang”]=20;
11 p1[“wu”]=28;
12 p1[“meng”]=31;
13 map< string,int> p2 (p1);
14 for ( it=p1.begin() ; it != p1.end(); it++ )
15 cout< < “[“< < (*it).first< < “]=”< < (*it).second< < “ “;
16 cout< < endl;
17 for ( it=p2.begin() ; it != p2.end(); it++ )
18 cout< < “[“< < (*it).first< < “]=”< < (*it).second< < “ “;
19 cout< < endl;
20 system(“pause”);
21 }
该函数范例的运行结果如图29-1所示。
图29-1 函数范例的运行结果
map< Key,T,Compare,Allocator>&operator=(constap< Key,T,Compare,Allocator>& x );
map的赋值构造函数是利用一个map对象x为新map对象赋值。
参数x:一个map对象。
该函数返回map对象。
/********************************************
*范例编号:29_02
*范例说明:利用一个map对象为另一个map对象赋值
*********************************************/
01 #include < iostream>
02 #include < map>
03 #include < string>
04 using namespace std;
05 template< typename T1, typename T2>
06 void DispMap(map< T1,T2> p);
07 void main ()
08 {
09 map< string,double> p1;
10 map< string,double> p2;
11 map< string,string> p3;
12 p١[“张郃”]=98.5;
13 p١[“徐晃”]=92.3;
14 p١[“典韦”]=93;
15 p2=p1;
16 cout< < “容器p1: “< < endl;
17 DispMap(p1);
18 cout< < “容器p2: “< < endl;
19 DispMap(p2);
20 p1=map< string,double>();
21 cout< < “容器p1的大小: “< < p1.size()< < endl;
22 cout< < “容器p2的大小: “< < p2.size()< < endl;
23 p٣[“赵云”]=”男”;
24 p٣[“赵飞燕”]=”女”;
25 cout< < “容器p3: “< < endl;
26 DispMap(p3);
27 system(“pause”);
28 }
29 template< typename T1, typename T2>
30 void DispMap(map< T1,T2> p)
31 {
32 map< T1,T2>::iterator it;
33 for(it=p.begin();it!=p.end();it++)
34 cout< < “ [“< < (*it).first< < “]:”< < it->second;
35 cout< < endl;
36 }
该函数范例的运行结果如图29-2所示。
图29-2 函数范例的运行结果
map的赋值构造函数使两个map对象的元素值和大小均相等。
在map容器中,迭代类函数主要包括begin函数和end函数、rbegin函数和rend函数。
iterator begin ();
const_iterator begin () const;
iterator end ();
const_iterator end () const;
begin函数的功能是返回map中第一个元素的位置。
end函数的功能是返回map中最后一个元素的后一个位置。
该函数没有参数。
begin函数返回map中第一个元素的位置。
end函数返回map中最后一个元素的后一个位置。
/********************************************
*范例编号:29_03
*范例说明:利用迭代器输出map中的关键字及值
*********************************************/
01 #include < iostream>
02 #include < map>
03 #include < string>
04 using namespace std;
05 void main ()
06 {
07 map< string,int> p;
08 map< string,int>::iterator it;
09 p[“田添”]=2016;
10 p[“刘娜”]=2020;
11 p[“崔晓涛”]=2021;
12 cout< < “容器中的元素:”< < endl;
13 for ( it=p.begin() ; it != p.end(); it++ )
14 cout< < “[“< < (*it).first< < “]:”< < (*it).second< < endl;
15 system(“pause”);
16 }
该函数范例的运行结果如图29-3所示。
图29-3 函数范例的运行结果
(1)map中的元素按照关键字从小到大的顺序排列,因此,迭代器函数begin总是指向map中关键字最小的元素。
(2)迭代器函数end不是返回最后一个元素的位置,而是返回最后一个元素的后一个位置。
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
rbegin函数的功能是返回与最后一个元素相关的反向迭代器。
rend函数的功能是返回map中第一个元素之前的反向迭代器。
该函数没有参数。
rbegin函数返回指向map中最后一个元素位置的反向迭代器,rend函数返回指向map中第一个元素之前位置的反向迭代器。
/********************************************
*范例编号:29_04
*范例说明:反向输出map中的元素
*********************************************/
01 #include < iostream>
02 #include < map>
03 using namespace std;
04 void main ()
05 {
06 map< int,int> mymap;
07 map< int,int>::reverse_iterator rit;
08 mymap[5]=10;
09 mymap[6]=200;
10 mymap[7]=90;
11 cout< < “容器中的元素:”< < endl;
12 cout< < “关键字 元素值”< < endl;
13 for ( rit=mymap.rbegin() ; rit != mymap.rend(); rit++ )
14 cout< < “ “< < rit->first< < “ “< < rit->second< < endl;
15 system(“pause”);
16 }
该函数范例的运行结果如图29-4所示。
图29-4 函数范例的运行结果
在map容器内部,元素按照关键字从小到大的顺序排列,因此,rbegin函数返回最大关键字元素的位置,而rend函数不是返回第一个元素的位置,而是返回第一个元素的前一个位置。
map容器中的容量类函数主要包括empty函数、size函数、max_size函数。
bool empty () const;
empty函数的功能是判断map容器是否为空,即map容器的大小是否为0。
该函数没有参数。
如果map容器为空,则返回true;否则,返回false。
/********************************************
*范例编号:29_05
*范例说明:判断map容器是否为空
*********************************************/
01 #include < iostream>
02 #include < map>
03 #include < string>
04 using namespace std;
05 void main ()
06 {
07 map< string,string> p,p2;
08 map< string,string>::iterator it;
09 p[“张居正”]=”湖北”;
10 p[“纪晓岚”]=”直隶”;
11 p[“徐达”]=”安徽”;
12 if (p.empty())
13 cout< < “容器p1为空”< < endl;
14 else
15 {
16 cout< < “容器p1:”< < endl;
17 for(it=p.begin();it!=p.end();it++)
18 cout< < “ [“< < it->first< < “]:”< < it->second;
19 cout< < endl;
20 }
21 if (p2.empty())
22 cout< < “容器p2为空”< < endl;
23 else
24 {
25 cout< < “容器p2:”< < endl;
26 for(it=p2.begin();it!=p2.end();it++)
27 cout< < “ [“< < it->first< < “]:”< < it->second;
28 cout< < endl;
29 }
30 system(“pause”);
31 }
该函数范例的运行结果如图29-5所示。
图29-5 函数范例的运行结果
empty函数并不会修改map容器中的内容,因此如果要清空map容器,则需要使用clear函数。
size_type size() const;
size函数的功能是返回map容器中元素的个数。
该函数没有参数。
函数返回map容器中元素的个数。
/********************************************
*范例编号:29_06
*范例说明:求出map容器中元素的个数
*********************************************/
01 #include < iostream>
02 #include < map>
03 #include < iomanip>
04 #include < string>
05 #include < iomanip>
06 using namespace std;
07 void main ()
08 {
09 map< string,string> mymap;
10 map< string,string>::iterator it;
11 mymap[“本草纲目”]=”李时珍”;
12 mymap[“三体”]=”刘慈欣”;
13 mymap[“明朝那些事儿”]=”当年明月”;
14 cout < < “map容器的元素个数: “ < < mymap.size() < < endl;
15 cout< < “ 关键字 元素值”< < endl;
16 for(it=mymap.begin();it!=mymap.end();it++)
17 cout< < setw(12)< < it->first< < setfill(‘ ‘)< < setw(12)< < it->second< < endl;
18 system(“pause”);
19 }
该函数范例的运行结果如图29-6所示。
图29-6 函数范例的运行结果
(1)size_type被定义为无符号整型。
(2)为了控制输出的对齐方式及空格数,可以使用流操作算子函数setiosflags和setw函数,但需要包含头文件iomanip.h。例如,setiosflags(ios::right)表示靠右端输出,setw(6)表示占用的宽度为6个字符。
size_type max_size () const;
max_size函数的功能是返回map容器中所能容纳的最大元素个数。
该函数没有参数。
函数返回map容器中能容纳的最大元素个数。
/********************************************
*范例编号:29_07
*范例说明:输出map容器中的元素个数和能容纳的最多元素数量
*********************************************/
01 #include < iostream>
02 #include < map>
03 #include < string>
04 using namespace std;
05 typedef struct university
06 {
07 string name;
08 string loaction;
09 }University;
10 void main ()
11 {
12 map< string,string> p;
13 map< string,string>::iterator it;
14 int i;
15 University u[]={{“清华大学”,”北京”},{“复旦大学”,”上海”},
16 {“南京大学”,”南京”},{“西北大学”,”西安”},{“湖南大学”,”长沙”}};
17 for (i=0; i< sizeof(u)/sizeof(u[0]); i++)
18 p[u[i].name]=u[i].loaction;
19 cout< < “map容器包含”< < p.size()< < “个元素.”< < endl;
20 for(it=p.begin();it!=p.end();it++)
21 cout< < “ [“< < it->first< < “]:”< < it->second< < endl;
22 cout< < “map容器最多可容纳的元素数量为:”< < p.max_size()< < endl;
23 system(“pause”);
24 }
该函数范例的运行结果如图29-7所示。
图29-7 函数范例的运行结果
map的存取类函数主要是下标运算符。
T&operator[] ( const key_type&x );
[]运算符的主要功能是存取map中的元素。如果x与map容器中的元素关键字相等,则[]运算符返回元素值的引用位置;否则,插入一个关键字和元素值。
参数x:被存取的元素对应的关键字。
函数返回关键字为x对应的元素值。
/********************************************
*范例编号:29_08
*范例说明:利用[]运算符存取map中的元素
*********************************************/
01 #include < map>
02 #include < iostream>
03 #include < string>
04 using namespace std;
05 void main ()
06 {
07 map< int,string> p;
08 int i;
09 string name[]={“西北大学”,”清华大学”,”西安交通大学”,”东北大学”,”东南大学”};
10 for(i=0;i< sizeof(name)/sizeof(name[0]);i++)
11 p[i]=name[i];
12 cout< < “map容器中的元素:”< < endl;
13 for(i=0;i< p.size();i++)
14 cout< < “p[“< < i< < “]:”< < p[i]< < endl;
15 cout< < “map容器的大小:”< < p.size()< < endl;
16 system(“pause”);
17 }
该函数范例的运行结果如图29-8所示。
图29-8 函数范例的运行结果
[]运算符是被C++重载的运算符,不是数组中某个元素的下标,而是map中元素的关键字。例如,mymap[6]表示关键字为6的元素。
map的操作类函数主要包括insert函数、erase函数、swap函数、clear函数、count函数和find函数。
pair< iterator,bool> insert ( const value_type&x );
iterator insert ( iterator position, const value_type&x );
template < class InputIterator>
void insert ( InputIterator first, InputIterator last );
insert函数的功能是插入一个新元素或者一个元素序列。其中,各个函数的功能如下。
(1)第1个函数确定序列中关键字与元素x匹配的元素y是否存在(如果!key_comp(x.first, y.first)&&!key_comp(y.first,x.first),则称关键字匹配)。如果没有,则创建这样的元素y,并以x的元素值初始化y。
(2)第2个函数返回insert(x),其中,使用it作为在控制序列中寻找插入点的开始位置。
(3)第3个函数插入范围为[first,last)的元素序列。
(1)参数x:用来初始化插入的元素。
(2)参数position:插入map中的元素的位置。
(3)参数first和last:迭代器,插入的元素范围为[first,last),包括first指向的元素,但是不包括last指向的元素。
(1)对于第1个函数来说,如果插入成功,则返回pair(it,true);否则,返回pair(it,false)。
(2)第2个函数返回新元素插入的位置。
(3)第3个函数没有返回值。
/********************************************
*范例编号:29_09
*范例说明:在map中插入元素并输出
*********************************************/
01 #include < iostream>
02 #include < map>
03 using namespace std;
04 void printmap(map< char,int> e);
05 void print_one_item(map< char,int>::const_iterator it);
06 void main()
07 {
08 map< char,int> mymap;
09 map< char,int>::iterator it;
10 int i;
11 for(i=0;i< 6;i++)
12 mymap.insert(pair< char,int>(‘a’+i,i));
13 cout< < “(key,value)\n”;
14 printmap(mymap);
15 cout< < “map容器中的元素个数:”< < mymap.size()< < endl;
16 system(“pause”);
17 }
18 void print_one_item(map< char,int>::const_iterator it)
19 {
20 cout< < “( “< < it->first< < “ , “< < it->second< < “ )”< < endl;
21 }
22 void printmap(map< char,int> e)
23 {
24 map< char,int>::const_iterator it;
25 for(it=e.begin();it!=e.end();it++)
26 print_one_item(it);
27 }
该函数范例的运行结果如图29-9所示。
图29-9 函数范例的运行结果
(1)每插入一个元素,map容器的大小就增加1。
(2)在map容器中,不允许有关键字相同的元素出现,因此在插入新元素时,首先要检查要插入的元素的关键字是否相等,如果相等,则不能插入。
void erase ( iterator position );
size_type erase ( const key_type&x );
void erase ( iterator first, iterator last );
erase函数的功能是从map容器中移除一个元素或一些元素。其中,各个函数的功能如下。
(1)第1个函数的功能是移除迭代器position指向的元素。
(2)第2个函数移除关键字为x的元素。
(3)第3个函数移除范围为[first,last]的元素序列。
(1)参数position:迭代器,指向要删除的元素。
(2)参数x:元素的关键字。
(3)参数first和last:迭代器,表示要删除的元素范围是[first,last]。
第1个函数和第3个函数没有返回值。
第2个函数的返回值是删除元素的个数。
/********************************************
*范例编号:29_10
*范例说明:输出移除前后map容器中的元素
*********************************************/
01 #include < iostream>
02 #include < map>
03 using namespace std;
04 void print_one_item(map< char,int>::const_iterator it)
05 {
06 cout< < “( “< < it->first< < “ , “< < it->second< < “ )”< < endl;
07 }
08 void print(map< char,int> e)
09 {
10 map< char,int>::const_iterator it;
11 for(it=e.begin();it!=e.end();it++)
12 print_one_item(it);
13 }
14 void main()
15 {
16 map< char,int> mymap;
17 map< char,int>::iterator it;
18 int i;
19 for(i=0;i< 5;i++)
20 mymap.insert(pair< char,int>(‘a’+i,i));
21 cout< < “map中的元素:”< < endl;
22 cout< < “(key,value)\n”;
23 print(mymap);
24 cout< < “移除第2个元素后:”< < endl;
25 it=mymap.begin();
26 it++;
27 mymap.erase(it);
28 print(mymap);
29 system(“pause”);
30 }
该函数范例的运行结果如图29-10所示。
图29-10 函数范例的运行结果
每移除一个元素,map容器的大小就减去1,并且系统自动调用析构函数释放其内存单元。
void swap ( map< Key,T,Compare,Allocator>&mp );
swap函数的功能是交换当前map容器与mp容器中的内容。
参数mp:一个map容器对象,与待交换的map容器中的元素类型一致。
该函数没有返回值。
/********************************************
*范例编号:29_11
*范例说明:输出交换前后两个map中的元素
*********************************************/
01 #include < iostream>
02 #include < map>
03 using namespace std;
04 void print_one_item(map< char,int>::const_iterator it)
05 {
06 cout< < “(“< < it->first< < “,”< < it->second< < “)”;
07 }
08 void print(map< char,int> e)
09 {
10 map< char,int>::const_iterator it;
11 for(it=e.begin();it!=e.end();it++)
12 print_one_item(it);
13 }
14 void main()
15 {
16 map< char,int> mymap1,mymap2;
17 map< char,int>::iterator it;
18 int i;
19 for(i=0;i< 5;i++)
20 {
21 mymap1.insert(pair< char,int>(‘a’+i,i));
22 mymap2.insert(pair< char,int>(‘A’+i,i+100));
23 }
24 cout< < “map1中的元素:”;
25 print(mymap1);
26 cout< < “\nmap2中的元素:”;
27 print(mymap2);
28 mymap1.swap(mymap2);
29 cout< < “\n交换mymap1和mymap2中的元素后:”< < endl;
30 cout< < “map1中的元素:”;
31 print(mymap1);
32 cout< < “\nmap2中的元素:”;
33 print(mymap2);
34 cout< < endl;
35 }
该函数范例的运行结果如图29-11所示。
图29-11 函数范例的运行结果
在调用swap函数时,需要保证两个map中的元素类型保持一致,但是元素个数可以不同。
void clear ();
clear函数的功能是清除map容器中的所有元素,并释放其内存空间。
该函数没有参数。
该函数没有返回值。
/********************************************
*范例编号:29_12
*范例说明:清除容器中的所有元素
*********************************************/
01 #include < iostream>
02 #include < map>
03 #include < string>
04 using namespace std;
05 void main ()
06 {
07 map< string,string> mymap;
08 map< string,string>::iterator it;
09 mymap[“数据结构”]=”严蔚敏”;
10 mymap[“机器学习”]=”周志华”;
11 mymap[“计算机网络”]=”谢希仁”;
12 cout < < “map容器中的元素个数:”< < mymap.size()< < endl;
13 cout < < “ 书名 作者”< < endl;
14 for ( it=mymap.begin() ; it != mymap.end(); it++ )
15 cout< < (*it).first< < “ : “< < (*it).second< < endl;
16 mymap.clear();
17 mymap[“操作系统”]=”汤子瀛”;
18 mymap[“算法导论”]=”潘金贵”;
19 cout< < “map容器中的元素个数:”< < mymap.size()< < endl;
20 cout < < “ 书名 作者”< < endl;
21 for ( it=mymap.begin() ; it != mymap.end(); it++ )
22 cout< < (*it).first< < “ : “< < (*it).second< < endl;
23 system(“pause”);
24 }
该函数范例的运行结果如图29-12所示。
图29-12 函数范例的运行结果
调用clear函数时,析构函数被自动调用,释放map对象的内存空间。
size_type count ( const key_type&x ) const;
count函数的功能是返回某个元素关键字的个数。
参数x:要查找的关键字。
如果找到关键字,则返回1;否则,返回0。
/********************************************
*范例编号:29_13
*范例说明:统计哪些关键字在map中,哪些不在map中
*********************************************/
01 #include < iostream>
02 #include < map>
03 #include < string>
04 using namespace std;
05 void main ()
06 {
07 map< string,int> map1,map2;
08 map< string,int>::iterator it;
09 int i,count=0;
10 string a[]={“南京大学”,”西北大学”,”郑州大学”,”河南工业大学”,”郑州轻工业大学”,
11 “河北大学”};
12 string b[]={“苏州大学”,”四川大学”,”燕山大学”,”河南工业大学”,”南京大学”,
13 “河南大学”,”西北大学”};
14 for(i=0;i< sizeof(a)/sizeof(a[0]);i++)
15 map1.insert(pair< string,int>(a[i],10+i));
16 for(i=0;i< sizeof(b)/sizeof(b[0]);i++)
17 map2.insert(pair< string,int>(b[i],10+i));
18 cout< < “map1中的元素:”< < endl;
19 for(it=map1.begin();it!=map1.end();it++)
20 cout< < “(“< < it->first< < “,”< < it->second< < “)”< < endl;
21 cout< < “map2中的元素:”< < endl;
22 for(it=map2.begin();it!=map2.end();it++)
23 cout< < “(“< < it->first< < “,”< < it->second< < “)”< < endl;
24 cout< < endl;
25 for (i=0; i< sizeof(a)/sizeof(a[0]); i++)
26 {
27 cout< < a[i];
28 if (map2.count(a[i])>0)
29 {
30 cout< < “同时在”< < “map1容器和map2容器中”< < endl;
31 count++;
32 }
33 else
34 cout< < “在map1容器中,但不在map2容器中”< < endl;
35 }
36 cout< < “同时在map1和map2容器中的元素个数为:”< < count< < endl;
37 system(“pause”);
38 }
该函数范例的运行结果如图29-13所示。
图29-13 函数范例的运行结果
因为map中不允许有重复的关键字,所以count函数的返回值只能是1和0。
iterator find ( const key_type&x );
const_iterator find ( const key_type&x ) const;
find函数的功能是在map容器中查找关键字为x的元素,如果找到,则返回迭代器。
参数x:待查找的关键字。
如果找到关键字为x的元素,则返回该元素的迭代器;否则,返回结束位置的迭代器。
/********************************************
*范例编号:29_14
*范例说明:查找元素并输出查找到的元素
*********************************************/
01 #include < iostream>
02 #include < map>
03 #include < string>
04 using namespace std;
05 void DispMap(map< string,int> p);
06 void main ()
07 {
08 map< string,int> p;
09 map< string,int>::iterator it;
10 p.insert(pair< string, int>(“南京大学”, 1));
11 p.insert(pair< string, int>(“东南大学”, 2));
12 p[“南京航空航天大学”]=3;
13 p[“南京理工大学”]=4;
14 p[“南京农业大学”]=5;
15 p[“中国矿业大学”]=6;
16 cout< < “容器中的元素个数:”< < p.size()< < endl;
17 DispMap(p);
18 it=p.find(“南京农业大学”);
19 if (it != p.end())
20 p.erase (it);
21 p.erase ((it=p.find(“南京理工大学”))!=p.end()?it:p.begin());
22 cout< < “容器中的元素个数:”< < p.size()< < endl;
23 DispMap(p);
24 cout< < “利用map容器中的find()方法查找元素:”< < endl;
25 cout< < “东南大学:”< < p.find(“东南大学”)->second< < endl;
26 cout< < “南京航空航天大学:”< < p.find(“南京航空航天大学”)->second< < endl;
27 system(“pause”);
28 }
29 void DispMap(map< string,int> p)
30 {
31 map< string,int>::iterator it;
32 int i=1;
33 for(it=p.begin();it!=p.end();it++,i++)
34 cout< < i< < “. [“< < it->first< < “]=”< < it->second< < endl;
35 }
该函数范例的运行结果如图29-14所示。
图29-14 函数范例的运行结果
key_type是一种关键字的数据类型。