字符串压缩是编程中常见的基础问题,核心目标是通过简化重复字符的表示来减少字符串长度。本文将带大家从零开始,用 C 语言实现一个简单的字符串压缩功能,并深入解析其中的逻辑细节。
一、需求分析:我们要做什么?
首先明确压缩规则:
- 对于连续重复的字符,用「字符 + 重复次数」表示(例如
"aaab"压缩为"a3b") - 若重复次数为 1,则不记录次数(例如
"abc"压缩后仍为"abc") - 若压缩后的字符串长度没有缩短,则输出 "NO"(例如
"aabb"压缩后为"a2b2",长度不变,输出 "NO")
二、核心思路:如何实现压缩?
要实现字符串压缩,关键在于统计连续重复字符的次数,步骤可拆解为:
- 遍历原始字符串,定位连续重复字符的起始位置(用
i标记) - 从起始位置向后查找,直到找到第一个不同的字符(用
j标记结束位置) - 计算重复次数:
j - i(结束位置 - 起始位置) - 根据重复次数决定如何存入压缩后的字符串:
- 若次数 > 1:存入「字符 + 次数」
- 若次数 = 1:只存入字符
- 最后比较压缩前后的长度,决定输出结果
三、代码实现:一步步构建功能
1. 准备工作:定义变量与输入
首先需要定义存储原始字符串和压缩后字符串的数组,以及辅助变量:
#include <stdio.h>
#include <string.h> // 用于strlen函数
int main() {
char str[502]; // 存储输入字符串(预留结束符位置)
char target[502]; // 存储压缩后的字符串
int k = 0; // target数组的当前下标(记录已存入字符数)
// 读取输入字符串
scanf("%s", str);
int len = strlen(str); // 计算原始字符串长度
2. 核心逻辑:遍历与压缩
使用循环遍历原始字符串,通过双指针i和j统计连续重复字符:
// 遍历原始字符串,i是当前字符的起始下标
for (int i = 0; i < len;) {
int j = i; // j用于查找连续重复的结束位置
// 找到第一个与str[i]不同的字符位置
while (str[i] == str[j]) {
j++; // 只要字符相同,j就后移
}
// 根据重复次数处理压缩
if (j - i > 1) { // 重复次数>1,需要记录次数
target[k++] = str[i]; // 先存字符
target[k++] = (j - i) + '0'; // 再存次数(转为字符)
} else { // 重复次数=1,只存字符
target[k++] = str[i];
}
i = j; // 跳过已处理的字符,i直接指向j(下一组字符的起始)
}
3. 结果处理:判断是否有效压缩
压缩完成后,需要给target添加字符串结束符,并比较长度:
target[k] = '\0'; // 添加结束符,确保字符串合法
// 比较压缩前后的长度
if (k == len) {
printf("NO"); // 长度不变,输出NO
} else {
printf("%s", target); // 输出压缩后的字符串
}
return 0;
}
四、关键细节解析
-
双指针
i和j的作用:i始终指向当前要处理的连续字符的起始位置j从i出发,向后移动直到找到不同的字符,因此j - i就是重复次数
-
字符与数字的转换:
- 代码中用
(j - i) + '0'将数字转为字符(例如 3 + '0' = '3') - 注意:这种方式仅支持次数≤9 的情况(若次数≥10,需要特殊处理多位数)
- 代码中用
-
数组下标
k的更新:- 每次存入字符后,
k通过k++自动加 1,确保下一次存储不会覆盖当前内容 - 最终
k的值就是压缩后字符串的长度(不含结束符)
- 每次存入字符后,
五、扩展思考
本文实现的压缩功能较为基础,实际应用中可考虑扩展:
- 支持重复次数≥10 的情况(例如
aaaaaaaaaaa→a11) - 处理带空格或特殊字符的字符串
- 实现压缩算法的逆过程(解压缩)
通过这个案例,我们不仅掌握了字符串压缩的基本逻辑,更熟悉了 C 语言中字符数组、指针遍历等核心操作。希望本文能帮助大家更好地理解字符串处理的思路!
5万+

被折叠的 条评论
为什么被折叠?



