为何统计单词数的整型变量会与统计字母数的整型变量相加?
问题分析
你的代码存在三个关键错误,直接导致了单词统计数值异常:
- 全局数组越界访问:
storeLetters和storeWords是大小为0的数组,循环中访问storeLetters[i]、storeWords[x]属于越界操作,会破坏内存中的其他数据(比如字母统计的数值被意外加到单词统计里),这是你看到“单词数=字母数+正确单词数”的根本原因。而且这两个数组完全多余,统计不需要存储每个位置的计数。 - 字母统计逻辑冗余:不需要借助数组,直接判断字符是否为字母并累加即可,当前写法纯粹是画蛇添足,还引入了内存风险。
- 单词统计逻辑错误:当前统计的是分隔符(空格、标点)的数量,而非单词数;再加上越界访问导致的内存数据混乱,最终放大了错误。
修正后的代码
#include <cs50.h> #include <string.h> #include <stdio.h> #include <ctype.h> // 声明函数 int count_letters(string text); int count_words(string text); int main(void) { // 获取用户输入文本 string text = get_string("Text: "); int numOfLetters = count_letters(text); printf("%d letters\n", numOfLetters); int numOfWords = count_words(text); printf("%d words\n", numOfWords); } int count_letters(string text) { int amountOfLetters = 0; int n = strlen(text); for (int i = 0; i < n; i++) { // 直接判断是否为字母,是则计数+1 if (isalpha(text[i])) { amountOfLetters++; } } return amountOfLetters; } int count_words(string text) { int amountOfWords = 0; int n = strlen(text); // 处理空字符串的情况 if (n == 0) { return 0; } // 初始:如果第一个字符不是分隔符,说明至少有一个单词 if (!isspace(text[0]) && text[0] != '?' && text[0] != '!' && text[0] != '.') { amountOfWords = 1; } // 遍历字符串,统计单词数:遇到分隔符后接非分隔符,说明新单词开始 for (int x = 1; x < n; x++) { bool currentIsSeparator = isspace(text[x]) || text[x] == '?' || text[x] == '!' || text[x] == '.'; bool prevIsNotSeparator = !isspace(text[x-1]) && text[x-1] != '?' && text[x-1] != '!' && text[x-1] != '.'; if (currentIsSeparator && prevIsNotSeparator) { amountOfWords++; } } return amountOfWords; }
关键修正点说明
- 移除多余全局数组:用局部变量直接累加计数,彻底避免内存越界和数据干扰问题。
- 简化字母统计:遍历每个字符,判断是字母就直接加1,逻辑清晰高效。
- 修正单词统计逻辑:
- 先处理空字符串的边界情况;
- 初始判断第一个字符是否为有效字符,确定初始单词数;
- 遍历过程中通过“分隔符+非分隔符”的组合判断新单词的开始,避免连续分隔符导致的重复计数,确保统计准确。
内容的提问来源于stack exchange,提问作者Joshua-Michael
相关产品推荐
相关产品推荐

