c++ - C++ 中的 CLI : cin and Ctrl+C

标签 c++ windows command-line-interface

我有一个无限循环来实现自定义 CLI,如下所示

while (1) {
    getline(cin, _input);
    _parse_cmd(_input);
}

我创建了一个信号处理程序,如下所示:

BOOL WINAPI _consoleSignalHandler(DWORD CEvent) {
    char mesg[128];

    switch (CEvent)
    {
    case CTRL_SHUTDOWN_EVENT:
    case CTRL_LOGOFF_EVENT:
    case CTRL_CLOSE_EVENT:
    case CTRL_BREAK_EVENT:
        if (_CLI_instance) {
            cout << "Close Signal" << endl;
        }
        break;
    case CTRL_C_EVENT:
        cout << "Ctrl + C to be implemented" << endl;
        break;
    default:
        return FALSE;
        break;
    }
    return TRUE;
}

使用此配置,当我按下 CTRL+C 时,CLI 会打印消息 "Ctrl + C to be implemented" 并且永远不会再次等待用户输入。我该如何解决这个问题?

注意:parse_cmd 是执行简单操作的通用命令解析器

最佳答案

编辑:

你的问题是,在 C++ 中,当 getline 函数被中断时,你必须在下次调用之前手动清除错误状态。在你的循环中写就足够了:

while (1) {

    getline(cin, _input);
     if (cin.fail() || cin.eof()) {
        cin.clear(); // reset cin state
    }
   _parse_cmd(_input);

}

但请注意:因为您还过滤 Ctrl-Break,您的循环可能很难停止...

TL/DR :下面是我对这个简单解决方案的第一步,首先是 C 惯用语,接下来是 C++,它只过滤 Ctrl-C 并在Ctrl-Break.

Ctrl-C 可以通过signal 函数轻松获取。

这是一个用法示例:

#include <stdio.h>
#include <signal.h>

void ctrl_c(int sig) {
    fprintf(stderr, "Ctrl-C caught\n");
    signal(sig, ctrl_c); /* re-installs handler */
}

int main() {
    char buf[256];
    void (*old)(int);

    old = signal(SIGINT, ctrl_c); /* installs handler */

    for (;;) {
        if (fgets(buf, sizeof(buf), stdin) != NULL) {
            printf("Got : %s", buf);
        }
    }
    signal(SIGINT, old); /* restore initial handler */
    return 0;
}

Ctrl-C 被拦截,Ctrl-Break 杀死程序。

编辑:

旧的 C 版本很简单。在 C++ 中,如果 getline 被中断,您必须清除 cin 中的标志:

#include <iostream>
#include <string>
#include <csignal>

using namespace std;

void ctrl_c(int sig) {
    cerr << "Ctrl-C caught" << endl;
    signal(sig, ctrl_c); // re-installs handler
}

int main() {
    string buf;
    void (*old)(int);

    old = signal(SIGINT, ctrl_c); // installs handler

    for (;;) {
        getline(cin, buf);
        if (cin.fail() || cin.eof()) {
            cin.clear(); // reset cin state
        }
        else {
            cout << "Got" << buf << endl;
        }
    }
    signal(SIGINT, old); // restore initial handler
    return 0;
}

即使我不使用 Microsoft 特定的 SetConsoleCtrlHandler,它现在也是正确的 C++。恕我直言,如果只需要捕获 Ctrl-C 就可以更简单地使用信号。

关于c++ - C++ 中的 CLI : cin and Ctrl+C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26762470/

相关文章:

c++ - 如何在使用此数组初始化对象时知道数组的大小?

c++ - 如何在 C 或 C++ 中进行字符串实习?

windows - 通过 Powershell 添加 JAVA_HOME 到系统变量 Path

CreateFileMapping() 用于将长度未知的文本写入文件

php - 找出运行当前脚本的 PHP 解释器的绝对路径

java - Apache CLI 参数和选项设置了吗?

c++ - 内存清理程序错误 : clang5 + msan + fwrite of structs with padding bytes

c++ - 为什么指定的初始化程序在 C++ 中工作?

python - 将特殊字符传递给 cmd.exe 中的 python 脚本

django - CodeDeploy 运行过时的 appspec 文件?