C语言中的可变长度数组:初学者指南
你好,未来的程序员们!今天,我们将踏上一段激动人心的旅程,探索C语言中的可变长度数组(Variable Length Arrays,简称VLAs)。如果你是编程新手,不用担心——我会作为你的友好向导,一步步解释所有内容。那么,让我们开始吧!
可变长度数组是什么?
在我们开始之前,先来了解一下可变长度数组是什么。想象你正在计划一个派对,但你不确定会有多少客人来。如果你能设置一个可以神奇地根据客人数量调整大小的桌子,那岂不是很好?这正是编程中VLAs的作用!
可变长度数组是一种在运行时(程序运行时)而不是在编译时(程序准备运行时)确定大小的数组。这个特性在C99标准中引入,为创建数组提供了更大的灵活性。
创建可变长度数组
让我们从一个简单的例子开始,创建一个VLA:
#include <stdio.h>
int main() {
int n;
printf("你想存储多少个数字? ");
scanf("%d", &n);
int numbers[n]; // 这就是我们的可变长度数组
printf("输入 %d 个数字:\n", n);
for (int i = 0; i < n; i++) {
scanf("%d", &numbers[i]);
}
printf("你输入了:");
for (int i = 0; i < n; i++) {
printf("%d ", numbers[i]);
}
return 0;
}
让我们分解一下:
- 我们询问用户想要存储多少个数字。
- 我们根据用户输入的大小创建一个名为
numbers
的数组。 - 我们使用循环从用户那里输入
n
个数字。 - 最后,我们打印用户输入的所有数字。
这就是VLAs的美妙之处——我们在编写代码时不需要知道数组的大小。大小是在程序运行时确定的!
二维可变长度数组
现在,让我们升级一下,看看二维的VLA。想象你正在为一个婚礼创建座位图,但你不知道会有多少桌子或者每张桌子会有多少座位。二维VLA可以帮助你!
这里有一个例子:
#include <stdio.h>
int main() {
int tables, seats;
printf("有多少桌子? ");
scanf("%d", &tables);
printf("每张桌子有多少座位? ");
scanf("%d", &seats);
int seating[tables][seats]; // 我们的2D可变长度数组
// 分配座位号
for (int i = 0; i < tables; i++) {
for (int j = 0; j < seats; j++) {
seating[i][j] = i * seats + j + 1;
}
}
// 打印座位安排
printf("\n座位安排:\n");
for (int i = 0; i < tables; i++) {
printf("桌子 %d: ", i + 1);
for (int j = 0; j < seats; j++) {
printf("%3d ", seating[i][j]);
}
printf("\n");
}
return 0;
}
在这个例子中:
- 我们询问用户桌子的数量和每张桌子的座位数量。
- 我们创建一个名为
seating
的2D VLA,尺寸为[tables][seats]
。 - 我们分配座位号。
- 最后,我们打印座位安排。
这种灵活性允许我们在运行时创建任何大小的座位图!
锯齿数组
现在,事情变得更加有趣。如果我们的婚礼上每张桌子都有不同数量的座位怎么办?这时候就引入了锯齿数组——一个数组,其中的子数组可以有不同的长度。
虽然C语言不直接支持像其他一些语言那样的锯齿数组,但我们可以使用VLA和指针来模拟它们。以下是如何操作的:
#include <stdio.h>
#include <stdlib.h>
int main() {
int tables;
printf("有多少桌子? ");
scanf("%d", &tables);
int *seats = malloc(tables * sizeof(int));
int **seating = malloc(tables * sizeof(int*));
// 输入每张桌子的座位数量
for (int i = 0; i < tables; i++) {
printf("桌子 %d 有多少座位? ", i + 1);
scanf("%d", &seats[i]);
seating[i] = malloc(seats[i] * sizeof(int));
}
// 分配座位号
for (int i = 0; i < tables; i++) {
for (int j = 0; j < seats[i]; j++) {
seating[i][j] = j + 1;
}
}
// 打印座位安排
printf("\n座位安排:\n");
for (int i = 0; i < tables; i++) {
printf("桌子 %d: ", i + 1);
for (int j = 0; j < seats[i]; j++) {
printf("%3d ", seating[i][j]);
}
printf("\n");
}
// 释放分配的内存
for (int i = 0; i < tables; i++) {
free(seating[i]);
}
free(seating);
free(seats);
return 0;
}
这个例子更复杂一些,让我们分解一下:
- 我们创建一个数组
seats
来存储每张桌子的座位数量。 - 我们创建一个指向指针的指针
seating
来模拟我们的锯齿数组。 - 我们根据每张桌子的座位数量动态分配内存。
- 我们分配座位号并像之前一样打印安排。
- 最后,我们释放分配的内存以防止内存泄漏。
这种方法允许我们每张桌子都有不同数量的座位——真正的灵活性!
方法表
这里是一个我们例子中用到的方法的快速参考表:
方法 | 描述 | 示例 |
---|---|---|
scanf() |
从用户读取格式化输入 | scanf("%d", &n); |
printf() |
向控制台打印格式化输出 | printf("你好,%s!", name); |
malloc() |
动态分配内存 | int *arr = malloc(n * sizeof(int)); |
free() |
释放动态分配的内存 | free(arr); |
记住,能力越大,责任越大。VLAs和动态内存分配是强大的工具,但需要谨慎使用,以避免栈溢出或内存泄漏等问题。
就是这样!你已经迈出了进入C语言可变长度数组世界的第一步。记住,熟能生巧,所以不要害怕尝试这些概念。快乐编码!
Credits: Image by storyset