使用 istream (std cin):防止 Windows 上的“[input] 不被识别为 ...”
Using istream (std cin): prevent "[input] is not recognized as ..." on Windows
我有一个具有命令行功能的 Qt gui 应用程序。
为了完成这项工作,我将其添加到 main()
函数的顶部:
#ifdef _WIN32
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
freopen("CONOUT$", "w", stdout);
freopen("CONIN$", "r", stdin);
freopen("CONOUT$", "w", stderr);
}
#endif
然后构造了我的mainclass的一个实例。在构造函数中,QCommandLineParser
判断是否有任何参数,并创建 cmdline 解析实例 class,或 gui 应用程序实例 class.
在命令行解析class中,我要求用户输入某些值:
QString qanswer;
// `answerToInt` is an std::unordered_map
while (answerToInt.find(qanswer) == answerToInt.end()) {
std::cout << std::endl << "File will be overwritten:" << std::endl
<< path.toStdString() << std::endl
<< "Are you sure? " << (multiple ? "(Yes/YesAll/No/NoAll)" : "(Yes/No)") << std::endl;
std::string answer;
std::cin >> answer;
qanswer = QString::fromStdString(answer).toLower();
std::cin.clear();
}
当输入 "Yes" "No"、"YesAll" 或 "NoAll"(不区分大小写)时,程序按预期继续,但当用户输入其他内容时, cmd 抛出这个:
'[input]' is not recognized as an internal or external command [...]
然后再次显示"C:\path\to\exe>",用户可以继续输入,直到输入正确的值之一。
输入有效字符串后,它会按预期再次继续。
我试过this answer和std::getline()
,但没有区别。
那么如何防止错误出现并继续显示 cout
?
AttachConsole
只是附加到父进程的控制台,它不会阻止父进程也从中读取。因此控制台输入在父进程 (cmd.exe
) 和您的应用程序之间交错,这可能难以管理(有些人建议 killing 父进程,这显然不是一个好主意) .
您可以做的是始终创建一个 新 控制台(参见 AllocConsole
)。
或者,如果您想重新使用 相同的 控制台,则可以改用控制台子系统(链接器选项 /SUBSYSTEM:CONSOLE
)并拥有一个常规 main()
函数而不是 WinMain
(是的,您可以在 main()
中创建 Win32 windows 和 句柄控制台 I/O ).
您甚至可以拥有一个可以链接为 Windows 的多子系统源以及带有这样填充程序的控制台子系统(nCmdShow
和命令行参数仍有待实现) :
HWND hwnd;
int main() {
std::thread t([] {
// let GUI run in its own thread ...
WinMain(GetModuleHandle(NULL), NULL, "", SW_SHOWDEFAULT);
exit(0);
});
// meanwhile in this thread we handle console I/O ...
std::string s;
std::cout << "Press Enter to exit" << std::endl;
while (std::getline(std::cin, s)) {
if (s == "")
break;
std::cout << "Hello " << s << std::endl;
}
PostMessageA(hwnd, WM_CLOSE, 0, 0);
t.join();
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// Your normal WinMain.
// CreateWindow, GetMessage loop etc. . .
我有一个具有命令行功能的 Qt gui 应用程序。
为了完成这项工作,我将其添加到 main()
函数的顶部:
#ifdef _WIN32
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
freopen("CONOUT$", "w", stdout);
freopen("CONIN$", "r", stdin);
freopen("CONOUT$", "w", stderr);
}
#endif
然后构造了我的mainclass的一个实例。在构造函数中,QCommandLineParser
判断是否有任何参数,并创建 cmdline 解析实例 class,或 gui 应用程序实例 class.
在命令行解析class中,我要求用户输入某些值:
QString qanswer;
// `answerToInt` is an std::unordered_map
while (answerToInt.find(qanswer) == answerToInt.end()) {
std::cout << std::endl << "File will be overwritten:" << std::endl
<< path.toStdString() << std::endl
<< "Are you sure? " << (multiple ? "(Yes/YesAll/No/NoAll)" : "(Yes/No)") << std::endl;
std::string answer;
std::cin >> answer;
qanswer = QString::fromStdString(answer).toLower();
std::cin.clear();
}
当输入 "Yes" "No"、"YesAll" 或 "NoAll"(不区分大小写)时,程序按预期继续,但当用户输入其他内容时, cmd 抛出这个:
'[input]' is not recognized as an internal or external command [...]
然后再次显示"C:\path\to\exe>",用户可以继续输入,直到输入正确的值之一。 输入有效字符串后,它会按预期再次继续。
我试过this answer和std::getline()
,但没有区别。
那么如何防止错误出现并继续显示 cout
?
AttachConsole
只是附加到父进程的控制台,它不会阻止父进程也从中读取。因此控制台输入在父进程 (cmd.exe
) 和您的应用程序之间交错,这可能难以管理(有些人建议 killing 父进程,这显然不是一个好主意) .
您可以做的是始终创建一个 新 控制台(参见 AllocConsole
)。
或者,如果您想重新使用 相同的 控制台,则可以改用控制台子系统(链接器选项 /SUBSYSTEM:CONSOLE
)并拥有一个常规 main()
函数而不是 WinMain
(是的,您可以在 main()
中创建 Win32 windows 和 句柄控制台 I/O ).
您甚至可以拥有一个可以链接为 Windows 的多子系统源以及带有这样填充程序的控制台子系统(nCmdShow
和命令行参数仍有待实现) :
HWND hwnd;
int main() {
std::thread t([] {
// let GUI run in its own thread ...
WinMain(GetModuleHandle(NULL), NULL, "", SW_SHOWDEFAULT);
exit(0);
});
// meanwhile in this thread we handle console I/O ...
std::string s;
std::cout << "Press Enter to exit" << std::endl;
while (std::getline(std::cin, s)) {
if (s == "")
break;
std::cout << "Hello " << s << std::endl;
}
PostMessageA(hwnd, WM_CLOSE, 0, 0);
t.join();
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// Your normal WinMain.
// CreateWindow, GetMessage loop etc. . .