为何控制台未输出"Hello"?scanf换行符问题排查
问题分析与解决方案
嘿,你猜的没错,换行符确实在输入缓冲区里搞事情,但更致命的是缓冲区溢出把你的s数组给覆盖了,这才是"Hello"没打印出来的核心原因。咱们一步步拆解:
先捋清楚你的输入和程序执行流程
你输入了三行内容:
C Hello My name is Mikey
- 第一个
scanf("%c", &ch)读取了C,但换行符\n留在了输入缓冲区里。 - 第二个
scanf("%s", s)会自动跳过开头的空白(包括那个残留的\n),成功读取了Hello,然后Hello后面的回车又留在了缓冲区。 - 你写的
scanf("\n")其实会匹配任意连续空白,所以吃掉了刚才的回车。 - 关键问题来了:
scanf(" %[^\n]", sen)前面的空格跳过了所有空白,然后读取My name is Mikey——这个字符串刚好是16个字符,而你的sen数组大小是MAX_LEN=16,刚好填满数组的0-15下标,没有多余的位置放字符串终止符\0。
为什么"Hello"没打印出来?
局部变量在栈上是连续存储的,s和sen挨得很近。当sen被填满16个字符后,本该自动添加的\0没地方放,就写到了s数组的第一个位置,把s[0]改成了\0。当你执行printf("%s\n", s)时,因为字符串第一个字符就是\0,所以输出的是空字符串,自然看不到"Hello"了。
解决方案:限制读取长度+可靠清空缓冲区
要解决这个问题,核心是避免缓冲区溢出,同时正确处理输入缓冲区的残留字符:
- 给
scanf加长度限制:对于大小为MAX_LEN的数组,读取时要留一个位置给\0,所以用%15s和%15[^\n](因为16-1=15)。 - 用
while循环清空缓冲区:比scanf("\n")或scanf("%*c")更可靠,能一次性吃掉所有残留的空白字符。
修改后的代码如下:
#include <stdio.h> #include <string.h> #define MAX_LEN 16 int main(){ char ch; char s[MAX_LEN]; char sen[MAX_LEN]; // 读取单个字符(第一个输入,前面无残留) scanf("%c", &ch); // 读取字符串,最多读15个字符,留位置给\0 scanf("%15s", s); // 清空缓冲区直到遇到换行,避免残留字符影响后续读取 while(getchar() != '\n'); // 读取带空格的字符串,限制长度15,前面的空格跳过空白 scanf(" %15[^\n]", sen); // 再次清空缓冲区 while(getchar() != '\n'); printf("%c\n", ch); printf("%s\n", s); printf("%s\n", sen); printf("sen[15] = %c\n", sen[15]); printf("string length = %lu\n", strlen(sen)); return 0; }
运行这个修改后的版本,你就能看到"Hello"正常打印出来了,而且不会有缓冲区溢出的问题。
内容的提问来源于stack exchange,提问作者MichaelJordan
相关产品推荐
相关产品推荐

