Home > database >  Beginner Q -ARGV and multiple files
Beginner Q -ARGV and multiple files

Time:12-09

Good afternoon, Old man trying to learn new tricks here, I have been given an assignment that I am trying to work my way through but I am stuck as I don't fully understand the argv[]

I have 4 files I want to read from and eventually use malloc and realloc but thats further down. My initial plan was to try read one file and get it onto the command line. I had it opening but made that many changes that now I'm lost.

Think my problem lies with argv[4] as i dont understand it, when I put 4 it goes into theloop and errors but with 1 it just bombs out. If someone can point me in the direction I am going wrong here it would be great

Thanks

struct Person { char lname[20]; char fname[20]; int id; };
int i, N;
struct Person *student;



int main(int argc, char *argv[])
{
FILE *outputfile;
printf("Please enter the name of the file to open: ");
scanf("%s", argv[4]);

outputfile = fopen(argv[4], "r") ;
if (outputfile==NULL){
    perror(argv[1]);
    fprintf(stderr,"Error while opeining file\n");
    exit(-1);
}

CodePudding user response:

You don't have to use argv[]. Argv is an array of strings that store the arguments passed in when running the executable. If you run the executable like this: ./a.out, then argv only contains one element, which is the path of the executable itself. If you run the program like this, and you try to access argv[4], it does not give you an error, but if you debug it using GDB, it will output the following: warning: Invalid parameter passed to C runtime function.

You could pass in a file on the command line like this: ./a.out yourfile.txt. In this case, argv[0] will be the path of the executable a.out, and argv[1] will be the string "yourfile.txt".

It might be easier to completely drop the use of argv and store the user input for the filename in a string. You can then pass that string as an argument to fopen. This would look something like this:

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

int main(int argc, char *argv[]) {
    char fileName[30];
    char ch;

    printf("Please enter a file name\n");
    scanf("%s", fileName);

    FILE *outputFile = fopen(fileName, "r");
    if(outputFile == NULL) {
        printf("Could not open %s\n", fileName);
        exit(-1);
    }
}

CodePudding user response:

  1. Use constants (NAME_LEN) instead of hard-coding magic values.
  2. Prefer multiple lines for your struct. It's easier to read and version control systems prefer lines for diffs.
  3. Avoid global variables.
  4. Do a boundary check using argc (count of elements in argv) before you read argv. argv[0] is the name of your program, argv[1] is the first argument.
  5. Treat argv as read-only, i.e. don't do scanf("%s", argv[4]).
  6. Prefer to initialize variables instead of declaring and assigning a value separately. It's easy to forget setting a variable before use which leads ot undefined behavior. Initialization might be faster, too.
  7. Your file handle is called outputfile but with fopen() you use the mode of r for reading. Either mode should be w or you want to change the variable name to inputfile.
#include <stdio.h>
#include <string.h>

#define NAME_LEN 20

struct Person {
    char lname[NAME_LEN];
    char fname[NAME_LEN];
    int id;
};

int main(int argc, char *argv[]) {
    char filename[FILENAME_MAX];
    if(argc > 4) {
        strcpy(filename, argv[4]);
    } else {
        printf("filename? ");
        fgets(filename, FILENAME_MAX, stdin);
        filename[strcspn(filename, "\n")] = '\0';
    }

    FILE *outputfile = fopen(filename, "w");
    if(!outputfile) {
        // ...
    }
    fclose(outputfile);
}

and you would run your program with either:

$ ./a.out dummy dummy dummy output.txt

or

$ ./a.out
filename? output.txt

CodePudding user response:

It sounds as if you are expected to provide 4 file names as command line parameters. In which case you should be doing this:

#include <stdio.h>

int main (int argc, char *argv[])
{
  const int files = 4;

  if(argc != files 1)
  {
    printf("Usage: myprog file1 file2 file3 file4");
    return 0;
  }

  FILE* fp [files];

  for(int i=0; i<files; i  )
  {
    fp[i] = fopen(argv[i 1], "r");
    ...
  }
  ...

}
  • Related