求助:输入超出限制时fgets跳过行,stdin缓冲区异常问题
搞定fgets输入超长跳过行的问题
嘿,我来帮你捋清楚这个问题——你遇到的情况其实是fgets的特性加上stdin缓冲区残留导致的,咱们一步步拆解:
为啥会跳过行?
当你输入的字符串长度超过MAX_LENGTH-1时,fgets只会老老实实读前MAX_LENGTH-1个字符,然后自动加个\0结尾。剩下的那些字符(包括你敲的回车换行符)会留在标准输入的缓冲区里,没被读走。
等下一次调用fgets的时候,它不会等你输入,直接就把缓冲区里剩下的内容读进来了——如果剩下的刚好是个换行符,那fgets就会读到空行,看起来就像是“跳过了输入行”,其实是它读了缓冲区里的残留内容而已。
你的代码里的小问题
看你写的lastName函数,里面用了strtok(pt[i].lastName, "\n");来去掉换行符,这个操作有个坑:
- 如果输入没超长,fgets读到了换行符,strtok能把换行符换成
\0,没问题; - 但如果输入超长,fgets根本没读到换行符,strtok找不到目标,啥也不会做,而且缓冲区里的残留字符还安安稳稳待着,下一次输入肯定要出问题。
怎么解决?
核心思路就是:每次用fgets之后,把stdin缓冲区里剩下的残留内容清干净,确保下一次输入是从头开始的。
第一步:写个清理缓冲区的小函数
先整个工具函数,专门负责把缓冲区里的残留字符读完:
void clear_stdin() { int c; // 一直读,直到读到换行符或者文件结束(EOF) while ((c = getchar()) != '\n' && c != EOF); }
第二步:修改你的输入函数
把原来的strtok换成更稳妥的strchr来处理换行符,同时判断是否需要清理缓冲区:
void lastName(int *counter, User *pt) { for (int i = *counter; i < (*counter + 1); i++) { pt[i].lastName = calloc(MAX_LENGTH, sizeof(char)); printf("Enter Last Name: "); // 先判断fgets是否读取成功 if (fgets(pt[i].lastName, MAX_LENGTH, stdin) == NULL) { // 遇到EOF或者读取错误,就把字符串设为空 pt[i].lastName[0] = '\0'; continue; } // 找字符串里的换行符 char *newline = strchr(pt[i].lastName, '\n'); if (newline != NULL) { // 找到换行符,替换成结束符 *newline = '\0'; } else { // 没找到换行符,说明输入超长了,赶紧清缓冲区 clear_stdin(); } } }
额外提一嘴内存问题
你用了calloc分配内存,记得后面不用这些用户数据的时候,要循环调用free(pt[i].lastName)释放内存,不然会有内存泄漏哦。
总结一下
本质就是fgets不会帮你处理超长输入的残留内容,得咱们自己手动清缓冲区。按照上面的方法修改后,不管输入多长,下一次输入都会正常等待用户输入,不会再跳过行了。
内容的提问来源于stack exchange,提问作者Kevin H
相关产品推荐
相关产品推荐

