C 试图理解fgets()

C 试图理解fgets(),c,fgets,file-read,C,Fgets,File Read,我正在写一个程序逐行读取文件。我知道fgets将一直读取到新行、n-1个字符或EOF。让我困惑的是fgets如何知道前进到一个新行/它在文件中的位置 更清楚地说,我知道在Java中,您必须明确地告诉扫描器读取下一行。但在C语言中,我只是把FGET放在一个while循环中,相信这就是它的工作 我怎样才能从逻辑上保证fgets实际上正在进入下一行,而不是在循环中一遍又一遍地读取同一行?是的,我知道我可以打印出来?fgets的语义非常简单:从文件*流指针读取字节,直到: 目标阵列已满,已读取并存储了n

我正在写一个程序逐行读取文件。我知道fgets将一直读取到新行、n-1个字符或EOF。让我困惑的是fgets如何知道前进到一个新行/它在文件中的位置

更清楚地说,我知道在Java中,您必须明确地告诉扫描器读取下一行。但在C语言中,我只是把FGET放在一个while循环中,相信这就是它的工作


我怎样才能从逻辑上保证fgets实际上正在进入下一行,而不是在循环中一遍又一遍地读取同一行?是的,我知道我可以打印出来?

fgets的语义非常简单:从文件*流指针读取字节,直到:

目标阵列已满,已读取并存储了n-1个字节。 从流中读取新行并将其存储到目标数组中。 fgetc调用或等效调用返回EOF时,已到达文件结尾或发生读取错误。在fgets返回NULL后,可以通过调用ferr和/或feof来区分文件结束和读取错误情况。 在从流中读取字节后,空终止符始终存储在数组中,除非fgets立即到达文件末尾,否则fgets返回空值,或者如果缓冲区大小指定为0

fgets的行为就像使用fgetc一次读取一个字节的流一样

fgets使用从流中读取的字节,并将它们存储到目标阵列中。如果流支持查找,则除非使用rewind、fseek或fsetpos显式向后查找到流中,否则它无法再次读取相同的字节。附加到常规文件的流通常支持查找,但在某些系统(尤其是Microsoft Windows)上,以文本模式打开的文件需要特定的处理。还请注意,使用ungetc推回流中的字节将在实际流中的任何字节之前由fgets读取

如果换行符足够短,可以放入空终止符之前的数组,则fgets会将换行符存储到目标数组中

如果行超过目标数组中的可用空间,fgets会将长行拆分为较小的块。处理长线很棘手,而且容易出错。请注意,当fgets由于目标数组中缺少空间而读取部分行时,对fgets的下一次调用将在上一次调用停止的点处继续从同一行读取

如果从fgets返回时,目标数组未以换行结束,则会发生以下情况之一:

当前行太长,只能从流中读取数组中适合的字节数。 读取的行是文件中的最后一行,文件不以换行序列结束。 从文件中读取了一个空字节。 错误处理这些情况可能会导致潜在的未定义行为和/或可利用的缺陷。

FGET的语义非常简单:从文件*流指针读取字节,直到:

目标阵列已满,已读取并存储了n-1个字节。 从流中读取新行并将其存储到目标数组中。 fgetc调用或等效调用返回EOF时,已到达文件结尾或发生读取错误。在fgets返回NULL后,可以通过调用ferr和/或feof来区分文件结束和读取错误情况。 在从流中读取字节后,空终止符始终存储在数组中,除非fgets立即到达文件末尾,否则fgets返回空值,或者如果缓冲区大小指定为0

fgets的行为就像使用fgetc一次读取一个字节的流一样

fgets使用从流中读取的字节,并将它们存储到目标阵列中。如果流支持查找,则除非使用rewind、fseek或fsetpos显式向后查找到流中,否则它无法再次读取相同的字节。附加到常规文件的流通常支持查找,但在某些系统(尤其是Microsoft Windows)上,以文本模式打开的文件需要特定的处理。还请注意,使用ungetc推回流中的字节将在实际流中的任何字节之前由fgets读取

如果换行符足够短,可以放入空终止符之前的数组,则fgets会将换行符存储到目标数组中

