【C++】《C++ Primer 》第三章
第三章 字符串、向量和数组
一、命名空间的using声明
- 使用某个命名空间:例如 using std::cin表示使用命名空间std中的名字cin。
- 头文件的代码一般不应该使用using声明,这是因为头文件的内容会拷贝到所有引用它的文件中去,这样使用了该头文件的源码也会使用这个声明,会带来风险。
二、标准库类型string
1. 定义和初始化string对象
1.1. 初始化string对象的方式
方式 | 含义 |
---|---|
string s1 | 默认初始化,s1是一个空串 |
string s2(s1) | s2是s1的副本 |
string s2 = s1 | 等价于s2(s1),s2是s1的副本 |
string s3("value") | s3是字面值“value”的副本,除了字面值最后的那个空字符外 |
string s3 = "value" | 等价于s3("value"),s3是字面值"value"的副本 |
string s4(n, 'c') | 把s4初始化为由连续n个字符c组成的串 |
1.2. 拷贝初始化(copy initialization)和 直接初始化(direct initialization)
- 拷贝初始化(copy initialization):使用等号=将一个已有的对象拷贝到正在创建的对象。
- 直接初始化(direct initialization):通过括号给对象赋值。
2. string对象上的操作
2.1. string的操作
操作 | 含义 |
---|---|
os << s | 将s写到输出流os当中,返回os |
is >> s | 从is中读取字符串赋给s,字符串以空白分割,返回is |
getline(is, s) | 从is中读取一行赋给s,返回is |
s.empty() | s为空返回true,否则返回false |
s.size() | 返回s中字符的个数 |
s[n] | 返回s中第n个字符的引用,位置n从0计起 |
s1+s2 | 返回s1和s2连接后的结果 |
s1=s2 | 用s2的副本代替s1中原来的字符 |
s1==s2 | 如果s1和s2中所含的字符完全一样,则它们相等;string对象的相等性判断对字母的大小写敏感 |
s1!=s2 | |
<, <=, >, >= | 利用字符在字典中的顺序进行比较,且对字母的大小写敏感 |
2.2. 读写string对象
- 执行读操作>>:忽略掉开头的空白(包括空格、换行符和制表符),直到遇到下一处空白为止。
- getline:读取一整行,包括空白符。
string s;
cin >> s; // 输入 " hello world! "
cout << s; // 输出 "hello"
string s1, s2;
cin >> s1 >> s2; // 输入 " hello world! "
cout << s1 << s2; // 输出 "helloworld!"
string line;
while(getling(cin, line)) // 每次读入一整行,直到到达文件末尾
cout << line << endl;
2.3. 字面量和string对象相加
- 字面值和string是不同的类型。但是标准库允许把字符字面量和字符串字面量转换成string类型。
- 当把字符字面量和字符串字面量和string对象混在一条语句时,必须确保每个加法运算符的两侧至少有一个时是string对象。
3. 处理string对象中的字符
- 建议使用C++版本的C标准库头文件。
3.1. cctype头文件中的函数
函数 | 含义 |
---|---|
isalnum(c) | 当c是字母或数字时为真 |
isalpha(c) | 当c是字母时为真 |
iscntrl(c) | 当c是控制字符时为真 |
isdigit(c) | 当c是十进制数字时为真 |
isgraph(c) | 当c不是空格但可以打印时为真 |
islower(c) | 当c是小写字母时为真 |
isprint(c) | 当c是可打印字符时为真(c是空格或者具有可视形式) |
ispunct(c) | 当c是标点符号时为真 |
isspace(c) | 当c是空白时为真(空格、横向制表符、纵向制表符、回车符、换行符、进纸符) |
isupper(c) | 当c是大写字母时为真 |
isxdigit(c) | 当c是十六进制数字时为真 |
tolower(c) | 当c是大写字母,输出对应的小写字母;否则原样输出c |
toupper(c) | 当c是小写字母,输出对应的大写字母;否则原样输出c |
3.2. 使用基于范围for语句
- for (auto c: str),或者 for (auto &c: str)使用引用直接改变字符串中的字符。
4. 本节习题
4.1. 练习3.6
4.2. 练习3.11
三、标准库类型vector
- 使用它:#include 然后 using std::vector;
- vector是一个容器,也是一个类模板。
- 类模板:本身不是类,但可以实例化instantiation出一个类。 vector是一个模板, vector是一个类型。
- 通过将类型放在类模板名称后面的尖括号中来指定类型,如vector v。
1. 定义和初始化vector对象
1.1. 定义和初始化vector对象
方式 | 含义 |
---|---|
vector v1 | v1是一个空vector,它潜在的元素是T类型的,执行默认初始化 |
vector v2(v1) | v2中包含有v1所有元素的副本 |
vector v2 = v1 | 等价于v2(v1),v2中包含v1所有元素的副本 |
vector v3(n, val) | v3包含了n个重复的元素,每个元素的值都是val |
vector v4(n) | v4包含了n个重复地执行了值初始化的对象 |
vector v5{a, b, c...} | v5包含了初始值个数的元素,每个元素被赋予相应的初始值 |
vector v5={a, b, c...} | 等价于v5{a, b, c...} |
2. 向vector对象中添加元素
- 向vector对象中添加元素
- v.push_back(e) 在尾部增加元素。
- 如果循环体内部包含有向vector对象添加元素的语句,则不能使用范围for循环,因为在范围for循环不应改变其所遍历序列的大小。
- vector对象(以及string对象)的下标运算符,只能对确知已存在的元素执行下标操作,不能用于添加元素。
- 只能对确知已存在的元素执行下标操作。
3. 其他vector操作
3.1. 其他vector操作
操作 | 含义 |
---|---|
v.emtpy() | 如果v不含有任何元素,返回真;否则返回假 |
v.size() | 返回v中元素的个数 |
v.push_back(t) | 向v的尾端添加一个值为t的元素 |
v[n] | 返回v中第n个位置上元素的引用 |
v1 = v2 | 用v2中的元素拷贝替换v1中的元素 |
v1 = {a,b,c...} | 用列表中元素的拷贝替换v1中的元素 |
v1 == v2 | v1和v2相等当且仅当它们的元素数量相同且对应位置的元素值都相同 |
v1 != v2 | 同上 |
<,<=,>, >= | 以字典顺序进行比较 |
四、迭代器介绍
- 所有标准库容器都可以使用迭代器,但是是由少数几种同时支持下标运算符。
- 严格来说,string对象不属于容器类型,但是它支持很多和容器类型类似的操作。
- 类似于指针类型,迭代器也提供了对对象的间接访问。
1. 使用迭代器
1.1. 迭代器运算符
运算符 | 含义 |
---|---|
*item | 返回迭代器iter所指向的元素的引用 |
item->mem | 解引用iter并获取该元素的名为mem的成员,等价于 ** (*item).mem ** |
++item | 令iter指示容器中的下一个元素 |
--iter | 令iter指示容器中的上一个元素 |
iter1 == iter2 | 判断两个迭代器是否相等。如果两个迭代器指向的同一个元素或者同一个容器的尾后迭代器则相等,反之不相等。 |
1.2. 迭代器类型
vector<int>::iterator it; // it能读写vector<int>的元素
string::iterator it2; // it2能读写string对象中的字符
vector<int>::const_iterator it3; // ii3只能读vector<int>的元素
string::const_iterator it4; // it4只能读string对象中的字符
1.3. cbegin和cend
为了专门的得到const_iterator类型的返回值,C++11引入了cbegin和cend。它们类似于begin和end,分别返回指向容器的第一个元素和最后元素下一个位置的迭代器。
但是不同的是,它们不论对象本身是否是常量,返回值都是const_iterator。
2. 迭代器运算
2.1. 迭代器运算
运算符 | 含义 |
---|---|
iter + n | 迭代器加上一个整数值仍得到一个迭代器,迭代器指示的新位置和原来相比向前移动了若干个元素。结果迭代器或者指示容器内的一个元素,或者指示容器尾元素的下一位置。 |
iter - n | 迭代器减去一个证书仍得到一个迭代器,迭代器指示的新位置比原来向后移动了若干个元素。结果迭代器或者指向容器内的一个元素,或者指示容器尾元素的下一位置。 |
iter1 += n | 迭代器加法的复合赋值语句,将iter1加n的结果赋给iter1。 |
iter1 -= n | 迭代器减法的复合赋值语句,将iter2减n的加过赋给iter1。 |
iter1 - iter2 | 两个迭代器相减的结果是它们之间的距离,也就是说,将运算符右侧的迭代器向前移动差值个元素后得到左侧的迭代器。参与运算的两个迭代器必须指向的是同一个容器中的元素或者尾元素的下一位置。 |
>、>=、<、<= | 迭代器的关系运算符,如果某迭代器 |
2.2. 使用迭代器完成二分搜索
auto beg = text.begin(), en = text.end();
auto mid = text.begin() + (en - beg) / 2;
while (mid != en && *mid != result) {
if (result < *mid) en = mid;
else beg = mid + 1;
// 迭代器的加法不存在,所以mid=(beg+en)/2不合法。但是支持迭代器和整数的加减法运算,即控制其左右移动。
mid = begin + (en - beg) / 2 ;
}
五、数组
- 它相当于vector的低级版,长度固定,特殊情况下性能更好,但是缺少灵活性。现代的C++程序应当尽量使用vector和迭代器,避免使用内置数组和指针;应该尽量使用string,避免使用C风格的基于数组的字符串。
1. 定义和初始化内置数组
1.1. 定义和初始化内置数组
- 初始化:char input_buffer[buffer_size];,长度必须是const表达式,或者不写,让编译器自己推断。
- 数组不允许直接赋值给另一个数组。
1.2. 访问数组元素
- 数组下标的类型:size_t 。
- 字符数组的特殊性:结尾处有一个空字符,如 char a[] = "hello";
- 用数组初始化 vector: int a[] = {1,2,3,4,5}; vector v(begin(a), end(a));
1.3. 数组和指针
- 使用数组时,编译器一般会把它转换成指针。
- 标准库类型限定使用的下标必须是无符号类型,而内置的下标可以处理负值。
- 指针访问数组:在表达式中使用数组名时,名字会自动转换成指向数组的第一个元素的指针。
六、多维数组
- 严格来说,C++中没有多维数组,它其实是数组的数组。不建议使用它,直接使用 vector<vector > 更好。
【C++】《C++ Primer 》第三章的更多相关文章
- [Effective Java]第三章 对所有对象都通用的方法
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- 对于所有对象都通用方法的解读(Effective Java 第三章)
这篇博文主要介绍覆盖Object中的方法要注意的事项以及Comparable.compareTo()方法. 一.谨慎覆盖equals()方法 其实平时很少要用到覆盖equals方法的情况,没有什么特殊 ...
- 【C++】《Effective C++》第三章
第三章 资源管理 条款13:以对象管理资源 当申请一块动态内存时,可能会发生内存泄漏. class Investment {}; void f() { Investment* pInv = creat ...
- 《Effective Java 第三版》新条目介绍
版权声明:本文为博主原创文章,可以随意转载,不过请加上原文链接. https://blog.csdn.net/u014717036/article/details/80588806前言 从去年的3月份 ...
- 【软件构造】第三章第三节 抽象数据型(ADT)
第三章第三节 抽象数据型(ADT) 3-1节研究了“数据类型”及其特性 ; 3-2节研究了方法和操作的“规约”及其特性:在本节中,我们将数据和操作复合起来,构成ADT,学习ADT的核心特征,以及如何设 ...
- 《Django By Example》第三章 中文 翻译 (个人学习,渣翻)
书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:第三章滚烫出炉,大家请不要吐槽文中 ...
- 《Linux内核设计与实现》读书笔记 第三章 进程管理
第三章进程管理 进程是Unix操作系统抽象概念中最基本的一种.我们拥有操作系统就是为了运行用户程序,因此,进程管理就是所有操作系统的心脏所在. 3.1进程 概念: 进程:处于执行期的程序.但不仅局限于 ...
- Python黑帽编程3.0 第三章 网络接口层攻击基础知识
3.0 第三章 网络接口层攻击基础知识 首先还是要提醒各位同学,在学习本章之前,请认真的学习TCP/IP体系结构的相关知识,本系列教程在这方面只会浅尝辄止. 本节简单概述下OSI七层模型和TCP/IP ...
- 《Entity Framework 6 Recipes》中文翻译系列 (11) -----第三章 查询之异步查询
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第三章 查询 前一章,我们展示了常见数据库场景的建模方式,本章将向你展示如何查询实体 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (19) -----第三章 查询之使用位操作和多属性连接(join)
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 3-16 过滤中使用位操作 问题 你想在查询的过滤条件中使用位操作. 解决方案 假 ...
随机推荐
- .pfx和.Cer 证书
通常情况下,作为文件形式存在的证书一般有三种格式: 第一种:带有私钥的证书,由Public Key Cryptography Standards #12,PKCS#12标准定义,包含了公钥和私钥的二进 ...
- TMOOC-1709-小明复仇
题目描述 小明所在的世界上一共有n个城市,城市间有m条双向道路.小明现在在城市1,他想到位于城市n的小韩隆家询问他为什么没有将自己的五三复原完成.由于小韩隆手下有许多小弟,小明担心自己可能再也回不来, ...
- 深入理解Java虚拟机(十)——线程安全与锁优化
什么是线程安全 当多个线程同时访问一个对象的时候,不需要考虑什么额外的操作就能获取正确的值,就是线程安全的. 线程安全的程度 1.不可变 不可变的对象一定是线程安全的,因为值始终只有一个. final ...
- git clone 速度太慢解决方法
本来想下载一个翻墙软件,实在是忍受不了每秒十几K的龟速,查阅各种资料,终于找到了失传已久的秘籍 先附图,实测有效,这速度简直要上天了啊啊啊啊啊(只支持HTTPS方式,SSH无效) 方案:使用githu ...
- Zabbix 新版微信告警-转载
Zabbix 新版微信告警 Zabbix可以通过多种方式把告警信息发送到指定人,常用的有邮件,短信报警方式,但是越来越多的企业开始使用zabbix结合微信作为主要的告警方式,这样可以及时有效的把告警信 ...
- Vscode:常用的插件
Chinese (Simplified) Language Pack for Visual Studio Code==>汉化 Live Server==>运行代码 ESLint==> ...
- Greenplum 性能优化之路 --(一)分区表
一.什么是分区表 分区表就是将一个大表在物理上分割成若干小表,并且整个过程对用户是透明的,也就是用户的所有操作仍然是作用在大表上,不需要关心数据实际上落在哪张小表里面.Greenplum 中分区表的原 ...
- 系统类 字符串String类
java编程语言中的字符串. 在java中,String类是不可变的,对String类的任何改变,都是返回一个新的String类对象. String 对象是 System.Char 对象的有序集合,用 ...
- Javascript 根据文件名判断是否未图片
var isImage = (/\.(gif|jpe?g|tiff?|png|webp|bmp)$/i).test(filename)
- (30)ASP.NET Core3.1 集成Apollo快速安装与使用
1.介绍 Apollo(阿波罗)是携程框架部研发并开源的一款生产级的配置中心产品,它能够集中管理应用在不同环境.不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限.流程治理等特性,适用 ...