I’m trying to implement an all-purpose function for printing 2D data. What I’ve come up with is:
int mprintf(FILE* f, char* fmt, void** data, size_t cols, size_t rows)
The challenge is determining how many bits to read at once from data, based on fmt.
The format fmt is going to be the stdlib’s-specific format for printf() and alike.
Do you have any knowledge of already-existing features from stdlibc (GNU GCC C’s) I could use to ease this up?
I try avoiding having to do it all manually, because I know “I am stupid” (I don’t want to introduce stupid bugs). Thus, reusing code would be the bug-freest way.
Thanks
Addendum
I see there’s a /usr/include/printf.h. Can’t I use any of those functions to do it right and ease my job at the same time?
Design proposed in question:
High-level design points
Low-level design points
The format string should be a
const char *.Clearly, your code can do what
printf()does, more or less. It looks at the format conversion specifier, and then determines what type to collect. Your code will be slightly more complex, in some respects. You’ll need to treat an array ofunsigned chardifferently from an array ofshort, etc. C99 provides for modifierhhforsigned charorunsigned char(before the format specifiersd,i,o,u,x, orX), and the modifierhforshortorunsigned short. You should probably recognize these too. Similarly, the modifiersLforlong doubleandlforlongandllforlong longshould be handled. Interestingly,printf()does not have to deal withfloat(because any singlefloatvalue is automatically promoted todouble), but your code will have to do that. By analogy withhandL, you should probably useHas the modifier to indicate afloatarray. Note that this case means you will need to pass to theprintf()function a different format from the one specified by the user. You can make a copy of the user-provided format, dropping the ‘H’ (or use exactly the user-provided format except when it contains the ‘H’; you will not modify the user’s format string – not least because the revised interface says it is a constant string).Ultimately, your code will have to determine the size of the elements in the array. It might be that you modify the interface to include that information – by analogy with functions such as
bsearch()andqsort(), orfread()andfwrite(). Or you can determine it from the format specifier.Note that although GCC allows pointer arithmetic on
void *, Standard C does not.Are you sure you want a
void **in the interface? I think it would be easier to understand if you pass the address of the starting element of the array – a single level of pointer.This changes the
dataparameter to avoid *. Maybe I’m too decaffeinated, but I can’t see how to make a double pointer work sanely.Outline
Illustration
This code assumes a ‘0 is success’ convention. It assumes you are dealing with numbers, not matrices of pointers or strings.
Working code
Left as an exercise:
size_tintmax_tptrdiff_tNote that I would not normally use the
+=or*=operators on the same line as other assignments; it was convenient for generating test numbers, though.