如果行超过目标数组中的可用空间,fgets会将长行拆分为较小的块。处理长线很棘手,而且容易出错。请注意,当fgets由于目标数组中缺少空间而读取部分行时,对fgets的下一次调用将在上一次调用停止的点处继续从同一行读取

如果从fgets返回时,目标数组未以换行结束,则会发生以下情况之一:

当前行太长,只能从流中读取数组中适合的字节数。 读取的行是文件中的最后一行,文件不以换行结束 序列 从文件中读取了一个空字节。

错误处理这些情况可能会导致潜在的未定义行为和/或可利用的缺陷。

如果fgets使用文件指针,它将使该指针在文件中前进,刚好经过下一个换行符。如果您在该文件上使用任何读取功能,而不仅仅是fgets,则这些功能将从fgets离开文件指针的位置开始:换行之后。在while循环中不反复读取同一行:从某种意义上说,您不能。您只需信任实现库功能的人员。所以,如果不知何故,在某个地方,您得到了一个4月1日风格的库,那么您的场景可能会发生,ftell之类的功能也会同样糟糕。但这当然不是应该的。关闭和打开文件是重新启动的一种方法,是的。使用rewind或fseek可能更简单、更快速。通读fgets、rewind、fseek等手册页,或者看看是否能找到C语言中关于文件/流访问的合理详细指南。这可能是一个很好的开始。一般来说,试着把一个文件看作是一个连续的字节序列,一路读下去。如果文件较短,则可以在一张纸上绘制各种动作,并查看事物如何移动,包括FGET。关于FGET,有一点需要注意:如果“大小”参数短于直线,则FGET将一直读取到该点。在下一次迭代中,它将从该点继续。它不会跳过该行的其余部分并从下一行开始。因此,如果要读取整行,请始终确保size参数和输入缓冲区与要读取的最长行(包括换行符)一样长。如果fgets使用文件指针,它将使该指针在文件中前进,刚好经过下一个换行符。如果您在该文件上使用任何读取功能,而不仅仅是fgets,则这些功能将从fgets离开文件指针的位置开始:换行之后。在while循环中不反复读取同一行:从某种意义上说,您不能。您只需信任实现库功能的人员。所以,如果不知何故,在某个地方,您得到了一个4月1日风格的库,那么您的场景可能会发生,ftell之类的功能也会同样糟糕。但这当然不是应该的。关闭和打开文件是重新启动的一种方法,是的。使用rewind或fseek可能更简单、更快速。通读fgets、rewind、fseek等手册页,或者看看是否能找到C语言中关于文件/流访问的合理详细指南。这可能是一个很好的开始。一般来说,试着把一个文件看作是一个连续的字节序列,一路读下去。如果文件较短,则可以在一张纸上绘制各种动作,并查看事物如何移动,包括FGET。关于FGET,有一点需要注意:如果“大小”参数短于直线,则FGET将一直读取到该点。在下一次迭代中,它将从该点继续。它不会跳过该行的其余部分并从下一行开始。因此,如果要读取整行,请始终确保size参数和输入缓冲区与要读取的最长行(包括换行符)一样长。是否只能查找常规文件?或者,更重要的是,标准是否规定了文件何时应支持定位请求的任何保证?回答不错。注:fgets可以使用ungetc重新读取最后一个字符。这个答案忽略了关于罕见输入错误的讨论——这对于最初的fgets理解是不必要的——除了知道它的存在之外。@david_bowling:没有任何保证。@chux:我还对不经意的读者隐瞒了关于宽方向流遇到编码错误的潜在问题的血淋淋的细节。。。有充分的理由。这是我所需要了解的关于fgets的所有信息。谢谢是否只能查找常规文件?或者,更重要的是,标准是否规定了文件何时应支持定位请求的任何保证?回答不错。注:fgets可以使用ungetc重新读取最后一个字符。这个答案忽略了关于罕见输入错误的讨论——这对于最初的fgets理解是不必要的——除了知道它的存在之外。@david_bowling:没有任何保证。@chux:我还对不经意的读者隐瞒了关于宽方向流遇到编码错误的潜在问题的血淋淋的细节。。。有充分的理由。这是我所需要了解的关于fgets的所有信息。谢谢