Question

It's possible to make a code that recognizes whether a file was passed like:

program.out < file.dat

I search an answer for this because I want to write code to do something like this:

int main (int argc, char *argv[])
{
    char filename[50];

    if ( argc > 1 )
    {
        strcpy (filename, argv[1]);
    }

    else if ( SOMETHING )
    {
        /* copy the stdin into fin (?) */
    }

    FILE *fin;

    fin = fopen (filename, "r");

    /* ... */

    fclose(fin);

    }

    return 0;
}

In which SOMETHING evaluates to 1 if the file was passed with <, and 0 otherwise.

If it's possible, I am looking for a solution working in standard C.

Was it helpful?

Solution

We cannot detect this in ISO C (that is, without resorting to platform extensions, like getting the file descriptor using fileno on POSIX and then running some tests on it by obtaining attributes with fstat and so forth.)

The stdin stream is required by ISO C to be line buffered if it is connected to an interactive device. This doesn't help us, however, since there are no portable functions to inquire about the buffering mode of a FILE *: there are only "setters", no "getters". The GNU C library has a __flbf (FILE *stream) which reports whether or not a stream is line-buffered, but it is an obvious extension, declared in a <stdio_ext.h> header.

If your program must work with a file, and not with standard input from an interactive device, then a good solution is to make the argument to the program mandatory. Make it require a filename argument and always open that file. Then you're sure you have the file.

You can also make the argument optional, and if it is missing, then open a default file, ignoring stdin.

You can also use freopen to make stdin point to a file. Then code which works with stdin implicitly will take input from that file:

Pseudo-code:

name = "some default"

if we have an argument
  name = that argument

if (freopen(name, mode, stdin) == 0)
   handle error
else
   stdin is now a file; process it

If you really must support the program < file situation, while flagging the program situation (interactive input) as invalid, you need the aforementioned platform-specific hacks.

OTHER TIPS

If you're OK with a Unix-specific solution, you can use isatty():

FILE *fin;
int need_to_close;

if (isatty(fileno(STDIN))) { // I/O not redirected
    fin = fopen("file.dat", "r");
    need_to_close = 1;
} else {
    fin = stdin;
    need_to_close = 0;
}

/* ... */

if (need_to_close) {
    fclose(fin);
}

May be this answer can help: It says,

On a Posix system, you can test whether or not cin comes from a terminal or is redirected using isatty

#include <unistd.h>

if (isatty(STDIN_FILENO)) {
    // not redirected
} else {
    // redirected
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top