The C Programming Language, 2nd Edition, by Kernighan and Ritchie
Exercise 7.03 on page 156
Revise minprintf
to handle more of the other facilities of printf
.
Solution by Gregory Pietsch
/* Gregory Pietsch - K&R2 Exercise 7-3 - 2001-01-28 gkp@flash.net */ #include <stdarg.h> #include <stdio.h> /* minprintf: minimal printf with variable argument list */ void minprintf(char *fmt, ...) { va_list ap; char *p, *sval; int ival; double dval; unsigned uval; va_start(ap, fmt); /* make ap point to the first unnamed arg */ for (p = fmt; *p; p++) { if (*p != '%') { putchar(*p); continue; } switch (*++p) { case 'd': case 'i': ival = va_arg(ap, int); printf("%d", ival); break; case 'c': ival = va_arg(ap, int); putchar(ival); break; case 'u': uval = va_arg(ap, unsigned int); printf("%u", uval); break; case 'o': uval = va_arg(ap, unsigned int); printf("%o", uval); break; case 'x': uval = va_arg(ap, unsigned int); printf("%x", uval); break; case 'X': uval = va_arg(ap, unsigned int); printf("%X", uval); break; case 'e': dval = va_arg(ap, double); printf("%e", dval); break; case 'f': dval = va_arg(ap, double); printf("%f", dval); break; case 'g': dval = va_arg(ap, double); printf("%g", dval); break; case 's': for (sval = va_arg(ap, char *); *sval; sval++) putchar(*sval); break; default: putchar(*p); break; } } va_end(ap); } /* end of function */
Solution by anonymous
I implemented all of the basic format specifiers for C that I could find except for %n. Also, I didn't include support for flags, field width, precision, character length, and length modifiers.
#include <stdio.h> #include <stdarg.h> /* Exercise 7-3. Revise minprintf to handle more of the other facilities of printf. */ void minprintf(char *fmt, ...); int main() { char *sval = "10"; int ival = 11; double dval = 12.13; unsigned int uival = 14; char cval = 'F'; void *pval = sval; minprintf("%%s=%s, %%d=%d, %%i=%i, %%f=%f, %%e=%e, %%E=%E, %%g=%g, %%G=%G, %%o=%o, %%x=%x\n", sval, ival, ival, dval, dval, dval, dval, dval, uival, uival); printf("%%s=%s, %%d=%d, %%i=%i, %%f=%f, %%e=%e, %%E=%E, %%g=%g, %%G=%G, %%o=%o, %%x=%x\n", sval, ival, ival, dval, dval, dval, dval, dval, uival, uival); minprintf("%%X=%X, %%u=%u, %%c=%c, %%p=%p, %%%%=%%\n", uival, uival, cval, pval); printf("%%X=%X, %%u=%u, %%c=%c, %%p=%p, %%%%=%%\n", uival, uival, cval, pval); } // minimal printf with variable argument list void minprintf(char *fmt, ...) { va_list ap; // points to each unnamed arg in turn char *p, *sval, format[3] = { '%', '\0', '\0' }; int ival; double dval; unsigned int uival; void *pval; va_start(ap, fmt); // make ap point to 1st unnamed arg for (p = fmt; *p; p++) { if (*p != '%') { putchar(*p); continue; } switch (*++p) { case 'd': case 'i': case 'c': // char is promoted to int when passed through '...' ival = va_arg(ap, int); format[1] = *p; printf(format, ival); break; case 'f': case 'e': case 'E': case 'g': case 'G': dval = va_arg(ap, double); format[1] = *p; printf(format, dval); break; case 's': for (sval = va_arg(ap, char *); *sval; sval++) putchar(*sval); break; case 'x': case 'X': case 'o': case 'u': uival = va_arg(ap, unsigned int); format[1] = *p; printf(format, uival); break; case 'p': pval = va_arg(ap, void *); printf("%p", pval); break; case '%': putchar(*p); break; default: // something is not handled, so print out the format string putchar('%'); putchar(*p); break; } } va_end(ap); // clean up when done }