1 #include <stdio.h> 2 3 int main() 4 { 5 char buff[50]; 6 while (true) 7 { 8 scanf("%s", buff); 9 printf("you inputed: %s\n", buff); 10 } 11 return 0; 12 }
问题描述:
这段程序不停的向用户要求输入一些文字,当用户输入后紧接着就把这些文字显示出来。
这个程序是无限循环的,但是这并没有什么关系,因为每一次 scanf() 调用的时候,都会停下来等待用户输入。所以用户可以不慌不忙的输入一些东西,然后回车,程序就把这些东西给显示了出来。
这个程序很简单,没什么太大的用处。一眼看起来似乎也没什么稀奇的,即使不亲自编译运行,也能猜到大概运行起来大概是个什么样子——这是许多人第一眼的印象,可是如果考虑重定向输入流,这个程序就会出现一个致命的 bug,请按照下面的步骤来重现这一 bug:
1、把程序编译为 bug.exe
2、在 bug.exe 所在的目录下新建文本文件 break.txt,内容随便输入即可,例如 123,然后保存
3、在控制台下运行 bug.exe < break.txt
结果就会发现程序陷入了死循环。而且是毫无等待,不停刷屏的死循环。
请给出解决方案,使得即使是重定向了输入流,我们的程序也能正常工作——等待用户用键盘输入一些东西,然后优雅的将他们显示出来,然后再让用户输入,再显示,如此往复,就好象没有重定向输入流时所表现的那样。
提示一点点:
正常情况下,即没有重定向输入流的情况下,当 scanf() 尝试从输入缓冲中读取数据却发现无数据可读的时候,就会阻塞住,等待用户输入一些数据,然后再返回。可是当重定向输入流后,scanf() 的行为却变了——如果发现无数据可读,不会阻塞,会立刻返回一个 EOF(数字 -1)。
在开始解决问题之前请注意四点:
1、这个程序还存在其他的 bug,例如缓冲区溢出等,但不是本次关注的内容,因此请忽略
2、一种“解决办法”是去判断 scanf() 的返回值是否为 EOF,如果是则 break,这样虽然不会死循环,但是意义也不大,因为程序虽然不会死循环刷屏,但是也不能再从用户处获取数据,因此并没有真正解决问题。(问题的本质是弄清楚 scanf() 为什么不阻塞了,如何让它再阻塞)
3、这是一个开放性问题,即使你的结论是——不可能做到——也是可以的,关键是你要能够从理论和实践两方面进行验证。当然我们更希望听到结论是——可以做到。
4、可以借助 C 标准库之外的其他第三方库/函数来解决。(转载)