【问题标题】:Does fgets() hold somehow where it stopped reading from a FILE *?fgets() 是否以某种方式保持它停止从 FILE * 读取的位置?
【发布时间】:2021-06-15 07:26:31
【问题描述】:

我正在尝试获取有关如何写入文件的示例(shell 脚本)程序:

#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv){
  char buff[1024];
  size_t len, idx;
  ssize_t wcnt;
  for (;;){
    if (fgets(buff,sizeof(buff),stdin) == NULL)
      return 0;
    idx = 0;
    len = strlen(buff);
    do {
      wcnt = write(1,buff + idx, len - idx);
      if (wcnt == -1){ /* error */
        perror("write");
        return 1;
      }
      idx += wcnt;
    } while (idx < len);
  }
}

所以我的问题是这样的:假设我想写一个 20000 字节的文件,所以每次我只能写(最多)1024(缓冲区大小)。
假设在我的第一次尝试中一切都很完美, fgets() 读取 1024 字节,而在我第一次尝试时,我写入 1024 字节。
然后,由于我们写入了“len”字节,我们退出了 do-while 循环。
现在怎么办?缓冲区已满,因为我们之前的读取。 在我看来,出于某种原因,暗示 fgets() 现在将从上次在文件中到达的点继续读取。(此处为 buf[1024])。
为什么 fgets() 知道它在文件中停止读取的位置?
我检查了手册页:

fgets() 从流中最多读入一个小于 size 的字符,并将它们存储到 s 指向的缓冲区中。在 EOF 或换行符后停止读取。如果读取了换行符,则将其存储在缓冲区中。终止空字节 (aq\0aq) 存储在缓冲区中的最后一个字符之后。
fgets() 成功时返回 s,错误时返回 NULL,或者在没有读取任何字符的情况下发生文件结尾。*

因此,我知道它返回一个指向 buf 的第一个元素的指针,它始终是 buf[0], 这就是为什么我很困惑。

【问题讨论】:

  • 为什么 fgets() 知道它在文件中停止读取的位置。该信息存储在文件流结构中(在这种情况下为stdin)。但听起来你可能对它与buff 的关系感到困惑——它不像fgets 每次被调用时都会写入buf 的开头,它总是返回buf 或@987654327 @.
  • 是的,您将fgets 交给您的缓冲区与您交给fgets 的FILE 对象中的流混淆了。
  • "FILE * ostream 指向文件的第一个字符。" --> 否。ostream 指向一个结构,其中包含以某种方式组织的各种数据。它的内容不适合用户阅读。
  • 正如其他人指出的那样,您将 C 运行时文件系统缓冲区与您自己的输入缓冲区混淆了。细节由实现定义,但对于终端设备(即标准输入),通常有一个异步进程在操作系统级别收集输入,然后当您的代码调用fgets 时,它会耗尽操作系统缓冲区,直至 EOL,通过 API 调用并将其写入您提供的缓冲区。
  • @brucebanner 是的,你是对的。

标签: c shell file unix


【解决方案1】:

当使用FILE 流时,它包含有关文件中位置的信息(以及其他信息)。 fgetsfreadfwrite 等其他功能仅使用此信息并在执行操作时对其进行更新。 因此,每当fgets 从流中读取数据时,都会更新流以保持位置,以便下一个操作从上一个结束的地方开始。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-19
    • 1970-01-01
    • 2021-05-13
    相关资源
    最近更新 更多