为什么while循环中fgets()、fread()无法正确替代scanf()?
问题原因及修复方案
故障根因
你原来的scanf("%s", kbinput)会自动跳过输入前的所有空白字符,且读到空白字符就停止,不会把末尾的换行符存入缓冲区,因此匹配"~"逻辑正常。换成fgets/fread后异常的原因如下:
- fgets读取输入时会将输入末尾的**换行符
\n**一同存入目标缓冲区,你输入~后按回车,实际存入kbinput的是"~\\n",和匹配串"~"不一致,strcmp返回非0,无法触发break。如果之前有scanf调用残留的换行符在stdin缓冲区,首次调用fgets还会直接读到空行,进一步导致匹配失败。 - fread是面向二进制流的按块读取接口,不会自动在读取内容末尾加字符串结束符
\0,后续调用strcmp、system这类要求合法C字符串的函数会触发内存越界,出现不可预期的异常,完全不适合读取键盘输入的字符串。
修复后的fgets实现代码
#include <string.h> // 需要引入头文件处理字符串 while (1){ system("echo $PWD$"); // 读取输入,读取失败(如遇到EOF)直接退出循环 if (fgets(kbinput, 1000, stdin) == NULL) { break; } // 移除fgets读入的末尾换行符 size_t input_len = strlen(kbinput); if (input_len > 0 && kbinput[input_len - 1] == '\n') { kbinput[input_len - 1] = '\0'; } if (strcmp(kbinput,"~") == 0) break; fprintf(fptr,"%s\n",kbinput); system(kbinput); }
注意事项
- 要保证
kbinput缓冲区的实际大小不小于fgets的第二个参数,避免缓冲区溢出。 - 如果输入内容长度超过你设置的读取上限,fgets只会读满上限减1的内容,剩余数据会留在stdin缓冲区,下次调用fgets会继续读取,如有需要可以自行加逻辑清空缓冲区剩余内容。
内容的提问来源于stack exchange,提问作者user17267060
相关产品推荐
相关产品推荐

