先看一段代码:代码①
#include <Windows.h>
int main()
{
int n = 0;
while (scanf( "%d", &n) != EOF) // 如果输入a死循环
{
printf( "b\n");
//getchar();
Sleep(1000);
}
return 0;
}
此程序的输出结果是 输出b 休眠1s (自动读取a) 输出b 休眠1s
反复循环。
分析:
输入a,但是%d读取的是10进制数字,所以认为读取的类型不符合,
此时scanf并不会跳过a,而是把a重新放在缓冲区,下一次scanf读取的时候,还是会读取a!
注意的是,并没有读取失败,只不过是在反复读取a。如果读取失败,那将无法进入循环!
但注意的是,不同于以下程序:代码②
int main()
{
int n = 'A';
printf("%d", n);
return 0;
}
这段程序不需要读取,只需要将A的ASC II码值,用10进制的形式打印出来!
再看代码③
int main()
{
int n = 0;
int m = 0;
scanf( "%d %d", &n, &m); //输入A 8
printf( "%d %d", n, m); //打印 0 0
return 0;
}
输入A 8,此时scanf的第一个%d读取数据时,由于类型不符,所以A会停留在缓冲区,留给下一个%d读取,因此才会给 n m赋值失败。(赋值失败不是读取失败,读取失败会返回EOF,接着往下读就明白了)
再看代码④
int main()
{
int n = 0;
int m = 0;
int ret = scanf("%d %d", &n, &m); //输入A 8
printf("%d",ret); //打印 0
return 0;
}
{
int n = 0;
int m = 0;
int ret = scanf("%d %d", &n, &m); //输入A 8
printf("%d",ret); //打印 0
return 0;
}
分析:此时ret会scanf的返回值,但是由于给n m读取数值都没有读取进去,所以ret为0。
再看代码⑤
int main()
{
int n = 0;
int m = 0;
int ret = scanf("%d %d", &n, &m); //输入Ctrl + z 8
printf("%d",ret); //打印 -1
return 0;
}
{
int n = 0;
int m = 0;
int ret = scanf("%d %d", &n, &m); //输入Ctrl + z 8
printf("%d",ret); //打印 -1
return 0;
}
分析:Ctrl + z会被认为成EOF,当scanf读取到EOF的时候,会认为读取失败,此时返回值为EOF(即-1)
再看代码⑥
int main()
{
int n = 0;
int m = 0;
int ret = scanf("%d %d", &n, &m); //输入8 Ctrl + z
printf("%d",ret); //打印 1
return 0;
}
解析:
此时第一个%d成功读取到数字8,会读取成功,再读取到EOF,会被认为读取失败。
scanf的返回值是成功读取的元素个数,为 1
因为只有n是成功被读取的,m并没有被成功读入(m还是初始化的值)。
所以ret 为 1
总结:当死循环、莫名读取的时候,学会使用Sleep来检查缓冲区!!!
2.当读取的类型不符合时,不会跳过此元素
3.EOF会读取失败