以前,fflush函数是用来对缓冲区进行操作的。fflush(stdin)用于清空缓区,fflush(stdout)强制输出当前缓冲区中的内容。但是自从VS2015之后,fflush(stdin)就不能用了(使用时不会报错,但是没有清空缓冲区的效果)。
我们在进行从键盘中输入数据时,有时不得不清空缓冲区,比如下面这段代码。
char a,b;
scanf("%c",&a);
scanf(%c",&b);
printf("%c %c",a,b);
当我输入1 2时,正常情况应该输出1 2,但实际的输出结果却并非如此。
当我输入完1,按完回车准备继续输入2时,发现程序输出了1,然后又输出了一个换行,之后程序就执行结束了。这是因为当你按回车的时候,程序以为这是你输入的第二个字符,这就解释了为什么程序输出一个1后,又输出了一个换行就结束了。
要解决这个问题,以前是可以这样修改代码的。
char a,b;
scanf("%c",&a);
fflush(stdin);
scanf(%c",&b);
printf("%c %c",a,b);
但是前面也说过,VS2015之后这个方法就失效了(VC依然可以使用此方法),使用新版的VS,有两种方法来解决这个问题。
1.把fflush(stdin)替换成rewind(stdin)
char a,b;
scanf("%c",&a);
rewind(stdin);
scanf("%c",&b);
printf("%c %c",a,b);
2.使用scanf(“%*[^\n]%*c”)
关于这个函数,我从网上搜了一大堆对它的解释,但还是没有特别理解。它好像是读取字符串,遇到换行符\n时读取结束,我用如下代码进行测试。
char a,b;
scanf("%[^\n]%*c", &a);
scanf("%[^\n]%*c", &b);
printf("%c %c",a,b);
测试结果如图
程序输出结果是正确的,但是却引发了异常中断,中断信息为:Run-Time Check Failure #2 - Stack around the variable ‘a’ was corrupted.从网上搜了一下,这是因为栈被破坏了。最常引起这种错误的情形是对数组进行操作时,比如说定义一个 int num[10]这样的数组,当你想要改变num[10]的值时,就会引发异常中断,这是因为数组下表是从0开始的,数组num的10个元素分别是num[0]~num[9],根本没有num[10]这个元素。前面说过,scanf(“%*[^\n]%*c”,&a)是用来读取一行字符串存储到&a这个地址,注意是字符串,字符串的末尾要有一个’\0’,这样当你输入一个字符之后按回车,实际上要存储两个字符,一个是你输入的字符,另一个是自动添加的’\0’,而我们对a的定义是char a,也就是说只能访问&a的地址,而不能访问&a + 1的地址,如果你想要强行访问,就会引发异常中断。下面的这段代码用来验证我的上述猜想。
char str[10];
scanf("%[^\n]%*c", str);
scanf("%[^\n]%*c", str+2);
设断点进行调试,发现str[1]和str[3]都是’\0’。
然后我又从网上搜索,找到了scanf("%*c")这个函数,它的功能是清除缓冲区的最后一个字符。因此可以把第一种法案中的rewind函数改为scanf("%*c"),代码如下。
char a,b;
scanf("%c",&a);
scanf("%*c");
scanf("%c",&b);
printf("%c %c",a,b);