#include #include #include #include #include #include "mprintf.h" #define DEFPRES 6 enum base { OCT = 8, DEC = 10, HEX = 16 }; struct flags { unsigned int fw; unsigned int pres; unsigned int fwc; unsigned int laligne : 1; } flags; void printnum(long long num, struct flags flags, int base); void printflt(double num, struct flags flags); void printstr(char *s, struct flags flags); int reverse(long long *num, int base); void mprintf(char *fmt, ...) { va_list ap; char *p; int dlim; va_start(ap, fmt); for (p = fmt; *p; ++p) { if (*p != '%') { putchar(*p); continue; } flags.fwc = ' '; flags.fw = dlim = flags.pres = 0; while (!isalpha(*++p) && *p != '\0') { if (isalnum(*p) && !dlim) flags.fw = flags.fw * 10 + *p - '0'; else if (isalnum(*p) && dlim) flags.pres = flags.pres * 10 + *p - '0'; else if (*p == '.') dlim = 1; else if (*p == '-') flags.laligne = 1; } if (!dlim) flags.pres = DEFPRES; switch (*p) { case 'd': case 'i': printnum(va_arg(ap, int), flags, DEC); break; case 'o': printnum(va_arg(ap, int), flags, DEC); break; case 'u': printnum(va_arg(ap, unsigned), flags, DEC); break; case 'x': printnum(va_arg(ap, unsigned), flags, HEX); break; case 'c': putchar(va_arg(ap, unsigned)); break; case 'p': mprintf("0x"); printnum(va_arg(ap, long long), flags, HEX); break; case 'f': printflt(va_arg(ap, double), flags); break; case 's': printstr(va_arg(ap, char *), flags); break; default: putchar(*p); break; } } va_end(ap); return; } void printstr(char *s, struct flags flags) { int blank; blank = flags.fw - strlen(s); for (; blank > 0 && !flags.laligne; --blank) putchar(flags.fwc); for (; *s; ++s) putchar(*s); for (; blank > 0 && flags.laligne; --blank) putchar(flags.fwc); } void printnum(long long num, struct flags flags, int base) { int temp, blank; if (num < 0) { putchar('-'); num *= -1; } blank = flags.fw - reverse(&num, base); for (; blank > 0 && !flags.laligne; --blank) putchar(flags.fwc); for (; num; num /= base) { switch (temp = num % base) { case 10: putchar('a'); break; case 11: putchar('b'); break; case 12: putchar('c'); break; case 13: putchar('d'); break; case 14: putchar('e'); break; case 15: putchar('f'); break; default: putchar(temp + '0'); break; } } for (; blank > 0 && flags.laligne; --blank) putchar(flags.fwc); } void printflt(double num, struct flags flags) { printnum((int) num, flags, DEC); if (flags.pres) { flags.fwc = '0'; putchar('.'); printnum((long long) ((num - (int) num) * powl(10, flags.pres)), flags, DEC); } } int reverse(long long *num, int base) { long long temp = *num; int len; for (*num = len = 0; temp; temp /= base, ++len) *num = *num * base + temp % base; return len; }