六、C语言字符串与字符

思维导图


一、 字符与转义字符

1.1 字符的本质是整数

在计算机眼里,'A' 只是一个数字 65
char 类型通常占用 1 个字节(8 bits),范围是 -128 到 127。

代码示例:

c 复制代码
char c = 'A';
printf("字符: %c\n", c);  // 输出 A
printf("ASCII: %d\n", c); // 输出 65

// 字符运算
char next = c + 1;
printf("下一个: %c\n", next); // 输出 B

1.2 转义字符

有些字符看不见(如换行),或者有特殊含义(如双引号),需要用反斜杠 \ 来转义。

转义符 含义
\n 换行
\t 制表符,用于对齐
\\ 反斜杠本身
\' 单引号(在字符常量中用)
\" 双引号(在字符串中用)
\0 空字符,字符串结束标志

二、 C 字符串的存储规则

2.1 核心规则:以 \0 结尾

C 语言没有记录字符串的长度。它怎么知道字符串在哪里结束?

答案: 只要遇到 ASCII 值为 0 的字符 \0,就认为结束了。

声明与初始化:

c 复制代码
// 写法 1:逐个字符,必须手动加 \0,否则打印乱码
char s1[] = {'H', 'e', 'l', 'l', 'o', '\0'}; 

// 写法 2:字符串字面量(编译器自动加 \0)
char s2[] = "Hello"; 

// 内存视角:
// s2 占用了 6 个字节:'H' 'e' 'l' 'l' 'o' '\0'

2.2 数组 vs 指针

代码对比:

c 复制代码
// 1. 字符数组:内容存放在栈上,可以随意修改
char str[] = "Hello";
str[0] = 'X'; // 合法,变成 "Xello"

// 2. 字符串指针:指向只读数据区(常量区)
char *ptr = "Hello";
// ptr[0] = 'X'; // 崩溃!Segfault (非法写入)

三、 常用字符串函数

3.1 strlen:计算长度

功能: 计算字符串的有效长度,不包括 \0
注意: 它需要从头走到尾数数,时间复杂度 O(N)。不要在循环条件里调用它!

手写 strlen:

c 复制代码
size_t my_strlen(const char *s) {
    size_t len = 0;
    while (s[len] != '\0') { // 只要没遇到结束符
        len++;
    }
    return len;
}

3.2 strcpy / strncpy:复制

strcpy(dst, src):把 src 的内容(含 \0)拷给 dst。

风险: 如果 dst 空间不够,会发生 缓冲区溢出。

推荐: strncpy(dst, src, n),限制拷贝 n 个字符。但要注意 strncpy 可能不补 \0,需要手动补。

3.3 strcmp:比较

错误写法: if (s1 == s2) ------ 这比的是 地址,不是内容!
正确写法: if (strcmp(s1, s2) == 0) ------ 相等返回 0。

3.4 strcat:拼接

strcat(dst, src):把 src 接到 dst 后面。
前提: dst 必须有 足够 的剩余空间容纳 src。

四、 字符串输入的坑与解决

4.1 scanf("%s") 的缺陷

  1. 遇空格即停: 输入 "Hello World",只能读到 "Hello"。 2. 不检查边界: 极易导致 溢出。

危险代码:

c 复制代码
char buf[10];
scanf("%s", buf); // 输入 "ThisIsTooLong",程序崩溃或被黑客利用

4.2 fgets:更安全的替代者

语法: fgets(buf, size, stdin);

优点:

1.限制读取大小(最多 size-1 个),绝对安全。

2.可以读取 空格。

缺点: 会把 \n 也读进去(如果空间够的话)。

最佳实践模板:

c 复制代码
char buf[100];
printf("请输入:");

if (fgets(buf, sizeof(buf), stdin)) {
    // 处理末尾的换行符
    size_t len = strlen(buf);
    if (len > 0 && buf[len-1] == '\n') {
        buf[len-1] = '\0'; // 替换为结束符
    }
    printf("你输入了: %s\n", buf);
}

五、 练习题

题目 1: char s[10] = "abc";sizeof(s)strlen(s) 分别是多少?

题目 2: char s[] = "abc"; 这个数组实际占用了几个字节?

题目 3: 为什么不能用 if (str == "hello") 来判断字符串内容?

题目 4: 下面代码输出什么?

c 复制代码
char s[] = "A\0B";
printf("%d", strlen(s));

