字符串、向量和数组

命名空间的 using 声明

using 声明的形式:

using namespace::name;

每个名字都需要独立的 using 声明
头文件不应包含 using 声明

标准库类型 string

使用 string 类型必须首先包含 string 头文件:

#include <string>
using std::string;

定义和初始化 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组成的串

使用等号(=)初始化一个变量,实际上执行的是拷贝初始化,编译器把等号右侧的初始值拷贝到新创建的对象中去,如果不使用等号,则执行的是直接初始化
对于多个值进行初始化的情况,使用拷贝初始化的方式为:

string s1 = string(10, 'c');

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                    等性判断对字母的大小写敏感
<, <=, >, >=                利用字符在字典中的顺序进行比较, 且对字母的大小写敏感‘’

在执行读取操作时, string 对象会自动忽略开头的空白(即空格符、换行符、制表符等等)并从第一个真正的字符开始读起, 直到遇见下一处空白为止

使用 getline 读取一整行

使最终得到的字符串中保留输入时的空白符,参数是一个输入流和一个 string 对象,从给定的输入流中读入内容,直到遇到换行符为止,换行符也被读入,然后将所读内容存到那个 string 对象中去,但最终换行符实际上被丢弃了,得到的 string 对象中并不包含该换行符

string 的 empty 和 size 操作

empty 函数根据 string 对象是否为空返回一个对应的布尔值, 使用点操作符指明是哪个对象执行了 empty 函数
size 函数返回 string 对象的长度

string::size_type 类型

size 函数返回的是一个 string::size_type 类型的值,是一个无符号类型的值而且能够放下任何 string 对象的大小,所有用于存放 string 类的 size 函数返回值的变量,都应该是 string::size_type 类型

比较 string 对象

1、 如果两个string对象长度不同,而且string对象的每个字符都与较长string对象对应位置上的字符相同,就说较短string对象小于较长string对象。
2、 如果两个string对象在某些对应的位置上不一会,则string对象比较的结果其实是string对象中第一对相异字符比较的结果

为 string 对象赋值

允许把一个对象的值赋给另一个对象

string s1(10, 'e'), s2;
s2 = s1;

两个 string 对象相加

string s1 = "hello", s2 = "world\n";
string s3 = s1 + s2;
s1 += s2;

字符值和 string 对象相加

当把string对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个加法运算符(+)的两侧的运算对象至少有一个是string

处理 string 对象中的字符

cctype头文件中定义了一组标准库函数

isalnum(c)          当c是字母或数字为真
isalpha(c)          当c是字母时为真
iscntrl(c)          当c是控制字符时为真
isdigit(c)          当c是数字时为真
isgraph(c)          当c不是空格但可打印时为真
islower(c)          当c是小写字母时为真
isprint(c)          当c是可打印字符时为真(即c时空格或c具有可视形式)
ispunct(c)          当c是标点符号时为真(即c不是控制字符、数字、字母、可打印空白中的一种)
isspace(c)          当c是空白时为真(即c是空格、横向制表符、纵向制表符、回车符、换行符、进纸符中的一种)
isupper(c)          当c是大写字母时为真
isxdigit(c)         当c是十六进制数字时为真
tolower(c)          如果c是大写字母,输出对应的小写字母;否则原样输出c
toupper(c)          如果c是小写字母,输出对应的大写字母;否则原样输出c

范围for(range for)语句

语法形式为:

for(declaration : expression)
    statement

其中,expression部分是一个对象,用于标识一个序列。declaration部分负责定义一个变量,该变量将被用于访问序列中的基础元素。每次迭代,declaration部分的变量会被初始化为expression部分的下一个元素值,如果想改变其值,必须把declaration定义为引用类型

标准库类型vector

表示对象的集合,其中所有对象类型都相同,每个对象都有一个与之对应的索引,索引用于访问对象
声明为:

#include <vector>
using std::vector;

vector是一个类模板,编译器根据模板创建类或函数的过程称为实例化, 使用模板时, 需要指出编译器应把类或函数实例化成何种类型

定义和初始化vector对象

vector<T> v1                            v1是一个空vector,它潜在的元素是T类型的,执行默认初始化
vector<T> v2(v1)                        v2中包含有v1所有元素的副本
vector<T> v2 = v1                       等价于v2(v1),v2中包含有v1中所有元素的副本
vector<T> v3(n, val)                    v3包含有n个重复的元素,每个元素的值都是val
vector<T> v4(n)                         v4包含有n个重复执行了值初始化的对象
vector<T> v5{a,b,c,......}              v5包含有初始值个数的元素,每个元素被赋予相应的初始值
vector<T> v5 = {a,b,c,......}           等价于v5{a,b,c,......}

向vector对象中添加元素

push_back 负责把一个值当成vector对象的尾元素“压到”vector对象的“尾端”,不可用下标形式添加-

其他vector操作

v.empty()                               如果v不含有任何元素,返回真;否则返回假
v.size()                                返回v中元素的个数
v.push_back()                           向v的尾端添加一个值为t的元素
v[n]                                    返回v中第n个位置上元素的引用
v1 = v2                                 用v2中元素的拷贝替换v1中的元素
v1 = {a,b,c,......}                     用列表中元素的拷贝替换v1中的元素
v1 == v2                                v1和v2相等当且仅当他们的元素数量相同且对应位置的元素值都相同
v1 != v2
<, <=, >, >=                            顾名思义,以字典顺序进行比较

