【问题标题】:Average word length for a sentence一个句子的平均词长
【发布时间】:2013-06-12 07:08:10
【问题描述】:

我想计算一个句子的平均字长。

例如,给定输入abc def ghi,平均字长将为3.0

该程序有效,但我想忽略单词之间的多余空格。所以,给定以下句子:

abc  def

(单词之间有两个空格),平均单词长度计算为2.0而不是3.0

如何考虑单词之间的多余空格?这些将被忽略,这将在上面的示例中给出3.0 的平均字长,而不是错误计算的2.0

#include <stdio.h>
#include <conio.h>

int main()
{
char ch,temp;
float avg;
int space = 1,alphbt = 0,k = 0;

printf("Enter a sentence: ");

while((ch = getchar()) != '\n')
{
    temp = ch;

    if( ch != ' ')
    {
       alphbt++;
       k++;         // To ignore spaces before first word!!!
    }  
    else if(ch == ' ' && k != 0)
       space++;

}

if (temp == ' ')    //To ignore spaces after last word!!!
   printf("Average word lenth: %.1f",avg = (float) alphbt/(space-1));
else
   printf("Average word lenth: %.1f",avg = (float) alphbt/space);

getch();
}               

【问题讨论】:

  • 欢迎来到 Stack Overflow!您的问题没有足够的细节,我们无法为您提供帮助。请提供一个 small 示例来说明您正在尝试做什么。还要解释编译和运行示例时的作用以及它与您希望它做的不同之处。
  • 查看strsep(3)
  • @Code-Guru;我已经在我的问题中给出了详细信息和示例。

标签: c


【解决方案1】:

计数逻辑有误。此代码似乎可以正确处理前导和尾随空格以及单词之间的多个空格等。注意int ch; 的使用,以便代码可以准确地检查EOF(getchar() 返回int)。

#include <stdio.h>
#include <stdbool.h>

int main(void)
{
    int ch;
    int numWords = 0;
    int numLetters = 0;
    bool prevWasASpace = true; //spaces at beginning are ignored

    printf("Enter a sentence: ");
    while ((ch = getchar()) != EOF && ch != '\n')
    {
        if (ch == ' ')
            prevWasASpace = true;
        else
        {
            if (prevWasASpace)
                numWords++;
            prevWasASpace = false;
            numLetters++;
        }
    }

    if (numWords > 0)
    {
        double avg = numLetters / (float)(numWords);
        printf("Average word length: %.1f (C = %d, N = %d)\n", avg, numLetters, numWords);
    }
    else
        printf("You didn't enter any words\n");
    return 0;
}

各种示例运行,使用 # 指示 Return 被击中的位置。

Enter a sentence: A human in Algiers#
Average word length: 3.8 (C = 15, N = 4)

Enter a sentence: A human in Algiers  #
Average word length: 3.8 (C = 15, N = 4)

Enter a sentence:   A human  in   Algiers  #
Average word length: 3.8 (C = 15, N = 4)

Enter a sentence: #
You didn't enter any words

Enter a sentence: A human in AlgiersAverage word length: 3.8 (C = 15, N = 4)

Enter a sentence: You didn't enter any words

在最后一个示例中,我输入了两次 Control-D(第一次将“A human in Algiers”刷新到程序中,第二次输入 EOF),一次在最后一个例子。请注意,此代码将制表符计为“非空格”;您需要#include &lt;ctype.h&gt;if (isspace(ch))(或if (isblank(ch)))代替if (ch == ' ') 来更好地处理标签。


getchar() 返回 int

我很困惑你为什么使用int chEOF

这个答案有几个部分。

  1. 使用int ch 的第一个原因是getchar() 函数返回一个int。它可以返回任何有效字符加上一个单独的值 EOF;因此,它的返回值不能是任何类型的char,因为它必须返回比char 更多的值。它实际上返回一个int

  2. 为什么重要?假设来自getchar() 的值被分配给char ch。现在,对于大多数角色来说,大多数时候,它都可以正常工作。但是,会发生两种情况之一。如果普通 char 是有符号类型,则有效字符(通常为 ÿ、y-变音符号、0xFF、正式的 Unicode U+00FF、带分音符号的拉丁小写字母 Y)被误识别为 EOF。或者,如果普通 char 是无符号类型,那么您将永远不会检测到 EOF。

  3. 为什么检测 EOF 很重要?因为您的输入代码可能会在您不期望的情况下获得 EOF。如果你的循环是:

    int ch;
    
    while ((ch = getchar()) != '\n')
        ...
    

    并且输入达到EOF,程序将花费很长时间没有做任何有用的事情。 getchar()函数会反复返回EOF,而EOF不是'\n',所以循环会重试。始终检查输入函数中的错误条件,无论该函数是 getchar()scanf()fread()read() 还是它们的无数亲属。

