天行健 发表于 2025-1-23 12:00:29

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]
查看完整版本: C++基础知识04.数组