使用size_type,需首先指定它是哪种类型定义的,vector对象的类型总是包含着元素的类型

vector<int>::size_type                  //正确
vector::size_type                       //错误

迭代器

使用迭代器

获取迭代器不是使用取地址符,有迭代器的类型同时拥有返回迭代器的成员
begin成员负责返回指向第一个元素(或第一个字符)的迭代器
end成员返回的迭代器被称作尾后迭代器或简称尾迭代器,负责返回指向容器“尾元素的下一个位置”的迭代器
如果容器为空,则begin和end返回的是同一个迭代器,都是尾后迭代器
begin和end返回的具体类型由对象是否是常量决定,如果对象是常量,begin和end返回const_iterator; 如果对象不是常量,返回iterator
不能在范围for循环中间向vector对象添加元素,任何一种可能改变vector对象容量的操作,都会使该vector对象的迭代器失效

迭代器运算符

*iter                                   //返回迭代器iter所指元素的引用
iter->mem                               //解引用iter并获取该元素的名为mem的成员,等价于(*iter).mem
++iter                                  //令iter指示容器中的下一个元素
--iter                                  //令iter指示容器中的上一个元素
iter1 == iter2                          //判断两个迭代器是否相等(不相等),如果两个迭代器指示的是同一个元
iter1 != iter2                          //素或它们是同一个容器的为后迭代器,则相等;反之,不相等

将迭代器从一个元素移动到另外一个元素

使用递增(++)运算符来从一个元素移动到下一个元素
end返回的迭代器并不实际指示某个元素,所以不能对其进行递增或解引用操作

迭代器类型

vector<int>::iterator it;                   //it能读写vector<int>的元素
string::iterator it2;                       //it2能读写string对象中的字符
vector<int>::const_iterator it3;            //it3只能读元素,不能写元素
string::const_iterator it4;                 //it4只能读元素,不能写元素

迭代器运算

iter + n                                迭代器加上一个整数值仍得一个迭代器,迭代器指示的新位置与原来相比向前移动了若干元素。
                                        结果迭代器或者指示容器内的一个元素,或者指示容器尾元素的下一个位置
iter - n                                迭代器减去一个整数值仍得一个迭代器,迭代器指示的新位置与原来相比向后移动了若干元素。  
                                        结果迭代器或者指示容器内的一个元素,或者指示容器尾元素的下一个位置
iter1 += n                              迭代器加法的复合赋值语句,将iter1加n的结果赋值给iter1
iter1 -= n                              迭代器减法的复合赋值语句,将iter1减n的结果赋值给iter1
iter1 - iter2                           两个迭代器相减的结果是它们之间的距离,也就是说,将运算符右侧的迭代器向前移动差值个元
                                        素将得到左侧的迭代器。参与运算的两个迭代器必须指向的是同一个容器中的元素或者尾元素的
                                        下一个位置
>, >=, <, <=                            迭代器的关系运算符,如果某迭代器指向的容器位置在另一个迭代器所指位置之前,则说前者小
                                        于后者。参与运算的两个迭代器必须指向的是同一个容器中的元素或者尾元素的下一个位置

距离指的是右侧的迭代器向前移动多少位置就能追上左侧的迭代器,其类型是名为difference_type的带符号整型数

数组

定义和初始化内置数组

const unsigned sz = 3;
int ial[sz] = {0, 1, 2};                //含有3个元素的数组,元素值分别是0,1,2
int a2[] = {0, 1, 2};                   //维度是3的数组
int a3[5] = {0, 1, 2};                  //等价于a3[] = {0, 1, 2, 0, 0}
string a4[3] = {"hi", "bye"};           //等价于a4[] = {"hi", "bye", ""}
int a5[2] = {0, 1, 2};                  //错误:初始值过多

不能将数组的内容拷贝给其他数组作为其初始值,也不能用数组为其他数组赋值
在使用数组下标的时候,通常将其定义为size_t类型,在cstddef头文件中定义

数组和指针

在很多使用到数组名字的地方,编译器都会自动将其替换为一个指向数组首元素的指针
当使用数组作为auto变量的初始值时,推断得到的类型是指针而非数组
当时用decltype关键字时不会发生转换成指针,而是返回数组类型
指针运算包括解引用、递增、比较、与整数相加、两个指针相减等
给一个指针加上(减去)某个整数值,结果仍是指针
两个指针相减的结果是它们之间的距离,类型是一种名为ptrdiff_t的标准库类型,定义在cstddef头文件中
如果两个指针分别指向不相关的对象,则不能比较

使用数组初始化vector对象

int int_arr[] = {0, 1, 2, 3, 4, 5};
vector<int> ivec(begin(int_arr), end(int_arr));

多维数组

当一个数组的元素仍然是数组时,通常使用两个维度来定义它:一个维度表示数组本身大小,另外一个维度表示其元素(也是数组)大小
允许使用花括号括起来的一组值初始化多维数组
在初始化多维数组时,并非所有元素的值都必须包含在初始化列表中
在使用range for时,要将最外层的循环控制变量设为引用类型,如若不用引用,则会退化为指针,外层循环步长错误
程序使用多维数组名字时,也会将其自动转化成指向数组首元素的指针


鱼儿咬了猫
6 声望2 粉丝