疫情所迫,希望用这种方法督促自己坚持学习。同时记录在找工作过程中的艰辛不易。博客内容持续增减修改,都为摘录和个人理解。欢迎各位批评指正其中错误,相互勉励,共同进步。
一、数组初始化与注意事项
数组相较于前面学习的string和vector数据类型,其更加固定。不能随意的往数组中增添元素。虽然一定程度上程序的运行性能会有所提升,但是缺乏灵活性。以下是几种数组常用的初始化方式:
int arr[5]; //含有5个int类型的数组
int *ptr[10]; //含有10个整型指针的数组
string arr1[10]; //含有10个string类型的数组
int arr = {5,8,9,6,4}; //显式初始化整型数组
string arr1[] = {"hello","world!"}; //显式初始化字符串数组
int arr[5] = {1,2,3}; //将数组的前三个元素赋值,剩余为0
int arr[3] = {1,2,3,4,5}; //编译出错,超过数组维度
重点需要注意的几个问题:
- 不能用变量动态规定数组大小,如下所示,编译错误;
int i; cin >> i ; int arr[i]; //编译报错,不能用变量分配数组大小 const j = 5; int arr1[j]; //编译通过,可以用const常数量规定数组大小
- 数组使用前必须定义和定义其空间大小(不同于string和vector);
- 不能用一个数组给另外一个数组初始化,也不能数组直接赋值给另一个;
int arr1[5] = {0,1,2,3,4}; int arr2[] = arr1; //编译报错 arr2 = arr1; //编译报错
- 定义数组末尾是否有字符“\0”,对比以下几种定义方式:
char a1[] = "shi"; //sizeof(a1)=4 末尾会自动添加'\0' char a2[] = {'s','h','i','\0'}; //与上一行定义方式等价 char a3[] = {'s','h','i'}; //sizeof(a3)=3 char a4[3] = "shi"; //编译出错,大小空间定义应该大于等于4
示例代码一:
对比vector和数组赋值方式与拷贝方式区别
int a[10], a1[10];
vector<int> b, b1;
for (int i = 0; i < 10; i++) {
a[i] = i;
b.push_back(i);
}
for (int j = 0; j < 10; j++)
a1[j] = a[j];
b1 = b;
二、几种复杂的数组申明(一定要完全弄清楚)
示例代码展示了三种复杂的数组申明。
- 定义一,iter1保存了5个整型数的指针。从右往左看,先是iter1[5]表示定义数组大小为5,再加上*表示为指针元素 ;
- 定义二,iter2指向一个大小为5的整型数组。由内往外看,先是*iter2表示为指针变量,再加上[5]表示指向大小为5的整型数组;
- 定义三,iter3为引用一个大小为5的整型数组。由内往外看,先是&iter3表示一个引用,再加上[5]表示引用一个大小为5的整型数组;
int a[5] = { 0,1,2,3,4 };
int *iter1[5] = { &a[0],&a[1],&a[2],&a[3],&a[4] }; //定义一
int(*iter2)[5] = &a; //定义二
int(&iter3)[5] = a; //定义三
cout << a << endl; //00000033F875F8E8
cout << iter1[0] << endl; //00000033F875F8E8
cout << iter2 << endl; //00000033F875F8E8
cout << iter3 << endl; //00000033F875F8E8
三、数组和指针
实际在使用数组时,编译器会把其变为指针。现有如下代码:所述两种定义方法中的指针p和p1都是指向a[0]。
string a[] = {'wdn','cer','vbtr'};
string *p = &a[0];
string *p1 = a;
auto p3(a); //p3是一个string指针,指向a;
指针迭代器
代码功能:利用指针遍历输出字符数组
char a[6] = { 'a','b','c','d','e','f' };
char *e = &a[6];
for (char *b = a; b<e; b++)
cout << *b << endl;
标准库函数的begin和end
数组不是类类型,因此begin和end不是其成员函数。其使用方法如下:
int a[6];
int *b = begin(a); //指向数组的首元素
int *e = end(a); //指向尾元素的后一位
指针运算
int a[10] = {0,1,2,3,4,5,6,7,8,9};
int *p = a;
int *p1 = p + 4; //指向数组中第五个元素
auto n = end(a) - begin(a); //输出该数组有多少元素
auto n1 = size(a);
//解引用
int b = *(a+4); //a[4]的值为3
int b = *a + 4; //等价于a[0]+4
需要注意,如果两个指针指向不同的类型,则比较没有意义。
四、字符串数组操作
对于字符串数组,有如下几种常用操作方式:(图片来源于Primer c++ P109)
字符串的长度
上诉操作中需要注意,对于字符数组要以‘\0‘结尾。如下代码所示:strlen只有当遇到‘\0’才会停止,并且不会将‘\0’作为一个字符计入;
char a[3] = {'C','+','+'};
int n = strlen(a); //输出一个不为3且大于3的数
/*****************/
char b[4] = {'C','+','+','\0'};
int n = strlen(b); //输出为3
字符串的比较
我们需要区别字符串数组和string比较方法
//对于string类型可以直接用比较运算符实现对两个字符串的比较
string s1 = "cnjsklcncnsil";
string s2 = "hxcskugcbkjsc";
if(s1<s2)
//对于数组字符串,直接比较相当于比较两个指针,虽然不会报错,但是没有任何意义
char c1[] = "cbjaskbc";
char c2[] = "casbhkjcb";
if(c1<c2)
//因此对于字符串数组,需要用strcmp进行比较
if(strcmp(c1,c2)>0)
字符串拼接与复制
同样的对于数组字符串我们与string类型字符串进行对比记忆
string s1 = "csbcbkavch";
string s2 = "xhasjcbsjkan";
char c1[100] = "chsacjasbjck";
char c2[] = "ahduskgcbcsjsag";
//对于字符串复制
string s3 = s1;
strcpy(c1,c2); //将c2拷贝到c1,如果c1内存小于c2则只复制c2部分
//对于字符串拼接
string s4 = s1 + s2;
strcat(c1,c2); //将c2附加到c1
对于字符串数组的拼接,要确保c1的内存大于等于c1+c2,否则会报错。因此,对于大小不确定的字符串,最好使用string类型变量。