题目 5: strcpymemcpy 最大的区别是什么?

题目 6: 使用 fgets 读取输入时,如果用户输入的字符数少于缓冲区大小,字符串末尾通常会有什么字符?

题目 7: 字符 '0' 和整数 0 有什么区别?

题目 8: 什么是 缓冲区溢出(Buffer Overflow)?为什么它很危险?

题目 9: 编写一个函数 my_strcpy,实现字符串复制。

题目 10: char *p = "Hello"; p[0] = 'h'; 这行代码会发生什么?

题目 11: 如何将字符串 "123" 转换为整数 123?

题目 12: 下面代码有没有问题?

c 复制代码
char s[5];
strcpy(s, "Hello");

题目 13: 在 C 语言中,字符串常量(如 "Hello")通常存储在哪个内存区域?

题目 14: 为什么说在循环条件中写 i < strlen(s) 是低效的?

题目 15: 给定 char a[] = "Hi"; char b[] = "Hi";,表达式 a == b 的结果是真还是假?

六、 解析

题 1 解析
答案: sizeof 是 10,strlen 是 3。
详解:

sizeof 看的是开辟的 总空间;strlen 看的是 \0 前面有多少个字符。

题 2 解析
答案: 4 字节。
详解:

'a', 'b', 'c', '\0'。编译器自动加结束符。

题 3 解析
答案: 比较的是 地址。
详解:

str 是数组首地址,"hello" 是常量区地址。这两个地址 永远不可能相等。必须用 strcmp

题 4 解析
答案: 1。
详解:

strlen 遇到第一个 \0 就停止计数。后面的 'B' 被忽略了。

题 5 解析
答案: 停止条件不同。
详解:

strcpy 遇到 \0 停止;memcpy 严格按照指定的字节数拷贝,不管内容是什么。

题 6 解析
答案: 换行符 \n
详解:

fgets 会把用户按下的回车键也存入缓冲区(只要空间足够)。

题 7 解析
答案:

'0' 的 ASCII 码是 48;整数 0 的值是 0(也就是 \0)。

题 8 解析
答案:

向缓冲区写入了超过其容量的数据,覆盖了相邻的内存(如返回地址)。黑客可利用此漏洞执行恶意代码。

题 9 解析
答案:

c 复制代码
char *my_strcpy(char *dest, const char *src) {
    char *ret = dest;
    while ((*dest++ = *src++));
    return ret;
}

题 10 解析
答案: 运行时错误 (Segfault)。
详解:

"Hello" 存储在 只读常量区,试图修改会导致硬件保护异常。

题 11 解析
答案: atoi("123")sscanf

题 12 解析
答案: 有问题(越界)。
详解:

"Hello" 需要 6 个字节(含 \0),而 s 只有 5 个。\0 会写到 s 的外面。

题 13 解析
答案: 只读数据段 (Text Segment / .rodata)。

题 14 解析
答案:

strlen 需要遍历字符串。如果放在循环条件里,每次循环都要遍历一次,时间复杂度从 O(N) 变成 O(N^2)。

题 15 解析
答案: 假。
详解:

ab 是两个独立的数组,它们在栈上的地址不同。

日期:2025年2月11日

专栏:C语言

相关推荐
ZHOUPUYU44 分钟前
PHP 8.3网关优化:我用JIT将QPS提升300%的真实踩坑录
开发语言·php
寻寻觅觅☆5 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
YJlio5 小时前
1.7 通过 Sysinternals Live 在线运行工具:不下载也能用的“云端工具箱”
c语言·网络·python·数码相机·ios·django·iphone
l1t5 小时前
在wsl的python 3.14.3容器中使用databend包
开发语言·数据库·python·databend
赶路人儿6 小时前
Jsoniter(java版本)使用介绍
java·开发语言
ceclar1236 小时前
C++使用format
开发语言·c++·算法
码说AI7 小时前
python快速绘制走势图对比曲线
开发语言·python
Gofarlic_OMS7 小时前
科学计算领域MATLAB许可证管理工具对比推荐
运维·开发语言·算法·matlab·自动化
星空下的月光影子7 小时前
易语言开发从入门到精通:补充篇·网络爬虫与自动化采集分析系统深度实战·HTTP/HTTPS请求·HTML/JSON解析·反爬策略·电商价格监控·新闻资讯采集
开发语言
老约家的可汗7 小时前
初识C++
开发语言·c++