C语言统计文件最高频字符,现有代码问题排查及优化咨询
问题解答
1. char类型作为数组下标问题的解决方法
C标准没有强制规定char的符号性,部分编译器默认char为signed char,取值范围是-128~127,当字符的ASCII值大于127时,会被解析为负数,直接作为数组下标会出现越界访问,触发未定义行为。
解决方法:访问数组时强制将char转换为unsigned char,保证下标取值范围固定在0~255,刚好匹配长度为256的频率数组。示例写法:freq[(unsigned char)line[i]]++;
2. 现有代码的已知问题
- 文件读取逻辑错误:第一个
fgets循环已经将文件指针移动到文件末尾,第二个fgets循环不会读取到任何内容,导致result变量最终是未初始化的随机值,输出结果错误。 - 资源释放逻辑错误:文件打开失败时
in_file为NULL,此时执行fclose(in_file)属于未定义行为,应该删除该分支下的fclose调用,仅在文件成功打开后执行关闭操作。 - 功能不匹配:函数声明要求实现将最高频字符替换为传入的
c并输出到destination,当前代码仅打印最高频字符,未完成替换和输出逻辑。 - 边界处理缺失:未处理空文件场景,
result未初始化,空文件时会输出垃圾值。
3. 更简便的实现方案
核心优化点:无需二次读取文件,统计完字符频率后直接遍历长度为256的频率数组即可找到最高频字符,比二次读文件效率高很多,代码也更简洁。
修正后的实现代码如下:
#define MAX 200 void replace_most_freq(const char *filename, char c, FILE *destination) { FILE *in_file = fopen(filename, "r"); if (!in_file) { fprintf(destination, "Error(replace_most_freq): Could not open file %s\n", filename); return; } int freq[256] = {0}; char line[MAX]; // 单次读取文件统计频率 while (fgets(line, sizeof(line), in_file)) { int len = strlen(line); for (int i = 0; i < len; i++) { freq[(unsigned char)line[i]]++; } } // 遍历频率数组找最高频字符 int max_cnt = -1; char most_freq = '\0'; for (int i = 0; i < 256; i++) { if (freq[i] > max_cnt) { max_cnt = freq[i]; most_freq = (char)i; } } // 若需要完成替换逻辑,放开下方注释即可 // rewind(in_file); // while (fgets(line, sizeof(line), in_file)) { // int len = strlen(line); // for (int i = 0; i < len; i++) { // if (line[i] == most_freq) { // line[i] = c; // } // } // fputs(line, destination); // } fprintf(destination, "Most frequent char = %c, count = %d\n", most_freq, max_cnt); fclose(in_file); return; }
内容的提问来源于stack exchange,提问作者williamclarke69
相关产品推荐
相关产品推荐

