1
#include <stdio.h>
#include <string.h>

int main(void)
{
    char string[100];
    int c = 0, count[26] = {0};
    int accum = 0;
    int a;

    while(1)
    {
       a = scanf("%s", string);
       while ( string[c] != '\0' )
       {

           if ( string[c] >= 'a' && string[c] <= 'z' ){
            count[string[c]-'a']++;
            accum++;
           }

           else if (string[c] >= 'A' && string[c] <= 'Z'){
            count[string[c]-'A']++;
            accum++;
           }
            c++;
       }
       if (a == EOF)
       {
           for ( c = 0 ; c < 26 ; c++ )
           {
            if( count[c] != 0 )
                printf( "%c %f\n", c+'a', ((double)count[c])/accum);
           }
       }
    }
   return 0;
}

所以我有一个程序可以计算在 EOF 之前出现在标准输入中的字母的频率。但是一旦我到达 EOF,我的程序就会进入一个无限循环,并且频率似乎不正确。当我只是将打印语句输入单个字符串时,它工作正常。我真的不知道问题是什么。有人能帮我解决这个问题吗?

4

3 回答 3

2

if (a == EOF)应该在之后a = scanf("%s", string);

那么这个if()条件应该存在循环。

c = 0应该在循环中每次重置

while(1) {
   a = scanf("%s", string);
   if (a == EOF) {
     ...
     break;
   }
   c = 0;
   while ( string[c] != '\0' ) {

通过上述更改,确信您的代码将运行良好。在较小程度上还有其他事情需要考虑。1)scanf("%s",...是无界的。2) 应限制输入。 if (a == EOF)还不如在循环之后编码。3) 建议循环条件是肯定的scanf()==1。循环在好的方面,而不是在坏的情况下退出。4)考虑unsignedint计数。5)for()循环而不是while()增量循环。6) 避免像 26 这样的幻数。

顺便说一句:您的代码很好地使用了浮点、文A​​字和数组{0}初始化的强制转换。

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

int main(void) {
  char string[100];
  unsigned count['z' - 'a' + 1] = { 0 };
  unsigned accum = 0;

  while (scanf("%99s", string) == 1) {
    for (int c = 0; string[c]; c++) {
      if (string[c] >= 'a' && string[c] <= 'z') {
        count[string[c] - 'a']++;
        accum++;
      } else if (string[c] >= 'A' && string[c] <= 'Z') {
        count[string[c] - 'A']++;
        accum++;
      }
    }
  }
  for (int c = 'a'; c <= 'z'; c++) {
    if (count[c - 'a'] != 0)
      printf("%c %f\n", c, ((double) count[c - 'a']) / accum);
  }
  return 0;
}
于 2014-11-01T23:10:51.060 回答
0

无限循环是由这一行引起的:

while(1)

如果您不需要它,请将其删除,或在break某处添加语句。

于 2014-11-01T23:10:23.160 回答
0

再用一些词来帮助描述您的问题和解决方案(如 chux 所建议的那样)。

您遇到的第一个问题是您没有退出while(1)循环的逻辑。

IE 你有一个无限循环,因为那是你编码的。

即使您检测到 EOF,您也不会对此做任何事情:您的代码中没有任何内容显示“现在我们有了 EOF,我们需要退出此while(1)循环”。

这就是 chux 在他的回答中所暗示的:这就是break声明的目的:它说“现在跳出循环”。

在检查是否有 EOF 之前,您还有一个额外的问题是解析字符串。如果aEOF,那么你不能解析字符串,因为你没有得到一个。

所以你需要重新排列你的代码,以便你的EOF检查在你的字符串解析之前,当你在检测之后完成打印字符串时EOF,你需要break.

于 2014-11-02T00:15:41.373 回答