The printf
family of functions includes (among others) printf(3)
, fprintf(3)
, vprintf(3)
, and vfprintf(3)
. The first three can easily be written in terms of the fourth.
Write four similar functions
void msg(char const *type, char const *fmt, ...);
void vmsg(char const *type, char const *fmt, va_list ap);
void fmsg(FILE *fp, char const *type, char const *fmt, ...);
void vfmsg(FILE *fp, char const *type, char const *fmt, va_list ap);
where the intended behavior is
msg("Info", "0x%x %d", 32, 5);
prints [Info] 0x20 5
.
Implement the first three in terms of the fourth. Feel free to use fprintf(3)
, vfprintf(3)
, or other standard I/O functions to implement vfmsg
.
Write a short program that tests them.
The execl(3)
function takes a path and a variable number of arguments. The end of the argument list is denoted by an explicit (char *)0
.
Using the same strategy of marking the end of the list with (char *)0
, write a function
char *join(char const *sep, ...)
That allocates and returns a string consisting of the variable number of strings joined together but separated the string sep
. For example,
join(" ", "This", "is", "a", "sentence.", (char *)0);`
should return the string "This is a sentence."
;
should return the empty string ""
; and
join("+-+" "a", "b", "c", (char *)0);
should return the string "a+-+b+-+c"
.
In all cases, the string should be allocated via malloc(3)
or realloc(3)
. Make sure you don’t leak memory.
Write a short program to test your functions. The strings returned from join
should ultimately be passed to free(3)
.