问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

C语言scanf函数输入时键盘缓冲区\n的问题385

发布网友 发布时间:2023-11-21 08:00

我来回答

3个回答

热心网友 时间:2024-01-19 05:59

你首先要明白,从键盘读入键盘缓冲区(buffer)的数据都是以ASCII码存储的(包括回车)。
程序1
#include "stdio.h"

void main()
{
char a;
char b;
scanf("%d",&a);
scanf("%d",&b);
printf("%d %d",a,b);
}

键盘输入
97<回车>
第一次回车后,buffer中的ASCII:39h,37h,0AH(0A是换行的ASCII), scanf会根据格式字符串中的第一个%d对buffer按字节顺序读取,当读取到0A时,认为%d型的数据结束,此时把已经读取到的39h,37h依据%d转为整型数据97存储在字符型变量a中。(这里是除去了扫描截止点0AH)
此时buffer中已经无任何数据了。

96<回车>
第二次回车后,按同样的流程,scanf会根据格式字符串中的第二个%d对buffer按字节顺序读取。最终b得到96.
此时buffer中已经无任何数据了。
输出
97 96

程序2
#include "stdio.h"

void main()
{
char a;
char b;
scanf("%c",&a);
scanf("%c",&b);
printf("%d %d",a,b);
}

键盘输入
9<回车>buffer:39H,0AH
因为scanf会按照第一个%c格式扫描buffer(只扫描一个字节就结束),然后把扫描到的39H直接送到变量a(当以%d格式读出来时,39H就是57)
此时,buffer中只有:0AH。
然后,scanft又遇到第二个%c,继续扫描buffer,得到0aH并送入变量b.
此时buffer中已经无任何数据了

输出
57 10

程序3
#include "stdio.h"

void main()
{
char a[100];
char b[100];
scanf("%s",a);
scanf("%s",b);
printf("%s %s",a,b);
}

键盘输入
abc<回车>
第一次回车后,buffer:61H,62H,63H,0AH。
scanf会按照%s的格式对buffer按字节顺序扫描,当扫描到0AH时,结束扫描(按照%s的要求,空格20H也是扫描结束点)。
然后把扫描到的(除去最后一个判断扫描截至的字节0AH)数据直接送入以a为起始地址的字符串。
此时,buffer无任何数据了。

def<回车>
第二次回车后,buffer:65H,66H,67H,0AH.扫描的流程与上面的完全一致。
输出
abc def

程序4
#include <stdio.h>
void main()
{
int i;
char j;
for(i=0;i<2;i++)
scanf("%c",&j);/*注意这里%前没有空格*/
printf("%d",j);
}

键盘输入
1<回车>,
这里scanf执行了两次(i==0时,与i==1时),而且每次都是想对j赋值。
第一次scanf,按%c的要求,只扫描buffer中的一个字节,但是buffer中并不数据,于是要求键盘输入数据到buffer,此时的1<回车>代表向buffer中输入了:31H,0AH。
然后按%c的要求,只扫描buffer中的一个字节:31h,并将它直接送入变量j.
此时,buffer中还留下:0AH。

第二次scanf要求键盘输入数据,按%c的要求,只扫描buffer中的一个字节:0Ah,并将它直接送入变量j.
此时,buffer无数据了。

最后,你用%d格式输出j的值(0AH换成整型就是10)

输出
10

程序5
#include <stdio.h>
void main()
{
int i;
char j;
for(i=0;i<2;i++)
scanf(" %c",&j);/*注意这里%前有一个空格*/
printf("%d",j);
}
1<回车>2<enter>的情况:
scanf会按照格式控制字符串的要求,顺序扫描buffer.
但是你其中有一个空格,这个很特殊,我也是第一次发现这个问题(一般我都不会在scanf中加入任何常量字符)

我测试了一下:我发现这个空格有吸收回车(0AH)和空格(20H)的“神奇功效”,吸收之后再要求buffer给一个字节,直到这个字节不是0AH或者 20H,此时把这个字节交给下一个格式字串。

第一次循环时遇到格式字串空格,就扫描buffer中的一个字节,但是buffer中无数据,要求从键盘输入数据:1〈回车〉,buffer中有数据了——31H,0AH。再读取到字节31H,scanf发现这个并不是0AH/20H,就把这个字节31H交给格式字符%c处理。
循环结束,此时buffer里面还有:0AH.

第二次循环时遇到格式字串空格,就扫描buffer中的一个字节——0AH,发现是0AH/20H,于是就要求buffer再来一个字节。此时buffer里面已经没有数据了,要求键盘输入:2<enter>.
buffer中有数据了——32H,0AH。于是再读一个字节31H,scanf发现这个并不是0AH/20H,就把这个字节32H交给格式字符%c处理(j最终得到32H)。
循环结束,此时buffer里面还有:0AH.

这里有一篇关于Printf的帖子:http://blog.csdn.net/arong1234/archive/2008/05/18/2456455.aspx

程序6
#include "stdio.h"

void main()
{
int a;
int b;
scanf("%c",&a);
scanf("%c",&b);
printf("%d %d",a,b);
}

键盘输入
1<回车>

问题5:

