这个问题是这样的:
调用函数scanf("%d", &i),根据格式指示符"%d",scanf()预期从输入流中读取到1个int数据,当你的输入能够成功转化为需要的int数据时(比如你输入了100),它就把字符串"100"转换为整数100,并通过指针(&i)把整数赋给变量i,并且函数返回1,表示成功读取了1个数据(类似地,如果你写scanf("%d%d", &x, &y),则需要返回2才能表示成功读取了2个所需的数据,若返回1,只读得第1个,第2个是不成功的,若返回EOF,则是读到了用Ctrl+Z键入的流结束符)。
现在你继续输入"a",这是一个无法成功转化为int数据的字符,因此scanf()返回0表示不成功,而不再干预地址&i处的变量值,此时i仍为原先的100。但关键问题在scanf()函数会记忆上次的动作,它从上次返回的0中知道上次没读成,那么这次干脆不做动作(可以推测这个返回值是寄存在一个静态或全局变量中的;另外一种可能是scanf()仍然尝试去读"a",因为它上次并没有被从输入流中取走,霸在头位,所有接续scanf()都要先把它取走,而你又总不肯取字符或字符串。对后面这种可能性,在代码中没有办法预期后面可能有多少这样的东西,很难写预防代码,可以写一个读并废弃无效字符的循环来处理,但在现实各式各样需求的环境下,这种手法不大高明),于是,死循环出现了。
解决的办法是两个:第一,消除上次scanf()运行的返回结果(现在暂时不好处理);第二,重置变量i的值。所以,不妨采取如下办法:
程序代码:
int i; // 如果你没有初始化,程序运行时会随机出现一个很巨大的整数,视内存变化而定,那就是你看到的那个大数
do
{
i = 0; // 此处初始化变量,回避随机值,也抛弃上次的值,给下面的if判断加一重保险,虽然可省,但写上不妨;若无下面判断,则必须有这个
if (scanf("%d", &i) != 1)
{
break;
}
printf("af");
} while (i == 100);
在现代C++语言中,是不建议使用scanf()函数的,改用一个带有保险功能的替代函数scanf_s(),你如果使用VS C++编译器,它会出警告你改用scanf_s()函数,用那个会有更好的处理办法。
这个问题也给你一个教训:尽量避免在一个scanf()语句中读取多个数据,甚至是不同类型的数据,那种做法有多危险,你仔细琢磨一下现在这个问题就能感觉得出来。
[
本帖最后由 TonyDeng 于 2012-4-2 23:39 编辑 ]