博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
scanf和缓冲区的一切
阅读量:6445 次
发布时间:2019-06-23

本文共 1740 字,大约阅读时间需要 5 分钟。

hot3.png

<!--从缓冲区到输入列表-->

程序获取输入时的过程比我们想象的复杂  我们考虑一个简单粗暴完整的程序
 

#include 
int main(){    int n;    scanf("%d", &n);    printf("%d\n", n);    return 0;}

 

程序运行到scanf()时会停止  请求外界输入

也许你输入了125然后回车了
但事实上 你从键盘上输入的是字符'1''2''5'  还有换行符'\n'  (因为你键入了回车)
在你按回车键之前  字符'1''2''5'都处于一个叫做缓冲区的位置里

回车键是特殊的  它先将字符'\n'添加到缓冲区 随后便清除缓冲区  将其中的所有字符发送到一个叫做输入列表的地方

scanf函数以及其他标准输入函数便会立刻从输入列表中获取内容

 

上述程序按照%d的规则从输入列表中获取字符  它获取了'1''2''5'  并且将其转变为整数125  存入了变量n中

对于那些从输人列表中获取输入的函数  它们并不知道什么是整数  因为整数是编程中的概念  而无论是缓冲区还是输入列表  其中只有字符  所以“获取整数”只是从结果上看的
再多说一点  由于每个字符是一个字节  所以便有了字节流这个术语
我们继续考虑上面的程序  你要求scanf获取一个整数到n中  它完成了
但是并没有结束  因为输入列表并不干净  回车符'\n'仍然留在输入列表中

 

所以如果程序如下

 

#include 
int main(){    int n;    char ch;    scanf("%d", &n);    printf("%d", n);    scanf("%c", &ch);    //! 不会停止等待    printf("%c", ch);    return 0;}

我们仍然键入125并且回车  那么第二个scanf将不会给你输入的机会  因为缓冲区中剩余的'\n'已经足够填饱ch的肚子

 

 

 

再考虑下一个程序

 

#include 
int main(){    int n;    char ch1, ch2;    scanf("%c%d%c", &ch1, &n, &ch2);    printf("ch1 = %c\n", ch1);    printf("n = %d\n", n);    printf("ch2 = %c\n", ch2);    return 0;}

我们的键入仍然是125回车

结果是ch1 == '1'  n == 25  ch2 == '\n'
格式说明符对于scanf是十分重要的   它便是“规则” 告诉scanf如何从输入列表中获取字符 并且如何做转换
时刻记住输入列表中的内容全是字符  规律就会十分容易
还有需要注意的是  尽管输入列表中的内容都是字符  但是字符还有分类  比如空白符  数字字符  字母字符等
 

 

%d 忽略前置空白符  获取连续数字字符 直到遇上非数字字符或者输入列表尾为止

但是如果忽略到空白符之后遇到的时非数字字符 那么就直接结束
获取前的输入列表
' '  ' '  ' '  'k'  'o'  'w'  '\n'
获取后
'k'  'o'  'w'  '\n'

 

%f 这个比较复杂 但是我们只要明白从何时开始 到何时为止即可

假如输入列表是这样
' '  ' '  '2'  '.'  '5'  '.'  '2'  '1'  '4'  'f'  'g'  '\n'
那么%f获取后 列表变为
'.'  '2'  '1'  '4'  'f'  'g'  '\n'

 

 

%c 直接获取一个字符到目标变量 “看见什么吃什么”

由于所有输入函数都共享同一个输入列表  所以在整数和字符的混合输入中可能出错
如果你不清楚在获取一个整数以后的下一个获取是否为字符 加上下面的语句是最保险的
while(getchar() != '\n') continue;
它将清除输入列表
 

 

 

 

尽管是写给初学者的  也有点太累赘了

反正我是绝对耐不下性子读完别人写的这么长的博客 (除非像我说得这么清楚明白  呵呵哒)

 

 

转载于:https://my.oschina.net/u/1780798/blog/372014

你可能感兴趣的文章
Virtualbox 虚拟机网络不通
查看>>
java概念基础笔记整理
查看>>
self parent $this关键字分析--PHP
查看>>
CC_UNUSED_PARAM 宏含义的解释
查看>>
leetcode124二叉树最大路径和
查看>>
AngularJS笔记整理 内置指令与自定义指令
查看>>
学习OpenCV——BOW特征提取函数(特征点篇)
查看>>
shell与正则表达式
查看>>
第三篇:白话tornado源码之请求来了
查看>>
10分钟搞定支付宝和微信支付的各种填坑
查看>>
表示数值的字符串
查看>>
JQUERY AJAX请求
查看>>
html css 伪样式
查看>>
超级账本Fabric区块链用弹珠游戏Marbles 部署
查看>>
网易星球增加网易云音乐任务,将用户流量变现是正确的做法
查看>>
最强面试题汇总:BAT最新前端题出炉,碰到技术HR这些题必考!
查看>>
自定义View之IndexView进度条(二)
查看>>
牢补基础,话说Service那点事
查看>>
云计算固然好 但挑战依然存在
查看>>
云服务器 ECS 最佳实践:借助于实例 RAM 角色访问其它云产品 API
查看>>