【问题标题】:How to get whole line using fgets如何使用 fgets 获取整行
【发布时间】:2015-01-28 16:31:38
【问题描述】:

我需要从不同的流(不仅仅是标准输入)中读取数据。我发现了 fgets 函数,可以读取一些有限数量的字符,但是我需要像 get 一样获取整个字符串,但我必须指定输入流。请帮忙解决这个问题。

【问题讨论】:

  • 如果你确定你的行有一个最大尺寸,那么使用fgets 和那个尺寸的字符数组(或者可能是两倍大小的好测量)。如果您根本不想要任何限制,那么您仍然需要为与fgets 一起使用的数组选择一个最大大小,然后使用malloc/realloc 动态分配和增长您复制缓冲区满的结果数组从fgets 调用中获取。如果fgets 返回的字符串不包含换行符,则要么 仅读取部分行 读取文件中的最后一行但它没有包含换行符。
  • 或者,如果你被允许使用非标准函数,你可以使用getline
  • @ooga: getline() 是 POSIX (2008) 标准函数(但不是 C11 标准函数)。如果您确实必须担心行数超过 4 KiB,那么这是一个不错的选择。至少,这是我使用的阈值。对于一般用途的工作,我使用 char buffer[4096];fgets(buffer, sizeof(buffer), fp) 并且我什至不总是确保前 4095 个字符中有换行符——这并不重要(就像我期待 32 个字符,但需要“处理”古怪的输入)。

标签: c++ c string unix stdin


【解决方案1】:

希望我明白了...您需要查找文件结尾 (EOF),它是在遇到文件结尾时(猜猜是什么?)设置的。

关于缓冲区大小,可以先检查流大小,确保为接收缓冲区分配足够的内存。

使用重新分配通常不是一个好的选择。它很慢,仅表明您没有预料到内存需求。除非绝对必要(真正的硬内存限制),否则分配比重新分配更多的东西要好。当然,没有什么比“正确”的分配更重要了。

【讨论】:

  • 这个答案是“查找文件结尾 (EOF)”,而 OP 的问题是“获取整行”
  • 你说得对,我认为它仍然可以派上用场。为了节省硬盘驱动器的读取操作,最好读取整个文件,然后将文件拆分为字符串指针数组。同意它必须是适合当今 +4Go 计算机内存的文件 =D
【解决方案2】:

读取整个文件的正常过程是这样的:

  • 打开文件
  • 寻求结束
  • 读取位置
  • 创建该大小的缓冲区
  • 寻求开始
  • 读取缓冲区
  • 关闭文件

本网站上的示例正是这样做的:http://www.cplusplus.com/reference/cstdio/fread/

如果你想读到一个特殊字符,那么只需在一个循环中运行 fgets,你可以在其中使用 realloc 来调整缓冲区的大小。一种常见的方法是不是每次都增加一个固定的缓冲区大小,而是增加一个值,例如每次循环迭代将其大小增加一倍。这样,您将执行最多 log(n) 个 realloc 调用。

【讨论】:

  • 虽然它适用于小文件,但这种“正常过程”对于读取千兆字节大小的日志文件而言内存效率不高,对于这种情况,基于行的方法更有意义。我认为这里应该提到这一点。
  • 这个答案是读取“整个文件”,但 OP 的问题是“获取整行”
猜你喜欢
  • 2023-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多