C语言字符频率排序程序求助:平局时无法按ASCII值升序排列
字符按频率排序:修复次数相同时的ASCII升序问题
问题描述
需要实现一个程序,按以下规则输出文本中的字符:
- 忽略空格
- 字符按出现次数升序排列
- 若出现次数相同,按ASCII值较小的字符优先输出
示例输入hello world,正确输出应为dehrwol,但当前程序输出hewrdol,原因是次数相同时未按ASCII升序排序。
问题根源
原代码的cmpLetters比较函数仅判断了字符出现次数的差异,没有处理次数相同的场景。当次数相等时,qsort的排序结果是不确定的(依赖底层实现),导致不符合ASCII升序的要求。
解决方案
修改cmpLetters函数,在次数相同时比较字符的ASCII值,确保ASCII小的字符排在前面:
int cmpLetters(const void* a, const void* b) { char charA = *(char*)a; char charB = *(char*)b; // 先比较出现次数,次数少的在前 if (times[charA] != times[charB]) { return times[charA] - times[charB]; } // 次数相同时,ASCII值小的在前 return charA - charB; }
额外优化点
原代码在统计字符时没有忽略空格,而是在输出时跳过,逻辑不够严谨。建议在统计阶段直接排除空格和换行符(因为fgets会读取输入末尾的换行):
for (i = lnum = 0; s[i] != '\0'; i++) { // 忽略空格和换行符 if (s[i] == ' ' || s[i] == '\n') { continue; } if (times[s[i]]++ == 0) { letters[lnum++] = s[i]; } }
修改后的完整代码
#include<stdio.h> #include<stdlib.h> #include<string.h> int times[256]; int cmpLetters(const void* a, const void* b) { char charA = *(char*)a; char charB = *(char*)b; if (times[charA] != times[charB]) { // 次数升序:次数少的返回负数,排在前面 return times[charA] - times[charB]; } // ASCII升序:值小的返回负数,排在前面 return charA - charB; } int main() { char letters[256]; int i, j, k, lnum; char s[1000]; fgets(s, sizeof(s), stdin); memset(times, 0, sizeof(times)); // 统计字符,忽略空格和换行 for (i = lnum = 0; s[i] != '\0'; i++) { if (s[i] == ' ' || s[i] == '\n') { continue; } if (times[s[i]]++ == 0) { letters[lnum++] = s[i]; } } // 按规则排序 qsort(letters, lnum, sizeof(char), cmpLetters); // 输出结果 for (i = 0; i < lnum; i++) { printf("%c", letters[i]); } printf("\n"); return 0; }
测试验证
输入hello world,程序输出dehrwol,符合预期。
内容的提问来源于stack exchange,提问作者edmung vunxh
相关产品推荐
相关产品推荐

