C++基础知识04.数组
# 数组## 一维数组
数组的初始化
```cpp
#include<iostream>
using namespace std;
int main(){
int a; // 声明数组,但是不会初始化,因此数组中的值都是未知的
cout<<a<<endl; // 4196768
cout<<a<<endl; // 0x7fff0c7d9730
int a2 = {1,2,3,4,5};
int *a3 = new int; // 使用new关键字分配内存,会对内存进行清零,有默认的值0
int a4 = {}; // 会有默认初始化值
// 1==0==0
cout<<a2<<"=="<<*a3<<"=="<<a4<<endl;
}
```
## 指针数组
```cpp
#include<iostream>
using namespace std;
int main(){
int balance = {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 初始化
```cpp
#include<iostream>
using namespace std;
// new 初始化 二维数组暂时不记录。
int main(){
int a = {1,2,3,4};
cout<<a<<endl; // 1
int b = { {1,2},{3,4} };
cout<<b<<endl;
}
```
## char数组
定义 char 数组,按照惯例,字符表示的字符串由特殊字符 `null` 结尾,其字面值可以写为 `\0`。注意:`null` 字符不用手动添加,C++ 在编译的时候会自动添加。
```c++
char ch; // 可以存储 10 个字符,包括 '\0'
#include<iostream>
using namespace std;
int main(){
char ch="Hello";
int index = 0;
while(ch!='\0'){
cout<<ch;
index++;
}
cout<<""<<endl;
}
```
## 从函数返回数组
如何将数组作为函数的返回值返回呢?使用指针即可。
```cpp
#include<iostream>
using namespace std;
int* getRandomArray(){
int *arr = new int{1,2,3,4,5};
return arr;
}
int main(){
int *arr = getRandomArray();
for (int i = 0; i < 5; i++){
/* code */
cout<<arr<<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 第一次出现的位置 |
```cpp
#include<iostream>
#include<cstring>
using namespace std;
int main(){
char str1 = "hello";
char str2 = "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`
```cpp
#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="hello";一些函数包括 strcpy 复制;strcat 连接;strlen 大小;strcmp 比较;strchr 返回指针;strstr 返回指针
C++ 中的 string 类:string str1="hello" 操作:str3=str; str3=str2+str1; str3.size()
页:
[1]