fgetc vs getline 或 fgets - 哪个最灵活
fgetc vs getline or fgets - which is most flexible
我正在从常规文件中读取数据,我想知道哪种方式最灵活。
我发现 fgets 和 getline 都读取一行(一个有最大字符数,另一个有动态内存分配)。在 fgets 的情况下,如果行的长度大于给定的大小,则行的其余部分将不会被读取,但会保留在流中的缓冲中。使用 getline,我担心它可能会尝试为超长的行分配一大块内存。
对我来说显而易见的解决方案似乎是转向fgetc,但这带来了一个问题,即调用该函数会多次,从而导致读取过程缓慢。
这种灵活性和效率之间的折衷是不可避免的,还是可以解决的?
很大程度上取决于具体情况。
getline()
是 而不是 标准 C 库的一部分。它的功能可能不同 - 取决于实现和它遵循的其他标准 - 因此标准 fgetc()/fgets()
.
的优势
... case between flexibility and efficiency unavoidable, ...
OP 缺少更高的优先级。
功能 - 如果代码无法正确使用所选功能,为什么要使用它?示例:fgets()
和读取 空字符 会产生问题。
清晰度 - 不清晰,感受到后来必须维护代码的可怜灵魂的愤怒。
would allow for the most flexibility. (?)
fgetc()
允许在低级别上提供最大的灵活性 - 但使用它来读取行的辅助函数往往会在极端情况下失败。
fgets()
在中级允许最大的灵活性 - 仍然必须处理长行和嵌入 空字符 的行,但在至少避免了杂草中的低水平。
getline()
在不需要高可移植性并且不担心允许用户淹没资源的风险时很有用。
为了稳健地处理 user/file 输入以读取一行,创建一个包装函数(例如 int my_read_line(size_t buf, char *buf, FILE *f)
)并仅在用户代码中调用它。然后当出现问题时,可以在本地处理它们,而不管选择的低级输入功能如何。
你提到的三个函数做不同的事情:
fgetc()
从 FILE *
描述符中读取单个字符,它缓冲输入,因此,您可以以缓冲方式处理文件,而无需为每个字符进行系统调用.当你的问题能以性格化的方式处理时,那是最好的。
fgets()
从 FILE *
描述符中读取一行,这就像调用 fgetc()
来填充您传递给它的字符数组以便逐行读取。如果您的输入行长于您指定的缓冲区大小,它的缺点是会进行部分读取。此函数还缓冲输入数据,因此效率很高。如果您知道您的行将受到限制,那么最好逐行读取您的数据。有时您希望能够以无限行大小的方式处理数据,并且您必须重新设计您的问题以使用可用内存。那么下面这一款估计选的比较好。
getline()
这个函数相对较新,不是 ANSI-C,因此您可能将程序移植到缺少它的某些体系结构。它是最灵活的,但代价是效率较低。它需要引用一个指向 realloc()
的指针来填充越来越多的数据。它不会以可能填满系统上所有可用内存为代价来绑定行长度。缓冲区指针和缓冲区的大小都通过引用传递以允许更新它们,因此您知道新字符串的位置和新大小。使用后必须 free()
d。
之所以有三个而不是只有一个功能,是因为你对不同的情况有不同的需求,选择最高效的通常是最好的选择。
如果您打算只使用一个,您最终可能会遇到这样一种情况:使用您选为最灵活的功能并不是最好的选择,您可能会失败。
我正在从常规文件中读取数据,我想知道哪种方式最灵活。
我发现 fgets 和 getline 都读取一行(一个有最大字符数,另一个有动态内存分配)。在 fgets 的情况下,如果行的长度大于给定的大小,则行的其余部分将不会被读取,但会保留在流中的缓冲中。使用 getline,我担心它可能会尝试为超长的行分配一大块内存。
对我来说显而易见的解决方案似乎是转向fgetc,但这带来了一个问题,即调用该函数会多次,从而导致读取过程缓慢。
这种灵活性和效率之间的折衷是不可避免的,还是可以解决的?
很大程度上取决于具体情况。
getline()
是 而不是 标准 C 库的一部分。它的功能可能不同 - 取决于实现和它遵循的其他标准 - 因此标准 fgetc()/fgets()
.
... case between flexibility and efficiency unavoidable, ...
OP 缺少更高的优先级。
功能 - 如果代码无法正确使用所选功能,为什么要使用它?示例:
fgets()
和读取 空字符 会产生问题。清晰度 - 不清晰,感受到后来必须维护代码的可怜灵魂的愤怒。
would allow for the most flexibility. (?)
fgetc()
允许在低级别上提供最大的灵活性 - 但使用它来读取行的辅助函数往往会在极端情况下失败。fgets()
在中级允许最大的灵活性 - 仍然必须处理长行和嵌入 空字符 的行,但在至少避免了杂草中的低水平。getline()
在不需要高可移植性并且不担心允许用户淹没资源的风险时很有用。
为了稳健地处理 user/file 输入以读取一行,创建一个包装函数(例如 int my_read_line(size_t buf, char *buf, FILE *f)
)并仅在用户代码中调用它。然后当出现问题时,可以在本地处理它们,而不管选择的低级输入功能如何。
你提到的三个函数做不同的事情:
fgetc()
从FILE *
描述符中读取单个字符,它缓冲输入,因此,您可以以缓冲方式处理文件,而无需为每个字符进行系统调用.当你的问题能以性格化的方式处理时,那是最好的。fgets()
从FILE *
描述符中读取一行,这就像调用fgetc()
来填充您传递给它的字符数组以便逐行读取。如果您的输入行长于您指定的缓冲区大小,它的缺点是会进行部分读取。此函数还缓冲输入数据,因此效率很高。如果您知道您的行将受到限制,那么最好逐行读取您的数据。有时您希望能够以无限行大小的方式处理数据,并且您必须重新设计您的问题以使用可用内存。那么下面这一款估计选的比较好。getline()
这个函数相对较新,不是 ANSI-C,因此您可能将程序移植到缺少它的某些体系结构。它是最灵活的,但代价是效率较低。它需要引用一个指向realloc()
的指针来填充越来越多的数据。它不会以可能填满系统上所有可用内存为代价来绑定行长度。缓冲区指针和缓冲区的大小都通过引用传递以允许更新它们,因此您知道新字符串的位置和新大小。使用后必须free()
d。
之所以有三个而不是只有一个功能,是因为你对不同的情况有不同的需求,选择最高效的通常是最好的选择。
如果您打算只使用一个,您最终可能会遇到这样一种情况:使用您选为最灵活的功能并不是最好的选择,您可能会失败。