-2

I just need to know how to pass and declare a FILE* array into a function

void openInputFiles(char* name, FILE* input[]){
    char filename[10];
    if (strcmp("average", name) == 0){
        int i;
        int k =1;
        for (i=1;i<=10;i++){
            if (i<10){
                sprintf(filename,"%s_00%d",name,k);
            }
            if (i == 10){
                sprintf(filename,"%s_0%d",name,k);
            }
            input[i-1] = fopen(filename,"r");
            k++;
        }
    }
    if (strcmp("median", name) == 0){
        int i,k;
        k=1;
        for (i=1;i<10;i++){
            sprintf(filename,"%s_00%d",name,k);
            input[i-1] = fopen(filename,"r");
            k++;
        }
    }
}

That's the code for the function and this is where I am trying to call it

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

    FILE* input[10];

    openInputFiles(argv[1],input);
}

I don't get any warnings when I compile this but when I try to gdb it to test what's wrong it's seeming that the FILE* isn't allocating a memory address to input[0] because it says its at address 0x0. What am I doing wrong?

Pablo
  • 13,271
  • 4
  • 39
  • 59
Harrison
  • 23
  • 1
  • 6
  • 2
    Do these files already exist? – Jongware Feb 19 '18 at 00:10
  • yes, they are files named the same as the sprintf. – Harrison Feb 19 '18 at 00:15
  • 2
    if `fopen` returns `NULL` it means there was an error opening the file and you need to check `errno` to see what the problem is: https://linux.die.net/man/3/fopen – yano Feb 19 '18 at 00:17
  • My problem is that FILE* input[10] doesn't seem to be allocating memory for the entire array but rather just for input[10] is there another notation I should be using to allocate for the entire array? – Harrison Feb 19 '18 at 00:20
  • not sure what you mean. `FILE* input[10];` declares an array of 10 file pointers in automatic storage. You don't need to allocate anything beyond that. `fopen` returns `NULL` if there was a problem opening a file, otherwise it will return a valid file pointer. You don't need to manually allocate any space for the file pointers if that's what you're asking, the internals of `fopen` will do that. – yano Feb 19 '18 at 00:25
  • That's what I thought as well, but when I GDB it and do the command "p *input[0]" I get an error that says it can't access memory at address 0x0. It says this for every print command except input[10] which it gives a valid address for. – Harrison Feb 19 '18 at 00:35
  • 1
    yes, `NULL` is zero (I don't think that's enforced by the standard, somebody here will know, but for every system I've ever worked on that has been true). `fopen` is returning 0 because there is a problem opening the file, you need to check `errno` to figure out why it's failing. And `input[10]` is out of bounds of your array, the valid indices are 0 to 9. – yano Feb 19 '18 at 00:45
  • 1
    @yano The constant literal `0` is used to check for null-pointers, it is also a null-pointer constant. A `void*` cast to the literal constant of 0 is also considered a null-pointer, that's why the definition of `NULL` is usually `#define NULL ((void*) 0)`. That does not mean however that `NULL` is equal to the value 0, but I don't know of any modern architecture where it isn't the case. See https://stackoverflow.com/a/1296865/1480131 – Pablo Feb 19 '18 at 01:05
  • you may want to put an if (argc>1) in the main function so that the program doesn't just segfault on its own when you run it without an argument – Snohdo Feb 19 '18 at 01:18
  • regarding: `sprintf(filename,"%s_00%d",name,k);` the array: `filename[]` is 10 characters long. 'average' is 7 characters, '_00' is 3 more characters = 10 characters, a digit in the range 1...9 is 1 character = 11 characters, the final NUL byte is 1 character = a total of 12 characters. So the code overflows the array `filename[]` This is undefined behavior and can lead to a seg fault event. – user3629249 Feb 19 '18 at 02:26

1 Answers1

2
char filename[10];
...
sprintf(filename,"%s_00%d",name,k);

As user3121023 correctly noted, there isn't enough space to fit "average_001" into the 9 characters (plus terminating NUL) that you've allocated for the filename. You need to make it char filename[12]; or bigger. As a result, your program exhibits undefined behavior, which means anything could happen.

You should also ~never use sprintf -- use snprintf instead, and always check for errors, like this:

if (snprintf(filename, sizeof(filename), "%s_00%d", name, k) >= sizeof(filename)) {
  abort();  // filename is too short.

You can also simplify your loops (there is absolutely no need to handle i == 1 through 9 differently from i == 10:

for (i = 0; i < 10; i++) {
  int n = snprintf(filename, sizeof(filename), "%s_%03d", name, i + 1);
  if (n == -1 || n >= sizeof(filename) {
    // handle format error or "filename" too short here.
  }
  input[i] = fopen(filename, "r");
  if (input[i] == NULL) {
    // handle fopen failure here.
  }
}
Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • @user3121023 From http://man7.org/linux/man-pages/man3/printf.3.html "The functions snprintf() and vsnprintf() write *at most* size bytes (including the terminating null byte ('\0')) to str." – Employed Russian Feb 19 '18 at 17:22