【讨论】:

  • 我很困惑为什么你使用 int ch 和 EOF!
  • 感谢您的回复先生。我知道 >getchar() 实际上返回 >int 而不是 >char。但我不明白你的观点。 2 & 3. 你介意再用更简单的方式向我解释一下吗(我是初学者)?
  • 对于第 (2) 点,对于初学者来说,最简单的方法可能是记住“getchar() 返回一个int”(因此,它的返回值应该分配给一个int ,永远不要char)。对于 (3),无限循环是不好的,如果在换行符之前到达 EOF,则显示的循环将无限期运行(这可能发生)。
  • 我在没有 EOF 的情况下运行了你的代码,并在 b/w 中按了 ctrl z 这两个词;并且o/p没有区别,后者没有无限循环:(
  • 出现这种情况的主要原因是终端的行为与文件不太一样,您可以在 EOF 之后继续阅读并获得新的输入。如果你调用你的程序 wc2 并且(在 Unix 上)运行 ./wc2 &lt; /dev/null(在 Windows 上可能是 ./wc2.exe &lt; nul:),那么你的代码没有在 EOF 上进行测试就永远不会正常退出或打印除了(可能)提示之外的任何东西——您必须中断程序,或重新启动系统,或其他方式来停止程序。
【解决方案2】:

显然计算非空格字符很容易,您的问题是计算单词。为什么要像您一样将单词视为空格?或者更重要的是,什么定义了一个词?

IMO 单词被定义为从空格字符到非空格字符的转换。所以,如果你能检测到这一点,你就可以知道你有多少单词,你的问题就解决了。

我有一个实现,有很多可能的方法来实现它,我认为你想出一个不会有问题。稍后我可能会将我的实现作为编辑发布。

*编辑:我的实现

#include <stdio.h>

int main()
{
    char ch;
    float avg;
    int words = 0;
    int letters = 0;
    int in_word = 0;

    printf("Enter a sentence: ");

    while((ch = getchar()) != '\n')
    {
        if(ch != ' ') {
            if (!in_word) {
                words++;
                in_word = 1;
            }
            letters++;
        }
        else {
            in_word = 0;
        }
    }

    printf("Average word lenth: %.1f",avg = (float) letters/words);
}

【讨论】:

    【解决方案3】:

    考虑以下输入:(连字符表示空格)

    --Hello---World--
    

    您当前忽略了初始空格和结尾空格,但您计算了每个中间空格,即使它们彼此相邻。只要稍微改变你的程序,特别是'k',我们就可以处理这种情况。

    #include <stdio.h>
    #include <conio.h>
    #include <stdbool.h>
    int main()
    {
      char ch;
      float avg;
      int numWords = 0;
      int numLetters = 0;
      bool prevWasASpace = true; //spaces at beginning are ignored
    
      printf("Enter a sentence: ");
    
      while((ch = getchar()) != '\n')
      {
          if( ch != ' ')
          {
             prevWasASpace = false;
             numLetters++;
          }  
          else if(ch == ' ' && !prevWasASpace)
          {
             numWords++;
             prevWasASpace = true; //EDITED this line until after the if.
          }
      } 
    
      avg = numLetters / (float)(numWords);
    
      printf("Average word lenth: %.1f",avg);
    
      getch();
    }          
    

    你可能需要稍微修改前面的(没有测试过)。

    但是,仅根据单词之间的空格来计算句子中的单词可能不是您想要的全部。考虑以下句子:

    约翰说:“拿起电话……现在!”

    电视播音员刚刚提供了买一送一的优惠,同时说他们 24/7 营业。

    每月花费不会超过 100.99 美元(3.25 欧元)。

    我立即用他/她的电话拨打 (555) 555-5555。

    A(n) = A(n-1) + A(n-2) - 换句话说,序列:0,1,1,2,3,5, . . .

    您需要确定单词的构成,这不是一个简单的问题(顺便说一句,你们所有人,没有一个例子包括所有种类的英语)。计算空格在英语中是一个相当不错的估计,但它不会让你一路走好。

    查看Text Segmentation 上的维基百科页面。这篇文章用了四次“不平凡”这个词。

    【讨论】:

    • 你不需要反转测试并在prevWasASpace = true; if (!prevWasASpace) { numWords++; }中设置,这样它就读作:if (!prevWasASpace) numWords++; prevWasASpace = true;事实上,你永远不会增加numWords,因为你刚刚设置了@987654327 @ 总是正确的。 `
    • @Xantix;谢谢老兄,特别是维基链接。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-02
    相关资源
    最近更新 更多