0

I am trying to run the following in cmd:

gcc my_mainFile

and then run the following:

a.exe 2 < file.ppm

Basically what it does is sees the value 2, calls a specific function based on that, and uses the contents inside the ppm file. However, I am unaware of how to access this file itself. I need to be using scanf() to read the file, but I don't have the format clear.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    if(*argv[1] - '0' == 2){
        //Open and read contents of the file
    }
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Mus
  • 23
  • 4
  • 2
    Does this answer your question? [How to read a file passed through stdin in C](https://stackoverflow.com/questions/55143159/how-to-read-a-file-passed-through-stdin-in-c) – Jongware Jan 21 '20 at 21:52
  • If you are redirecting the file into the program then you don't need to open the file. Just use one of the input functions like `read`, `fgets`, `scanf` etc to read the data into a buffer or variables. Is your problem that you don't know how to call those functions or you don't know the format of the file contents? – kaylum Jan 21 '20 at 21:52
  • 3
    Rather than your roundabout `if(*argv[1] - '0' == 2` the more common way to test that `argv` is actually just `if (argv[1][0] == '2')` ... – Jongware Jan 21 '20 at 21:54
  • I am redirecting the file into the program. My issue is I dont know how to call the function scanf to see the file contents. – Mus Jan 21 '20 at 21:57
  • Be specific. What is it about calling `scanf` that you don't understand? And I would suggest `scanf` is not the best for this anyway - unless you have been required to do that for the assignment/task. – kaylum Jan 21 '20 at 21:58
  • I have been required to use scanf. Let me try to explaini my difficulty. The file named file.ppm contains a set of mostly integers. I want to open it with scanf and modify these values and represent it back on the screen. I am unsure as to how I can access this specific file thats given through the main statement when the program is run; a.exe 2 < file.ppm Since its not technically an argument, and how to use scanf to get these values stored if that makes sense – Mus Jan 21 '20 at 22:01
  • 1
    What exactly do you mean by "modify these values"? Modify them before writing them to the screen? Or also modifying them in the file, i.e. changing the file contents? – Andreas Wenzel Jan 21 '20 at 22:04
  • Well, `scanf` by nature reads from `stdin`. So it has nothing to do with the command line arguments. To read the first `int` just do something like: `int my_int, r; r = scanf("%d ", &my_int);` Then go from there. Give it a try - take small steps, understand that step, get it right and then expand. – kaylum Jan 21 '20 at 22:05
  • Modify before writing to screen, not the file itself. Also, let me try this out. thanks for the guidance – Mus Jan 21 '20 at 22:07
  • 1
    I suggest to test the `argc` value before you use `argv[]` to avoid using a non-supplied parameter... – CiaPan Jan 21 '20 at 23:49

1 Answers1

2

Many Linux utilities allow you to pass the filename to read as the first argument or read from stdin by default. This allows you to read from a given filename, or to pipe or redirect output from another process to your code on stdin. To implement the alternative, you can take advantage that stdin has type FILE* and simply check whether a filename argument has been provided to read (and if so, open and read from that file), or read from stdin by default.

For example:

#include <stdio.h>

#define MAXC 1024   /* if you need a constant, #define one (or more) */

int main (int argc, char **argv) {

    char buf[MAXC]; /* buffer to hold entire line (adjust MAXC as needed) */
    /* use filename provided as 1st argument (stdin by default) */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        perror ("file open failed");
        return 1;
    }

    while (fgets (buf, MAXC, fp)) {                 /* read each line of input */
        int a, b;                                   /* example variables */
        if (sscanf (buf, "%d %d", &a, &b) == 2) {   /* parse/validate values */
            /* do what you need with your values */
            printf ("a: %d    b: %d\n", a, b);
        }
    }

    if (fp != stdin)   /* close file if not stdin */
        fclose (fp);

    return 0;
}

Above, fgets() is used to ensure a complete line on input is consumed with each read, preventing stray characters from be left unread in your input stream that will cause read failure (or infinite loop) on your next attempted read. Any values needed from the line are parsed with sscanf. This avoids a great number of pitfalls new C programmers fall into by attempting to read directly with scanf or fscanf before understanding how to detect and properly handle matching or input failures due to either a mismatch between the format specifier and input, or exhausting input before all specified conversions take place.

Examples

Piping input on stdin:

$ printf "1 2\n3 4\n" | ./bin/readfileorstdin
a: 1    b: 2
a: 3    b: 4

Example Input File

$ cat dat/2x2.txt
2 4
3 5

Handling File Directly or on stdin

Reading file directly:

$ ./bin/readfileorstdin dat/2x2.txt
a: 2    b: 4
a: 3    b: 5

Redirecting on stdin:

$ /bin/readfileorstdin < dat/2x2.txt
a: 2    b: 4
a: 3    b: 5

You don't have to do it this way, you can just read from stdin directly and avoid checking whether a filename was given -- but this method provides a lot of convenience and flexibility for input handling in just a few extra lines of code.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85