5.7 每次一行I/O

5.7 每次一行I/O

下面两个函数提供每次输入一行的功能。

 

#include <stdio.h>

char* fgets(char*restrict buf, int n, FILE*restrict fp);

char* gets( char* buf);

这两个函数都指定了缓存地址,读入的行将送入其中。gets从标准输入读,而fgets则从指定的流读。

对于fgets,必须指定缓存的长度n。此函数一直读到下一个新行符为止,但是不超过 n1个字符,读入的字符被送入缓存。该缓存以null字符结尾。如若该行,包括最后一个新行符的字符数超过n1,则只返回一个不完整的行,而且缓存总是以null字符结尾。对fgets的下一次调用会继续读该行。

gets是一个不推荐使用的函数。问题是调用者在使用gets时不能指定缓存的长度。这样就可能造成缓存越界(如若该行长于缓存长度),写到缓存之后的存储空间中,从而产生不可预料的后果。这种缺陷曾被利用,造成1988年的因特网蠕虫事件。getsfgets的另一个区别是,gets并不将换行符存入缓存中。

尽管ISO C要求实现提供gets,但不要使用它,还是使用fgets为好。

fputsputs提供每次输出一行的功能。

#include <stdio.h>

int fputs(const char*restrict str, FILE*restrict fp);

int puts(const char*str);

函数fputs将一个以null符终止的字符串写到指定的流,终止符null不写出。注意,这并不一定是每次输出一行,因为它并不要求在null符之前一定是新行符。通常,在null符之前是一个新行符,但并不要求总是如此。

puts将一个以null符终止的字符串写到标准输出,终止符不写出。但是,puts然后又将一个新换行符写到标准输出。

puts并不像它所对应的gets那样不安全。但是我们还是应避免使用它,以免需要记住它在最后又加上了一个新行符。如果总是使用fgetsfputs,那么就会熟知在每行终止处我们必须自己加一个新行符。