这是我研究的一个理解性小白问题,我不清楚我的解释准不准确,但是逻辑是没错了,阅读前需要先对~scanf,%[^\n],%*c,缓冲区进行理解。
# include <stdio.h>
void main()
{
char a[40];
while(~scanf("%[^\n]%*c",a))
printf("%s\n",a);
}
运行起来很简单,输入什么字符串,按下回车键后就输出什么字符串,可以达到一个持续输出的效果。感觉没有问题,我就进行了接下来的测试和分析。程序启动,我开始输入nihao,然后按下第一次回车,换行就输出nihao,第一次循环结束。第一次循环中的nihao被%[^\n]读掉了,它无法读换行字符,换行字符被%*c给读掉了。
开始第二次循环,此时缓冲区没有任何未读字符,于是我按下回车键。按照之前的分析,我输入的换行字符会被%*c读掉,输出nihao,接着等待第三次循环的输入,结果却不是。
结果是无限循环。到底是为什么呢?于是我对%[^\n]中的\n换成其他的字母数字,发现缓冲区中只有以那些其他字母数字开头的字符串,按下回车键,才能出现无限循环。
(%[^\n]读字符串,读到\n就停止,并且不读入\n)
也就是说%[^\n],被停止读入并且又什么也没读到,scanf就会直接返回值0,不再进行%*c的读入。导致了\n一直在缓冲区无法读入。
为了验证,于是我又将%*c提在前面
# include <stdio.h>
void main()
{
char a[40];
while(~scanf("%*c%[^\n]",a))
printf("%s\n",a);
}
输入nihao ,按下回车,换行输出ihao。显然%*c先读,将n读掉,%[^\n]后读,所以它们读入有先后性。
接下来继续分析,此时进入第二次循环,缓冲区中还有一个换行字符,所以scanf直接继续读,由于%*c放在前面,先进行读入,所以\n就被读掉了。然后缓冲区没有任何未读字符,那么程序便会停在%[^\n]位置等待输入。输入nihao,按下回车后,nihao被复制到a为首地址的内存空间去了,回车字符则还在缓冲区,到第三次循环,回车字符就会被%*c率先读掉。
若在第二次循环时,直接按下回车。第一次循环留下的回车字符被第二次循环的%*c读掉,%[^\n]等待输入,
我按下回车键,此时回车字符输入到缓冲区,%[^\n]遇到回车字符就停止读入,并且回车字符前又没有任何可读字符,结果导致scanf直接返回值0,直接输出ihao。但是到第三次循环,由于%*c的提前,它会先把第二次循环留下在缓冲区中的\n率先读掉,结果是不会出现无限循环。