简体   繁体   English

在 C 中检测 Ctrl-D

[英]Detecting Ctrl-D in C

I am trying to detect the Ctrl + D user input, which I know returns EOF .我试图检测Ctrl + D用户输入,我知道它返回EOF Right now, I know the code waits for input from the stdin stream, but is there a way to let the program continue until the Ctrl + D command is in stdin?现在,我知道代码等待来自 stdin 流的输入,但是有没有办法让程序继续运行,直到Ctrl + D命令在 stdin 中? The program should continue running past the if statement if Ctrl + D isn't inputted.如果没有输入Ctrl + D ,程序应该继续运行超过 if 语句。

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

You want to stop your program when the user presses Ctrl + D without actually reading stdin ?您想在用户按Ctrl + D而不实际读取stdin时停止您的程序吗? In this case, you should consider using Ctrl + C instead.在这种情况下,您应该考虑改用Ctrl + C。 But first I will write something about non-blocking I/O, since this is what you are asking for.但首先我会写一些关于非阻塞 I/O 的东西,因为这就是你所要求的。


There is no way to achieve nonblocking I/O in standard C .在标准C 中无法实现非阻塞 I/O。 However, you could use POSIX -functions like select or fcntl in combination with read .但是,您可以将selectfcntlPOSIX函数与read结合使用。 There are other questions about it on StackOverflow which should provide all information you need. StackOverflow 上还有其他关于它的问题,应该提供您需要的所有信息。 This question for example.例如这个问题


If you want to handle Ctrl + C instead, you can use the signal function:如果要改为处理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;
}

Note that signal handlers (ie sighandler ) might interrupt your thread at any moment.请注意,信号处理程序(即sighandler )可能随时中断您的线程。 This means they are prone to race conditions.这意味着它们容易出现竞争条件。 You must even avoid acquiring any locks within a signal handler.您甚至必须避免在信号处理程序中获取任何锁。 This means just calling printf within a signal handler can cause a deadlock.这意味着仅在信号处理程序中调用printf会导致死锁。 Just setting boolean flags as shown in the example is fine, though.不过,只需设置示例中所示的布尔标志就可以了。 There are solutions like signal masks and the self pipe trick to circumvent these limitations, but they should not be necessary here.有诸如信号掩码自管道技巧之类的解决方案来规避这些限制,但在这里它们不是必需的。

Since the machine generates EOF on Ctrl + D , you should be checking fgets() for NULL , as fgets() is obliged to return NULL on end of file.由于机器在Ctrl + D上生成EOF ,您应该检查fgets()是否为NULL ,因为fgets()必须在文件末尾返回NULL

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

It is too much to post here and you are not specific what you have currently and what you want.在这里发帖太多了,而且您没有具体说明您目前拥有什么以及想要什么。 So here gives you a general idea of how to do it:因此,这里为您提供了如何做到这一点的总体思路:

  1. Put that if statement inside a forked process or other thread将该 if 语句放在分叉进程或其他线程中

  2. Send a posix signal to your (parent) process when the key is captured捕获密钥时向您的(父)进程发送 posix 信号

  3. Add signal handler in your program在程序中添加信号处理程序

    If you just wanna terminate the program when Cd is entered, just send a SIGKILL in step 2 and ignore step 3.如果您只想在输入 Cd 时终止程序,只需在步骤 2 中发送 SIGKILL 并忽略步骤 3。

If you do not know any term above, Google is your friend如果你不知道上面的任何术语,谷歌是你的朋友

On most operating systems, stdin is buffered one line at a time, and any attempt to read it (without going into low-level nasties) will stop until either a line or EOF is available.在大多数操作系统上,stdin 一次缓冲一行,并且任何读取它的尝试(不进入低级别的麻烦)都将停止,直到一行或 EOF 可用。 If you don't mind this, and just want to check for EOF without reading-in any waiting input if EOF is not present, you could use ungetc:如果您不介意这一点,并且只想在不存在 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");
}

You are only guaranteed one character of push-back from ungetc, although most implementations give you much more.尽管大多数实现为您提供了更多,但您只能保证从 ungetc 回退一个字符。 And it works only if you're not going to seek the stream later (which is the case with stdin).并且只有在您以后不打算查找流时才有效(标准输入就是这种情况)。 Notice also that I'm calling it "bytes typed", not "characters typed": Chinese, Japanese and Korean characters for example cannot fit into the char type of most C implementations, and it would depend how the console encodes them when you type (if you have a CJK input method set up or can copy/paste some, you can try it on the above program and see).另请注意,我将其称为“字节类型”,而不是“字符类型”:例如,中文、日文和韩文字符无法适应大多数 C 实现的 char 类型,这取决于您键入时控制台如何对它们进行编码(如果你设置了 CJK 输入法或者可以复制/粘贴一些,你可以在上面的程序上试试看)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM