1. 数组概述

在C语言中,数组是一种存储多个相同类型元素的数据结构。数组在内存中是连续存储数据的,通过索引访问和操作数组中的元素。

image-20230731173511678

在C语言中,数组使用一个中括号来描述其固定的容量,格式如下:

1
数据类型 变量名[数组大小];

按数组元素类型的不同,可分为:数值数组字符数组指针数组结构数组等类别。

1
2
3
int a[10];      // 数值数组, 可以存储 10 个整形数值
char s[24]; // 字符数组, 可以存储 24 个字符
char *p[5]; // 指针数组, 可以存储 10 个 char* 类型的指针(地址)

通常情况下,数组元素下标的个数也称为维数,根据维数的不同,可将数组分为一维数组、二维数组、三维数组、四维数组等。通常情况下,我们将二维及以上的数组称为多维数组

2. 一维数组

2.1 定义和使用

想要定义一个一维数组,有以下几个知识点需要我们注意:

  • 数组名字符合标识符的书写规定(数字、英文字母、下划线

  • 数组名不能与其它变量名相同,同一作用域内是唯一的

  • 方括号[]中常量表达式表示数组元素的个数

    • int a[3] 表示数组 a3个元素

    • 数组的下标从0开始计算,因此3个元素分别为a[0],a[1],a[2]

  • 定义数组时[]内最好是常量,使用数组时[]内可以是常量,可以是变量

    • 在定义数组时 C99 标准允许在 []指定变量,但是有些编译器不支持这种语法,比如 VS,使用 GCC 编译是没问题的。
    • 数组的使用指的是通过下标读写数组中的元素的值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
int main()
{
int a[10];
for (int i = 0; i < 10; i++)
{
a[i] = i + 100; //给数组赋值
}
//遍历数组,并输出每个成员的值
for (int i = 0; i < 10; i++)
{
printf("%d ", a[i]);
}
printf("\n");

return 0;
}
  • 第 4 行:定义了一个数组,名字叫a,有10个成员,每个成员都是int类型
    • 没有 a 这个变量,a 是数组的名字,但不是变量名,它是常量
      • 数组名本身被视为指向数组第一个元素的指针(地址)常量
      • 数组的10个成员分别是:a[0]…… a[9],没有a[10]
  • 第 7 行:通过for循环依次给数组的各个元素赋值
  • 第 12 行:通过for循环依次打印数组中各个元素的值

程序输出的结果如下:

1
100 101 102 103 104 105 106 107 108 109

2.2 数组名

关于数组名需要再次对其进行剖析,它(数组名)是一个地址的常量,代表数组中首元素的地址

  • 数组名相当于单元楼,坐落于某个固定位置
  • 数组元素相当于单元楼中的住户
  • 数组下标相当于单元楼内住户的门牌号

定义一个数组相当于盖一座单元楼,很显然楼盖好了是不能挪地方的,所以数组被定义出来之后,数组名对应的内存地址也不允许挪地方,因此是常量,常量就是只读,不允许修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
int main()
{
int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int n = sizeof(a);
int n1 = sizeof(a[0]);
printf("a = %p\n", a);
printf("&a[0] = %p\n", &a[0]);
printf("n = %d, n1 = %d\n", n, n1);

for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
{
printf("a[i] = %d\n", a[i]);
}
printf("\n");

return 0;
}
  • 第 4 行:定义数组并给元素初始化
  • 第 5 行:计算数组占用内存的大小,10个int类型,10 * 4 = 40
  • 第 6 行:计算数组下标为 0 的元素占用内存大小,第 0 个元素为 int,4
  • 第 7 行:打印数组的地址
  • 第 8 行:打印数组中下标为 0 的元素(第一个元素)的地址

程序输出的结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
a = 000000A0E80FF8B8
&a[0] = 000000A0E80FF8B8
n = 40, n1 = 4
a[i] = 1
a[i] = 2
a[i] = 3
a[i] = 4
a[i] = 5
a[i] = 6
a[i] = 7
a[i] = 8
a[i] = 9
a[i] = 10

通过输出的日志信息再次给大家强调这句话:数组名对应的地址和数组中第一个元素的地址是相同的。

2.3 初始化

在定义数组的同时进行赋值,称为初始化。全局数组若不初始化,编译器将其初始化为零。局部数组若不初始化,内容为随机值。

1
2
3
4
5
int a1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int a2[10] = { 1, 2, 3 };
int a3[10] = { 0 };
// []中不指定元素个数,定义时必须初始化, 否则无法确定数组的固定大小
int a4[] = { 1, 2, 3, 4, 5 };
  • a1[10]:定义一个数组,同时初始化所有成员变量
  • a2[10]:初始化前三个成员,后面所有元素都设置为0
  • a3[10]:所有的成员都设置为0
  • a4[]:定义了一个数组,有5个成员
    • []中不指定元素个数,定义时必须初始化, 否则无法确定数组的固定大小

局部变量

在 C 语言中,局部变量有如下特点:

  1. 局部变量是在函数或块内{}部声明的变量,它们只在声明它们的函数或块的范围内可见。
  2. 局部变量在其所在的函数或块的生命周期内存在,并且每次进入该函数或块时都会重新创建
  3. 局部变量必须在使用之前先声明,并且可以被初始化。
  4. 局部变量的作用域仅限于声明它们的函数或块。

以下是一个示例,展示了局部变量的使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<stdio.h>
int myFunction()
{
int x = 10;
if (x == 10)
{
int y = 20;
printf("hello y\n");
}
printf("%d\n", x);
return x / 2;
}

int main()
{
int index;
index = myFunction();
printf("index = %d\n", index);
return 0;
}

在上述示例中,一共有如下几个局部变量:

  • xmyFunction 函数内部的局部变量,只能在该函数内部可见和使用,作用域范围是3~12行
  • yif结构内部的局部变量,作用域范围是6~9行,只能在该范围内部可见和使用
  • indexmain 函数内部的局部变量,只能在该函数内部可见和使用,作用域范围是15~20行

全局变量

在 C 语言中全局变量有如下特点:

  • 全局变量是在所有函数外部声明的变量,它们在程序的整个执行过程中都有效。
  • 全局变量在程序开始执行时创建,在程序结束时销毁。它们在内存中的位置固定不变,全局变量会自动进行初始化,值为 0。
  • 全局变量可以在任何函数中访问和修改,如果全局变量跨文件访问需要使用 extern 关键字声明它们。
  • 全局变量的作用域跨越整个程序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<stdio.h>

int index;
int x = 10;
int myFunction()
{
if (x == 10)
{
int y = 20;
printf("hello y\n");
}
printf("%d\n", x);
return x / 2;
}

int main()
{
index = myFunction();
printf("index = %d\n", index);
return 0;
}

在上述示例中,一共有如下2个全局变量,可以在程序的任何地方使用它们:

  • 第 3 行:定义全局变量index但是没有初始化,默认初始化为 0
  • 第 4 行:定义全局变量x并且初始化为 10

2.4 一展身手

学了数组之后,我们就能够处理更多的、更复杂的数据,满足更多的需求,下面来看几个例子。

2.4.1 找最大值

定义并初始化一个整形数组,找出数组中值最大的那个数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
int main()
{
int a[] = { 1, -2, 3,-4, 5, -6, 7, -8, -9, 10 };
int max = a[0];
for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
{
if (a[i] > max)
{
max = a[i];
}
}
printf("数组中最大值为:%d\n", max);
return 0;
}

2.4.2 数组逆置

定义并初始化一个数组,将数组中的数据首尾颠倒,比如:

  • 原始数据:1, 2, 3, 4, 5, 6
  • 逆置之后:6, 5, 4, 3, 2, 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
int main()
{
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

int i = 0, tmp = 0;
int j = sizeof(a) / sizeof(a[0]) - 1;

while (i < j)
{
tmp = a[i];
a[i] = a[j];
a[j] = tmp;
i++;
j--;
}

for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
{
printf("%d ", a[i]);
}
printf("\n");

return 0;
}

2.4.3 冒泡排序

冒泡排序规则:

  1. 比较相邻的两个元素。从序列的第一个元素开始,比较第一个和第二个元素的大小。
  2. 如果第一个元素大于第二个元素,则交换它们的位置,把较大的元素向后移动。
  3. 继续比较相邻的元素,逐个向后移动,直到比较到序列的倒数第二个元素和最后一个元素。
  4. 重复上述步骤,直到整个序列按照从小到大(或从大到小)的顺序排列。

冒泡排序的核心思想是通过反复交换相邻的元素来实现排序,每一轮遍历都会将当前未排序部分中最大(或最小)的元素交换到正确的位置上。重复执行这个过程,直到整个序列有序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>

void bubbleSort(int arr[], int n)
{
for (int i = 0; i < n - 1; i++)
{
for (int j = 0; j < n - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
// 交换 arr[j] 和 arr[j+1] 的位置
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}

int main()
{
int arr[] = { 64, 34, 25, 12, 22, 11, 90 };
int n = sizeof(arr) / sizeof(arr[0]);
bubbleSort(arr, n);
printf("排序后的数组:");
for (int i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}

return 0;
}

在上述示例中,我们使用两层循环来遍历待排序序列,并通过比较相邻元素交换位置,将较大的元素逐步向后移动,最终实现对给定数组的升序排序。输出结果为 11 12 22 25 34 64 90

3. 二维数组

3.1 定义和使用

在 C 语言中,二维数组是由多个一维数组按照一定规律排列而成的数据结构。它可以被看作是一个表格或矩阵。二维数组的声明和使用如下所示:

1
类型说明符 数组名[常量表达式1][常量表达式2];
  • 常量表达式1表示第一维下标的长度,对应矩阵的行
  • 常量表达式2 表示第二维下标的长度,对应矩阵的列
1
int array[12][6];	// 定义一个12行6列的数组

关于二维数组的命名规则和一维数组是一样的,下图定义了一个3行4列的数组,数组名为a其元素类型为整型,该数组的元素个数为3×4个,即:

img

二维数组a是按行进行存放的,先存放a[0]行,再存放a[1]行、a[2]行,并且每行有4个元素,也是依次存放的。

  • 二维数组在概念上是二维的:其下标在两个方向上变化,对其访问一般需要两个下标

  • 内存中并不存在二维数组,二维数组实际的硬件存储器是连续编址的,也就是说内存中只有一维数组,即放完一行之后顺次放入第二行,和一维数组存放方式是一样的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>
int main()
{
int a[4][3];
//给数组每个元素赋值
int num = 0;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 3; j++)
{
a[i][j] = num++;
}
}

//遍历数组,并输出每个成员的值
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%d, ", a[i][j]);
}
printf("\n");
}

return 0;
}
  • 第 4 行:定义了一个二维数组,4行3列,在内存中要连续存储 12 个元素
  • 第 11 行:通过两个下标访问二维数组中的某个元素,并给其赋值
  • 第 20 行:通过两个下标访问二维数组中的某个元素的值

3.2 数组名

和一维数组的名字一样,二维数组名也是一个地址的常量,代表数组中首元素的地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
int main()
{
int a[3][4] = { 1, 2, 3, 4 , 5, 6, 7, 8, 9, 10, 11, 12 };
printf("a = %p\n", a);
printf("a[0] = %p\n", a[0]);
printf("a[0][0] = %p\n", &a[0][0]);

// 计算内存大小
printf("sizeof(a) = %zd\n", sizeof(a));
printf("sizeof(a[0]) = %zd\n", sizeof(a[0]));
printf("sizeof(a[0][0]) = %zd\n", sizeof(a[0][0]));

printf("行数 i = %zd\n", sizeof(a) / sizeof(a[0]));
printf("列数 j = %zd\n", sizeof(a[0]) / sizeof(a[0][0]));
printf("元素总个数 n = %zd\n", sizeof(a) / sizeof(a[0][0]));

return 0;
}
  • 第 4 行:定义了一个二维数组,3行4列,共12个元素
  • 第 5 行:打印二维数组的地址数组名为数组首元素地址
  • 第 6 行:打印第 0 行的首(起始)地址,即:a[0]
    • 每一行的一维数组都有4个整形元素,在此记作int[4]
    • 可以将a[0]视为第一行一维数组的名字,一维数组的名字对应的就是一个地址
    • 基于上面一条进行类推,打印第2、3、4行一维数组的起始地址对应的名字就是a[1]、a[2]、a[3]
  • 第 7 行:打印 第0行0列的首(起始)地址,即:&a[0][0]
    • 上文说到 a[0]代表第一行的一维数组,这个一维数组有4个元素,如果取出这个一维数组中的第一个元素就应该写成这样:a[0][0]
    • 如果想要得到数组元素的地址,方法和获取变量的地址相同,即在数组元素名字或者变量名前加取地址符&
  • 第 10 行:计算二维数组占用的内存大小
  • 第 11 行:计算二维数组的一行占用的内存大小
  • 第 12 行:计算二维数组的一个元素占用的内存大小
  • 第 14行:计算二维数组的行数
  • 第 15 行:计算二维数组的列数
  • 第 16 行:计算二维数组的总元素个数

