数组
一维数组
数组的初始化
#include<iostream>
using namespace std;
int main(){
int a[5]; // 声明数组,但是不会初始化,因此数组中的值都是未知的
cout<<a[0]<<endl; // 4196768
cout<<a<<endl; // 0x7fff0c7d9730
int a2[5] = {1,2,3,4,5};
int *a3 = new int[5]; // 使用new关键字分配内存,会对内存进行清零,有默认的值0
int a4[5] = {}; // 会有默认初始化值
// 1==0==0
cout<<a2[0]<<"=="<<*a3<<"=="<<a4[0]<<endl;
}
指针数组
#include<iostream>
using namespace std;
int main(){
int balance[5] = {1,3,5,7,8};
int *p = balance; // balance 是数组的地址值。指针存储地址值。
for (int i = 0; i < 5; i++){
cout<<*(p+i)<<endl;
}
}
/*
1
3
5
7
8
*/
二维数组
二维数组的初始化 -- 不包括用 new 初始化
#include<iostream>
using namespace std;
// new 初始化 二维数组暂时不记录。
int main(){
int a[2][2] = {1,2,3,4};
cout<<a[0][0]<<endl; // 1
int b[2][2] = { {1,2},{3,4} };
cout<<b[0][0]<<endl;
}
char数组
定义 char 数组,按照惯例,字符表示的字符串由特殊字符 null
结尾,其字面值可以写为 \0
。注意:null
字符不用手动添加,C++ 在编译的时候会自动添加。
char ch[10]; // 可以存储 10 个字符,包括 '\0'
#include<iostream>
using namespace std;
int main(){
char ch[10]="Hello";
int index = 0;
while(ch[index]!='\0'){
cout<<ch[index];
index++;
}
cout<<""<<endl;
}
从函数返回数组
如何将数组作为函数的返回值返回呢?使用指针即可。
#include<iostream>
using namespace std;
int* getRandomArray(){
int *arr = new int[5]{1,2,3,4,5};
return arr;
}
int main(){
int *arr = getRandomArray();
for (int i = 0; i < 5; i++){
/* code */
cout<<arr[i]<<endl;
cout<<*(arr+i)<<endl;
}
}
C++ 的函数不允许返回整个数组,不支持返回局部变量的地址,除非为 static 变量;int * getRandomArray() 表示返回 int 的指针;arr=getRandomArray(),其中定义 arr 在 main 函数为 int 的指针,这个时候 arr 可以指向数组的第一个值的地址。
cstring
在 C++ 中有大量用于操作 C-style 字符串的函数,它们集成在头文件 <cstring>
中。其常见的函数:
函数 |
作用 |
strcpy(s1,s2) |
复制字符串 s2 到 s1,可能会越界写。 |
strcat(s1,s2) |
将字符串 s2 连接到 s1 末尾,可能会越界写。 |
strlen(s) |
计算字符串 s 长度 |
strcmp(s1,s2) |
比较字符串 s1 和 s2 的长度,相同为 0;s1<s2 为 -1;s1>s2 为 1 |
strchr(s1,ch) |
返回一个指针,指向 s1 中字符 ch 第一次出现的位置 |
strstr(s1,s2) |
返回一个指针,指向 s1 中字符串 s2 第一次出现的位置 |
#include<iostream>
#include<cstring>
using namespace std;
int main(){
char str1[6] = "hello";
char str2[10] = "world ccc";
cout<<strlen(str1)<<endl; // 5
strcat(str1,str2);
cout<<str1<<","<<strlen(str1)<<endl; // helloworld ccc, 14
strcpy(str1,str2);
cout<<str1<<endl; // world ccc
cout<<sizeof(str1)<<endl; // 6
}
<span style="color:red">注意:在复制字符串的时候,千万要注意写越界的问题!strcpy 和 strcat 不会自动增加目标字符串的长度;著名的黑客攻击手段--缓冲区溢出,就是根据这个特点产生的。</span>
<span style="color:red">当调用 strcpy(), strcat(), gets(), fgets()... 而传入一段过长的串时,如果程序员未检查源字符串的长度。就会导致紧跟在目标字符串后面的内存被覆盖,如果该内存记录的是函数的返回地址,那么当函数该返回时,程序就会试图跳到该地址内容(为一指针值)所指的地方继续执行。从而造成安全漏洞。</span>
<span style="color:red">解决方法:尽量使用这些函数对应的安全类型函数。如,strncpy(), strncat()..</span>
string
推荐用 string 而非 *char
#include<iostream>
using namespace std;
int main(){
string str1 = "hello";
string str2 = "world";
str1.append(" ").append(str2);
cout<<str1<<endl;
cout<<str1.length()<<endl; // hello world
cout<<str1+str2<<endl; // hello worldworld
}
<div align="center"><img src="img/string.jpg"></div>
两种类型的字符串
C 风格:char str[10]="hello";一些函数包括 strcpy 复制;strcat 连接;strlen 大小;strcmp 比较;strchr 返回指针;strstr 返回指针
C++ 中的 string 类:string str1="hello" 操作:str3=str; str3=str2+str1; str3.size()