0

I am trying to not hardcode the name of the input file in my C program. I have all of the other components working when I hardcode the filename. But would like to be able to pass it a string filename. I am trying to execute compile a file called Matrix.c and name its executable matrix.

So, in terminal, when I get to my working directory.

gcc -g Matrix.c -o matrix

then when I compile

./matrix 

It doesn't have a filename passed to it so I am gonna check for that and have the user input a filename to load.

However, when someone passes the filename, should it be passed as:

./matrix filename.txt

or

./matrix < filename.txt

With the latter option, I can't seem to get the name of the argument passed to the function from argv[1] — it's just "(Null)".

I know this is very simplistic question. But am I just completely off my rocker? Is it something to do with me running on OS X El Capitan. I know I've used the '<' convention before.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
WallofKron
  • 33
  • 8

2 Answers2

4

The issue is how the shell works, mainly. When you use:

./matrix filename.txt

then the program is given two arguments — the program name and the file name. When you use:

./matrix < filename.txt

then the program is given just one argument — the program name — and the shell arranges for its standard input to come from the file (and the file name is not passed to your program).

Either can be made to work; you just have to decide which you want to support. What should happen if the user types ./matrix file1.txt file2.txt file3.txt? One version of conventional behaviour would be to process each file in turn, writing each set of results to standard output. There are plenty of alternative behaviours — most of them have been used by someone at some time or another. Reading from standard input when there is no file name specified is a common mode of operation (think cat and grep and …).

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Thank you for clearing that up. I just fixed it and tried to address all three modes of input. Thanks – WallofKron Sep 25 '16 at 21:11
  • I frequently use functions similar to `int processor(FILE *fp, const char *fn)` which reads the input from the stream `fp` which is the opened file `fn` (or a pseudo-name for 'standard input'), sometimes using an extra argument `FILE *ofp` to specify which file the output should be written to. The return value is 0 for 'success' and anything else for failure. The code in your main program can then call `processor()` quite easily. Indeed, I have a set of functions that handle the processing for zero or more residual arguments, so `main()` ends `return filter(argc, argv, optind, processor);`. – Jonathan Leffler Sep 25 '16 at 21:16
  • `isatty()` can be useful here, see http://stackoverflow.com/questions/1312922/detect-if-stdin-is-a-terminal-or-pipe-in-c-c-qt – cdarke Sep 26 '16 at 07:07
0

Arguments to a command are in argv[1 .. argc-1].

The redirect from '<' sends the contents of the file to the program's stdin.

A third way to get the filename would be to print "Enter filename: " and then read the string typed by the user.

stark
  • 12,615
  • 3
  • 33
  • 50