C语言循环输入字符串写文件遇end死循环问题求解
问题根因
程序无限循环的核心原因是scanf的%[^\n]格式符行为不符合预期:
- 该格式符仅读取换行符之前的字符,不会消费输入缓冲区中残留的换行符
\n - 第一次输入完成按下回车后,换行符始终留在输入缓冲区头部,下一轮循环执行
scanf时,首个字符就是\n,和%[^\n]的匹配规则冲突,直接读取失败,既不会更新text数组的内容,也不会清除缓冲区的残留字符,最终导致循环反复执行、无限打印输入提示,无法接收新的用户输入。
原代码还存在两个隐藏风险:
%[^\n]未设置读取长度上限,输入超过99个字符时会触发数组越界,造成内存溢出text数组未初始化,若用户首次直接输入回车,scanf匹配失败后text内容不确定,直接传给strcmp会触发未定义行为
修正方案
- 每次调用
scanf读取行内容后,主动遍历清空输入缓冲区,直到读到换行符或文件结束符,把残留的换行符和多余输入全部消费掉 - 给
%[^\n]增加长度限制,写为%99[^\n],最多读取99个字符,预留1字节位置存放字符串结束符\0,避免数组越界 - 初始化
text数组,同时处理scanf匹配失败的场景,避免未定义行为 - 行输入场景更推荐使用
fgets,原生支持长度限制,逻辑更简洁,不易出缓冲区残留问题
修正后代码
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char text[100] = {0}; FILE *output = fopen("output.txt", "a"); if (output == NULL) { printf("Could not open file\n"); return 1; } while (1) { printf("Enter Text: \n"); // 增加长度限制避免越界,ret接收scanf的匹配成功次数 int ret = scanf("%99[^\n]", text); // 清空输入缓冲区所有残留内容 int c; while ((c = getchar()) != '\n' && c != EOF); // 处理直接输入回车等匹配失败的场景 if (ret != 1) { text[0] = '\0'; } if (strcmp(text, "end") != 0) { fprintf(output, "%s\n", text); } else { break; } } fclose(output); return 0; }
补充:如果用
fgets实现行读取,需要注意fgets会将用户输入的换行符一并存入字符串,判断终止字符串"end"前需要手动剔除末尾的换行符即可。
内容的提问来源于stack exchange,提问作者rtp_46
相关产品推荐
相关产品推荐

