【问题标题】:Detecting Ctrl-D in C在 C 中检测 Ctrl-D
【发布时间】:2016-03-06 06:24:17
【问题描述】:

我正在尝试检测 Ctrl+D 用户输入,我知道它返回 EOF。现在,我知道代码等待来自标准输入流的输入,但是有没有办法让程序继续运行,直到 Ctrl+D 命令在标准输入中?如果没有输入 Ctrl+D,程序应该继续运行超过 if 语句。

char buffer[];
if (fgets(buffer, 10, stdin) == NULL{
    //write to file
}

【问题讨论】:

  • 发布的代码无法编译。
  • 不,这是不可能的。程序要么运行,要么停止并等待输入。它不能同时做这两件事。 (在有人说这可以通过多线程实现之前:我不建议现在就深入研究多线程)。
  • 这对我来说就像一个关于XY problem的问题
  • 您的缓冲区数组有问题 - EOF 不是 char(为此您需要 int)。

标签: c stdin exit fgets ctrl


【解决方案1】:

您想在用户按下 Ctrl+D 而不实际读取 stdin 时停止程序?在这种情况下,您应该考虑改用 Ctrl+C。但首先我会写一些关于非阻塞 I/O 的内容,因为这是您所要求的。


在标准 C 中没有办法实现非阻塞 I/O。但是,您可以将selectfcntlPOSIX 函数与read 结合使用。 StackOverflow 上还有其他关于它的问题,应该提供您需要的所有信息。以This question 为例。


如果你想处理Ctrl+C,你可以使用signal函数:

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

volatile bool shouldRun = true;

void sighandler(int) {
    shouldRun = false;
}

int main(int argc, char *argv[]) {
    if (signal(SIGINT, &sighandler) == SIG_ERR) {
        fprintf(stderr, "Could not set signal handler\n");
        return EXIT_FAILURE;
    }

    printf("Program started\n");
    while (shouldRun) {
        // Do something...
    }
    printf("Program is shutting down.\n");
    return EXIT_SUCCESS;
}

请注意,信号处理程序(即sighandler)可能随时中断您的线程。这意味着他们容易出现竞争条件。您甚至必须避免在信号处理程序中获取任何锁。这意味着仅在信号处理程序中调用printf 可能会导致死锁。不过,只需按照示例中所示设置布尔标志就可以了。有像 信号掩码self pipe trick 这样的解决方案来规避这些限制,但在这里它们应该不是必需的。

【讨论】:

    【解决方案2】:

    由于机器在 Ctrl+D 上生成EOF,因此您应该检查fgets() 中的NULL,因为fgets() 必须返回@ 987654325@ 在文件末尾。

    line = fgets(l, BUFFSIZE, stdin)
    if (line == NULL)
        continue;
    

    【讨论】:

    • 这不是我的问题。问题是 fgets() 将等待标准输入流,但如果没有输入 Ctrl-D,我希望我的程序继续。
    【解决方案3】:

    在这里发帖太多了,您并没有具体说明您目前拥有什么以及您想要什么。所以这里给你一个大致的思路:

    1. 将 if 语句放在分叉进程或其他线程中

    2. 当密钥被捕获时向你的(父)进程发送一个 posix 信号

    3. 在您的程序中添加信号处理程序

      如果您只想在输入 C-d 时终止程序,只需在步骤 2 中发送 SIGKILL 并忽略步骤 3。

    如果您不知道以上任何术语,Google 就是您的朋友

    【讨论】:

      【解决方案4】:

      在大多数操作系统上,stdin 一次缓冲一行,并且任何读取它的尝试(不进入低级 nasties)都将停止,直到有一行或 EOF 可用。如果您不介意这一点,并且只想检查 EOF 而不读取任何等待输入(如果 EOF 不存在),您可以使用 ungetc:

      #include <stdio.h>
      
      int check_for_EOF() {
          if (feof(stdin)) return 1;
          int c = getc(stdin);
          if (c == EOF) return 1;
          ungetc(c, stdin);
      }
      
      int main() {
          printf("Start typing:\n");
          while (!check_for_EOF()) {
              int bytes_typed = 0;
              while (getchar() != '\n') bytes_typed++;
              printf("You typed a line of %d bytes\n", bytes_typed);
          }
          printf("You typed EOF\n");
      }
      

      你只能保证得到 ungetc 的一个回推字符,尽管大多数实现会给你更多。并且它仅在您以后不打算寻找流时才有效(标准输入就是这种情况)。另请注意,我将其称为“键入的字节”,而不是“键入的字符”:例如,中文、日文和韩文字符不适合大多数 C 实现的 char 类型,这取决于控制台在您键入时如何对它们进行编码(如果你设置了CJK输入法或者可以复制/粘贴一些,你可以在上面的程序上试试看)。

      【讨论】:

      • 还要注意,来自 Unix 或 GNU/Linux 控制台的 Control D 只有在行首按下时才有效。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-08
      • 2021-03-17
      • 2012-06-14
      • 2023-04-04
      • 2020-09-01
      • 2011-02-23
      相关资源
      最近更新 更多