C语言中用fgets读取stdin时,如何处理超长输入及解决段错误?
问题:如何限制stdin输入长度不超过缓冲区大小(仅用ferror/feof)
我被这个基础错误卡了好一阵子。想请教下,怎么避免stdin输入的字符串长度超过word_new的sizeof(也就是输入长度大于缓冲区大小),而且只能用ferror或feof函数?
补充提示:输入里没有'\n'字符,我本来想基于这点处理。
补充说明:段错误是我没贴的代码导致的,是我的问题。
补充说明:我们不用规避超长输入,而是读取char* str允许的最大字符数就行,要清楚str可能以'\n'或其他字符结尾,毕竟字符串是以'\0'结尾的。
原代码片段
int main() { char word_new[42]; while(1) { /*此处需要帮助:运行出现段错误*/ if (fgets(word_new, sizeof(word_new), stdin) == NULL){ // 发生错误,调用perror if(ferror(stdin)){ perror("error occured in stdin"); exit(1); } // 无错误,仅到达EOF break; } //此前未提供的代码片段: char *wordpt = strchr(word_new, '\n'); *wordpt = '\0'; //无'\n'字符 => 错误 }
解决方案
首先明确:fgets本身就会自动限制读取长度——它最多读取sizeof(word_new)-1个字符,然后自动在末尾添加'\0',所以缓冲区溢出的问题fgets已经帮你解决了。你当前的段错误是因为strchr找不到'\n'时返回NULL,直接解引用*wordpt导致的。
按照要求仅用ferror和feof处理的话,修改思路如下:
- 保留
fgets的基础逻辑,用ferror和feof区分fgets返回NULL的原因(输入错误/到达EOF)。 - 处理
'\n'时先判断strchr的返回值,避免访问空指针。 - 若输入超长(无
'\n'),可选清空stdin缓冲区的剩余字符,避免影响后续读取。
修改后的完整代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> int main() { char word_new[42]; while(1) { if (fgets(word_new, sizeof(word_new), stdin) == NULL){ if(ferror(stdin)){ perror("error occured in stdin"); exit(1); } // 确认是到达EOF,退出循环 if(feof(stdin)) break; } char *wordpt = strchr(word_new, '\n'); if (wordpt != NULL) { *wordpt = '\0'; } else { // 无换行符,说明输入超长或已到EOF // 清空stdin剩余字符(可选,避免残留字符干扰下一次读取) int c; while ((c = getchar()) != '\n' && c != EOF) { // 仅读取字符,不做额外操作 } // 检查清空缓冲区时是否出错 if (ferror(stdin)) { perror("error clearing stdin"); exit(1); } // 此时word_new已是合法的'\0'结尾字符串,可正常使用 } // 这里添加word_new的业务处理代码 } return 0; }
关键说明
fgets的安全机制:只要第二个参数传入sizeof(word_new),就不会出现缓冲区溢出,它会自动保证字符串以'\0'结尾。- 空指针判断:必须先检查
strchr的返回值,不能直接解引用,这是解决段错误的核心。 - 超长输入处理:清空剩余字符是可选操作,但能避免残留的输入字符被下一次
fgets读取,保证逻辑连贯。 - 符合
ferror/feof要求:所有错误和EOF判断都通过这两个函数完成,满足需求。
内容的提问来源于stack exchange,提问作者plantpot
相关产品推荐
相关产品推荐

