【问题标题】:How to use EOF to run through a text file in C?如何使用 EOF 在 C 中运行文本文件?
【发布时间】:2010-12-22 14:25:36
【问题描述】:

我有一个文本文件,每行都有字符串。我想为文本文件中的每一行增加一个数字,但是当它到达文件末尾时,它显然需要停止。我曾尝试对 EOF 进行一些研究,但无法真正理解如何正确使用它。

我假设我需要一个 while 循环,但我不知道该怎么做。

【问题讨论】:

    标签: c file eof


    【解决方案1】:

    我建议你使用 fseek-ftell 函数。

    FILE *stream = fopen("example.txt", "r");
    
    if(!stream) {
        puts("I/O error.\n");
        return;
    }
    
    fseek(stream, 0, SEEK_END);
    long size = ftell(stream);
    fseek(stream, 0, SEEK_SET);
    
    while(1) {
    
        if(ftell(stream) == size) {
            break;
        }
    
        /* INSERT ROUTINE */
    
    }
    
    fclose(stream);
    

    【讨论】:

      【解决方案2】:

      你应该在读取文件后检查 EOF。

      fscanf_s                   // read from file
      while(condition)           // check EOF
      {
         fscanf_s               // read from file
      }
      

      【讨论】:

        【解决方案3】:

        如何检测 EOF 取决于您使用什么来读取流:

        function                  result on EOF or error                    
        --------                  ----------------------
        fgets()                   NULL
        fscanf()                  number of succesful conversions
                                    less than expected
        fgetc()                   EOF
        fread()                   number of elements read
                                    less than expected
        

        检查输入调用的结果是否符合上述条件,然后调用feof() 以确定结果是由于遇到 EOF 还是其他错误。

        使用fgets()

         char buffer[BUFFER_SIZE];
         while (fgets(buffer, sizeof buffer, stream) != NULL)
         {
           // process buffer
         }
         if (feof(stream))
         {
           // hit end of file
         }
         else
         {
           // some other error interrupted the read
         }
        

        使用fscanf()

        char buffer[BUFFER_SIZE];
        while (fscanf(stream, "%s", buffer) == 1) // expect 1 successful conversion
        {
          // process buffer
        }
        if (feof(stream)) 
        {
          // hit end of file
        }
        else
        {
          // some other error interrupted the read
        }
        

        使用fgetc()

        int c;
        while ((c = fgetc(stream)) != EOF)
        {
          // process c
        }
        if (feof(stream))
        {
          // hit end of file
        }
        else
        {
          // some other error interrupted the read
        }
        

        使用fread()

        char buffer[BUFFER_SIZE];
        while (fread(buffer, sizeof buffer, 1, stream) == 1) // expecting 1 
                                                             // element of size
                                                             // BUFFER_SIZE
        {
           // process buffer
        }
        if (feof(stream))
        {
          // hit end of file
        }
        else
        {
          // some other error interrupted read
        }
        

        注意形式都是一样的:检查读操作的结果;如果失败,然后检查 EOF。你会看到很多这样的例子:

        while(!feof(stream))
        {
          fscanf(stream, "%s", buffer);
          ...
        }
        

        这个表单并不像人们想象的那样工作,因为feof() 直到您尝试读取文件末尾之后才会返回 true。结果,循环执行了太多次,这可能会也可能不会让您感到悲伤。

        【讨论】:

        • 很好,但对这个流行的答案有一些建议:1)“函数:fscanf()result on EOF 或错误:成功转换的次数少于预期”将输入“错误”等同于格式转换失败. 不是一个正确的分组 IMO。建议另一列 OTOH 这是一个复杂的功能 2) 拼写检查 3) 建议对 while(!feof(stream)) 示例进行“错误代码”评论。
        【解决方案4】:

        一个可能的 C 循环是:

        #include <stdio.h>
        int main()
        {
            int c;
            while ((c = getchar()) != EOF)
            {
                /*
                ** Do something with c, such as check against '\n'
                ** and increment a line counter.
                */
            }
        }
        

        现在,我会忽略 feof 和类似的功能。经验表明,在错误的时间调用它并在认为尚未达到 eof 的情况下处理两次太容易了。

        要避免的陷阱:将char 用于c 的类型。 getchar 将下一个字符转换为unsigned char,然后返回到int。这意味着在大多数 [sane] 平台上,EOF 的值和 c 中的有效“char”值不会重叠,因此您永远不会意外检测到 EOF 的“正常”char .

        【讨论】:

        • 看我的回答我定义了一个eof
        • @streetparade:有什么效果?
        • 来自getchar 的有效字符值在任何符合标准的平台上永远不会EOF 重叠,因为getchar 返回的字符在unsigned int 的范围内(因此是非负数),并且EOF 必须是负数。
        • @caf:这就是我的想法,直到有人向我指出有些平台具有 32 字符和 32 整数。这意味着 char -> unsigned char -> int 最终可能是负数。因此'[理智]'。
        • 哦,是的,还有关于忽略feof 的好建议——根据我的经验,使用该功能几乎总是表明存在错误。在 99% 的情况下,测试最近一次输入函数调用的返回值就足够且正确。
        猜你喜欢
        • 2016-12-22
        • 1970-01-01
        • 2017-02-04
        • 2020-07-19
        • 2017-11-18
        • 1970-01-01
        • 2018-12-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多