scanf与cout的误区:探究其内部的机制 目录引入误区Ⅰscanf内的\n没有换行的作用Ⅱ空格也算一个字符Ⅲ按下enter后会添加‘\n’在末尾Ⅳ输入过后剩余的字符不会丢弃Ⅴscanf内部的空白作用Ⅵcin的输入也会跳过空白字符Ⅶendl的作用全程过程详解总结小测答案误区Ⅷ缓冲区有可用的不会再读取引入#define _CRT_SECURE_NO_WARNINGS #include iostream #include cstdio using namespace std; int main() { char a, b; scanf(%c%c, a, b); printf(%c %c\n, a, b); scanf(%c %c, a, b); printf(%c %c\n, a, b); cin a b; cout \n endl; cout a b endl; return 0; }如果每次输入都输入“a c”结果是怎么样的①a c//输入 a c a c//输入 a c a c//输入 a c②a c//输入 a a c//输入 a c a c//输入 a c③a c//输入 a a c//输入 c a a c//输入 a c④a c//输入 a a c//输入 c a a c//输入 c a误区答案是④这个情景本来是我今天学c测试不同的输入输出方式的区别我一开始幻想的结果是②的类型可以运行后发现差别有点大而我又不懂其中的机制干脆就了解一下。Ⅰscanf内的\n没有换行的作用这是我一开始犯的错误我记录一下以免再犯错这点本身没什么可讲的了解就可以了。Ⅱ空格也算一个字符在第一次输入“a c”时候会依次读出‘a’, ,c,\n这四个字符至于为什么最后会有一个‘\n’后续会讲所以第一次的输出会是‘a’‘ ’‘\n’(这个\n是printf里带有的)只有%c还有%[ ]扫描集会把\n、空格、Tab 这类空白字符当成普通数据读入变量。格式符是否读取空白空格 /\n%c✅会读取空白就是普通字符%d/%f❌自动跳过空白不读取空白%s❌自动跳过开头空白遇到空白结束空白不读入%[ ]扫描集可以配置能接收换行 / 空格Ⅲ按下enter后会添加‘\n’在末尾对于操作系统控制台黑框按下回车产生\n是告诉操作系统这一行输入完毕可以把整行数据交给程序。你敲一堆字符不按回车scanf是拿不到任何字符的。 从控制台设备角度\n触发行输入提交。但是❗\n本身并没有 “结束输入” 的语义它只是一个普通字符留在缓冲区里面不会自动消失。举例子 输入ab回车 缓冲区ab\n\n只是把这一行放行给程序它自己也留在缓冲区队列里作为一个实实在在的字符。对于 scanf 函数本身❌\n不代表 scanf 读取结束%d、%f读到数字结束就完成读取后面的\n仅仅留在缓冲区不会终止函数。%c把\n当成普通字符直接读入变量。cchar a,b; scanf(%c%c, a,b);输入1然后回车 缓冲区1,\na 拿到1b 拿到\nscanf 直接执行完毕不需要你继续输入。 这里\n被当成第二个有效字符不是结束标记是被读取的数据。Ⅳ输入过后剩余的字符不会丢弃会进入缓冲区用于后续的读取第一次输入输出后就还剩下‘c’‘\n’(enter产生的)留在了缓冲区⚠️缓冲区就相当于一个队列字符排队先进先出。Ⅴscanf内部的空白作用scanf(%c %c)【中间带空格】空格会吞噬空白读完第一个字符之后会把后面所有空白吃掉再等待下一个有效字符。第二步scanf(%c %c, a, b);格式字符串%c %c两个%c中间写了一个空格。 scanf 格式串内的空格规则消耗任意数量空白字符空格、Tab、\n一直读到不是空白才停止。执行分步读到格式串第一个%c准备读取字符。遇见格式串里的空格程序去缓冲区跳过所有空白。 缓冲区队首现在是c——c不是空白停止跳过。第一个%c读取字符c赋值给a现在a c。继续往后走格式串又遇到一个空格再次触发吃掉所有空白。 现在缓冲区队列剩下[\n]就是你敲的回车。\n属于空白被空格规则消耗完毕缓冲区空了。来到第二个%c缓冲区已经空了scanf 阻塞等待你键盘输入新字符目前缓冲区域还有[ ,c,\nenter产生]Ⅵcin的输入也会跳过空白字符cin 对于 char自动跳过开头所有空白字符。 缓冲区队列现在[ , c, \n]cin a跳过开头空格读取c存入a队列剩余[\n]cin b缓冲区队首是\n属于空白跳过缓冲区空阻塞等待键盘输入。Ⅶendl的作用\n输出 1 个换行endl输出 1 个换行并且强制刷新缓冲区cout \n endl;等于连续输出两次换行 输出两个换行字符中间就空出来一整行空白。代码输出行为cout \n;输出 1 次换行cout endl;输出 1 次换行 刷新 IO 缓冲区所以\n endl两个换行这就是看见一大段空隙的根源。全程过程详解运行环境VS Windows 控制台文本模式回车送入\n。第 1 段第一次输入a c回车键盘输入texta c缓冲区进入texta 空格 c \n第 2 段执行第一个scanf(%c%c, a, b);%c%c中间没有空格第一个%c读a第二个%c读后面的空格所以cppa a; b ;缓冲区剩余textc \n执行cppprintf(%c %c\n, a, b);输出texta注意这里是a加一个空格再换行。第 3 段执行第二个scanf(%c %c, a, b);格式串是c%c %c两个%c中间有一个空格。这个空格的作用是在读取第二个%c之前先吃掉缓冲区里所有连续空白。当前缓冲区textc \n执行过程第一个%c直接读队首字符c所以a c缓冲区剩余\n格式串遇到中间的空格开始清理空白\n属于空白被清理掉缓冲区变空第二个%c需要新字符程序等待输入注意text第二个 %c 不会读刚才剩下的那个 \n因为格式串中间的空格已经先把\n吃掉了。第 4 段第二次输入a c回车你输入texta c缓冲区进入新字符texta 空格 c \n第二个%c现在读取队首cppb a;所以当前变量是cppa c; b a;执行cppprintf(%c %c\n, a, b);输出textc a第 5 段缓冲区现在还剩什么刚才第二次输入是texta 空格 c \n其中a已经被第二个%c读走所以缓冲区剩余text空格 c \n第 6 段执行cin a b;cin 读取char时会自动跳过开头空白。当前缓冲区text空格 c \n执行过程cin a先跳过空格然后读取c所以a c缓冲区剩余\ncin b看到队首是\n也跳过缓冲区空程序等待输入注意text这里 a 被更新成了 c第 7 段第三次输入a c回车你输入texta c缓冲区进入texta 空格 c \ncin b读取队首字符cppb a;所以现在变量变成cppa c; b a;不是a c。这里是之前文本最关键的错误。第 8 段执行输出cppcout \n endl; cout a b endl;先看第一句cppcout \n endl;它会输出text一个 \n 再加一个 endl也就是连续两次换行。所以控制台会先空出一行。然后执行cppcout a b endl;当前cppa c; b a;所以输出textc a不是a c。最终控制台完整结果texta c a a c c a a c c a总结图标关键点说明scanf(%c%c)无空格原样读取空格、\n全部当作普通字符存入变量scanf(%c %c)中间带空格读完第一个字符在读下一个 % c 之前吞噬全部空白\n不会被读到变量输入缓冲区先进先出队列键盘输入回车往队列存入\n%d、%f不会拿走\n会遗留⚠️经典坑%d之后直接跟%c%c会直接读取遗留的\n程序不等输入✅修复方案%c格式里前面加空格scanf( %c, ch);读取前自动吃掉空白cout \n endl;\n换行endl也换行 刷新两个一起写 两次换行产生多余空白行✨cin ch自动跳过所有空白空格、\n、tab不需要手动加空格小测阅读下面代码假设运行在 Windows 环境按下 Enter 会向输入缓冲区存入\n缓冲区先进先出。c#include stdio.h int main(void) { char x, y; scanf(%c%c, x, y); printf(%c %c\n, x, y); scanf(%c %c, x, y); printf(%c %c\n, x, y); return 0; }用户键盘操作 第一行输入m nm 和 n 之间 3 个空格回车 第二行输入s t回车请你作答第一次 printf 输出什么变量 x、y 分别是什么执行完第一个 scanf 之后输入缓冲区剩余哪些字符第二个 scanf 内部每一步缓冲区如何变化第二次 printf 输出什么1.m空格 m 空格 空格空格n\n2.先读走一个空格 再删去一个空格 再读走n 在最后面追加s空格t\n3.空n答案输入第一行m nm 后面 3 个空格 回车 缓冲区初始[m, , , ,n,\n]问题 1第一次printf输出m变量xmy 第一个 scanf 执行完缓冲区剩余[ , ,n,\n]误区Ⅷ缓冲区有可用的不会再读取问题 2第二个scanf(%c %c, x, y);完整过程起始缓冲区[ , ,n,\n]第一个%c读取队首空格x 缓冲区变为[ ,n,\n]遇到格式串中间的空格吞噬所有连续空白吃掉剩下的空格缓冲区变为[n,\n]第二个%c读取nyn缓冲区变为[\n]缓冲区里有n可用程序不会阻塞等待输入第二行输入s t完全不会被读取。//实测的时候不会让你再输入了问题 3第二次printf(%c %c\n,x,y);x yn输出n解释打印 x (空格)printf 自带的分隔空格再打印 n。肉眼看先一个空格再一个空格再字母 n。感谢观看