跳转至

『C语言教程』6. 数组与字符串

T18:50:00+08:00

一、数组

数组,顾名思义。,一坨数。

一个某数据类型的数组可以存储多个该种数据类型的数据,下标从0开始。

「C语言」数组与字符串_数组

上图:普通 int 变量、一维 int 数组、二维 int 数组......

一些概念:

  • 元素 :对于数组 aa[1] 为数组的一个元素

  • 下标 :数学中 \(a_i\)\(i\),这里为数组元素 a[i]i

1.1 数组的声明

C
数据类型 数组变量名[数组长度];

「C语言」数组与字符串_一维数组

C
1
2
3
4
// 声明一个长度为3的数组a
int a[3];
// 声明一个长度为3的数组b,并赋初值 a[0] = 0, a[1] = 1, a[2] = 2
int b[3] = {0, 1, 2};

当然初始化的时候也可以不输全:

C
// 声明一个长度为3的数组,并赋初值 a[0] = 0, a[1] = 1
int a[3] = {0, 1};

未被赋值的元素就像未被赋值的变量,也许是垃圾值

当想要声明的长度与初始化数据长度相同时,可以省略掉,让编译器自行推断。

C
1
2
3
// 声明一个数组,并赋初值 a[0] = 0, a[1] = 1, a[2] = 2,自动推断数组长度为3
int a[] = {0, 1, 2};
// 相当于 int a[3] = {0, 1, 2};

1.2 数组的使用

数组的每一个元素相当于一个该类型的变量,数组的元素要使用 数组名[] 加下标来访问。

然后将其当成正常变量来用即可。

C
1
2
3
4
5
6
7
int a[3] = {0, 1, 2};

printf("%d", &a[1]); // 输出1

a[0] = a[1] + a[2]; // 执行完此句后 a[0] = 3, a[1] = 1, a[2] = 2

scanf("%d", &a[2]); // 读入一个整数存入a[2]

1.3 获取数组的长度

这里介绍一个函数 sizeof() ,可以获取参数所占内存大小(Byte字节数):

  • sizeof(int) 输出 int 型变量所占字节数。

在不同机器、不同编译器上,大小会有所不同。

  • sizeof(变量名) 输出对应变量所占字节数。

    sizeof(数组名) 即可输出整个数组所占字节数。

一个某类型数组由多个该类型变量组成,那么我么可以得到数组的长度为:

Text Only
sizeof(数组名) / sizeof(数组类型)

例:

C
#include <stdio.h>
#include <stdlib.h>

int main() {
    int arr[] = {0, 1, 2};
    int arr1[3];
    printf("%d\n", sizeof(arr) / sizeof(int));
    printf("%d\n", sizeof(arr1) / sizeof(int));
    return 0;
}

输出:

Text Only
3
3

1.4 数组与地址(Lv1)

Lv2 或许大概可能会在下面的下面的很下面出现,因为与指针数组与指针的指针等花里胡哨的玩意儿相关。

我们来看以下程序:

C
#include <stdio.h>

int main() {
    int arr[3] = {0, 1, 2};

    printf("&array[0]    = %p\n", &arr[0]);
    printf("&array[1]    = %p\n", &arr[1]);
    printf("array        = %p\n", arr);
    printf("array + 1    = %p\n", arr + 1);
    printf("*array       = %d\n", *arr);
    printf("*(array + 1) = %d\n", *(arr + 1));

    return 0;
}

%p 是打印地址用的,按16进制输出,不够8位左边补零。(详见 格式化输出 (你点啥,我还没写))

输出为:

Text Only
1
2
3
4
5
6
&array[0]    = 0x7ffe9129e5bc
&array[1]    = 0x7ffe9129e5c0
array        = 0x7ffe9129e5bc
array + 1    = 0x7ffe9129e5c0
*array       = 0
*(array + 1) = 1

看起来很乱,梳理一下:

  • 直接使用数组名,为一个 指向数组首元素的指针(存储了数组首元素地址的指针).

    指针 + 1 会得到指向内存中紧接着的下一个变量的指针,对于数组来说,若 arr 指针指向 arr[0],那么 arr + 1 则指向 arr[1]

  • 使用取址运算符 & 加数组元素,为 对应元素的地址

这二者区别在于:前者为指针可以用 *arr, *(arr +1) 操作,而后者为地址不能用 *(&arr[0]), *(&arr[1]) 操作。

二、字符串 —— 字符数组

字符串,还是顾名思义。字符

我们其实已经使用字符串很久了:printf("nb")puts("PengGeNiuBi"),参数中用 "" 包起来的内容即为字符串型数据。

正如字符是字符,字符串是字符串 字符的字面值常量使用 '' 括起来,而字符串的字面值常量使用 "" 括起来。

在 C++ 中有专门的 string 类型,而 C 中字符串为字符数组。

这是一个长度为6的字符数组:

C
char str[6];

我们可以使用 scanf 来读入一个字符串存入其中,字符串的格式符为 %ss 代表 string ),传入的地址为开始存储字符串的地址(用来存储字符串首字符的地址):

Text Only
scanf("%s", &str[0]);

由 1.4,对于从下标0开始存储字符串的需求,下面的写法也可:

Text Only
scanf("%s", str);

输入 Hello

使用 printf 输出字符串:

Text Only
printf("%s\n", str);

当然还有一个专门用来输出字符串的函数(末尾会自带换行):puts()

Text Only
puts(str);

2.1 字符串是怎么存到字符数组中的?

上例中的 Hello 存储到 str[6] 中,如果我们遍历数组,打印出每一个元素:

C
1
2
3
4
int i;
for (i = 0; i < 6; i++) {
    printf("str[%d]: %c (%d)\n", i, str[i], str[i]);
}

输出为:

Text Only
1
2
3
4
5
6
str[0]: H (72)
str[1]: e (101)
str[2]: l (108)
str[3]: l (108)
str[4]: o (111)
str[5]:   (0)

str[5] 看起来是空的(确实),不过也存了一个ASCII码值为0的字符(空字符),也就是 '\0' 。(如下图)

「C语言」数组与字符串_字符串

这被用来标记字符串的结束,scanf 读入后会自动向输入的字符后添加一个 '\0'printf 输出时遇到 '\0' 也会停止。

正是因为这个 '\0' 的存在,printf 才可以在输出字符串时使用字符数组中的元素下标到哪停止。

如果我们手动将 str[2] 的值改为 \0 ,再用 printf 输出,则会输出 He

评论