1

I am trying to detect the Ctrl+D user input, which I know returns 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? The program should continue running past the if statement if Ctrl+D isn't inputted.

char buffer[];
if (fgets(buffer, 10, stdin) == NULL{
    //write to file
}
Fabrizio
  • 7,603
  • 6
  • 44
  • 104
Melissa Ding
  • 11
  • 1
  • 1
  • 3

4 Answers4

5

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.

line = fgets(l, BUFFSIZE, stdin)
if (line == NULL)
    continue;
Fabrizio
  • 7,603
  • 6
  • 44
  • 104
Vlad
  • 115
  • 7
  • 1
    That's not my problem. The issue is that fgets() will wait for the stdin stream, but I want my program to continue if Ctrl-D is not entered. – Melissa Ding Mar 06 '16 at 06:43
5

You want to stop your program when the user presses Ctrl+D without actually reading stdin? In this case, you should consider using Ctrl+C instead. But first I will write something about non-blocking I/O, since this is what you are asking for.


There is no way to achieve nonblocking I/O in standard C. However, you could use POSIX-functions like select or fcntl in combination with read. There are other questions about it on StackOverflow which should provide all information you need. This question for example.


If you want to handle Ctrl+C instead, you can use thesignal function:

#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 (i.e. sighandler) might interrupt your thread at any moment. 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. 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.

JojOatXGME
  • 3,023
  • 2
  • 25
  • 41
1

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. 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:

#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. 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).

Silas S. Brown
  • 1,469
  • 1
  • 17
  • 18
0

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

  2. Send a posix signal to your (parent) process when the key is captured

  3. Add signal handler in your program

    If you just wanna terminate the program when C-d is entered, just send a SIGKILL in step 2 and ignore step 3.

If you do not know any term above, Google is your friend

Community
  • 1
  • 1
SwiftMango
  • 15,092
  • 13
  • 71
  • 136