程序打印的结果如下:

1
2
3
4
5
6
7
8
9
a = 000000ECF89EFBB8
a[0] = 000000ECF89EFBB8
a[0][0] = 000000ECF89EFBB8
sizeof(a) = 48
sizeof(a[0]) = 16
sizeof(a[0][0]) = 4
行数 i = 3
列数 j = 4
元素总个数 n = 12

通过输出的信息我们可以得出这样一个结论:二维数组的地址和二维数组首行的起始地址以及二维数组第一个元素的地址是内存中的同一个位置(重合)。

3.3 初始化

二维数组的初始化和一维数组类似,下面举例说明:

1
2
3
4
5
6
7
8
9
10
int a1[3][4] = 
{
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8, },
{ 9, 10, 11, 12 }
};
int a2[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
int a3[3][4] = { 1, 2, 3, 4 };
int a4[3][4] = {0};
int a5[][4] = { 1, 2, 3, 4, 5, 6, 7, 8};
  • a1:分段赋值,按照逻辑结构对行、列分别赋值,每行对应一个{}
  • a2:连续赋值,数据在内存中就是以这种形式存储的
  • a3:可以只给部分元素赋初值,未初始化的部分自动被设置为 0
  • a4:所有的成员都设置为0
  • a5行对应的[]中不指定元素个数,定义时必须对数组初始化
    • 列对应的[]不允许为空

3.4 一展身手

需求:使用二维数组进行班级小组学生成绩统计。

假设该小组有5人,考试科目为:语文、数学、英语

  • 求各科平均分
  • 求各科不及格的人数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdio.h>
int main()
{
float a[5][3] = {
{ 80, 75, 56 },
{ 59, 65, 71 },
{ 59, 63, 70 },
{ 85, 45, 90 },
{ 76, 77, 45 }
};

int person_low[3] = { 0 };
float s = 0, lesson_aver[3] = { 0 };

for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 5; j++)
{
s = s + a[j][i];
if (a[j][i] < 60)
{
person_low[i]++;
}
}
lesson_aver[i] = s / 5;
s = 0;
}

