C语言实现输入字符串单词出现次数统计的问题求解
问题根因与修复方案
1. 长字符串输入截断问题原因&修复
- 问题根因:
- 存储输入的
word数组仅分配了1000字节容量,输入长度超过1000字符就会溢出截断 scanf("%[^EOF]", word)写法错误:%[^EOF]的匹配规则是遇到字符'E'/'O'/'F'任意一个就停止读取,不是读到输入EOF- 执行
scanf读取输入前,提前调用了strtok(word, " "),此时word是未初始化的野值,会破坏后续读取逻辑
- 存储输入的
- 修复方案:
- 可根据需要调大
MAX_WORDS的数值,同时给scanf增加长度限制,或者直接用更安全的fgets读取输入 - 删除提前调用的无效
strtok语句
- 可根据需要调大
2. 重复单词计数失败问题原因&修复
- 问题根因:
- 去重统计的内层循环遍历上限写为
index,但uniqueWords数组中只有前uniqueLen个元素是有效存储的唯一单词,剩余都是未初始化的垃圾值,strcmp比对结果不可预测 - 匹配到重复单词的分支中没有执行对应计数累加的逻辑,只有新增唯一单词时才会给count赋值1
- 去重统计的内层循环遍历上限写为
- 修复方案:
- 内层循环仅遍历
0 ~ uniqueLen-1的有效范围 - 匹配到重复单词时,直接给对应下标的
count[j]加1
- 内层循环仅遍历
修正后完整代码
#include <stdlib.h> #include <string.h> #include <stdio.h> #include <ctype.h> #define MAX_WORDS 4096 // 调大输入缓存容量,可按需调整 int main(void) { int i,j,isUnique,uniqueLen; char word[MAX_WORDS]; char words[200][30]; char uniqueWords[200][30]; int count[200]; char *p; int index=0; // 读取输入直到EOF,限制读取长度避免溢出 if (fgets(word, MAX_WORDS, stdin) == NULL) { return 0; } // 初始化计数数组 for (i = 0; i < 200; i++) { count[i] = 0; } // 统一转大写,用标准库函数兼容性更好 for (i = 0; word[i] != '\0'; i++) { word[i] = toupper(word[i]); } // 分词存入words数组,增加边界判断避免数组越界 p = strtok(word, " ,.;!\n"); while (p != NULL && index < 200) { strncpy(words[index], p, 29); words[index][29] = '\0'; // 强制补字符串结束符,避免溢出 p = strtok(NULL, " ,.;!\n"); index++; } // 去重统计逻辑修正 uniqueLen = 0; for (i = 0; i < index; i++) { isUnique = 1; // 仅遍历已存储的有效唯一单词 for (j = 0; j < uniqueLen; j++) { if (strcmp(uniqueWords[j], words[i]) == 0) { isUnique = 0; count[j]++; // 匹配到重复,对应计数+1 break; } } if (isUnique && uniqueLen < 200) { strncpy(uniqueWords[uniqueLen], words[i], 29); uniqueWords[uniqueLen][29] = '\0'; count[uniqueLen] = 1; // 新单词初始计数为1 uniqueLen++; } } // 输出结果 for (i = 0; i < uniqueLen; i++) { printf("%s => %i\n", uniqueWords[i], count[i]); } return 0; }
内容的提问来源于stack exchange,提问作者Roodolpha
相关产品推荐
相关产品推荐

