C ++中的CLI:cin和Ctrl + C.

时间:2014-11-05 16:42:27

标签: 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是执行简单操作的通用命令解析器

1 个答案:

答案 0 :(得分:1)

编辑:

您的问题是在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中被杀死。

您可以使用signal函数轻松获取Ctrl-C拦截。

以下是一个使用示例:

#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 ++中,如果cin被中断,则必须在getline中清除标记:

#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,则更简单的恕我直言信号使用。