C语言scanf函数的匹配和缓冲机制
创始人
2025-05-31 12:44:09
0

在这里插入图片描述

文章目录

    • scanf函数的数据匹配规则
    • 缓冲区的三种类型
      • 举例
    • 实战:通过几个问题搞明白缓冲机制
      • 问题 1:两个整型数据之间没有空格?
      • 问题 2:读取字符型数据时会把空格读入吗?
      • 问题 3:字符型数据和整型数据需要空格吗?
      • 问题 4:字符型数据之间的换行?(1)
      • 问题 5:字符型数据之间的换行?(2)
      • 问题 6:两个整型数据之间多个空行?
    • 一切的罪魁祸首:原来是缓冲区还有多余的数据!
      • 方法一:用 getchar() 把换行符吸收掉
      • 方法二:使用 fflush(stdin) 把输入缓冲区刷新一遍
    • 实战:空一行表示输入完毕

scanf函数的数据匹配规则

数据类型匹配规则
整型%d两个数据间的分割符可以是空格符(ASCII=32)、换行符(ASCII=10)、制表符(ASCII=9)
浮点型%f两个数据间的分割符可以是空格符(ASCII=32)、换行符(ASCII=10)、制表符(ASCII=9)
字符串%s以非空白字符开始,以第一个空白字符(空格符、换行符、制表符)结束
字符型%c两个数据间没有分割符,所有字符(包括控制字符)都能匹配

缓冲区的三种类型

缓冲区的三种类型:

  • 全缓冲:在这种情况下,当填满标准 I/O 缓存后才进行实际 I/O 操作。全缓冲的典型代表是对磁盘文件的读写。
  • 行缓冲:在这种情况下,当在输入和输出中遇到换行符时,才执行真正的 I/O 操作。这时,输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的 I/O 操作。典型代表是键盘输入数据,标准输入(stdin)和标准输出(stdout)。
  • 不带缓冲:也就是不进行缓冲,标准出错情况 stderr 是典型代表,这使得出错信息可以直接尽快地显示出来。

以下情况将引发缓冲区的刷新:

  • 缓冲区满时;
  • 行缓冲区遇到换行符 \n;
  • 关闭文件;
  • 使用特定函数刷新缓冲区。

scanf 函数的原理就是行缓冲!大家应该都有经验吧,比如输入一行数据,这些数据并非刚输入完就能被程序读取,还需要你按下回车键才能读取到。不过需要注意,用户最后输入的回车也会储存在缓冲区中。

举例

例子来源C语言输入输出缓冲区:

#include#includeint main() {printf("hello");int i = 0;for (; i < 10; i++) {putchar('a');sleep(1000); // 延时 1 秒钟}return 0;}

运行该程序,等待 10s 后,输出 helloaaaaaaaaaa。

这是由于键盘输入是标准的行缓冲,只有遇到换行符或者程序结束后才会输出到屏幕上

