【问题标题】:C programming: a program that counts the number of words in a text file?C 编程:一个计算文本文件中字数的程序?
【发布时间】:2013-02-20 19:29:52
【问题描述】:

我正在尝试实现计算文本文件中字数的函数。

到目前为止,这是我的尝试。

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

int main()
{
  FILE *fp;
  char word[1000];
  int count = 0, i;
  int *ptr = NULL;

  printf("Enter filename: ");
  scanf("%s", word);
  fp = fopen(word, "r");

  while(fscanf(fp, "%s", word) != EOF) //dynamically allocate contents of the file into word
    ptr = (int *)malloc(sizeof(int));
  for(i = 0; i < 4000; i++)
  {
    if(word[i] == ' ')
      count++;
  }
  printf("Total: %d", count);
  return 0;
}//main

当我使用 gcc- 编译时,我得到类似 "variable 'ptr' set but not used" 之类的错误,但我以为我在动态分配的内容时使用了它归档到word[80]

我认为我的单词计数器存在严重问题......当显然有 200 多个单词时,它也会返回 0。有人可以请教我吗?

【问题讨论】:

  • while 循环和 malloc 损坏并泄漏内存。不要施放malloc。 word 是 1000 个字符,你的 for 循环循环 4000 次等等
  • 那么你的单词计数器怎么样?完全没有反馈...

标签: c arrays file-io malloc


【解决方案1】:

hmm,但我以为我在将文件内容动态分配到word[80]时使用了它?

不,你一次又一次地设置它:

int *ptr = NULL;   // <-- pointer is set to null

while(fscanf(fp, "%s", word) != EOF) 
  ptr = (int *)malloc(sizeof(int)); // ptr is being set to some memory, again and again
                                    // also this could be a nice memory leak

这就是为什么你有 gcc 告诉你“变量 'ptr' 设置但未使用”,因为你不使用它。

所以问题:

  1. ptr 已设置但未使用
  2. 将 (sizeof int) 字节分配给 (int *)
  3. 内存泄漏,不断重写ptr
  4. fscanf() 返回成功分配的数量,您应该使用它而不是 EOF
  5. word[] 的长度为 1000,但您正在循环到 4000
  6. 通过将 fscanf() 结果放入“word”中,您会不断地覆盖其中的内容
  7. 你不应该返回malloc()
  8. "%s" 真的应该是 "%999s" 以限制输入的长度,但如果是 1000,我认为无论如何你都是安全的。

这就是我想到的全部,尝试修复这些,看看你会得到什么。

【讨论】:

    【解决方案2】:

    很遗憾,您的程序有很多问题。对于初学者来说,'word' 有一个索引溢出(它分配了 1000 字节,但你的索引运行到 4000)。

    为什么每次在 while 循环中读取字符串时都分配一个整数?

    你的程序应该看起来更像这样:

    char buffer[1000];
    int count = 0;
    while(fscanf(fp, "%s", buffer) != EOF) count++;
    

    编辑:对不起,我以为你在读字符,上面现在应该反映了变化。

    【讨论】:

      【解决方案3】:

      这里有很多问题。 fscanf(fp, "%s", word) 每次调用时都会从文件中抓取一个新单词并将其存储在单词缓冲区中。您的 while 循环没有打开/关闭大括号,因此对于您从文件中读取的每个单词,您将分配一个新的 int*。从文件中读取所有内容后,您将遍历文件中最后一个单词的单词缓冲区并计算空格,但您迭代的是 4000 而不是 1000。尝试搜索“C++ 字数”而且我相信您将能够在比我输入此答案所需的时间更短的时间内找到有效的解决方案。

      【讨论】:

        【解决方案4】:

        从您的评论 “将文件的内容动态分配到 word”中判断,您似乎对代码的实际作用有些困惑:

        while(fscanf(fp, "%s", word) != EOF)
            ptr = (int *)malloc(sizeof(int));
        

        实际上反复调用fscanf,直到返回EOF。尽管每个fscanf 调用都会从文件中读取单词并将其存储到临时缓冲区(word)中,但这个循环的主体没有任何意义。它动态分配足够大的内存以容纳 1 个整数,并使ptr 指向该内存(已分配但从未释放的内存,这也会产生内存泄漏)。

        您可以检查fscanf 的返回值是否等于1,因为此函数“返回成功匹配和分配的输入项的数量”。您的 while 循环实际上应该如下所示:

        while(fscanf(fp, "%s", word) == 1)
            count++;
        

        另请注意,您的 char word[1000]; 定义了一个长度为 1000 的数组,但您的 for 循环有 4000 次迭代,并且您试图访问数组边界之外的元素,这会导致 未定义的行为。此外,for 循环的逻辑似乎更倾向于计算存储在word 中的空格 (' ')。这个循环对你一点用处都没有,把它去掉就行了。

        希望这会有所帮助:)

        【讨论】:

          【解决方案5】:
          #include <stdio.h>
          #include <string.h>
          
          int main()
          {
            FILE *fp;
            char word[1000];
            int count = 0, i;
          /*  (why. What are you doing with this?)
            int *ptr = NULL;
          */
          
            printf("Enter filename: ");
            scanf("%s", word);
            fp = fopen(word, "r");
          
            while(fscanf(fp, "%s", word) != EOF) //dynamically allocate contents of the file into     word
          count++;
          /*
              ptr = (int *)malloc(sizeof(int));
            for(i = 0; i < 4000; i++)
            {
              if(word[i] == ' ')
                count++;
            }
          */
          
            printf("Total: %d \n", count);   // added a newline, always nice to end that way
            return 0;
          }//main
          

          【讨论】:

            【解决方案6】:
            #include <stdio.h>
            
            int main()
            {
              FILE *fp;
              int count = 0;
              char word[15], c;
            
              printf("Enter filename: ");
              scanf("%s", word);
              fp = fopen(word, "r");
              if(fp == NULL)
                return -1;
            
              while((c = fgetc(fp)) != EOF) {
                if(c == ' ')
                  count++;
              }
            
              fclose(fp);
              printf("Total: %d", count+1);
            
              return 0;
            }
            

            其实就是这么简单。

            【讨论】:

              【解决方案7】:

              我修改了你的,只是为了告诉你要取出什么。您可以通过对文件运行“wc”并从文件中获取字数来验证它在 Linux 上是否有效。

              【讨论】:

                猜你喜欢
                • 2016-07-13
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-04-22
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多