scanf 与 缓冲区 之间的 “小秘密“

一、scanf

(一)语法

scanf("格式控制",地址表列);

scanf("a = %d");  
   a.普通字符    --- 原样输入  
   b.占位符      --- 将从键盘输入的数据 转换成指定的格式 

1.格式控制字符

    整型 
   %d  --- 转换为 有符号 十进制形式
   %u  --- 转换为 无符号 十进制形式
   %o  --- 转换为 八进制形式
   %x  --- 转换为 十六进制形式
   %X  --- 转换为 十六进制形式 a b c d e f以大写形式输出
                             
   浮点型
   %f  --- 转换为 十进制形式的小数,输出时默认保留6位小数,不足6位 补0

      输入的时候 ,这里要做到精确匹配 
      %f --- float 
      %lf --- double 
      %Lf --- long double
      %ld   --- long 
      %lld  --- long long
   %e  --- 转换为 科学计数法的形式 
           %E  指数形式中e 变成 大写 E 
   %g  --- 以 一种 更简洁的方式输出,同时不会输出无意义的0
  
   字符型
   %c  --- 转换为字符形式输出 
   %s  --- 转换为字符串形式输出 
   

2.地址表列 

   int a; 
   scanf("a = %d",&a); 
     

3.辅助控制符

%md  
      m   //数据宽度 ---输入宽度

%7.2f // 输出宽度为7,保留两位小数 
       
      注意:
   1. scanf 格式控制字符串中 尽量不出现 普通字符,一般只写 占位符 
   2. scanf 的地址列表中,一定是有效的地址 
   3. scanf 输入结束的条件(匹配结束的条件)

int a,b=0;
scanf("%d%d",&a,&b);

如果你输入一个数比如(1234),scanf不会把它分割而只会把它当作输入的第一个数。

(二)scanf 读取结束条件

1)遇到与格式说明符不匹配的字符
例如,如果格式字符串是 "%d" 但输入是 "abc",则 scanf 将无法读取到整数,并立即返回。
“abc”会留在缓冲区供后续读取。
2)读取到足够的数据项
3)遇到文件结束符
 Unix/Linux 系统中通常是 Ctrl+D,在 Windows 系统中通常是 Ctrl+Z 后跟回车键。
4)遇到空白符(空格,换行,tab)匹配结束

(三) 格式控制中如果出现空白符

表示 可以匹配多个空白符
注意 空白符 不要出现在格式控制末尾,因为他会一直读取,直到非空白字符的出现,也就是空白符不能结束读取了。

(四)scanf 函数读取时遵循的规则:

1.自动跳过前导空白:

在读取任何非字符串类型的数据(如整数、浮点数等)之前,
scanf 会自动跳过输入缓冲区中的任何前导空白字符(空格、制表符、换行符等)。
读取数据:根据格式说明符,scanf 会从输入缓冲区中读取相应的数据。

2.处理尾随空白:

如果格式字符串中的某个格式说明符后面紧跟一个或多个空白字符(空格、制表符等),
则 scanf 在读取完该数据项后,会尝试读取并丢弃输入缓冲区中的这些尾随空白字符。
但是,请注意,scanf 只有在遇到非空白字符时才会停止读取并返回。


二、缓冲区

(一)缓冲区的作用

缓冲区:stdin 、stdout、 stderr 都有缓冲区。


1.临时存储:

缓冲区是用于临时存储从输入设备(如键盘)读取的数据的内存区域。
对于标准输入(stdin),C语言会提供缓冲区来存储用户输入的字符。

2.提高效率:

使用缓冲区可以减少程序和输入设备之间的交互次数,
因为数据可以首先被读取到缓冲区,然后程序再从缓冲区中批量读取数据,这比逐个字符地从输入设备读取数据要高效。

3.格式化输入:

缓冲区允许 scanf 这样的函数在读取输入时执行格式化输入,它会从缓冲区中提取数据并将其转换为指定的类型(如整数、浮点数等)。

(二)为什么使用scanf时要清除缓冲区

因为在缓冲区的数据会影响下一次读取,所以必须要清除缓冲区的数据

常用的清除缓冲区的方法

1、while(getchar() !='\n');

2、char buffer[100];
fgets(buffer,sizeof(buffer),stdin);

3、scanf("%*s");


(三)缓冲区与scanf的关系


1.读取数据:

scanf 从标准输入的缓冲区中读取格式化的输入。
当用户输入数据并按下回车键时,这些数据被存储在缓冲区中,scanf 会从缓冲区中读取并解析这些数据。

2.处理空白字符:

scanf 默认使用空白字符(空格、制表符、换行符等)作为分隔符,来确定输入数据的界限。
它会从缓冲区中跳过这些空白字符,从而分隔不同的输入项。

3.返回读取项的数量:

scanf 返回成功匹配并读取的输入项的数量。
如果输入数据在缓冲区中不符合预期格式,scanf 可能无法读取所有预期的输入项。

4.残留数据:

如果用户的输入不完全符合 scanf 的格式字符串,一些输入数据可能会残留在缓冲区中,导致后续的输入读取操作可能无法正确执行。

5.清除缓冲区:

当 scanf 未能正确读取输入时,通常需要清除缓冲区,以防止残留数据影响后续的读取。
这可以通过读取并丢弃缓冲区中的剩余字符直到换行符来实现。


(四)缓冲区和回车键:

我们可能时常有疑问,为什么在使用scanf函数输入数据时,最后都要敲击一下回车键,数据才能被写入,程序才运行。

我们已知从键盘输入进去的数据是先进入输入缓冲区的,那么缓冲区和回车键到底是一个什么关系呢?


首先我们要了解行缓冲
标准输入(stdin)通常是行缓冲的。(从键盘输入进去的,就是标准输入)
这意味着输入被存储在缓冲区中,直到遇到换行符(\n)或缓冲区满了,这时缓冲区中的内容会被发送给程序。

其次就是缓冲区的刷新:
当用户按下回车键时,缓冲区中累积的字符(包括换行符)会被刷新(即传递给程序处理)。

最后才是程序读取
程序通过调用如 scanf、getchar 等输入函数从标准输入读取数据。
这些函数从缓冲区中读取数据,直到换行符,换行符通常不会被读取到程序变量中。

至于为什么使用回车键刷新跟早期打字机习惯有关。打字机有一个“回车”动作,它的作用是将纸张卷回起始位置,准备下一行的打字。所以我们就沿用了回车键刷新数据、换行这一习惯。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值