Q一旦我使用了freopen,我该如何找回原来的stdout(或stdin)?
A没有好的方法。如果你需要切换回来,最好的解决方案是最初就不要使用freopen。尝试使用你自己的显式输出(或输入)流变量,你可以随意重新分配它,同时保持原始的stdout(或stdin) 不受影响。例如,声明一个全局的
FILE *ofp;,并将所有对printf(... )的调用替换为fprintf(ofp,... )。 (显然,你还需要检查对putchar和puts的调用。)然后你可以将ofp与stdout设置为任何值。
你可能想知道是否可以完全跳过freopen,并做类似
FILE *savestdout = stdout; stdout = fopen(file, "w"); /* WRONG */的操作,以便稍后通过执行stdout来恢复
stdout = savestdout; /* WRONG */,但像这样的代码不太可能奏效,因为stdout(和stdin和stderr)通常是不能重新赋值的常量(这就是为什么freopen存在的原因)。
在调用freopen来打开一个文件替换它之前,可能有可能以一种不可移植的方式保存流的信息,以便以后可以恢复原始流。最直接可靠的方法是使用系统特定的调用(如dup或dup2)来操作底层的}`;`文件描述符,如果可用的话(示例)。另一种方法是复制或检查`;`结构的内容,但这极其不可移植且不可靠。`FILE结构的内容,但这极其不可移植且不可靠。
在某些系统上,你可能能够重新打开一个特殊的设备文件(例如,现代 Unix 版本下的/dev/fd/1),它仍然连接到(例如)原始的标准输出。在某些系统上,你可以显式地重新打开控制终端(请参阅问题 12.36),但这不一定是你想要的,因为原始的输入或输出(即调用stdin或stdout之前freopen的内容)可能已经从命令行重定向了。
所有这些都与最初由freopen执行的标准 I/O 重定向有关,影响了调用freopen的同一个程序中的 I/O 调用。如果你想捕获子程序执行的结果,freopen可能也无法正常工作;请参阅问题 19.30。
其他链接:示例