C语言字符数组的用法(非常详细)
在众多的数组中,有一个特殊的数组,即字符数组,我们需要对其进行额外的讲解。
在探究字符数组之前,我们来回顾与字符串相关的知识点,看个例子:

图 1 字符串"HelloWorld"内部存储
字符 '0' 对应的 ASCII 码为十进制 48。为了不与字符 '0' 冲突,将标记字符串结尾的数值 0,使用转义序列 '\0' 表示。
此外,我们还可以使用更简便的字符数组初始化方式,即将初始化列表直接写成一个字符串常量,代码如下:
代码如下:
此外,转换规范 %s 也可以作为字符数组的占位符,代码如下:
例如:
在这种情况下,字符数组中的字符串无法结尾,这可能会导致数组越界访问。例如:
例如,下面的代码将输出字符数组 str 中的所有元素,以及其后面的不确定值。
例如:
例如,下面的代码:
我们还可以使用初始化列表来初始化数组,例如:
需要注意的是,如果我们使用以下代码初始化数组,则该数组中的字符将不会正常结尾。
在实际编程中,我们应该避免出现这种情况,以确保程序的正确性和稳定性。
接下来,我们将提供两种方法来测量字符串的长度。
strlen() 函数的使用方法如下:
下面展示了一个使用 strlen() 函数的例子:
这个程序的运行结果为:
下面展示了一个修改字符数组的例子:
在探究字符数组之前,我们来回顾与字符串相关的知识点,看个例子:
#include <stdio.h> int main() { printf("sizeof HelloWorld = %d\n", sizeof("HelloWorld")); return 0; }使用 sizeof 操作符测量字符串 "HelloWorld" 占用了 11 字节,执行结果为:
sizeof HelloWorld = 11
内存中的字符串常量由每个字符的 ASCII 码按照顺序排列构成,每个字符仅占 1 字节,并且末尾会附上一个数值 0,指示字符串结尾,如下图所示:
图 1 字符串"HelloWorld"内部存储
字符 '0' 对应的 ASCII 码为十进制 48。为了不与字符 '0' 冲突,将标记字符串结尾的数值 0,使用转义序列 '\0' 表示。
字符数组存储字符串
由于字符串满足数组的类型相同且按顺序排列的特点,元素为 char 的数组可以用于存储字符串。1) 初始化字符数组
我们可以声明一个 char 类型的数组,并将其初始化为 "HelloWorld",代码如下:char str[20] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'};在上述代码中,由于数组大小为 20,而初始化列表中仅有 10 个元素,数组中剩余的 10 个元素会被自动初始化为 0,即自动添加了字符串结尾标识符 '\0'。
此外,我们还可以使用更简便的字符数组初始化方式,即将初始化列表直接写成一个字符串常量,代码如下:
char str[20] = "HelloWorld";在上述代码中,字符串常量的末尾会被自动添加 '\0' 作为字符串结尾标识符,因此上述代码等价于:
char str[20] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd', '\0'};
2) 省略数组大小
有时候,我们希望一个数组被初始化为某个字符串,但是又不想数清楚到底有多少个字符。此时,我们可以在数组声明时省略数组大小,此时数组的大小就是初始化列表中元素的个数。代码如下:
char str1[] = "HelloWorld"; char str2[] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd', '\0'};上述两种写法是等价的,数组的大小为 11,即初始化列表中的元素个数。
3) 输出字符数组
接下来,我们可以使用 printf() 函数将字符数组中存储的字符串输出到控制台中,由于 printf() 函数的第一个参数可以接收一串字符串,因此我们可以直接将数组作为 printf() 的第一个参数,如下所示:printf("HelloWorld"); printf(str); //使用字符数组在 C语言中,字符数组和字符串常量是存储字符串的两种方式。字符串常量是一种特殊类型的字符数组。当我们在 C语言中使用 printf() 函数时,可以直接将字符数组作为参数传递给该函数,因为 printf() 函数会将字符数组中的字符逐个输出到控制台中,直到遇到空字符。
此外,转换规范 %s 也可以作为字符数组的占位符,代码如下:
printf("%s", str);下面是一个将字符数组输出到控制台中的示例:
#include <stdio.h> int main() { char str[20] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'}; printf(str); printf("\n"); printf("%s", str); printf("\n"); return 0; }运行结果为:
HelloWorld
HelloWorld
字符串结尾标记'\0'
在使用字符串常量时,系统会自动为我们在字符串末尾添加 '\0' 标记字符串结束。但是在使用字符数组时,有些情况不能保证字符串末尾有 '\0',需要格外注意。1) 初始化列表长度小于数组长度
如果使用初始化列表初始化字符数组,并且初始化列表长度小于数组长度,则数组前面的元素将被初始化为字符串,后面的元素将被填充为 0。在这种情况下,字符数组中的字符串正常结尾,因为系统在初始化期间已经为字符串添加了结尾标记 '\0'。例如:
char str[20] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'};上面的代码将数组前 10 个元素初始化为字符串 "HelloWorld",后面的 10 个元素被填充为 0。
2) 初始化列表长度等于数组长度
如果使用初始化列表初始化字符数组,并且初始化列表长度等于数组长度,则数组中的元素都被初始化为字符串。但由于初始化列表已经占用了数组中的所有空间,因此没有空间可以保存结尾标记 '\0'。在这种情况下,字符数组中的字符串无法结尾,这可能会导致数组越界访问。例如:
char str[10] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'};上面的代码将数组中的所有 10 个元素都初始化为字符串 "HelloWorld"。但由于缺少结尾标记 '\0',在使用 printf() 等函数输出该字符数组时,程序将继续输出数组外的元素,直到遇到一个 '\0' 才停止。这可能导致数组被越界访问。
例如,下面的代码将输出字符数组 str 中的所有元素,以及其后面的不确定值。
printf("%s", str);运行结果为:
HelloWorld烫烫烫烫烫烫烫烫烫
因此,在使用初始化列表初始化字符数组时,必须确保数组中有足够的空间保存结尾标记 '\0'。3) 初始化列表长度大于数组长度
如果使用初始化列表初始化字符数组,并且初始化列表长度大于数组长度,则将无法通过编译。这是因为初始化列表中的元素数量超过了数组的容量,无法被全部存储。例如:
char str[5] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'};上面的代码将会导致编译错误,因为初始化列表中有 10 个元素,而数组只有 5 个元素的容量。
4) 省略数组大小的情况
在 C语言中,我们有时会省略数组的大小并直接使用字符串常量来初始化数组。例如,下面的代码:
char str[] = "HelloWorld";这段代码省略了数组的大小,直接使用字符串常量来初始化数组。由于系统会自动为字符串常量结尾添加 '\0',因此字符串常量大小为 11。使用该字符串初始化数组,数组大小也为 11,并且最后一个字符为 '\0',即字符串正常结尾。
我们还可以使用初始化列表来初始化数组,例如:
char str[] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd', '\0'};在这段代码中,我们使用了初始化列表来初始化数组。该初始化列表包含了 11 个字符常量,其中最后一个字符常量为 '\0',表示字符串的结尾。使用该初始化列表初始化数组,数组大小为 11,并且最后一个字符为 '\0',即字符串正常结尾。
需要注意的是,如果我们使用以下代码初始化数组,则该数组中的字符将不会正常结尾。
char str[] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'};该初始化列表包含了 10 个字符常量,最后一个字符常量为 'd',因此使用该初始化列表初始化数组,数组大小为 10,并且最后一个字符为 'd'。这意味着该字符数组中的字符串无法正常结尾。
在实际编程中,我们应该避免出现这种情况,以确保程序的正确性和稳定性。
字符数组的大小及长度
在下面的代码中,我们声明一个长度为 20 的字符数组 str,并使用字符串常量"HelloWorld"对它进行初始化。这样,字符数组的前 10 个元素为 HelloWorld,第 11 个元素为 '\0'。char str[20] = "HelloWorld";为了测试 str 的大小,我们可以使用 sizeof 关键字,结果为 20。从结果可以看出,str 的大小为 20 字节,和我们声明的数组大小一致。因此,我们无法直接用 sizeof 关键字测量字符串的长度。
接下来,我们将提供两种方法来测量字符串的长度。
1) 使用循环测量字符串长度
一个字符串用 '\0' 标记结尾,只要知道在 '\0' 之前,有多少个字符,就能知道字符数组中的字符串的长度了。具体的代码如下:#include <stdio.h> int main() { char str[20] = "HelloWorld"; int len = 0; while(str[len] != '\0') // 检查字符串结束符 { len++; } printf("%d", len); return 0; }在程序中,我们声明了一个 len 变量,用于统计字符串长度。while 循环从第一个元素开始,检查元素是否为 '\0',如果不是,则将 len 加 1,直到元素为 '\0'。循环结束时,len 的值即为字符串的长度。运行结果为 10。
2) 使用strlen()测量字符串长度
我们还可以使用 strlen() 函数来计算字符串的长度。strlen() 是由 string(字符串)和 length(长度)两个单词组合而成。strlen() 函数的使用方法如下:
- strlen() 函数可以接收一个字符串作为参数;
- strlen() 函数的返回值是这个字符串的长度;
-
在使用 strlen() 函数之前,需要包含头文件
<string.h>
。
下面展示了一个使用 strlen() 函数的例子:
#include <stdio.h> #include <string.h> int main() { char str[20] = "HelloWorld"; int len1; len1 = strlen(str); printf("len1 = %d\n", len1); int len2; len2 = strlen("HelloWorld"); printf("len2 = %d\n", len2); printf("sizeof str %d\n", sizeof(str)); printf("sizeof helloworld %d\n", sizeof("HelloWorld")); return 0; }在这个例子中,len1 是由 strlen() 函数测量的字符数组 str 内字符串的长度,len2 是由 strlen() 函数测量的字符串常量 "HelloWorld" 的长度。后续,用 sizeof 分别测量字符数组 str 和字符串常量 "HelloWorld" 占用的空间大小。
这个程序的运行结果为:
len1 = 10
len2 = 10
sizeof str 20
sizeof helloworld 11
总的来说,strlen(str) 测量从第一个元素开始直到元素值为 '\0' 的字符串的长度,而 sizeof(str) 测量数组本身占用的空间大小。
修改字符数组
字符串常量是不可变的,但字符数组却可以被修改。下面展示了一个修改字符数组的例子:
#include <stdio.h> #include <string.h> int main() { char str[20] = "abcde"; // 修改前 printf("%s\n", str); // 使用%s格式符来打印字符串 // 每个元素减 32 for(int i = 0; i < strlen(str); i++) { str[i] = str[i] - 32; } // 修改后 printf("%s\n", str); return 0; }在程序中,数组被初始化为 "abcde",然后我们将其中的小写字符转换为大写字符。根据 ASCII 码,将小写字符的 ASCII 码减去 32 即可得到对应的大写字符。运行结果为:
abcde
ABCDE
从键盘输入字符串到字符数组中
可以使用 scanf() 函数将从键盘中输入的一串字符串存储到字符数组中,其转换规范为 "%s"。例如:char str[20]; scanf("%s", str); // 将从键盘中输入的一串字符串存储到字符数组str中下面程序使用 scanf() 函数将一串字符串存储到字符数组中,并将其中的小写字符转换为大写字符后再进行输出。
#include <stdio.h> #include <string.h> int main() { char str[20]; // 输入一串字符到 str 中 scanf("%s", str); // 修改前 printf("%s\n", str); // 每个元素减 32 for(int i = 0; i < strlen(str); i++) { str[i] = str[i] - 32; } // 修改后 printf("%s\n", str); return 0; }scanf() 函数会自动在输入的字符串后面加上 '\0',因此输入的字符串可以正常结束。运行结果为:
apple
apple
APPLE