我有一个无限循环来实现自定义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
是执行简单操作的通用命令解析器
答案 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,则更简单的恕我直言信号使用。