scanf的阻塞和缓冲区

1.缓冲区:

键盘(标准输入)->缓冲区->内存

2.scanf的执行逻辑:

(1)sizof依照输入的顺序依次读取变量:

a.依据打印类型的不同来判断是否从缓冲区读取数据

b.依照输入格式来判断,例:

scanf("=+%c",&a)

在输入时需要  =+(数据)

c.碰到不符合输入格式的数据,会跳过之后的数据

d.scanf和阻塞:

如果缓冲区无数据,scanf会等待输入数据,即阻塞(IO),反正 NIO(Non-Blocking IO)

3.常见问题:

(1)scanf和\n:

scanf("%d\n",&a);

a.问题:在输入第一个数据之后,编译器提示输入第二个数据,输入后发现a被赋予的是第一个值

b.原因:2.(b)和2.(d):

回车符代表\r和\n(好像是,没找到准确回答),再输入第一个数据之后,再按回车,刚好符合scanf的输入格式,即清空了缓冲区,接着发生了阻塞,所以此现象会发生在任何类型

c.其他:该问题会联想到另一现象"整形,字符串,浮点型会忽略前导空白符,而char类型不会",区别于此问题,在于该问题是scanf的输入格式契合:

(1)另一现象:除char类型外,在输入操作中,首次输入空白符,会一直提示再次输入,而char:

(2):前导空白符:从字符串的开头到第一个非空白符(回车符,制表符,空格符等)

(2):scanf的非法输入和循环:

a.原因:对于上图,scanf要求读取到十进制的整形,而标准输入为  `  ,所以scanf读取到零个数据,返回0,并且缓冲区中第一次输入的 `  仍然存在,所以每一次循环都不会发生阻塞,每一次都如此循环

b.解决方法:

(1)用 flush(stdin) 或  rewind(stdin):

用上述两个函数来清楚缓冲区(全部清除)

flush(stdin)在vs2015之后的vs版本中不可用,可用rewind(stdin)代替,或者使用getchar(只能接受一个字符)

getchar:

(2)用scanf("%*[]"):

(1)*代表不赋值,^代表跳过,[]为集合,第一个scanf的输入格式带来的效果:会清除缓冲区内非数字,然后第二个scanf可以正常输入,达到某些情况下本只想要获得数字而意外输入非法字符带来的错误(如用程序计算金额)

并且:该输入格式读取的是整个字符串,所以应对以下输入格式也可以:

(2)

scanf("%[a-zA-Z]"),表示除了二十六个字母的大小写之外其他数据全部忽略

scanf("%n[]")n代表至多读取n个字符

scanf("%*[^\n]")表示除换行符,读入全部字符

scanf("%*[^\n]%c"),%c会匹配并储存一个字符,可以起到跳过行尾换行符的作用(个人理解是%c于的格式相对应)

(3)

在字符串的输入中,碰到空白符也影响输入,上图若改为scanf(%s),会导致数组arr1的长度始终为0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值