gpt4 book ai didi

我可以让 ungetc 取消阻止阻塞的 fgetc 调用吗?

转载 作者:太空狗 更新时间:2023-10-29 15:59:58 24 4
gpt4 key购买 nike

我想在收到 SIGUSR1 时使用 ungetc 将一个“A”字符填回标准输入。想象一下,我有充分的理由这样做。

当调用 foo() 时,stdin 中的阻塞读取不会在收到信号时被 ungetc 调用中断。虽然我没想到它会按原样工作,但我想知道是否有办法实现这一点 - 有人有建议吗?

void handler (int sig){  ungetc ('A', stdin);}void foo (){  signal (SIGUSR1, handler);  while ((key = fgetc (stdin)) != EOF)  {    ...  }}

最佳答案

而不是尝试获取 ungetc()解除阻塞 fgetc()通过信号调用,也许您可​​以尝试不使用 fgetc()使用 select() 开始阻止并等待标准输入上的事件.


默认情况下,终端设备的线路规程可以在规范模式下工作。在此模式下,终端驱动程序不会将缓冲区呈现给用户空间,直到看到换行符(按下Enter 键)。

要完成您想要的,您可以使用 <a href="http://www.opengroup.org/onlinepubs/000095399/functions/tcsetattr.html" rel="noreferrer noopener nofollow"><b>tcsetattr()</b></a> 将终端设置为原始(非规范)模式操纵 termios结构体。这应该阻止对 fgetc() 的调用立即返回用 ungetc() 插入的字符.


void handler(int sig) {
/* I know I shouldn't do this in a signal handler,
* but this is modeled after the OP's code.
*/
ungetc('A', stdin);
}

void wait_for_stdin() {
fd_set fdset;
FD_ZERO(&fdset);
FD_SET(fileno(stdin),&fdset);
select(1, &fdset, NULL, NULL, NULL);
}

void foo () {
int key;
struct termios terminal_settings;

signal(SIGUSR1, handler);

/* set the terminal to raw mode */
tcgetattr(fileno(stdin), &terminal_settings);
terminal_settings.c_lflag &= ~(ECHO|ICANON);
terminal_settings.c_cc[VTIME] = 0;
terminal_settings.c_cc[VMIN] = 0;
tcsetattr(fileno(stdin), TCSANOW, &terminal_settings);

for (;;) {
wait_for_stdin();
key = fgetc(stdin);
/* terminate loop on Ctrl-D */
if (key == 0x04) {
break;
}
if (key != EOF) {
printf("%c\n", key);
}
}
}

注意:为简单起见,此代码省略了错误检查。

清除 ECHOICANON flags 分别禁用字符输入时的回显,并导致直接从输入队列中满足读取请求。设置 VTIME 的值和 VMINc_cc 中归零array 导致读取请求 ( fgetc() ) 立即返回而不是阻塞;有效地轮询标准输入。这导致 key设置为 EOF因此需要另一种终止循环的方法。通过使用 select() 等待 stdin 上的事件,减少了对 stdin 的不必要轮询。 .


执行程序,发送 SIGUSR1信号和打字t e s t 产生以下输出1:

Atest

1) 在 Linux 上测试

关于我可以让 ungetc 取消阻止阻塞的 fgetc 调用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2620010/

24 4 0
文章推荐: c - #define中的for循环
文章推荐: html - 使用 chrome DevTools 切换