#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdarg.h>
#include <ctype.h>
#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;
}