fgets函数的使用

以字符串为单位的I/O函数
2009年12月20日 星期日 14:59

fgets从指定的文件中读一行字符到调用者提供的缓冲区中,gets从标准输入读一行字符到调用者提供的缓冲区中。

#include <stdio.h>

char *fgets(char *s, int size, FILE *stream);
char *gets(char *s);
返回值:成功时s指向哪返回的指针就指向哪,出错或者读到文件末尾时返回NULL

gets函数无需解释,Man Page的BUGS部分已经说得很清楚了:Never use gets()。gets函数的存在只是为了兼容以前的程序,我们写的代码都不应该调用这个函数。gets函数的接口设计得很有问题,就像strcpy一样,用户提供一个缓冲区,却不能指定缓冲区的大小,很可能导致缓冲区溢出错误,这个函数比strcpy更加危险,strcpy的输入和输出都来自程序内部,只要程序员小心一点就可以避免出问题,而gets读取的输入直接来自程序外部,用户可能通过标准输入提供任意长的字符串,程序员无法避免gets函数导致的缓冲区溢出错误,所以唯一的办法就是不要用它。

现在说说fgets函数,参数s是缓冲区的首地址,size是缓冲区的长度,该函数从stream所指的文件中读取以'/n'结尾的一行(包括'/n'在内)存到缓冲区s中,并且在该行末尾添加一个'/0'组成完整的字符串。

如果文件中的一行太长,fgets从文件中读了size-1个字符还没有读到'/n',就把已经读到的size-1个字符和一个'/0'字符存入缓冲区,文件中剩下的半行可以在下次调用fgets时继续读。

如果一次fgets调用在读入若干个字符后到达文件末尾,则将已读到的字符串加上'/0'存入缓冲区并返回,如果再次调用fgets则返回NULL,可以据此判断是否读到文件末尾。

注意,对于fgets来说,'/n'是一个特别的字符,而'/0'并无任何特别之处,如果读到'/0'就当作普通字符读入。如果文件中存在'/0'字符(或者说0x00字节),调用fgets之后就无法判断缓冲区中的'/0'究竟是从文件读上来的字符还是由fgets自动添加的结束符,所以fgets只适合读文本文件而不适合读二进制文件,并且文本文件中的所有字符都应该是可见字符,不能有'/0'

fputs向指定的文件写入一个字符串,puts向标准输出写入一个字符串。

#include <stdio.h>

int fputs(const char *s, FILE *stream);
int puts(const char *s);
返回值:成功返回一个非负整数,出错返回EOF

缓冲区s中保存的是以'/0'结尾的字符串,fputs将该字符串写入文件stream,但并不写入结尾的'/0'。与fgets不同的是,fputs并不关心的字符串中的'/n'字符,字符串中可以有'/n'也可以没有'/n'puts将字符串s写到标准输出(不包括结尾的'/0'),然后自动写一个'/n'到标准输出。

<think>好的,用户之前问过如何用scanf读取带空格的字符串,我给出了几种方法,其中推荐了fgets。现在用户接着问如何使用fgets函数,这说明他们可能在实际使用中遇到了问题,或者想更深入了解这个方法。 首先,我需要确定用户的使用场景。他们可能正在处理输入包含空格的字符串,比如用户输入的名字、地址等。之前的问题中,用户已经知道scanf的局限性,现在想正确使用fgets来替代。因此,我需要详细解释fgets的用法,参数,以及注意事项。 用户可能对fgets的参数不太清楚,比如第二个参数和第三个参数的作用。需要解释清楚,第二个参数是缓冲区大小,避免溢出,第三个参数是文件流,通常是stdin。同时,用户可能注意到fgets会读取换行符,这可能导致后续处理的问题,所以需要说明如何去除换行符,比如使用strcspn或者手动查找替换。 另外,用户之前提到的scanf方法中,使用%[^\n]可能会导致缓冲区残留的问题,所以在介绍fgets时,可能需要对比两者的区别,强调fgets的安全性。同时,用户可能遇到的常见错误,比如忘记处理换行符,或者数组大小设置不当,需要指出这些陷阱并提供解决方法。 还要考虑用户可能的后续问题,比如如何处理不同的输入情况,或者在不同平台下的兼容性,但当前问题集中在fgets的基本使用,所以保持重点在这里。最后,给出示例代码,展示正确的使用方式,并提醒注意事项,帮助用户巩固理解。</think>`fgets()` 是 C 语言中用于安全读取字符串的标准库函数,尤其适合读取包含空格的整行输入。以下是它的基本用法和注意事项: --- ### **函数原型** ```c char *fgets(char *str, int n, FILE *stream); ``` - **参数说明**: - `str`:指向字符数组的指针,用于存储读取的字符串。 - `n`:最大读取字符数(包括末尾自动添加的 `\0`)。 - `stream`:输入流,通常用 `stdin` 表示从键盘读取。 --- ### **基本用法** ```c #include <stdio.h> int main() { char buffer[100]; // 定义足够大的缓冲区 printf("请输入内容:"); fgets(buffer, sizeof(buffer), stdin); // 从键盘读取输入 printf("你输入的是:%s", buffer); return 0; } ``` - **执行流程**: 1. 用户输入内容(如 `Hello World\n`,`\n` 是换行符)。 2. `fgets()` 会读取字符,直到: - 遇到换行符 `\n`(会包含在结果中)。 - 读取了 `n-1` 个字符(保留一个位置给 `\0`)。 - 到达文件末尾(如输入流的结尾)。 3. 最终字符串末尾会自动添加 `\0`。 --- ### **关键特性** 1. **安全性**: - 通过 `n` 限制最大读取长度,避免缓冲区溢出(比 `gets()` 更安全)。 2. **保留换行符**: - 如果输入行的长度未超过 `n-1`,`\n` 会被保留在字符串中(需手动处理)。 3. **返回值**: - 成功时返回 `str` 的地址,失败或到达文件末尾时返回 `NULL`。 --- ### **处理换行符** `fgets()` 会保留换行符 `\n`,可以通过以下方法移除: ```c #include <string.h> // 方法1:使用 strcspn 函数 buffer[strcspn(buffer, "\n")] = '\0'; // 方法2:手动查找替换 size_t len = strlen(buffer); if (len > 0 && buffer[len-1] == '\n') { buffer[len-1] = '\0'; } ``` --- ### **示例代码(完整版)** ```c #include <stdio.h> #include <string.h> int main() { char input[50]; printf("输入一行文字(最多49字符): "); if (fgets(input, sizeof(input), stdin) != NULL) { // 移除可能的换行符 input[strcspn(input, "\n")] = '\0'; printf("处理后的输入: \"%s\"\n", input); } else { printf("读取失败!\n"); } return 0; } ``` --- ### **常见问题** 1. **输入超出缓冲区大小**: - 若用户输入超过 `n-1` 个字符,`fgets()` 会截断剩余内容,后续输入可能残留在缓冲区中(需用 `getchar()` 清理)。 2. **多次调用 fgets**: - 如果连续调用 `fgets()`,需注意前一次输入可能残留的换行符(可通过检查并清除缓冲区解决)。 --- ### **总结** - **适用场景**:安全读取整行输入(含空格)。 - **核心优势**:避免缓冲区溢出风险。 - **注意事项**:处理换行符、检查返回值、清理残留输入。 通过合理使用 `fgets()`,可以更安全地处理用户输入!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值