数组和字符串是 C 语言最基础也最常用的数据组织方式。这篇讲清楚数组的定义、遍历,以及 C 语言里字符串的本质与常用操作。

一、一维数组的定义与初始化

数组是一批相同类型变量在内存中的连续存储:

#include <stdio.h>

int main(void) {
    int scores[5] = {90, 85, 77, 92, 88};  /* 定义并初始化 */
    printf("%d\n", scores[0]);  /* 输出:90(下标从 0 开始) */
    printf("%d\n", scores[4]);  /* 输出:88(最后一个元素) */
    return 0;
}

注意两点:下标从 0 开始;初始化时元素个数不能超过数组长度。也可以省略长度让编译器自动推算:

int nums[] = {1, 2, 3};  /* 长度自动为 3 */

二、用 for 循环遍历数组

数组通常配合循环使用:

int scores[5] = {90, 85, 77, 92, 88};
int sum = 0;
for (int i = 0; i < 5; i++) {
    sum += scores[i];
}
printf("平均分:%.1f\n", sum / 5.0);  /* 输出:平均分:86.4 */

循环条件写 i < 5 而不是 i <= 5,否则会越界访问,这是新手最常见的错误。

三、二维数组:按行列组织数据

int matrix[2][3] = {
    {1, 2, 3},
    {4, 5, 6}
};
printf("%d\n", matrix[1][2]);  /* 输出:6(第 2 行第 3 列) */

二维数组可以理解为"数组的数组",第一个下标是行,第二个下标是列,适合存表格、棋盘类数据。

四、字符串就是字符数组

C 语言没有专门的字符串类型,字符串是以 \0(空字符)结尾的字符数组:

char name[] = "Tom";   /* 实际存储:'T' 'o' 'm' '\0',占 4 字节 */
printf("%s\n", name);  /* 输出:Tom */
printf("%zu\n", sizeof(name));  /* 输出:4(包含结尾的 \0) */

\0 是字符串结束的标志,printf 用 %s 打印时就是从头逐个输出字符,直到遇到 \0 为止。

五、字符串的常用函数

标准库 <string.h> 提供了一组常用字符串函数:

#include <stdio.h>
#include <string.h>

int main(void) {
    char s1[20] = "hello";
    char s2[] = "world";

    printf("%zu\n", strlen(s1));          /* 输出:5(长度不含 \0) */
    printf("%d\n", strcmp(s1, "hello"));  /* 输出:0(相等返回 0) */
    strcat(s1, s2);                       /* 把 s2 拼接到 s1 末尾 */
    printf("%s\n", s1);                   /* 输出:helloworld */
    return 0;
}

三个最常用的函数:strlen 求长度、strcmp 比较、strcat 拼接。特别提醒:比较字符串内容不能用 ==,那比较的是地址,必须用 strcmp,返回 0 表示完全相同。

六、常见坑:数组越界与 \0 丢失

char buf[5] = "hello";  /* 危险:5 个字符 + \0 需要 6 个字节! */

这句编译器可能只是警告,但运行时 buf 末尾没有 \0,用 %s 打印会一直读到内存里未知的位置。定义字符数组时,长度至少要比可见字符多留 1。

小结

  • 数组下标从 0 开始,遍历条件用 i < 长度,谨防越界
  • 二维数组按 [行][列] 组织,适合表格类数据
  • C 的字符串是 \0 结尾的字符数组,定义时要为它留位置
  • strlen 求长、strcmp 比较、strcat 拼接,比较字符串别用 ==