0%

C++字符串、向量和数组

字符串、向量和数组

1、using声明

作用:使用using声明命名空间的相关成员后,后续不需再声明

1
2
3
using std::cin;
int i;
cin>>i;
  • 每个名字都需要独立的using声明

2、string类型

  • 使用前需包含头文件<string>(没有.h),且需声明string定义于命名空间中

初始化string类型的方法

1
2
3
4
5
string s1;
string s2=s1;
string s3("value");
string s3 ="value";
string s4(n,'c');//此处只能为字符

读写string对象

当要将标准输入内容读取到一个string对象时,string对象会自动忽略开头的空白(空格、换行等),从第一个真正的字符开始,直到遇到遇到下一个空白(但读取结束的标准是换行)

使用getline函数读取一整行

1
2
string s;
getline(cin,s);

getline只有当读取到换行符时才会结束,并且这个换行符会被丢弃。

相加问题

string对象可以相加,string对象也可以与字面值相加,但字面值不能与字面值相加!

单独处理字符

C++11提供了一种语句:范围for

1
2
string str("something");
for(auto c:str) cout<<c<<endl;
  • 每次循环中,都会把序列中的基础元素存入c中

还可以通过引用等方式单独改变字符

1
2
string str("something");
for(auto &c:str) c=toupper(c);//大写转换函数

下标问题

C++支持对字符串使用下标运算符[]访问字符串的单个字符,规则同python,但貌似C++不支持截取。

3、vector类型

要想使用vector,需包含<vector>头文件。类型vector表示对象的集合

实例化:

1
2
vector<int> a;
vector<vector<int>> b;

定义与初始化

1
2
3
4
5
6
7
vector<int> a;
vector<int> a(b); //a包含b中所有元素的副本 a和b的类型需相同
vector<int> a=b;
vector<int> a(n,val); //a中有n个重复的val
vector<int> a(n); //包含n个对象
vector<int> a{A,B,C};
vector<int> a={A,B,C};

向vector对象尾部添加元素

1
2
vector<int> a;
a.push_back(1);//a={1}

其他函数

1
2
a.empty(); //如果a不含元素则返回真
a.size(); //返回元素个数

其他的类函数参考书p91

索引

vector对象同样支持使用下标运算符进行单个元素的索引,但不能通过下标添加元素。

4、迭代器

迭代器(iterator)是一种可以遍历容器元素的数据类型。迭代器是一个变量,相当于容器和操纵容器的算法之间的中介。C++更趋向于使用迭代器而不是数组下标操作,因为标准库为每一种标准容器(如vector、map和list等)定义了一种迭代器类型,而只有少数容器(如vector)支持数组下标操作访问容器元素。可以通过迭代器指向你想访问容器的元素地址,通过*x打印出元素值。这和我们所熟知的指针极其类似。

C语言有指针,指针用起来十分灵活高效。
C++语言有迭代器,迭代器相对于指针而言功能更为丰富。

迭代器的使用

可以看出,迭代器的基本使用和指针极其相似

1
2
3
4
5
6
7
8
int main()
{
vector<string> v{"aaaa","bbbb"};
auto i=v.begin();
cout<<*(i+1); //bbbb
system("pause");
return 0;
}

迭代器运算符

  • 获得迭代器所指元素

    1
    *iter  or  iter->mem
  • 获取迭代器长度

    1
    i.end()-i.begin()

迭代器类型

1
2
3
4
5
6
7
8
9
10
11
vector<string> v{"aaaa","bbbb"};
auto i=v.begin();
//vector<string>::iterator i; 类型

string str("12345");
auto i=str.begin();
//string::iterator i; 类型

对应的只读类型
//vector<string>::const_iterator v;
//string::const_iterator str;

当需要对迭代器进行遍历时,需注意for循环的条件3:

1
2
3
4
5
6
7
8
9
10
11
int main()
{
vector<int> v{1,2,3,4,5,6,7,8,9,10};
for(auto i=v.begin(); i !=v.end(); ++i)//应使用++i,这是因为end为元素10之后的位置
{
*i=*i*2;
}
for(auto a:v) cout<<a<<endl;
system("pause");
return 0;
}

5、数组

大部分规定与C相同。

  • 定义数组时不允许用auto关键字由初始值推断类型。

  • 可使用decltype(数组名)定义数组类型。

  • 数组不是类类型,因此没有成员函数。

    因此C++11引入了begin、end函数来查询数组相关元素的地址

    1
    2
    int a[]={1,2,3};
    int *p=begin(a);

注意:end()和vector类型的子函数.end()不同,end()函数返回的是数组最后一个元素的地址,而vector类型的end子函数返回的是最后一个元素的后一位地址

单个元素类型

通常对数组的单个类型定义为size_t型,该类型为一种机器相关的无符号类型,它被设计得足够大以便能表示内存中任意对象的大小

要使用该类型,应包含cstddef头文件

C与C++的字符串风格

1
2
char a[10]="dhk"; //C风格
string a("dhk"); //C++风格

在C中,通常我们要对字符串进行一些例如比较、拷贝、连接等的操作时,通常使用的是标准库中的相关字符串长度,相较于C++中string类型的变量可以对存放字符串的变量直接进行运算等操作,C的字符串风格更加繁琐,且极容易在数组的内存方面引发严重问题

混用规则:

1
2
3
string a("dhk");
char *str=a;//错误,a的类型为string,而str类型为char*,冲突
char *str=a.c_str();//正确。c_str()函数返回的是C风格字符串(一个地址)

上述用法相当于是在内存中创建了一个”dhk”字符串,而用于找到该字符串的指针一旦改变,该字符串就将不能再被找到,因此通常对存放该类型的指针进行const操作。其规则类似C中的char *str="dhk"所遵循的规则。

使用数组初始化vector类型

C++不允许用一个数组为另一个数组赋初值,也不允许通过vector类型对象为一个数组初始化,但是允许通过数组为vector对象初始化。

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

6、多维数组

一些基础内容同C,详见二维数组复习 | 小董的BLOG (gitee.io)

多维数组可以理解为数组的数组例如int a[3][4]可以理解为a数组包含三个元素,而这三个元素都为大小为4的数组

下标引用

使用范围for语句和下标引用处理多维数组

1
2
3
4
5
6
7
8
9
10
int a[3][4]={0};
size_t x=0;
for(auto &row : a)
{
for(auto &col : row)
{
col=x;
x++;
}
}