关于CMD重定向<0/<1/<2的检测与错误输出适配问题
控制台重定向检测问题解决方案
咱们一步步来解决你遇到的控制台重定向检测问题,先回顾下你的测试代码和执行结果:
测试代码
int main(int argc, char *argv[]){ cout << "cout argc: " << argc << endl; cerr << "cerr argc: " << argc << endl; cout << "cout usatty: " << _isatty(_fileno(stdin)) << endl; cerr << "cerr usatty: " << _isatty(_fileno(stdin)) << endl; if (argc == 1 && _isatty(_fileno(stdin))) { cout << "cout Error: No space between num and <" << endl; cerr << "cerr Error: No space between num and <" << endl; } }
CMD执行输出
program.exe 0< "A:/input.txt" cout argc: 1 cerr argc: 1 cout usatty: 0 cerr usatty: 0 program.exe 1< "A:/input.txt" cerr argc: 1 cerr usatty: 64 cerr Error: No space between num and < program.exe 2< "A:/input.txt" cout argc: 1 cout usatty: 64 cout Error: No space between num and <
问题1:如何打印可同时适配1<和2<的错误信息?
你现在的问题核心是:当stdout被1<重定向时,cout的输出会被写到文件里;当stderr被2<重定向时,cerr的输出会被写到文件里,导致错误信息无法在终端显示。这里有两个可靠的解决思路:
直接输出到控制台设备(Windows专属)
绕过标准流,直接向控制台窗口写入内容,不管stdout/stderr是否被重定向,错误信息都能显示在终端:#include <windows.h> #include <cstring> void printTerminalError(const char* errorMsg) { HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); DWORD bytesWritten; // 写入错误信息 WriteConsoleA(consoleHandle, errorMsg, strlen(errorMsg), &bytesWritten, NULL); // 换行 WriteConsoleA(consoleHandle, "\n", 1, &bytesWritten, NULL); } // 在你的判断逻辑里调用: printTerminalError("Error: No space between num and <");检测标准流的终端状态,动态选择输出流
分别检查stdout和stderr是否连接到终端,优先选择能在终端显示的流输出:bool isStdoutTerminal = _isatty(_fileno(stdout)) != 0; bool isStderrTerminal = _isatty(_fileno(stderr)) != 0; if (isStdoutTerminal) { cout << "Error: No space between num and <" << endl; } else if (isStderrTerminal) { cerr << "Error: No space between num and <" << endl; } else { // 如果两个流都被重定向,可选择写入日志文件或其他备用方式 // ofstream log("error.log"); // log << "Error: No space between num and <" << endl; }
问题2:如何检测0<(标准输入重定向)?
从你的输出可以看到,当执行program.exe 0< "A:/input.txt"时,_isatty(_fileno(stdin))返回了0——这其实已经正确检测到标准输入被重定向了!因为_isatty的返回规则是:非0值表示当前流连接到终端,0表示流被重定向或指向文件。
你之前的判断条件argc == 1 && _isatty(_fileno(stdin)),只有当没有命令行参数且标准输入是终端时才触发错误输出。而0<重定向时,_isatty返回0,条件不满足,所以没有输出。
如果要检测0<的情况,只需要调整判断逻辑,检查标准输入不是终端即可:
if (argc == 1) { if (_isatty(_fileno(stdin))) { // 标准输入是终端,未被重定向 cout << "Error: No space between num and <" << endl; cerr << "Error: No space between num and <" << endl; } else { // 标准输入被重定向(即`0<`的情况) cout << "Standard input is redirected via 0<" << endl; cerr << "Standard input is redirected via 0<" << endl; } }
这样就能准确捕获0<的重定向场景了。
内容的提问来源于stack exchange,提问作者Sinery
相关产品推荐
相关产品推荐

