为什么 scanf(“%d”,n) 后 getchar() 直接结束了90% 的新手都被这个坑过你有没有遇到过这种情况#includestdio.hintmain(){intage;charname[50];printf(请输入年龄);scanf(%d,age);printf(请输入姓名);fgets(name,50,stdin);printf(年龄%d姓名%s\n,age,name);return0;}运行结果请输入年龄25 请输入姓名年龄25姓名等一下——我还没输入姓名呢程序怎么直接跳过去了很多人第一次遇到这个 bug调试了半小时都找不到原因。今天用 3 分钟彻底搞懂。一句话结论缓冲区里藏着一个换行符问题的根源在于你输入25然后按了回车键。键盘实际发送给程序的是25\nscanf(%d, age)读走了25但\n换行符还留在输入缓冲区里。轮到fgets()/getchar()执行时它发现缓冲区里已经有东西了——就是那个\n于是立刻读走程序直接跳过等待。画个图就清楚了用户输入: 25\n │ ▼ ┌───────────┐ │ 输入缓冲区 │ │ 2 5 \n │ └───────────┘ │ ▼ scanf(%d, age) ┌───────────┐ │ 输入缓冲区 │ │ \n │ ← 25 被读走了\n 还在 └───────────┘ │ ▼ fgets(name, 50, stdin) ┌───────────┐ │ 输入缓冲区 │ │ │ ← \n 被 fgets 当一行读走了 └───────────┘fgets看到\n心想「哦这是一行我已经读完了。」——于是 name 里只有一个换行符用户根本没机会输入。为什么会这样scanf 的工作方式决定了这个行为scanf(%d)会跳过前面的空白字符读取数字但它不会读取数字后面的空白字符包括换行符换行符\n就留在了缓冲区里等着下一个输入函数来读这不仅仅是scanffgets的问题同样的坑还有scanf(%d,n);getchar();// 本来想等用户按任意键结果直接读到了 \nscanf(%d,n);scanf(%c,ch);// ch 变成了 \n不是用户想输入的字符怎么解决方法一用 getchar() 吃掉换行符最简单scanf(%d,age);getchar();// 吃掉残留的 \nprintf(请输入姓名);fgets(name,50,stdin);方法二scanf 格式串里加空格scanf(%d ,age);// 注意 %d 后面有空格这个空格告诉 scanf「把后面的空白字符包括换行符也吃掉。」但这个方法有个缺点scanf 会一直等待直到遇到非空白字符才停止有时候反而让程序卡住。方法三用循环清空缓冲区最稳健scanf(%d,age);while(getchar()!\n);// 一直读直到遇到换行符不管缓冲区里残留了多少垃圾一行代码全部清空。方法四不用 scanf用 fgets sscanf推荐charinput[100];fgets(input,sizeof(input),stdin);// 读整行sscanf(input,%d,age);// 从行里解析数字这是最推荐的做法——fgets会把整行包括\n都读走不会给后续输入留坑。总结记住一句话scanf 读取完数据后换行符还留在缓冲区里。下一个输入函数会立刻读到它导致程序跳过用户输入。这种问题排查起来很隐蔽因为代码逻辑上看不出任何问题。但只要理解了输入缓冲区的机制就能秒定位秒修复。你还被哪些输入函数的坑绊倒过评论区聊聊。#c语言 #算法 #数据结构
为什么 scanf() 后 getchar() 直接结束了?90%的新手都被这个坑过
为什么 scanf(“%d”,n) 后 getchar() 直接结束了90% 的新手都被这个坑过你有没有遇到过这种情况#includestdio.hintmain(){intage;charname[50];printf(请输入年龄);scanf(%d,age);printf(请输入姓名);fgets(name,50,stdin);printf(年龄%d姓名%s\n,age,name);return0;}运行结果请输入年龄25 请输入姓名年龄25姓名等一下——我还没输入姓名呢程序怎么直接跳过去了很多人第一次遇到这个 bug调试了半小时都找不到原因。今天用 3 分钟彻底搞懂。一句话结论缓冲区里藏着一个换行符问题的根源在于你输入25然后按了回车键。键盘实际发送给程序的是25\nscanf(%d, age)读走了25但\n换行符还留在输入缓冲区里。轮到fgets()/getchar()执行时它发现缓冲区里已经有东西了——就是那个\n于是立刻读走程序直接跳过等待。画个图就清楚了用户输入: 25\n │ ▼ ┌───────────┐ │ 输入缓冲区 │ │ 2 5 \n │ └───────────┘ │ ▼ scanf(%d, age) ┌───────────┐ │ 输入缓冲区 │ │ \n │ ← 25 被读走了\n 还在 └───────────┘ │ ▼ fgets(name, 50, stdin) ┌───────────┐ │ 输入缓冲区 │ │ │ ← \n 被 fgets 当一行读走了 └───────────┘fgets看到\n心想「哦这是一行我已经读完了。」——于是 name 里只有一个换行符用户根本没机会输入。为什么会这样scanf 的工作方式决定了这个行为scanf(%d)会跳过前面的空白字符读取数字但它不会读取数字后面的空白字符包括换行符换行符\n就留在了缓冲区里等着下一个输入函数来读这不仅仅是scanffgets的问题同样的坑还有scanf(%d,n);getchar();// 本来想等用户按任意键结果直接读到了 \nscanf(%d,n);scanf(%c,ch);// ch 变成了 \n不是用户想输入的字符怎么解决方法一用 getchar() 吃掉换行符最简单scanf(%d,age);getchar();// 吃掉残留的 \nprintf(请输入姓名);fgets(name,50,stdin);方法二scanf 格式串里加空格scanf(%d ,age);// 注意 %d 后面有空格这个空格告诉 scanf「把后面的空白字符包括换行符也吃掉。」但这个方法有个缺点scanf 会一直等待直到遇到非空白字符才停止有时候反而让程序卡住。方法三用循环清空缓冲区最稳健scanf(%d,age);while(getchar()!\n);// 一直读直到遇到换行符不管缓冲区里残留了多少垃圾一行代码全部清空。方法四不用 scanf用 fgets sscanf推荐charinput[100];fgets(input,sizeof(input),stdin);// 读整行sscanf(input,%d,age);// 从行里解析数字这是最推荐的做法——fgets会把整行包括\n都读走不会给后续输入留坑。总结记住一句话scanf 读取完数据后换行符还留在缓冲区里。下一个输入函数会立刻读到它导致程序跳过用户输入。这种问题排查起来很隐蔽因为代码逻辑上看不出任何问题。但只要理解了输入缓冲区的机制就能秒定位秒修复。你还被哪些输入函数的坑绊倒过评论区聊聊。#c语言 #算法 #数据结构