你的编译器VC认为%d数据应该是4个字节,但是你采用的是%c读数据,
scanf("%c",&a);此句读到的是1的ascii码:31h.然后把31H直接送入地址&a(而并没有改写a的三个高字节地址)。
scanf("%c",&b);同理。
你可以用printf("a=%x,b=%x\n",a,b);来验证我说的。它们的最低字节肯定是31H,0AH。

PS1:
当你把 int a;int b;放在main()外进行定义时,a,b的初值就是0。此时你会得到正确的结果。
当你把 int a;int b;放在main()内进行定义时,a,b不会被初始化(它们的三个三个高字节地址的内容是不确定的),你就会得到上面错误的结果。(定义的动态变量都不会被初始化,静态变量会被初始化为0)

PS2:以下也是不正确的用法。
char c;
scanf("%d",&c);/当你用%d给c赋值时,会对从&c开始的连续4个字节进行赋值。当从buffer得到的值是在一个字节范围内(-128~127),下面是可以正常输出的。但是不管怎样,这样做是很危险的——越界。
printf("%d",c);
=================请你测试下这个程序========================
#include "stdio.h"
void main()
{
char c[4],i=4;
scanf("%d",c);/*请输入258<回车>*/

while(i-->0)
printf("%02x ",c[i]);
printf("\n");
}/*如果得到的结果是00 00 00 01 02就说明我的结论是正确的(258的转为16进制数就是00 00 01 02H,然后scanf会把这个数放入以c为起始地址的)

================以下程序也是======================
#include "stdio.h"
void main()
{
char c,i=4;
char *p=&c;
scanf("%d",&c);/*请输入258<回车>*/

while(i-->0)
printf("%02x ",p[i]);
printf("\n");
}

热心网友 时间:2024-01-19 06:00

你忽略了一个问题,就是scanf的格式控制符的用处。%d只接受整数的输入,%c和%s可以接受字符的输入,其中也包括\n等转义字符。因此“scanf输入遇到空格、跳格、回车才会从缓冲区往变量送字符”不是绝对的。清楚了%c %s可以接受字符,问题就解决了。
至于程序6,我不用VC不清楚,但gcc是可以通过的

热心网友 时间:2024-01-19 06:00

getchar 和 %c 格式 涉及 '\n',常使初学者困扰。
清除缓冲区残存信息其实很简单:
fflush(stdin);
就可以了,这样,后面的读就不受前面的影响。

键入数据的格式应当与输入语句格式相配:
char a; 相当1字节整型。所以可以用%d格式输入。用%d格式,默认分隔符是所有的 white-spaces

用%c格式输入,则按ASCII字符考虑。无分隔符。必要时用fflush(stdin);清除缓冲区

%s 是 字符串格式,默认分隔符是所有的 white-spaces,输入后自动有结束符"\0".
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
小米平板6Max没有网络怎么办 ...wifi和4G网络我都试过都现实吗没有网络。刚买的是正品没有刷机_百度... 2023年淘宝双11招商规则 淘宝国庆狂欢季招商规则及玩法 淘宝年货买不停招商规则 淘宝超来电活动招商规则 ZIP转换成RAR怎么转换? 衢州醉根艺品有限公司怎么样? 徐谷青主要业绩 徐谷青人物介绍 158821是不是轴对称图形 疾风之刃如何设置自己心情在名字上面 怎么在网页上查询自己的疾风之刃游戏角色7 疾风之刃有没有因为id名字太奇葩而被封的 环保部什么时间取消生物颗粒锅炉·有人议论说2017年前取消.也有人说... 什么叫2B青年?2 在淘宝网上看到好多卖公务员考试一本通的,不知道可不可靠,麻烦知情人帮... 国家允不允许燃烧生物质。 1250KVA干式变压器的损耗功率是多少,怎么计算!型号SCB10-1250/10... 高水平运动员到大学里还继续训练吗? 同在河北省的事业单位为什么待遇不一样,有的单位发的年底前很多...1 怎么快速注销? 河北省建筑科学研究院怎么样啊,待遇是怎样的啊,要本科生吗?男...27 wxid开头的如何添加好友? 淮安市海天毛巾有限公司怎么样? 淮安市远洋毛巾有限公司怎么样? 淮安欧航毛巾有限公司怎么样? 淮安雅信毛巾有限公司怎么样? C语言里面如何两次用scanf函数获取键盘输入的字符1 快板上什么油1 30岁的女人补什么牌子的钙片好207 成人补钙什么牌子最好?求推荐46 哪些字带有贵重、珍宝的意思? 在国企单位当一名实习生有哪些需要注意的地方?6 2B青年 是什么意思155 淮安市康特毛巾有限公司怎么样? 改过一次,就只能等一年后再进行第二次修改了吧? 道不同不相为谋,志不同不相为友,是说的什么意思呢?21 道不同不相为谋,志不同不相为友是什么意思747 人而无信不知其可的意思是什么?????2168 怎么在一年内修改两次 怎么一年改两次 中药材诚实通怎么改银行卡 人而无信不知其可的意思是什么?????2168 一年内只能改一次吗? 怎么正确开摩托车(125)?63 wxid开头的怎么加好友? wxid开头的如何添加好友? 古筝小快板怎么会练得更熟练15 wxid怎么加对方?