string
定义和初始化string对象
string s1;//默认初始化,s1是空字符串
string s2 = s1;//拷贝初始化
string s3(s1);//直接初始化
string s4 = "hello";//拷贝初始化
string s5("hello");//直接初始化
string s6(10, 'c');//直接初始化,s4的内容是cccccccccc
string s7 = 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中字符的个数,返回值是string::size_type类型的值
s[n];//返回第n个字符的引用,位置n从0记起
s1 + s1//返回s1和s2连接后的结果,字面值和string对象相加时要保证加法运算符两侧至少有一个string对象
s1 = s2//用s2的副本代替s1中原来的字符
s1 == s2//字符完全一样,则返回true,对大小写敏感
s1 != s2
<,<=,>,>=
希望在最终的字符串中保留输入时的空白符,使用getline函数替代>>运算符。
getline只要一遇到换行符久结束读取操作,返回结果。若只有换行符,则返回空字符串。
//>>运算符 和getline均返回它的流参数
while(cin >> s1){...}//s1不包含空格
while(getline(cin, s2){...}//s2包含空格,不包含换行符
处理string对象中的字符
在cctype(ctype.h)头文件中定义了一组标准库函数来处理string对象中的字符
isalnum(c)//当c是字母或数字时为真
isalpha(c)//当c是字母时为真
iscntrl(c)//当c时控制字符时为真
isdigit(c)//当c是数字时为真
isgraph(c)//当c不是空格但可打印时为真
islower(c)//当c是小写字母时为真
isupper(c)//当c是大写字母时为真
isprint(c)//当c是可打印字符时为真(c是空格或具有可视形式)
ispunct(c)//当c是标点符号时为真(c不是控制字符、数字、字母、可打印空白字符中的一种)
isspace(c)//当c是空白字符时为真(c是空格、制表符、回车符、换行符的一种)
isxdigit(c)//当c是十六进制时为真
tolower(c)//输出c的小写字母
toupper(c)//输出c的大写字母
使用范围for语句遍历每个字符并执行某种操作(范围for循环语句体内不应改变其所遍历序列的大小)
string str("hello world!");
for (auto c:str)//c是char类型
cout << c << endl;
for (auto &c:str)//要想改变字符的值,要把循环变量定义成引用类型
c = toupper(c);
vector
标准库类型vector
//定义初始化vector对象
vector<T> v1;//空vector,执行默认初始化
vector<T> v2(v1);//v2中包含v1中所有元素的副本
vector<T> v3 = v2;//v3中包含v2中所有元素的副本
vector<T> v4(n, val);//v4中包含n个重复元素val
vector<T> v5(n);//v5包含了n个重复执行了值初始化的对象
vector<T> v6{a, b, c};//v6包含初始值个数的元素,每个元素被赋予相应的初始值
vector<T> v7={a, b, c};//等价于v6
//vector操作
v.empty() //是否含有元素
v.size() //返回v中元素个数 vector<int>::size_type类型
v.push_back(t)//向v的尾端添加一个值为t的元素
v[n] //返回中第n个位置上的引用,下标可访问已有元素,不可添加元素
v1 = v2 //用v2的元素拷贝替换v1中的元素
v1 = {a, b, c}//用列表中的元素拷贝替换v1中的元素
v1 == v2 //判断是否数量且对应位置元素值相等
v1 != v2
<, <=, >=, >//以字典顺序进行比较
迭代器
每个容器定义了一个名为iterator的类型。
*iter //返回迭代器iter所指元素的引用
iter->men //解引用iter并获取该元素的名为men的成员,等价于(*iter).men
++iter //令iter指向容器中的下一个元素
--iter
iter1 == iter2//判断两个迭代器是否指向同一个元素或同为尾后迭代器
iter1 != iter2
迭代器类型:iterator和const_iterator
vector<int>::iterator it1;
string::iterator it2;
vector<int>::const_iterator it3;//只读
string::const_iterator it4;
迭代器支持的运算
iter + n //迭代器向前移动n个元素
iter - n //迭代器向后移动了n个元素
iter += n //iter加n的结果赋给iter
iter -= n
iter1 - iter2 //两个迭代器相减
>, >=, <=, < //参与关系运算符的两个迭代器必须指向同一个容器中的元素或者尾元素的下一个位置
//迭代器应用二分查找
vector<int> v = {...};
vector<int>::iterator beg = v.begin();
vector<int>::iterator end = v.end();
vector<int>::iterator mid = beg + (end-beg)/2;
while(beg != end){
if(sought < *mid)//查找sought
end = mid;
else
beg = mid+1;
mid = beg + (end - beg)/2;
}
只要两个迭代器指向的是同一个容器中的元素或者尾元素的下一个位置,就能将其相减,等到的结果是两个迭代器的距离,类型是名为difference_type的带符号整数。
数组
数组的大小确定不变,不能随意向数组中增加元素,如果不清楚元素的确切个数,请使用vector。
数组是一种复合类型。数组的声明形如a[d]
,其中a是数组的名字,d是数组的维度(数组中元素的个数)。编译时维度应该是已知的,即维度必须是一个常量表达式。
定义数组的时候必须指定数组的类型,不允许使用auto关键字来推断类型。默认情况下,数组的元素被默认初始化。如果定义的是某种内置类型的数组,默认初始化会令数组含有未定义的值。
//数组初始化
const unsigned sz = 3;
int arr[sz] = {1,2,3};
int arr1[] = {1,2,3};
int arr2[5] = {1,2,3,4,5};
string arr3[3] = {"hello", "world"};//支持部分初始化,未初始化执行默认初始化。
int arr4[2] = {1,2,3};//error
int arr5[] = arr;//error:不能将数组的内容拷贝给其他数组作为初始值,也不能用数组给其他数组赋值
//字符数组,字符串字面值初始化字符数组
char a1[] = {'c','+','+'};
char a2[] = {'c','+','+','\n'};//含有显式的空字符
char a3[] = "C++";
const char a4[6] = "ABCDEF";//error,字符串结尾含有空字符,字符大小至少为7
//数组支持范围for
int a[] = {1,2,3,4,5};
for (auto i : a)
cout << i << " ";
cout << endl;
指向数组的指针也是迭代器
在很多用到数组名字的地方,编译器都把名字自动地替换为一个指向数组首元素的指针。vector和string的迭代器支持的运算,数组的指针全都支持。
标准库函数begin和end
数组可以通过计算得到尾后指针,但这种用法易出错。C++11新标准引入两个名为begin和end函数(iterator头文件中),与容器中两个同名成员功能类似。
int arr[] = {0,1,2,3,4,5,6,7,8,9};
int *beg = begin(arr);//标准库函数,不同于容器成员函数调用方法
int *en = end(arr);
beg += 1;//指针加上一个整数还是一个指针,此处指向下一个元素
//数组两指针相减的结果类型是ptrdiff_t的标准库类型(cstddef头文件)
auto n = end(arr) - begin(arr);//n的值是10,也就是元素数量
解引用和指针运算的交互
int arr[] = {1,0,2,4};
int first = *arr;//把first初始化为1,等价于first = arr[0]
int last = *(arr + 3);//把last初始化为4,等价于last = arr[4]
int *p = &arr[2];//p指针指向索引为2的元素
int j = p[-2]//j = a[0]
不允许使用一个数组为另一个数组赋初值,也不允许使用vector对象为数组赋初值,但是允许数组来初始化vector对象。
int int_arr[] = {0,1,2,3,4,5};
vector<int> ivec(begin(int_arr), end(int_arr));//两个指针指向用来初始化的值在数组中的位置(可以是数组的一部分)