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]);
}

相关内容

热门资讯

在大吉订购APP订购交易亏损被...   近期,不少投资者反映在“大吉订购App”上投资白银、铂金等商品遭遇严重亏损。该平台宣称提供现货订...
铂银壹号APP商品订购交易亏损...   许多中小投资者误以为网上的“商品现货订购”是合规合法的理财渠道,殊不知这背后隐藏着巨大的合规风险...
兴鑫淘金APP贵金属订购交易亏...   白银、贵金属或其他商品类投资,除国家批准的正规期货交易场所及持牌期货公司外,市面上大量第三方交易...
铂银掘金APP无资质的违规平台...   铂银掘金等平台的投资者,往往是被“注册送现金”“充值返现券”“首单免亏”等广告话术吸引,进而下载...
八方淘金APP订购交易不合规,...   “八方淘金APP”“铂银掘金APP”“铂银壹号APP”等软件被指以“现货订购”为名,实际采用高杠...
在指尖订购APP订购商品亏损被...   指尖订购APP这类平台,表面是“订购交易”,实则是披着电商外衣的非法期货陷阱。绝大多数投资者被蒙...
在犀贝易购APP做商品订购交易...   市面上打着“现货投资”“贵金属交易”旗号的APP并不少,但真正合规、受监管的平台并不多。犀贝易购...
易达淘金APP虚假商品订购交易...   易达淘金APP存在严重的虚假宣传与违规交易行为。该平台打着“商品订购”的旗号,实则通过不合规的交...
大浪淘金APP白银订购亏损被骗...   大浪淘金APP最隐蔽的套路,在于其完全封闭的内盘交易系统。表面上,它宣称与国际贵金属市场接轨;实...
一品好购APP上订购白银出现亏...   一品好购APP原名“一品订购”,运营方为上海宝智未来信息技术有限公司。近期不少投资者反映在该平台...
九州订购APP贵金属订购投资骗...   九州订购APP正通过抖.音、快手、今日头条等平台大量投放投资广告,用“5元起投”“充值返现”“0...
坚锅淘金APP交易软件并不正规...   当前,市面上大量所谓的“现货商城订购”交易软件,早已偏离了正常的实物商品买卖,演变为高杠杆、高手...
斗金订购APP贵金属期货交易骗...   斗金订购APP的投资者往往被铺天盖地的广告宣传所诱导——注册即送现金、充值返现券等看似诱人的福利...
警惕!云启购APP违规经营,披...   "5元起投、充值返现、稳赚不赔"——这些诱人的广告语背后,可能是一个精心设计的金融陷阱。  近期...
量子淘金APP贵金属投资不合规...   "4元起投""充值返券""月入过万"——这些极具诱惑力的广告语在短视频平台、社交软件上铺天盖地。...
鑫汇智投APP贵金属商品订购骗...   鑫汇智投APP非法期货投资骗局,受害者在投资过程中根本不懂交易,也不去研究和验证这个平台是否正规...
矅光智策APP平台违规经营非法...   矅光智策APP对外宣称是“商城订购”“现货交易”,但查询其经营范围,并未显示具备开展现货期货交易...
黄金珠宝怎么选?内侧刻字都代表... 潮新闻客户端 记者 马焱 通讯员 任倩影 9月8日下午,“云游杭州 乐购金秋”——“浙城·浙放心”活...
原创 冰... 最近全球国债市场正在上演魔幻一幕: 美债、日债、欧债遭遇猛烈抛售,收益率冲到几十年新高,美国财政部都...
日韩股市开盘表现分化 上证报中国证券网讯 9月9日,日韩股市开盘表现分化,韩国综合指数开盘上涨0.26%,报6972.87...