CLI在C++:CIN和Ctrl + C

问题描述:

我有无限循环实现定制CLI,如下CLI在C++:CIN和Ctrl + C

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是一个通用的命令分析器执行简单的行动

+0

什么是_parse_cmd? – 2014-11-05 16:53:27

+0

@MarcoA。这是一个简单的命令解析函数,只执行简单的动作 – manatttta 2014-11-05 16:57:01

+0

为什么不禁用'ENABLE_PROCESSED_INPUT'模式,所以CTRL + C被报告为键盘输入而不是信号? – Sam12345 2014-11-05 17:27:02

编辑:

你的问题是,在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; 
} 

这是正确的,现在C++,即使我不使用特定SetConsoleCtrlHandler微软。恕我直言,信号使用如果更简单,如果只有Ctrl-C必须被捕获。

+2

为什么你将OP的代码从C++更改为20世纪20年代的C? – 2014-11-05 17:36:04

+0

@LightnessRacesinOrbit:因为我有这个我曾经使用的旧代码(很久很久以前......),我确信它的工作。但是你是对的,它没有回答OP问题:-(。谢谢你的评论。 – 2014-11-05 19:44:48

+0

解决了它!谢谢:) – manatttta 2014-11-10 10:04:34