C语言实现单词字母排列组合数计算及程序报错排查
解决重复字母排列数计算的段错误与逻辑问题
原代码的核心问题
- 变量未初始化:
nf、rf、r这些计算阶乘的变量直接参与乘法操作却未初始化,会触发未定义行为,甚至引发段错误。 - 无限循环:统计字母次数的内层循环写错了条件——
for (j=i;i<len;j++)里的循环条件是i<len,但i在循环中不会改变,导致无限循环,直接造成段错误。 - 重复计数:对重复字母会多次统计次数(比如"hello"里的两个'l',会被i=2和i=3分别统计),导致分母的阶乘乘积计算重复,结果错误。
- 无效遍历:计算分母时遍历了整个
cnt数组(100个元素),但只有前len个元素是有效数据,后面的都是未初始化的垃圾值,会导致计算出错。 - 未用递归阶乘:题目明确要求用递归实现阶乘,但原代码用循环计算,不符合要求。
- 溢出风险:
int类型最大值有限,长字符串的阶乘会溢出,需要更大的数据类型。
修正后的代码
#include <stdio.h> #include <string.h> // 递归实现阶乘计算 long long factorial(int n) { if (n == 0 || n == 1) { return 1; } return n * factorial(n - 1); } long long calculatePermutations(char arr[], int len) { // 统计每个字母的出现次数,避免重复统计 int count[256] = {0}; // 覆盖所有ASCII字符 for (int i = 0; i < len; i++) { count[(unsigned char)arr[i]]++; } // 计算分子:len的阶乘 long long numerator = factorial(len); // 计算分母:所有重复字母阶乘的乘积 long long denominator = 1; for (int i = 0; i < 256; i++) { if (count[i] > 1) { denominator *= factorial(count[i]); } } return numerator / denominator; } int main() { char arr[100]; scanf("%s", arr); int len = strlen(arr); printf("%lld\n", calculatePermutations(arr, len)); return 0; }
代码说明
- 递归阶乘:
factorial函数通过递归实现,符合题目要求,当n为0或1时返回1作为终止条件。 - 正确统计次数:用256长度的数组对应ASCII码,每个字母只统计一次,避免重复计数。
- 变量初始化:所有计算变量都初始化为合理值,消除未定义行为。
- 数据类型优化:用
long long存储阶乘结果,避免长字符串的阶乘溢出。 - 高效遍历:只统计字符串内的字母,计算分母时只处理出现次数大于1的字母,提升效率。
测试验证:
- 输入
Whats,输出120 - 输入
hello,输出60 - 输入
little,输出180 - 输入
document,输出40320
内容的提问来源于stack exchange,提问作者Harshavardhan K K
相关产品推荐
相关产品推荐

