您的位置:首页 > 其它

scanf这个函数--论坛里的一个帖子

2011-04-25 23:13 399 查看
原帖地址:http://topic.csdn.net/u/20110423/19/a1e4c5ae-5b44-4e94-8f2c-55f7ba6486de.html

int a;
char b;
printf("请输入a的值");
scanf("%d",&a);
getchar()//假如这里不加getchar,那么后面的输入都直接无效了
printf("请输入b的值:");
scanf("%c",&b);

大家看看这个程序,假如把输入字符放在输入整数之前,那么不用加getchar(),否则必须加getchar(),这到底是怎么回事??

处理空白符的问题,当 scanf 中的输入格式说明符 (Format specifiers) 是 "%c"的时候,那么空白字符 (whitespace) 将会被正常读入,不再起到分隔符的作用。这个时候要注意处理缓冲区中残留的空白符

那为什么将scanf("%c",&b)与scanf("%d",&a)交换过来就不会出现这样的情况,不是也有个换行符在缓冲区中吗??

引用 3 楼 mmothermother 的回复:

那为什么将scanf("%c",&b)与scanf("%d",&a)交换过来就不会出现这样的情况,不是也有个换行符在缓冲区中吗??

当 scanf 中的输入格式说明符 (Format specifiers) 不是 "%c"的时候,那么空白字符 (whitespace) 将起到分隔符的作用。把分隔好的两个数据分别赋值到各自定义好的变量或数组中去,两个数据之间的 whitespace 被从缓冲区读出但是不起任何作用,当然最后一个 '/n' 会被留在缓冲区内,除非用 getchar(); 或 scanf("%c",&ch); 把它读出来。

引用 8 楼 mmothermother 的回复:

引用 6 楼 delphiwcdj 的回复:
引用 3 楼 mmothermother 的回复:

那为什么将scanf("%c",&b)与scanf("%d",&a)交换过来就不会出现这样的情况,不是也有个换行符在缓冲区中吗??

当 scanf 中的输入格式说明符 (Format specifiers) 不是 "%c"的时候,那么空白……

仔细看下6L的解释 注意什么时候把空白字符当成分隔符什么时候不当

想象输入设备(键盘)连接着一个叫“缓冲”的东西,把缓冲认为是一个字符数组。当你的程序执行到scanf时,会从你的缓冲区读东西,如果缓冲区是空的,就阻塞住,等待你从键盘输入。 现在假设你的缓冲区里有: abcd/n1234/n (其中/n是回车符) 执行: scanf("%s",name); 的时候,由于scanf是读数据直到看见空白符(空白符:指空格符、制表符、回车符)就停止的输入函数。所以执行后,把abcd存到了name中。缓冲区于是变成了 /n1234/n 接下来的执行就有问题了,如果遇到了: scanf("%d",&number); 怎么办?因为遇到了回车符,它并不是一个数字,所以应该抛出错误,让程序死掉?不对吧,明明是编程序的你让用户输入完名字回车的(不然怎么提示用户该输入数字了?),怎么能出尔反尔地报错呢? 所以scanf还有一个特性,就是忽略先导的空白符。不管是有几百个回车也好,几万个空格也罢,只要它们连续地出现在缓冲区的开头,就统统忽略他们。然后再读有意义的字符。于是1234被读入number。 回到刚刚,当缓冲区还是: /n1234/n 的时候,如果遇到了: scanf("%c",&sex); 应该怎么办呢?你说,那好办呀,不是说了忽略前导空白符吗?跳过回车读'1'呀! 想法是好的,可这只针对你的程序这一种情况。如果我编写的程序就是统计用户输入了多少个回车呢?缓冲里明明有回车符,却读不出来,你不是忽悠我吗? 所以对scanf来讲跳过前导空白符有个例外,当参数是%c的时候,就把缓冲区的第一个字符返回回去,不管是什么。 这样的设计就有个问题,scanf对不同的参数表现出来的特性不一样。 得承认,这是个缺陷,但不是说这样不好。 这样的设计至少把发现所有字符的机会交给了用户, 设计者这样想: 如果程序员使用了scanf("%c",..),那他就有必要知道这函数能把回车符读出来,至于程序员对回车符感不感兴趣,那就看他了,不感兴趣的话,程序员也一定知道该怎么处理。 回到你的程序里。 当执行scanf("%s",name)的时候,要求你从键盘输入, 于是你输入了"abc",然后“回车”。 缓冲区里自然而然地是: abc/n scanf把abc拿走了,留下了/n,缓冲区里现在就剩下/n 于是,下一个scanf ("%c",&sex); 想当然地读取了/n 明白了? 关于scanf忽略前导空白符这一点,可以这样验证: 写个程序,用scanf()读数据,只要不是%c就行。 然后输入的时候,随便输入回车、空格、制表符,然后“回车”确认。 会发现程序依然提示等待你输入。 就是因为它忽略掉所有前导空白符之后发现缓冲区是空的!于是乖乖地阻塞住,等待你输入。关于scanf是直到看见空白符结束读取这一点,如果你是初学C的话,那么很快你就会遇到另一个函数,叫gets()。 程序里如果我们想一次读入一个英文句子: I am a student. 如果你用scanf读的话,只能读出"I",想读出后面的东西要不断调scanf。 此时需要用gets,这个函数不管是什么一律读进来,直到遇到回车符才停下。 总之,各有各的用途,全都熟悉之后,才能在恰当的时候恰当地使用。
本文来自CSDN博客,转载请标明出处: http://blog.csdn.net/wangyadong/archive/2009/04/23/4103774.aspx
的却,如果人人都用万能钥匙,那天下就没有钥匙了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