C语言(八)
一、字符型数组与字符串的存储
1. 三大特性
连续性
字符数组在内存中连续存储,字符依次排列,无空隙。举例:
char s[5] = "abcd";
在内存中依次存放'a'
、'b'
、'c'
、'd'
、\0
,地址是连续分配的。有序性
字符型数组中各字符存储顺序固定,字符的位置决定其意义,不能随意打乱。
单一性
字符型数组的每个元素都是同一种数据类型,即单个char
字符,占用1个字节。整个数组只存放字符类型,不会掺杂其他类型数据。
2. 字符数组定义方式
char 数组名[元素个数];
示例:
char s[100];
说明:方括号 []
是类型说明符的一部分,数组容量应满足字符串加结束符 \0
的需求。
3. 初始化方式
char s[100] = "Hello"; // 自动添加 '\0' char s[20] = {'a', 'b'}; // 其余自动补 \0
注意事项:
使用双引号时可省略
{}
。空字符串
""
表示仅含一个\0
,占 1 字节。字符串以
\0
结尾,必须为其留出空间。字符数组内容可修改,字符串常量不可以。
二、字符串常用函数
1. puts
函数
int puts(const char *s);
功能:输出字符串并自动换行。
示例:
puts(s); // 等价于 puts(&s[0]);
注意:不能输出单个字符或整型。
2. 判别不同字符串类型
表达式 | 类型 | 占用字节 | 含义说明 |
---|---|---|---|
0 | 整型常量 | 4 字节 | 值为 0 |
'0' | 字符常量 | 1 字节 | 字符 '0',ASCII 为 48 |
'\0' | 字符常量 | 1 字节 | 空字符,ASCII 为 0(结束符) |
"0" | 字符串常量 | 2 字节 | '0' + \0 |
"" | 字符串常量 | 1 字节 | 仅含 \0 |
3. gets
函数(不推荐)
char *gets(char *s);
从标准输入读取一行字符串,末尾自动加
\0
。问题:不会检查越界,存在安全风险。
4. fgets
函数(推荐)
char *fgets(char *s, int size, FILE *stream);
功能:从文件流
stream
中读取字符串,通常配合stdin
使用,能够防止越界访问。
示例:
char s[100]; fgets(s, 100, stdin);
说明:
最多读取
size - 1
个字符,最后一位补\0
。可读取空格,包括换行符
\n
。安全性高于
gets
。小写转大写:
5. scanf
函数
int scanf(const char *format, ...);
示例:
scanf("%s", s);
注意:
不加
&
,因为s
是数组名,代表地址。空格、Tab、回车会结束读取,不能读取含空格的字符串。
6. strlen
函数
size_t strlen(const char *s);
功能:返回有效字符数(不含
\0
)。示例:
char str[] = "abc"; printf("%lu\n", strlen(str)); // 输出3
printf("%lu\n", sizeof(str)); // 输出4
内存分配:需要
strlen + 1
字节。
7. strcpy
函数
char *strcpy(char *dest, const char *src);
功能:将
src
拷贝到dest
。示例:
strcpy(s2, s1);
注意:
dest
空间必须足够大。
8. strcat
函数
char *strcat(char *dest, const char *src);
功能:将
src
追加到dest
的末尾。示例:
strcat(s1, s2);
注意:
dest
空间需 ≥strlen(dest) + strlen(src) + 1
。
9. strcmp
函数
int strcmp(const char *s1, const char *s2);
功能:比较两个字符串。
返回值说明:
>0:
s1 > s2
= 0:
s1 == s2
< 0:
s1 < s2
示例:
printf("%d\n", strcmp(s1, s2));
比较规则:按 ASCII 逐字符比较,遇不同即判断大小。
三、字符串相关练习题
求三个字符串中的最大值
字符串逆序输出