【问题标题】:How may I count the number of words in a paragraph? I keep miscounting我如何计算段落中的单词数?我一直数错
【发布时间】:2020-10-26 10:17:21
【问题描述】:

我正在尝试编写一个程序来计算文本中的字母、单词和句子的数量。我可以假设一个字母是从 a 到 z 的任何小写字符或从 A 到 Z 的任何大写字符,任何由空格分隔的字符序列都应该算作一个单词,并且任何出现的句点、感叹号或问号表示句尾。

到目前为止,我可以正确计算字母和句子的数量,但我错过了单词的数量:

例如 是的!

输出应该是: 3 个字母 1 个字 1 句

我得到的是: 3 个字母 0 字 1 句

更新:在 printf 函数之前最后输入另一个(words++)后,它现在可以正常工作了。谢谢你们的帮助:)。

#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

int main(void)
{
    string text = get_string("Enter text: ");
    printf("Output:\n");
    int lettercount;
    int words = 0;
    int sentences = 0;
    int letters = 0;
    int length = strlen(text);
    for(lettercount = 0; lettercount < length; lettercount++)
    {
        if(isalpha(text[lettercount]))
        {
            letters++;
        }
        else if(text[lettercount] == ' ' || text[lettercount] == '\t' || text[lettercount] == '\n' || text[lettercount] == '\0')
        {
            words++;
        }
        else if(text[lettercount] == '.' || text[lettercount] == '!' || text[lettercount] == '?')
        {
            sentences++;
        }
    }
    words++;
    printf("%i letter(s)\n", letters);
    printf("%i word(s)\n", words);
    printf("%i sentence(s)\n", sentences);
}

【问题讨论】:

  • 你用更短的句子测试和调试过吗?将测试数据减少到尽可能简单并且仍然重现问题(例如两个词)。然后使用调试器和/或调试打印语句来跟踪程序执行。
  • 提示:text[lettercount] == '\0' 总是错误的。另外提示:strlen 的字符串长度为 O(n),不要在每次循环中调用它。
  • 我认为您的问题可以通过一个单词的句子来重现,例如:Yes!

标签: c cs50


【解决方案1】:

您的代码的主要问题是,如果输入文本中没有空格,它不会计算输入文本中的任何“最终”单词(终止 '\0' 字符将 不是测试字符串的一部分,因为strlen 函数不包含该部分。

此外,如果您的单词被多个空格分隔,您将遇到问题;为了解决这个问题,您可以使用inWord 标志来跟踪当前字符是否已经在单词中,如果没有,则在我们找到字母时设置该标志。

此外,如果您的输入中有"..." 之类的内容,您的句子计数将会有问题; sentences++; 行之后的注释行将解决该问题(如果您愿意的话)。

最后,准确地说,你不应该假设字母“a”到“z”和“A”到“Z”将是连续的序列。它们可能会是(现在大多数系统都使用 ASCII 编码),但您应该使用 isalpha 函数以获得更高的可移植性(以及 isspace 函数)。

int main(void)
{
    string text = get_string("Enter text: ");
    printf("Output:\n");
    int lettercount;
    int words = 0;
    int sentences = 0;
    int letters = 0;
    int inWord = 0;// Set to 1 if we are inside a (new) word!
    int length = (int)(strlen(text)); // Don't evaluate length on each loop!
    for (lettercount = 0; lettercount < length; lettercount++) {
        int testChar = text[lettercount]; // Get a local copy of the current character
        if (isalpha(testChar)) { // Don't assume that 'a' ... 'z' and 'A' ... 'Z' are in contiguous sequences
            letters++;
            if (!inWord) words++; // Any letter means that we're in a (possibly new) word...
            inWord = 1;           // ... but now set this 'flag' so as not to count others!
        }
        else if (testChar == '.' || testChar == '!' || testChar == '?') {
            sentences++;
        //  if (inWord) sentences++; // Check that we're in a word, or stuff like "..." will be wrong
            inWord = 0; // Now we are no longer inside our current word
        }
        else if (isspace(testChar)) { // We could also just assume ANY other character is a non-word
            inWord = 0; // Now we are no longer inside our current word
        }
    }
    printf("%i letter(s)\n", letters);
    printf("%i word(s)\n", words);
    printf("%i sentence(s)\n", sentences);
    return 0;
}

请随时要求任何进一步的澄清和/或解释。

【讨论】:

  • 此外,您的方法可以轻松扩展以处理更多选项。例如,如何处理数字?以及如何处理连字符:“自我谦虚”算一两个词吗?
  • 阿德里安,非常感谢您的帮助!哈哈,我是编码的超级新手。我将 CS50 Introduction to Computer Science 作为我的第一门课程。我现在是第二周,所以我很难一次掌握所有这些概念。我想知道您是否可以解释 inWord 和 (!inWord) 更多?感叹号代表什么?再次感谢您。
  • @Bryce inWord 变量跟踪我们当前的位置是否已经在一个单词中;如果它为零(这是 !inWord 测试的内容 - 如果我使用 if (inWord == 0) 可能会更清楚),我们找到了一个新单词的开头,所以我们将该标志设置为 1(所以我们不要继续增加我们的字数,直到我们找到一个非字母,当我们将它设置回零时)。希望这会有所帮助。
【解决方案2】:

你总是有单词-1,因为你只在空格或换行之后向你的计数器添加新单词但是最后一个单词呢!?总是最后一个单词不会被计算在内,所以在计算任何段落后将 1 添加到你的单词计数器.. 例如:是的! --> 3个字母1个句子0个单词!所以你加一个就解决了 另一个例子:你好世界! --> 10 个字母 1 个句子 1 个单词!加一个就解决了

【讨论】:

  • 谢谢你,奥马尔!我只是在最后 printf 之前写了另一个词++,它修复了它:)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-16
  • 1970-01-01
  • 1970-01-01
  • 2021-08-22
  • 2014-04-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多