tags:

views:

102

answers:

4

I'm working on a program that generates an FDF file for filling in an Adobe PDF form. Currently, I have various procedures that are called, as before each one terminates, it opens the FDF file, writes its particular data, and closes the file.

I'm trying to put the code for writing the data to the FDF file in a separate procedure, and then have the other procedures call it. This would allow for a greater separation of the code by task, and if I had to change it in the future, I could do so easily.

I'm having some problems though, as I need to pass varying amounts of variables to fprintf. That is, I used to have a line like this:

fprintf(fp,"<</T(f1_44(0))/V(%d)>>\n",wages);

I wrote the below function, but I can't get it to work:

void writeToFDF(FILE *fp, char *filename, char *data, char *arg)
{
/* independent method for writing to FDF file */

/* open file */
fp=fopen(filename,"a");

fprintf(fp,data,arg);

/* close file */
fclose(fp);
}

So in theory, I would then in the parent function call:

writeToFDF(fp,"1040.fdf","<</T(f1_44(0))/V(%d)>>\n",wages);

I'm getting errors right now, and I believe it has to do with the last part of the function's arguments. Also, how can I get it to work if I have multiple arguments?

Thank you.

+4  A: 

You need vfprintf. It will accept a variable list of arguments.

Like this:

void writeToFDF(FILE *fp, char *filename, char *data, ...)
{
va_list pl;

/* independent method for writing to FDF file */

/* open file */
fp=fopen(filename,"a");

va_start (pl, data);

vfprintf(fp,data,pl);

/* close file */
fclose(fp);
va_end(pl);
}

EDIT: while I tried to stay as close to your original code, ephemient's solution that omits the FILE *fp argument is in fact better: fp has only local significance (it's opened and closed in this function) so it should not be passed around.

fvu
Yes, I've thought about that, I'll have to clean up my code. I think you're right using va_start though, at least on my Linux box, it didn't recognize va_begin.
Sam
Thanks again though!
Sam
Oops, `va_begin` belongs with the older `varargs.h`. The new standard is indeed `stdarg.h` with its `va_start`.
ephemient
Why do you need FILE *fp as an argument. You are not using it.
eyalm
@eyalm: you're right, the reason is explained in my edit.
fvu
+2  A: 

You will need to use a Variadic function. See Forward an invocation of a variadic function in C

gwell
+2  A: 

This is what vfprintf is for.

#include <stdarg.h>
#include <stdio.h>

void writeToFDF(const char *filename, const char *format, ...) {
    va_list ap;
    FILE *fp = fopen(filename, "a");
    va_begin(ap, format);
    vfprintf(fp, format, ap);
    va_end(ap);
    fclose(fp);
}
ephemient
Thank you all! I had seen something about using variable argument functions, but I hadn't seen vfprintf. Thanks!
Sam
On most systems the argument macro is called "va_start"
eyalm
Yes, as I commented on fvu's answer, I screwed up: pre-standard `varargs.h` used `va_begin`, standardized `stdarg.h` uses `va_start`.
ephemient
+1  A: 
   #include <stdio.h>
   #include <stdarg.h>

   void foo(FILE *file, char *fmt, ...)
   {
       va_list ap;

       va_start(ap, fmt);
       vfprintf(file, fmt, ap);
       va_end(ap);
   }
eyalm