C++字符串_数组_向量
标准库类型string
标准库类型string表示可变长的字符序列,但使用string类型必须首先包含string头文#include < string >
定义和初始化string对象
string s1; //默认初始化,s1是一个空字符串
string s2(s1) //s2是s1的副本
string s2 = s1 //等价于s2(s1),s2是s1的副本
string s3("value") //s3是字面值“value”的副本,除了字面值最后的那个空字符外
string s4(n,'c') //把s4初始化为由连续n个字符c组成的串
string对象上的操作
使用getline读取一整行
当我们需要在最终得到的字符串中保留输入时的空白符,可以使用getline函数来替代原来的>>运算符。getline函数的参数是一个输入流和一个string对象,函数从给定的输入流中读入内容。直到遇到换行符为止(注意换行符也被读进来了),然后将所读的内容存入到string对象中(注意不存在换行符)
int main()
{
string line;
//每次读入一整行,直至到达文件末尾
while(getline(cin,line))
cout << line <<endl; //line中不包含换行符,所以手动加上换行操作符,使用endl结束当前行并刷新显示缓冲区
return 0;
}
处理string对象中的字符
处理string对象最关键的问题是==如何获取字符本身 ==,在cctype头文件中定义了如下的函数供我们使用:
使用基于范围的for语句
范围for语句其语法形式为:
//使用范围for语句把string对象中的每个字符每行一个输出出来
string str(“some string”);
//每行输出str中的一个字符
for(auto c : str) //对于str中的每个字符
cout << c << endl; //输出当前字符,后面紧跟一个换行符
使用范围for语句改变字符串的字符
如果想要改变string对象中字符的值,必须把循环变量定义成引用类型。如下列所示
//将字符串改写为大写形式
string s("Hello World!!!");
//转换成大写形式
for(auto &c : s) //对于s中的每个字符(c是引用)
c = toupper(c); //c是一个引用,因此赋值语句将改变s中字符的值
cout << s <<endl;
输出结果:
HELLO WORLD!!!
只处理一部分字符
访问string对象中的单个字符有两种方式:一种是使用下标,另外一种是使用迭代器
下标运算符([ ])接收的输入参数是string::size_type类型的值,这个参数表示要访问的字符的位置;返回值是该位置上的字符的引用。
string对象s的最后一个字符为s[s.size()-1]。
注:
string对象的下标必须大于等于0而小于s.size()。
//使用下标运算符输出string对象中的第一个字符:
if (!s.empty()) //确保确实有字符需要输出
cout << s[0] << endl; //输出s的第一个字符
*********在访问指定字符之前,首先检查s是否为空,其实不管什么时候只要对string对象使用了下标,都要确定在那个位置上确实有值******************
标准库类型 vector
标准库类型vector表示对象的集合,其中所有对象的类型都相同。集合中的每个对象都有一个与之对应的索引,索引用于访问对象。
使用vector,必须包含适当的头文件,如下所示:
#include <vector>
using std::vector;
以vector为例,提供的额外信息是vector内所存放对象的类型:
vector<int> ivec; //ivec保存int类型的对象
vector<Sales_item> Sales_vec; //保存Sales_item类型的对象
vector<vector<string>> file; //该向量的元素是vector对象
vector能容纳绝大多数类型的对象作为其元素,但是因为引用不是对象,所以不存在包含引用的vector。
定义和初始化vector对象
如下表所示:
### 如何判断列表初始值还是元素数量?
vector<int> v1(10); //v1有10个元素,每个的值都是0
vector<int> v2{10}; //v2有1个元素,该元素的值是10
vector<int> v3(10,1); //v3有10个元素,每个的值都是1
vector<int> v3{10,1}; //v4有2个元素,值分别是10和1
******如果用的是圆括号,提供的值是用来构造vector对象;如果是花括号,可以理解为列表初始化该Vector对象,但需注意花括号里面的值必须与元素类型相同************
向vector对象中添加元素
vector对象直接初始化的方式适用于三种情况:
- 初始值已知且数量较少
- 初始值是另一个vector对象的副本
- 所有元素的初始值都一样
想创建一个vector对象,令其包含0~999最好的处理方法是先创建一个空vector,然后在运行时再利用vector的成员函数push_back向其中添加元素。push_back负责把一个值当成vector对象的尾元素“压到(push)”vector对象的“尾端(back)”。
vector<int> v2;
for (int i=0;i!=100;++i)
v2.push_back(i);//依次把整数值放到V2尾端
其他vector操作
计算vector内对象的索引
注:vector对象不能用下标形式添加元素
以下为错误的示例:
vector<int> ivec; //空vector对象
for(decltype(ivec.size()) ix = 0; ix !=10; ++ix)
ivec[ix] = ix; //严重错误:ivec不包含任何元素,正确的方法是使用push_back;
注:vector对象(以及string对象)的下标运算符可用于访问已存在的元素,而不能用于添加元素
迭代器
使用迭代器
迭代器类型都拥有名为begin和end的成员,其中begin成员负责返回指向第一个元素的迭代器,end成员负责返回指向容器“尾元素的下一个位置”的迭代器。特殊情况下如果容器为空,则begin和end返回的是同一个迭代器,都是尾后迭代器
迭代器运算符
使用==和!=来比较两个合法的迭代器是否相等,如果两个迭代器指向的元素相同或者都是同一个容器的尾后迭代器,则它们相等;否则就说这两个迭代器不相等。
迭代器运算
数组
数组的大小固定,所以不能随意向数组中增加元素。如果不清楚元素的确定个数,请使用vector。
复杂的数组声明
int *ptrs[10]; //ptrs 是含有10个整型指针的数组
int &refs[10] = /*?*/; //错误:不存在引用的数组
int (*Parray)[10] = &arr; //Parray指向一个含有10个整数的数组
int (*arrRef)[10] = arr; //arrRef引用一个含有10个整数的数组
指针和数组
int ia[] = {0,1,2,3,4,5,6,7,8,9};
auto ia2(ia); //ia2是一个整型指针,指向ia的第一个元素
ia2 = 42; //错误:ia2是一个指针,不能用int值给指针赋值
两个函数begin和end与容器中的两个同名成员功能类似。
int ia[ ] = {0,1,2,3,4,5,6,7,8,9}; //ia是一个含有10个整数的数组
int *beg = begin(ia); //指向ia首元素的指针
int *last = end(ia); //指向arr尾元素的下一位置的指针