0

I would like to iterate over a list/array of file objects: file_x,file_y,file_z,..., calling a function on each file object, in C.

Question

How can I create a function that would take (i) file object, and (ii) a string as arguments to the function and then write the string to that file object. A For loop could then execute the function over a list/array of file objects.

void file_write(file_object, string_to_write){
   fprintf(file_object, "%s\n", string_to_write);
}

Research

I have searched Google, watched parts of several Youtube tutorials and searched for relevant questions on SO, but the following is the best I could achieve. Any advice on how to better answer the above question, with the ideal function, would be much appreciated.

FILE *file_x, *file_y, *file_z, *file_vx, *file_vy

file_x  = fopen("./data/x.dat","w"); 
file_y  = fopen("./data/y.dat","w"); 
file_z  = fopen("./data/z.dat","w"); 
file_vx = fopen("./data/vx.dat","w"); 
file_vy = fopen("./vy.dat","w"); 

fprintf(file_x,  "#X(t) Coordinates\n#Time (t)\n");
fprintf(file_y,  "#Y(t) Coordinates\n#Time (t)\n");
fprintf(file_z,  "#Z(t) Coordinates\n#Time (t)\n");
fprintf(file_vx, "#X(t) Velocities\n#Time (t)\n");
fprintf(file_vy, "#Y(t) Velocities\n#Time (t)\n");

fclose(file_x);
fclose(file_y);
fclose(file_z);
fclose(file_vx);
fclose(file_vy);
hello_there_andy
  • 2,039
  • 2
  • 21
  • 51
  • 1
    Here: `void file_write(file_object, string_to_write){`, is `file_object` supposed to be an array of `FILE*` or a single `FILE*`? – Spikatrix Oct 10 '15 at 09:03
  • @CoolGuy preferably the single one, but then I would greatly appreciate if you could also explain how to create an array of file objects, outside of the function. Is it possible to create an array of files? – hello_there_andy Oct 10 '15 at 09:06
  • 3
    You could try to use a two dimension array or a one dimension arry to a `char*` to store all the file name/path and use indexes to refer to them as `char *fileName[num of files] = {"path/name", ...};` This way you can use a for loop to open them and store the opened file descriptor to another array which you can another for loop to loop through can call your function. – SSC Oct 10 '15 at 09:17
  • `void file_write(FILE *file_object, const char *string_to_write)` – melpomene Oct 10 '15 at 09:32

1 Answers1

4

you declare a single FILE pointer and then,you can declare two arrays,one for file names,and one for the data to be written to them.make a loop and iterate like this :

int main(void)
{
    FILE *file_x;

    const char *dirs[] = { "./data/x.dat",
                           "./data/y.dat",
                           "./data/z.dat",
                           "./data/vx.dat",
                           "./vy.dat"
                         };

    const char *data[] = { "#X(t) Coordinates\n#Time (t)\n",
                           "#Y(t) Coordinates\n#Time (t)\n",
                           "#Z(t) Coordinates\n#Time (t)\n",
                           "#X(t) Velocities\n#Time (t)\n",
                           "#Y(t) Velocities\n#Time (t)\n",
                         };

    for( int n = 0 ; n < 5 ; n++ )
    {
        file_x = fopen(dirs[n],"w");

        if ( !file_x )
        {
            perror(dirs[n]);
            exit(EXIT_FAILURE);
        }
        fprintf(file_x , "%s" , data[n]);

        fclose(file_x);
    }
    return 0;
}
machine_1
  • 4,266
  • 2
  • 21
  • 42
  • 2
    You open only one file at a time, process it and then close immediately, so you only need a single FILE *. – Jongware Oct 10 '15 at 09:35
  • @machine_1 thanks for the answer, but the code as it is shown in the answer is leading to a seg fault *works on it* – hello_there_andy Oct 10 '15 at 09:44
  • 1
    That should be `fprintf(file_x, "%s", data[n]);`. Never use `fprintf` without a literal format string. – melpomene Oct 10 '15 at 09:46
  • 1
    You should also check whether `fopen` succeeded: `if (!file_x) { perror(dirs[n]); exit(EXIT_FAILURE); }` – melpomene Oct 10 '15 at 09:48
  • @melpomene I encountered a bug in our software two days ago with user input being passed as the format string crashing the application. It was very entertaining. – Millie Smith Oct 10 '15 at 09:50
  • @MillieSmith Crashing is nice and harmless, but people have written exploits for that kind of bug (http://stackoverflow.com/questions/7459630/how-can-a-format-string-vulnerability-be-exploited). Great fun. – melpomene Oct 10 '15 at 09:53
  • Actually I am still getting a seg fault, I have so far made it iterate over a single file `FILE *file_x` and `fprintf(file_x, "%s", data[n]);` – hello_there_andy Oct 10 '15 at 09:53
  • @hello_there_andy So what did your debugger say? What statement does it crash on? – melpomene Oct 10 '15 at 09:54
  • Silly me: I was writing to a directory that didn't yet exist... thank you! Just some warnings, shouldn't be bad: `char *data[]={ "#X(t) Coordinates\n#Time (t)\n","#Y(t) Coordinates\n#Time (t)\n","#Z(t) Coordinates\n#Time (t)\n","#X(t) Velocities\n#Time (t)\n","#Y(t) Velocities\n#Time (t)\n" }; test_file_write.c:29:183: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]` – hello_there_andy Oct 10 '15 at 09:58
  • 1
    @hello_there_andy Change `char *` to `const char *`. – melpomene Oct 10 '15 at 09:59
  • @melpomene I'm aware. It was just entertaining to me. The filename input was so perfect. It had a "%20S", a "%20f", and a "%20C". – Millie Smith Oct 10 '15 at 18:15