C90环境下RLE压缩逻辑修正及解压缩实现技术问询
解决你的C90 RLE压缩问题及解压缩实现思路
首先,咱们先搞清楚为什么你的压缩结果不对——你现在的代码是统计每个字符在整个文件里的总出现次数,而不是统计连续重复的字符段。这就是为什么输入AAAAAA333333FFFFF22222时,你得到的是2536A6F5,而正确结果应该是6A635F52。接下来咱们先修正压缩代码里的问题,再聊聊解压缩的实现思路。
1. 压缩代码的错误修正
核心逻辑问题
你的count[256]数组统计的是每个字符的全局出现次数,但RLE算法要求的是连续重复的字符计数。比如你的输入包含4个连续段:6个A、6个3、5个F、5个2,而不是把所有A的数量、所有3的数量按ASCII顺序输出。
循环与if条件的修正
你当前的while循环有个致命bug:
while((n=fgetc(fp))) { if(n == EOF) { break; } else count[n]+=1; }
- 循环条件
while((n=fgetc(fp)))会在读取到ASCII值为0的字符时提前退出(因为0在C里被视为false)。 - 你在进入循环后才判断是否为EOF,这种写法既低效又容易出错。
下面是重写后的压缩逻辑,专门跟踪连续重复的字符段:
#include <stdio.h> #include <stdlib.h> int main(void) { FILE *fp = fopen("test.txt", "r"); FILE *fptr = fopen("compressed_test.txt", "w"); if (fp == NULL) { printf("错误:输入文件不存在\n"); printf("没有可压缩的内容\n"); exit(EXIT_FAILURE); } int current_char = fgetc(fp); if (current_char == EOF) { // 空文件,直接退出 fclose(fp); fclose(fptr); return 0; } int run_count = 1; int next_char; while ((next_char = fgetc(fp)) != EOF) { if (next_char == current_char) { // 字符相同,增加连续计数 run_count++; } else { // 字符不同:写入当前连续段的结果 fprintf(fptr, "%d%c", run_count, current_char); // 重置为下一个连续段的初始状态 current_char = next_char; run_count = 1; } } // 循环结束后,别忘了写入最后一个连续段 fprintf(fptr, "%d%c", run_count, current_char); printf("压缩完成\n"); fclose(fp); fclose(fptr); return 0; }
重点修正点:
- 用
current_char和run_count跟踪当前连续重复的字符及其次数,替代全局计数的数组。 - while循环直接用
next_char != EOF作为条件,确保只处理有效字符。 - 循环结束后处理最后一个连续段(因为循环在遇到EOF时终止,最后一段还没写入文件)。
2. RLE解压缩(解码)的实现思路
解压缩的逻辑是反过来的:读取压缩文件中的“数字+字符”对,然后将字符重复对应数字的次数输出即可。具体步骤如下:
- 打开压缩文件和输出文件。
- 循环读取文件内容:
- 先读取数字部分(如果你的压缩只处理单数字计数(比如最多9个连续字符),直接读一个数字字符转成整数即可;如果要支持多位数,
fscanf的%d格式会自动读取连续的数字字符)。 - 读取对应的字符。
- 将该字符重复数字次数写入输出文件。
- 先读取数字部分(如果你的压缩只处理单数字计数(比如最多9个连续字符),直接读一个数字字符转成整数即可;如果要支持多位数,
- 处理完所有内容后关闭文件。
举个简单的解压缩示例代码框架:
#include <stdio.h> #include <stdlib.h> int main(void) { FILE *compressed_fp = fopen("compressed_test.txt", "r"); FILE *decompressed_fp = fopen("decompressed_test.txt", "w"); if (compressed_fp == NULL) { printf("错误:压缩文件不存在\n"); exit(EXIT_FAILURE); } int count; char c; while (fscanf(compressed_fp, "%d%c", &count, &c) == 2) { // 重复count次写入字符c for (int i = 0; i < count; i++) { fputc(c, decompressed_fp); } } printf("解压缩完成\n"); fclose(compressed_fp); fclose(decompressed_fp); return 0; }
注意:如果遇到压缩文件损坏等格式异常情况,还可以添加额外的错误判断逻辑,比如检查读取的数字是否为正整数等。
内容的提问来源于stack exchange,提问作者Albert
相关产品推荐
相关产品推荐