printf("各科的平均成绩:\n");
for (int i = 0; i < 3; i++)
{
printf("%.2f\n", lesson_aver[i]);
}

printf("各科不及格的人数:\n");
for (int i = 0; i < 3; i++)
{
printf("%d\n", person_low[i]);
}

return 0;
}

4. 多维数组(了解)

多维数组的定义与二维数组类似,其语法格式具体如下:

1
类型 数组名 [n1][n2]…[nn];

对于3维以及以上维度的数组在编程的时候是很少、很少、很少用的,下面以三维数组举例:

1
int a[3][2][3];

上面定义了一个三维数组,数组的名字是a

  • 数组的长度为3,每个数组的元素又是一个二维数组
  • 二维数组的长度是2,并且这个二维数组中的每个元素又是一个一维数组
  • 一维数组的长度是3,元素类型是 int。

实例中的三维数组在内存中的存储结构如下图:

image-20230801021041873

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>
int main()
{
int a[3][4][5] = {
{
{ 1, 2, 3, 4, 5 },
{ 6, 7, 8, 9, 10 },
{ 0 }, { 0 }
},
{
{ 0 }, { 0 }, { 0 }, { 0 }
},
{
{ 0 }, { 0 }, { 0 }, { 0 }
}
};

int i, j, k;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
for (k = 0; k < 5; k++)
{
//添加访问元素代码
printf("%d, ", a[i][j][k]);
}
printf("\n");
}
}
return 0;
}

5. 字符数组

5.1 定义

C语言中,没有字符串这种数据类型,可以通过char的数组来替代,字符串一定是一个char的数组,但char的数组未必是字符串

  • 以数字0(字符‘\0’的 ascii 值为 0)结尾的char数组就是一个字符串
  • 如果char数组没有以字符\0结尾,那么它就不是字符串,只是一个普通的字符数组
  • 字符串是一种特殊的char类型数组。
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
int main()
{
char c1[] = { 'h', ' ', 'e', 'l', 'l', 'o' };
printf("c1 = %s\n", c1);
char c2[] = { 'h', ' ', 'e', 'l', 'l', 'o', '\0' };
printf("c2 = %s\n", c2);
char c3[] = { 'h', ' ', 'e', 'l', 'l', 'o', '\0', 'w', 'o', 'r', 'l', 'd', '\0' };
printf("c3 = %s\n", c3);

return 0;
}

