哈哈……孔明啊……那个帖子里面你菜得可爱呢,哈哈哈~~~~~
目前认为,scanf会向下“查看”一个字符,然后判断是否接受。scanf一定会尽量大地接受合法字符。这个应该这么理解:(以下<CR>代表回车)
例一:%d(以后只写控制符),输入123<CR>
为什么会得到123呢?scanf查看1,是数字,接受,然后查看2,也接受,最后查看到你输入的回车,不是数字,不接受,所以得到123,把回车留在缓冲区里面。
例二:%d%c(或者%d%*c),输入123<CR>
这个也是常用的用法,主要用在scanf和gets混用的情况下。例一的时候,scanf把回车留在了缓冲区里面,所以如果马上调用gets,gets会得到这个scanf“不要”的回车,而读不到下面一行。所以我们用%c读取这个回车字符(%c大家都知道吧?%*c的意思是读取以后把读到的内容扔掉,不赋值给任何变量)。这样,就可以用gets读到下一行得内容了。不过这种方式对输入要求很高,如果你输入123<空格><CR>,那么gets照样得不到下一行的内容了,为什么,大家仔细思考就能知道。
例三:%d (或者%d\n),输入123<CR>
这是我们讨论的用法,注意%d后面有一个空格。这样,读取123之后,遇到回车,scanf发现不满足%d的要求了,于是查看下面一个字符,发现是空白字符(' ','\t','\n'这三个,叫空白字符)。scanf的逻辑是,遇到空白字符,则读取[bo]所有[/bo]的空白字符。那么,scanf接受了回车。但是这个时候,缓冲区空了!scanf会继续等待在原地(为什么?因为没用接受到非法字符啊,scanf只有在接受到非法字符的时候才会返回)。这样就出现了LS某人说的“输入以后没反映”的情况了,这个时候,你随便输入一个非空白字符,让scanf接受到这个非法字符(为了能刷新缓冲区,别忘了输入回车哦~),比如aa<CR>,这样scanf查看到“a”这个字符,发现不满足“空白字符”这个格式,就返回了,你也得到了输入。注意,直接按回车是没有反应的,因为回车本身就是空白字符,你必须输入一个非空白字符。
大家都明白了?
这里做一个说明,就是scanf默认"%d"和" %d"是一样的,就是说scanf自动忽略掉开始读入的任何空白字符。这就解释了为什么缓冲区里面有回车,scanf仍然可以读到想要的内容的原因(就是这个原因,所以scanf和gets不好混用)。
上面第三种方法实现了scanf和gets的混用,但是觉得不爽,必须一次输入两行才能得到输出,第二种方法又对格式限制太严格,有没有更好的办法呢?
有!请使用"%d%*[^\n]%*c",这样就消掉了你输入的数字后面所有的非法字符,直到回车,然后吃掉回车字符。比如你可以输入123abc<CR>,没关系,scanf照样读取,而且缓冲区不会剩下任何垃圾。
为什么可以这么写呢?请百度。
目前认为,scanf会向下“查看”一个字符,然后判断是否接受。scanf一定会尽量大地接受合法字符。这个应该这么理解:(以下<CR>代表回车)
例一:%d(以后只写控制符),输入123<CR>
为什么会得到123呢?scanf查看1,是数字,接受,然后查看2,也接受,最后查看到你输入的回车,不是数字,不接受,所以得到123,把回车留在缓冲区里面。
例二:%d%c(或者%d%*c),输入123<CR>
这个也是常用的用法,主要用在scanf和gets混用的情况下。例一的时候,scanf把回车留在了缓冲区里面,所以如果马上调用gets,gets会得到这个scanf“不要”的回车,而读不到下面一行。所以我们用%c读取这个回车字符(%c大家都知道吧?%*c的意思是读取以后把读到的内容扔掉,不赋值给任何变量)。这样,就可以用gets读到下一行得内容了。不过这种方式对输入要求很高,如果你输入123<空格><CR>,那么gets照样得不到下一行的内容了,为什么,大家仔细思考就能知道。
例三:%d (或者%d\n),输入123<CR>
这是我们讨论的用法,注意%d后面有一个空格。这样,读取123之后,遇到回车,scanf发现不满足%d的要求了,于是查看下面一个字符,发现是空白字符(' ','\t','\n'这三个,叫空白字符)。scanf的逻辑是,遇到空白字符,则读取[bo]所有[/bo]的空白字符。那么,scanf接受了回车。但是这个时候,缓冲区空了!scanf会继续等待在原地(为什么?因为没用接受到非法字符啊,scanf只有在接受到非法字符的时候才会返回)。这样就出现了LS某人说的“输入以后没反映”的情况了,这个时候,你随便输入一个非空白字符,让scanf接受到这个非法字符(为了能刷新缓冲区,别忘了输入回车哦~),比如aa<CR>,这样scanf查看到“a”这个字符,发现不满足“空白字符”这个格式,就返回了,你也得到了输入。注意,直接按回车是没有反应的,因为回车本身就是空白字符,你必须输入一个非空白字符。
大家都明白了?
这里做一个说明,就是scanf默认"%d"和" %d"是一样的,就是说scanf自动忽略掉开始读入的任何空白字符。这就解释了为什么缓冲区里面有回车,scanf仍然可以读到想要的内容的原因(就是这个原因,所以scanf和gets不好混用)。
上面第三种方法实现了scanf和gets的混用,但是觉得不爽,必须一次输入两行才能得到输出,第二种方法又对格式限制太严格,有没有更好的办法呢?
有!请使用"%d%*[^\n]%*c",这样就消掉了你输入的数字后面所有的非法字符,直到回车,然后吃掉回车字符。比如你可以输入123abc<CR>,没关系,scanf照样读取,而且缓冲区不会剩下任何垃圾。
为什么可以这么写呢?请百度。