【发布时间】:2015-04-04 20:34:54
【问题描述】:
我正在编写名为“Headfirst C”的 C 文本中的一些示例代码。我编写了一个演示信号处理的练习应用程序,在完成本章后,我决定尝试一下。我是一名工程师,习惯于在 LabVIEW 中工作(高度并发和直观的事件处理功能),因此我对使用警报和信号处理程序生成周期性事件很感兴趣。我的问题是这样的:
在以下示例代码中,丢弃标准输入中可变数量的用户输入的正确方法或最佳实践是什么?我编写了这个小应用程序作为演示,一个 3 秒的警报会触发一个烦人的“你好!”中断 fgets 调用的消息。然而,我注意到的是,如果用户在打字过程中被打断,当他最终按下 enter 时,输入的任何文本(是否被打断)都会被回显。我想丢弃在用户按下回车之前被中断的任何内容。
//Sample Program - Signal Handling & Alarms
//Header Includes
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
//Function Declarations
//Handler Functions
void diediedie(int sig);
void howdy(int sig);
//Handler Register Function
int catchSignal(int signum, void(*handler)(int));
//Variable declarations
//Declare interrupted flags
static int interrupted = 0;
//Program entrypoint
int main() {
//Register interrupt hander, catch errors
if(catchSignal(SIGINT, diediedie) == -1) {
fprintf(stderr, "Could not register interrupt handler");
exit(2);
}
//Register alarm handler, catch errors
if(catchSignal(SIGALRM, howdy) == -1) {
fprintf(stderr, "Could not register alarm handler");
exit(2);
}
//Create initial alarm trigger
alarm(3);
//Do something stupid while waiting for signals
char name[30];
printf("Enter your name: ");
//Keep waiting for user input even if interrupted by alarm signal
while(1) {
fgets(name, 30, stdin);
if(interrupted) {
// reset interrupted flag
interrupted = 0;
// ***** ADD CODE TO DISCARD INTERRUPTED INPUT HERE ******
}
else {
//echo user input and break out
printf("Hello %s\n", name);
break;
}
}
//end program
return 0;
}
//interrupt handler definition
void diediedie(int sig) {
//write some stuff, exit program
puts("Goodbye world!");
exit(1);
}
//alarm handler definition
void howdy(int sig) {
//set interrupted flag
interrupted = 1;
//write some annoying message
puts("howdy!");
//set another alarm trigger
alarm(3);
//**** COULD STDIN BE FLUSHED HERE? ****
}
//signal handler registration function definition
int catchSignal(int signum, void(*handler)(int)) {
//register handler
struct sigaction action;
action.sa_handler = handler;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
return sigaction(signum, &action, NULL);
}
在警报处理程序中执行此清除的适当位置是否合适?请注意 cmets 表明我对正确代码位置的想法。
我考虑过以下几点:
while(getchar() != EOF) {}
我也想知道,当 fgets 等待用户输入并引发 SIGALRM 时会发生什么?该功能是否终止?我观察到,如果我不包括 while 循环来检查中断标志并做出适当的响应,程序将完成 fget,在屏幕上转储一些垃圾(我假设 stdin 的当前状态?)并结束程序。
感谢您的建议!
【问题讨论】:
-
可能是
tcflush(),也可能不是。 -
@JonathanLeffler 如果标准输入确实是终端,则可以使用。
-
这条线
tcflush(fileno(stdin), TCIFLUSH);似乎确实有效。
标签: c signals stdin alarm fgets