c++ - 使用 istream (std cin) : prevent "[input] is not recognized as ..." on Windows

标签 c++ cmd cin

我有一个具有命令行功能的 Qt gui 应用程序。 为了完成这项工作,我将其添加到 main() 函数的顶部:

#ifdef _WIN32
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
    freopen("CONOUT$", "w", stdout);
    freopen("CONIN$", "r", stdin);
    freopen("CONOUT$", "w", stderr);
}
#endif

然后构造了我的主类的一个实例。在构造函数中,QCommandLineParser 确定是否有任何参数,并创建 cmdline 解析类或 gui 应用程序类的实例。

在 cmdline 解析类中,我要求用户输入某些值:

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(是的,您可以创建 Win32 窗口并且main( )).

您甚至可以拥有一个可以链接为 Windows 的多子系统源以及带有这样一个 shim 的控制台子系统(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. . .

关于c++ - 使用 istream (std cin) : prevent "[input] is not recognized as ..." on Windows,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61544872/

相关文章:

windows - 从批处理文件切换注册表值

python - 在pycharm中使用linux控制台

c++ - 如果调试运行正常但发布崩溃怎么办

c++ - 使用头文件而不是标准命名空间

c++ - 为什么我们不能释放由 new 分配的内存?

c++ - 如何将 YYYY/MM/DD HH:MM:SS 转换为 std::chrono::system_clock::time_point?

在后台以静默模式运行我的 installer.exe 文件的 C# 代码,

c++ - cin.getline 跳过一行输入并获取下一行

c++ - 当输入在带有空格的单行中给出时,cin 在 while 循环中如何工作?

c++ - std::cin >> vector[i] 不会让迭代器正常工作?