0

I am running a C Program ( on Ubuntu - bash terminal) that expects input from 3 files - f1, f2, f3.

for(...)
    scanf(....)//reads input from f1
for(...)
    scanf(....)//reads input from f2
for(...)
    scanf(....)//reads input from f3

I want to provide the input to the C Program using the redirection operator on bash.

However if I run my program as follows I am able to read from only 1 file:

./a.out < f1

How do I redirect the input of f1, f2,andf3 to my C Program?

Varun Rao
  • 393
  • 1
  • 5
  • 19
  • 1
    not a `c` question, but the answer is `cat`, the \*nix tool for concatenating streams. `cat f1 f2 f3 | ./a.out` does the job. –  Jun 14 '17 at 18:35
  • @FelixPalmen sure but he will be unable to differentiate files then. I think the question is badly stated... – Jean-Baptiste Yunès Jun 14 '17 at 18:35
  • @Jean-BaptisteYunès from the sample code, it looks like he somehow already knows. Otherwise, this should be the first doubt trying to read from `stdin`. –  Jun 14 '17 at 18:36
  • I would be able to differentiate since my first loop reads up the entire contents of f1, and the second loop reads up the entire contents of f2 and the third loop reads up the entire contents of f3 – Varun Rao Jun 14 '17 at 18:37

2 Answers2

10

Usually, you'd only use redirections for standard input (fd 0, with the < redirection operator), standard output (fd 1, >) and standard error (fd 2, 2>), which seems to limit you to only one input stream.

(Of course you could do something like cat f1 f2 f3 | program, but telling the files apart would be hard.)

But, if you actually really want to, you can use other file descriptor numbers for inputs too. This is done in the same way as when redirecting stderr, just add the number before the redirection operator. So, running

./prog 3<file1 4<file2 5< file3

would open the given files in fd's 3, 4 and 5 and pass those on to ./prog. The program can then use fdopen to associate stdio streams (FILE *) with them. The biggest issue here is that you'll need some way of knowing which fd's to use in the program, and that would quickly require using something like command line arguments. The toy example below is fixed to use those three fd's, which of course does not scale in the least.

Instead, you'd be better off doing what all other programs do, and passing the file names as command line arguments. Even in the situations where you need to refer to an already-open file descriptor, many Unixes have a way of referring to them by name: /dev/fd/1 etc. (Process substitution, which is something like a generalized pipe, is one of those things that need to do this.)


Silly fdopen() example:

#include <stdio.h>

void read_a_line(int fd)
{
    char buf[64];
    FILE *f = fdopen(fd, "r");
    fgets(buf, 64, f);
    printf("fd %d: %s\n", fd, buf);
    fclose(f);
}

int main(void)
{
    read_a_line(3);
    read_a_line(4);
    read_a_line(5);
    return 0;
}
ilkkachu
  • 6,221
  • 16
  • 30
1

The function I think you might be looking for is getopt. That way you can take command line arguments instead of redirecting (which is only for one input stream) three files to your program. Then just call it like this:

./a.out f1 f2 f3

Additionally, I just saw this question, which uses a structure like this:

#include <stdio.h>
int main(int argc, const char* argv[]) {
    for(int i = 1; i < argc; i++) {
       //work with each file name
       //note that argv[0] is: ./a.out
    }
}
  • 2
    You don't need `getopt` to process a simple list of filenames. But of course, the moment you want to support flags, it starts being useful. The customary names for arguments to `main` are `argc` and `argv`, i.e. `int main(int argc, char *argv[])`, it might be a _very_ good idea to follow that custom, it will make it much easier to work with other people's code. ([It seems](https://stackoverflow.com/a/2108208/6372809) that particular signature is mentioned in the language standard, but it doesn't explicitly _require_ it.) – ilkkachu Jun 14 '17 at 18:57