C语言Huffman编码项目统计文件字符频率函数输出异常排查
问题排查与修复方案
现有代码核心错误
- 局部频率数组未初始化:
unsigned long freq[256];定义后未清零,初始值为栈内存随机垃圾值,直接导致统计结果、最值计算、总字符数全部异常。 - 字符下标计算错误:统计频率时错误使用
c-'0'作为数组下标,'0'的ASCII值为48,会导致所有字符的统计下标偏移48,比如字符a(ASCII 97)会被统计到下标49的位置,完全不符合字符频率统计逻辑。如果字符值小于'0',c-'0'会得到负数,造成数组越界写内存,进一步破坏程序数据。 getc返回值存储类型错误:getc的返回值是int类型,用char类型存储会导致读取到值为0xFF的字符时,和EOF(值为-1)混淆,提前终止读取循环。- 返回栈内存指针:函数将栈上分配的
freq数组地址作为返回值,函数执行结束后栈内存会被系统回收,返回的指针属于野指针,后续访问该指针会触发未定义行为。
修复后代码
#include <stdlib.h> #include <string.h> #include <stdio.h> // 假设三个全局变量已在外部定义 extern int minFreqIndex; extern int maxFreqIndex; extern unsigned long totalChars; unsigned long* printFreqTable(FILE* in, FILE* out) { int i, j, k; unsigned long tCount = 0; unsigned long max = 0; int maxIndex = 0; unsigned long min; int minIndex = 0; // 改用堆内存分配,避免返回野指针 unsigned long* freq = (unsigned long*)malloc(sizeof(unsigned long) * 256); // 初始化数组所有值为0 memset(freq, 0, sizeof(unsigned long) * 256); // 用int存储getc返回值,避免和EOF混淆 int c; printf("Entered printFreqTable()\n"); while((c = getc(in)) != EOF) { // 转为unsigned char保证下标范围在0~255,直接用字符值作为下标 unsigned char uc = (unsigned char)c; freq[uc]++; if(freq[uc] > max) { max = freq[uc]; maxIndex = uc; } } min = max; for(i = 0; i < 33; i++) { tCount += freq[i]; if(freq[i] != 0) {fprintf(out, "\n=%d\t\t%2lu", i, freq[i]);} if(freq[i] < min && freq[i] > 0) { min = freq[i]; minIndex = i; } } for(j = 33; j < 127; j++) { tCount += freq[j]; if(freq[j] != 0) {fprintf(out, "\n%c\t\t%2lu", j, freq[j]);} if(freq[j] < min && freq[j] > 0) { min = freq[j]; minIndex = j; } } for(k = 127; k < 256; k++) { tCount += freq[k]; if(freq[k] != 0) {fprintf(out, "\n=%d\t\t%2lu", k, freq[k]);} if(freq[k] < min && freq[k] > 0) { min = freq[k]; minIndex = k; } } minFreqIndex = minIndex; maxFreqIndex = maxIndex; totalChars = tCount; fprintf(out, "\n\nTotal number of characters in file %lu", tCount); printf("Finished printFreqTable()\n"); return freq; }
注意:调用方使用完返回的频率数组后,需要调用
free()手动释放该堆内存,避免出现内存泄漏问题。
内容的提问来源于stack exchange,提问作者A. Mitchev
相关产品推荐
相关产品推荐