程序打印的结果如下:

1
2
3
4
c1 = h ello烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫
烫?徾?
c2 = h ello
c3 = h ello
  • 第 4 行:定义并初始化一个char类型的一维数组,不是字符串
  • 第 5 行:打印有乱码,因为字符数组末尾没有’\0’结束符
  • 第 6 行:定义并初始化一个char类型的一维数组,是字符串
  • 第 7 行:打印没有乱码,因为字符数组末尾以字符’\0’结束
  • 第 8 行:定义并初始化一个char类型的一维数组,是字符串
  • 第 9 行:打印没有乱码,因为字符数组末尾以字符’\0’结束,如果字符串中有多个\0结束符,数据读到第一个结束符就结束了,会忽略后边的内容,因此world没有被输出到屏幕。

5.2 初始化

字符数组的初始化和前面讲到的数组的初始化方式类似,下面举例说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdio.h>
int main()
{
char buf1[] = { 'a', 'b', 'c' };
printf("buf = %s\n", buf1);

char buf2[100] = { 'a', 'b', 'c' };
printf("buf2 = %s\n", buf2);

char buf3[100] = { 0 };

char buf4[2] = { '1', '2', '3' }; // error

char buf5[50] = { '1', 'a', 'b', '0', '7' };
printf("buf5 = %s\n", buf5);

char buf6[50] = { '1', 'a', 'b', 0, '7' };
printf("buf6 = %s\n", buf6);

char buf7[50] = { '1', 'a', 'b', '\0', '7' };
printf("buf7 = %s\n", buf7);

char buf8[] = "agjdslgjlsdjg";
printf("buf8 = %s\n", buf8);

char buf9[] = "\012abc";
printf("str = %s\n", buf9);

return 0;
}

程序输出的结果如下:

1
2
3
4
5
6
7
8
9
buf = abc烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫
烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫蘰i
buf2 = abc
buf5 = 1ab07
buf6 = 1ab
buf7 = 1ab
buf8 = agjdslgjlsdjg
str =
abc
  • buf1:不指定长度, 没有0结束符,元素个数就是数组长度

    • 将这个字符数组数据按照字符串打印,因为没有\0结束符,将数组后面内存中的数据也一并读出来了,所以会尾部会出现乱码
  • buf2:指定长度,后面没有赋值的元素,自动补0

  • buf3:将所有元素赋值为0

  • buf4:数组元素个数大于数组的容量,数组越界

    • 数组越界相当于访问了非法内存,可能会导致程序异常退出
  • buf5:定义并初始化了一个指定长度的字符数组,没有\0结束符

  • buf6:定义并初始化了一个指定长度的字符数组,有\0结束符

    • 第四个字符的整型值为0,也就是字符\0,此处会进行隐式类型转换
  • buf7:定义并初始化了一个指定长度的字符数组,有\0结束符

    • 结束符为数组的第4个字符,\0后的字符在打印的时候会被舍弃
  • buf8:使用字符串初始化字符数组,编译器会自动在尾部补\0,推荐

  • buf9:使用字符串初始化字符数组,编译器会自动在尾部补\0,但是'\0'后面最好不要连着数字,有可能几个数字连起来刚好是一个转义字符

    • '\ddd'八进制字义字符,后面两个dd的范围是 0~7
    • '\xdd'十六进制转移字符,后面两个dd的范围是 0~9,a~f,A~F
    • \012 相当于\n

5.3 一展身手

现有两个字符串str1 和 str2,请将这两个字符串合并,将最终的结果存储到一个字符数组dst中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>
int main()
{
char str1[] = "abcdef";
char str2[] = "123456";
char dst[100];

int i = 0;
while (str1[i] != 0)
{
dst[i] = str1[i];
i++;
}

int j = 0;
while (str2[j] != 0)
{
dst[i + j] = str2[j];
j++;
}
dst[i + j] = 0; //字符串结束符

printf("dst = %s\n", dst);

return 0;
}