#include
#include
int main() {printf("hello");fflush(stdout);  // 刷新缓冲区,使得hello被强制输出,现在缓冲区什么都没有了int i = 0;for (; i < 10; i++) {putchar('a');sleep(1000); // 延时 1 秒钟}return 0;}

运行该程序,首先输出 hello,等待 10s 后,继续输出 aaaaaaaaaa。这是由于 fflush 刷新了缓冲区,所以会首先输出 hello。

现在用几道题目来解释缓冲机制,顺便加深对匹配规则的理解!

实战:通过几个问题搞明白缓冲机制

问题 1:两个整型数据之间没有空格?

【语句】

scanf("%d%d", &a, &b);

【输入】

1 2

【匹配情况】

a = 1, b = 2

【输入缓冲区分析】请注意,这是当你输入完数据并按下回车键后输入缓冲区里的情况,不能将运行窗口的输入输出混为一谈。它们不是同一个东西!

匹配前:

1 2\n

匹配后:

\n

【结论】连续输入两个数值时,两个数值之间必须有空格,无论 %d 是否紧挨着。scanf 函数就是靠空格、换行等匹配不同的数值,但匹配完后不会将换行符吸收掉。该语句等同于以下语句:

scanf("%d %d", &a, &b);

问题 2:读取字符型数据时会把空格读入吗?

【语句】

scanf("%c%c", &a, &b);

【输入 1】

xy

【匹配情况 1】

a = 'x', b = 'y'

【输入缓冲区分析 1】

  • 匹配前:
xy\n
  • 匹配后:
\n

【输入 2】

x y

【匹配情况 2】

a = 'x', b = ' '

【输入缓冲区分析 2】

  • 匹配前:
x y\n
  • 匹配后:
y\n

如果此时再来一个scanf(“%c%c”, &c, &d),则c = ‘y’, d = ’ '

【结论】开始匹配字符型数据时,scanf 函数不会忽略空格。如果你确实需要空格间隔,需改成:

scanf("%c %c", &a, &b);

问题 3:字符型数据和整型数据需要空格吗?

【语句】

scanf("%d%c", &a, &b);

【输入 1】

11y

【匹配情况 1】

a = 11, b = 'y'

【输入缓冲区分析 1】

  • 匹配前:
11y\n
  • 匹配后:
\n

【输入 2】

11 y

【匹配情况 2】

a = 11, b = ' '

【输入缓冲区分析 2】

  • 匹配前:
11 y\n
  • 匹配后:
y\n

【结论】当匹配完前一个数值后,scanf 函数在给出的格式中发现下一个数据是字符型数据,于是开始匹配字符型数据,此时不会忽略空格。如果你确实需要空格间隔,需改成:

scanf("%d %c", &a, &b);

问题 4:字符型数据之间的换行?(1)

【语句】

scanf("%c%c", &a, &b);

【输入】

x
y

【匹配情况】

a = 'x', b = ' '

【输入缓冲区分析】

  • 匹配前:
x\n
y\n
  • 匹配后:
y\n

【结论】scanf 函数在匹配字符型数据时,不仅匹配空格,还匹配任何字符,包括控制字符。所以字符 b 读入了换行字符 \n。

问题 5:字符型数据之间的换行?(2)

【语句】

scanf("%c", &a);
printf("a=%c\n", a);scanf("%c", &b);
printf("b=%c", b);

【输入 1】

x

【输出 1】然而,当你输入完 a,按下回车,输出 a 的同时,也输出了 b。

a = x
b = 

【输入缓冲区分析 1】

  • 第一次匹配前:
x\n
  • 第一次匹配后,并输出 a 的值为“x”,第二次匹配前:
\n
  • 第二次匹配后,b 匹配到了换行符 \n:

【输入 2】

xy

【输出 2】

a = x
b = y

【输入缓冲区分析 2】

  • 第一次匹配前:
xy\n
  • 第一次匹配后,并输出 a 的值为“x”,第二次匹配前:
y\n
  • 第二次匹配后,b 匹配到了“y”:
\n

问题 6:两个整型数据之间多个空行?

【语句】

scanf("%d%d", &a, &b);

【输入】

1 
(换行)
(换行)
2

【匹配情况】

a = 1, b = 2

【输入缓冲区分析】

第一个匹配前:

1\n

当你按了三次回车、并输入 2 前,其实第一个已经得到了匹配:

\n
\n
\n

第二个匹配前:

\n
\n
\n
2\n

第二个得到匹配后:

\n
\n
\n
\n

【结论】scanf 函数就是靠空格、换行等匹配不同的数值,而且必须严格按照给出的格式进行匹配(比如%d%d必须要两个整数,少一个都不行)。在没有匹配完成之前,无论有多少个空格和换行,都要等待用户输入下一个数据。

一切的罪魁祸首:原来是缓冲区还有多余的数据!

为什么实际的运行情况跟设想的不一样?为什么这个字符变量读到的是换行符?原来一切的罪魁祸首是:缓冲区还有多余的数据!缓冲区并没有设想的那样干净,而是残留了一些不该有的东西!那么如何解决呢?

方法一:用 getchar() 把换行符吸收掉

【语句】

scanf("%c", &a);
printf("a=%c\n", a);
getchar();scanf("%c", &b);
printf("b=%c", b);

【输入和输出】

x
a = x
y
b = y

【输入缓冲区分析】

  • 输入 a,第一次匹配前:
x\n
  • 第一次匹配后,并输出 a 的值为“x”:
\n
  • 执行 getchar,读取了换行符 \n,此时缓冲区为空:

  • 输入 b,第二次匹配前:
y\n
  • 第二次匹配后,b 匹配到了“y”:
\n

方法二:使用 fflush(stdin) 把输入缓冲区刷新一遍

需要注意,fflush 在有些编译器是没有的,它不属于 C 标准。不推荐使用。

【语句】

scanf("%c", &a);
printf("a=%c\n", a);
fflush(stdin); // 清理输入缓冲区scanf("%c", &b);
printf("b=%c", b);

【输入和输出】

输入:x
输出:a = x
输入:y
输出:b = y

【输入缓冲区分析】

  • 输入 a,第一次匹配前:
x\n
  • 第一次匹配后,并输出 a 的值为“x”:
\n
  • 执行 fflush,此时缓冲区为空:

  • 输入 b,第二次匹配前:
y\n
  • 第二次匹配后,b 匹配到了“y”:
\n

实战:空一行表示输入完毕

【描述】每行输入两个字符串,当输入到空行时,表示输入完毕。请输出这些字符串。

【输入实例】

aaa bbb
ccc ddd
eee fff
(该行空行,表示输入完毕)

该输入等价于:

aaa bbb\nccc ddd\neee fff\n\n

当读到只有 \n 的一行时,表示输入完毕。

【输出实例】

aaa bbb
ccc ddd
eee fff

【分析】这题很考验你对输入缓冲区原理的理解。每次检测字符串 A 的第一个字符,若第一个字符是 \n 则停止输入;若不是 \n,则用另一个字符串变量 B 读取剩下的字符串,并将 B 拼接到 A 的后面。除此之外,每读入一行字符串,就要吸收掉最后的 \n。

【题解】

#include 
#include 
using namespace std;int main(){	char word[20][20] = {0};char mean[20][20] = {0};char tmp[20];int i, j;for (i = 0; ; i++){if ((word[i][0] = getchar()) == '\n') //检测第一个字符break;word[i][1] = '\0';scanf("%s", tmp); // 读入 word 的剩余字符 scanf("%s", mean[i]);strcat(word[i], tmp);  // word 的第一个字符与剩余字符拼接在一起 tmp[0] = '\0'; // 清空字符串 getchar();  // 吸收换行符 }for (j = 0; j < i; j++)printf("%s %s\n", word[j], mean[j]);
}

相关内容

热门资讯

香港金融管理局对三家银行采取纪... 北京商报讯(记者 孟凡霞 实习记者 周义力)7月22日,香港金融管理局宣布,根据《打击洗钱及恐怖分子...
原创 突... 美国突然变卦了!就在中美贸易谈判进入关键阶段,美国财长贝森特冷不防抛出新要求——打算在协议里硬塞两条...
深圳新晋13家独角兽企业,福田... 7月18日,2025中国(深圳)独角兽企业大会发布《GEI中国独角兽企业研究报告2025》和《深圳市...
汇划1180亿元!“跨境理财通... 7月21日,记者从人民银行广东省分行获悉,“跨境理财通”自2021年启动以来,极大地促进了粤港澳大湾...
秦洪看盘|热门主线波动不改A股... 来源:澎湃新闻 周二A股市场出现了探底回稳的走势。 早盘由于银行股的疲软,主要股指一度翻绿,升势有受...
股票行情快报:美凯龙(6018... 证券之星消息,截至2025年7月22日收盘,美凯龙(601828)报收于3.07元,上涨0.66%,...
原创 煜... 在全球能源格局加速演变、国内“双碳”目标持续深化的大背景下,电力行业正站在变革的前沿。2025年是“...
星环科技拟港交所上市:年亏损额... 近日,科创板上市公司星环科技(688031.SH)发布公告称,为进一步提高公司综合竞争力,更好地利用...
中国启动水电珠峰水利隧道工程!... 2025年7月,中国雅江集团的成立和雅鲁藏布江下游水电工程的开工,标志着世界水电史迎来新的里程碑。 ...
OpenAI CEO:Deep... 【环球网科技综合报道】7月22日消息,据windowscentral报道称,OpenAI 首席执行官...
国家外汇局贾宁:未来外资配置人... 7月22日,国家外汇管理局国际收支司司长贾宁在国新办新闻发布会上表示,未来外资配置人民币资产仍具有较...
并购 | 深度拆解地方国资收购... 一、交易背景 2023年9月20日晚间,上海雅仕投资发展股份有限公司(以下简称“上海雅仕”)公告称...
21日豆二上涨0.19%,最新... 来源:新浪期货 新浪期货 根据交易所数据,截至7月21日收盘主力合约豆二2509,涨跌+0.19%,...
兴证资管国企红利优选混合发起式... AI基金兴证资管国企红利优选混合发起式A(023169)披露2025年二季报,第二季度基金利润112...
专访新辰商业集团联合创始人及C... 在当前商业环境持续变革的背景下,社区商业正逐步成为商业领域的重要发展方向。新辰商业作为这一领域的后起...
与美国斗了整整七年,中国总结出... 与美国斗了整整七年,中方总结出4句话,想看美国是否吸取了教训 国新办日前召开系列主题新闻发布会,商务...
以“诚”破局,利他共生——稻盛... 在中国民营经济迈向高质量发展的关键阶段,企业呼唤更加坚定的精神信仰与先进的经营哲学。6月8日,稻盛和...
詹记桃酥频现日期乱象,有消费者... 近日,有消费者爆料称,其在连锁中式糕点品牌詹记桃酥(下称“詹记”)门店买到了“未来蛋糕”,门店回应称...
李开复:零一万物AI Agen... 李开复入场做AI Agent智能体。 7月22日消息,零一万物创始人兼CEO李开复博士今天上午宣布,...