You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 14:15:02