printf
一个小型的printf函数,只需要实现myputs函数。这个代码可以用于嵌入式开发的调试。
程序代码:
#undef ullong
#undef sllong
#undef llong
#define llong __int64
#define sllong signed llong
#define ullong unsigned llong
const int _my_chartab[256] =
{
98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 99, 99, 99, 99, 99, 99,
99, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 99, 99, 99, 99, 99,
99, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
};
const int _my_chartab2[256] =
{
98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
};
const char _my_tabCHAR[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const char _my_tabchar[] =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
unsigned long myatoul(const char *s, char **endp, int base_)
{
unsigned long res = 0;
unsigned c, base = (unsigned)base_;
if (base < 2) {
base = 10;
if (*s == '0') {
base = 8;
c = *++s;
if (c == 'b' || c == 'B') base = 2, ++s;
else if (c == 'x' || c == 'X') base = 16, ++s;
}
}
for (; (c = _my_chartab[(int)*s]) < base; ++s)
res = res * base + c;
if (endp)
*endp = (char*)s;
return res;
}
int mystrlen(const char *s)
{
const char *s0 = s;
while (*s) ++s;
return s - s0;
}
#define FLAGS_FILL (1U << 0)
#define FLAGS_PREFIX (1U << 1)
#define FLAGS_SPEC (1U << 2)
#define FLAGS_ADD (1U << 3)
#define FLAGS_ADDR (1U << 4)
#define FLAGS_LEFT (1U << 6)
#define FLAGS_SIGN (1U << 7)
#define FLAGS_UNSIGNED (1U << 8)
#define FLAGS_UPPER (1U << 9)
#define FLAGS_SIGNED (1U << 10)
extern const int _my_chartab[];
extern const char _my_tabCHAR[];
extern const char _my_tabchar[];
struct vsprintf_status {
unsigned flags;
int width;
int base;
int prec;
int filled;
int nrl, nrh;
ullong value;
char sign;
char buffer[128];
int nlen;
const char *ptrout;
const char *prefix;
};
static void init_status(struct vsprintf_status *st)
{
st->flags = 0;
st->width = 0;
st->base = 10;
st->prec = 1000000;
st->filled = ' ';
st->value = 0;
st->nrl = st->nrh = 0;
st->nlen = 0;
st->sign = 0;
st->ptrout = "";
st->prefix = "";
}
int myvsprintf(char *dst, const char *fmt_, va_list ap)
{
char *dst_orig = dst, *cp;
struct vsprintf_status st;
unsigned long ulval;
const char *p_chartab, *str;
int c, i, tmpi, align;
ullong uval;
const unsigned char *fmt = (const unsigned char *)fmt_;
repeat:
switch((c = *fmt++)) {
case 0: goto finsh;
default: *dst++ = c; goto repeat;
case '%': break;
}
init_status(&st);
spec:
switch((c = *fmt++)) {
case '+': st.flags |= FLAGS_ADD; goto spec;
case '-': st.flags |= FLAGS_LEFT; goto spec;
case '#': st.flags |= FLAGS_SPEC; goto spec;
case '%': *dst++ = c; goto repeat;
default: break;
}
if (c == '0') {
st.filled = '0';
c = *fmt++;
}
if (c == '*')
st.width = va_arg(ap, int), c = *fmt++;
else if (_my_chartab[c] <= 9)
st.width = myatoul ((const char*)(fmt-1), (char**)&fmt, 10), c = *fmt++;
if (c == '.') {
if ((c = *fmt++) == '*')
st.prec = va_arg(ap, int), c = *fmt++;
else if (_my_chartab[c] <= 9)
st.prec = myatoul((const char*)(fmt-1), (char**)&fmt, 10), c = *fmt++;
}
if (c == 'l' || c == 'L') st.nrl++, c = *fmt++;
else if (c == 'h' || c == 'H') st.nrh++, c = *fmt++;
if (c == 'l' || c == 'L') st.nrl++, c = *fmt++;
else if (c == 'h' || c == 'H') st.nrh++, c = *fmt++;
switch(c) {
default: goto repeat;
case 0: goto finsh;
case 'c': st.buffer[0] = va_arg (ap, int);
st.buffer[1] = 0;
st.ptrout = st.buffer;
st.nlen = 1;
goto print_string;
case 's': st.ptrout = va_arg (ap, const char *);
if (st.ptrout == NULL) {
st.ptrout = "(NULL)";
st.nlen = 6;
st.filled = ' ';
goto print_string;
}
st.nlen = mystrlen(st.ptrout);
goto print_string;
case 'B': st.flags |= FLAGS_UPPER;
case 'b': st.base = 2;
goto get_and_print_int;
case 'X': st.flags |= FLAGS_UPPER;
case 'x': st.base = 16;
goto get_and_print_int;
case 'O': st.flags |= FLAGS_UPPER;
case 'o': st.base = 8;
goto get_and_print_int;
case 'U': st.flags |= FLAGS_UPPER;
case 'u':
goto get_and_print_int;
case 'd':
case 'i': st.flags |= FLAGS_SIGNED;
goto get_and_print_int;
case 'P': st.flags |= FLAGS_UPPER;
case 'p': st.base = 16;
st.width = sizeof (void *) * 2;
st.filled = '0';
st.value = (unsigned long) va_arg (ap, void*);
if (st.value == (unsigned long)(NULL)) {
st.ptrout = "NULL";
st.nlen = 4;
st.filled = ' ';
goto print_string;
}
goto print_ptr_int;
}
get_and_print_int:
if (st.base < 2 || st.base > 16)
st.base = 16;
switch(st.nrl) {
case 2: st.value = va_arg(ap, ullong);
if ((st.flags & FLAGS_SIGNED) && (sllong)st.value < 0)
st.sign = '-', st.value = (ullong)-(sllong)st.value;
break;
case 1: st.value = va_arg(ap, unsigned long);
if ((st.flags & FLAGS_SIGNED) && (signed long)st.value < 0)
st.sign = '-', st.value = (unsigned long)-(signed long)st.value;
break;
case 0: st.value = va_arg(ap, unsigned);
if ((st.flags & FLAGS_SIGNED) && (signed)st.value < 0)
st.sign = '-', st.value = (unsigned)-(signed)st.value;
if (st.nrh == 2) st.value &= 0xFF;
else if (st.nrh == 1) st.value &= 0xFFFF;
break;
}
print_ptr_int:
if (st.width > st.prec)
st.width = st.prec;
if (st.sign == 0 && (st.flags & FLAGS_ADD))
st.sign = '+';
if (st.width > (int)(sizeof (st.buffer) - 8))
st.width = sizeof (st.buffer) - 8;
cp = st.buffer + sizeof (st.buffer) - 1;
*cp = 0;
p_chartab = _my_tabchar;
if (st.flags & FLAGS_UPPER)
p_chartab = _my_tabCHAR;
uval = st.value;
i = 0;
do {
++i;
*--cp = p_chartab[uval % st.base];
} while ((uval /= st.base) != 0);
if (st.sign) i++;
if ((st.flags & FLAGS_SPEC)) {
if (st.base == 8 && *cp != 0) ++i, st.prefix = "0";
else if (st.base == 2) {
i += 2;
st.prefix = (st.flags & FLAGS_UPPER) ? "B0" : "b0";
}else if (st.base == 16) {
i += 2;
st.prefix = (st.flags & FLAGS_UPPER) ? "X0" : "x0";
}
}
if (st.filled == '0' && i < st.width) {
for (; i < st.width; ++i)
*--cp = st.filled;
}
if (st.prefix != NULL && st.prefix[0] != 0) {
for (str = st.prefix; *str; ++str)
*--cp = *str;
}
if (st.sign != 0)
*--cp = st.sign;
st.nlen = i;
st.ptrout = cp;
goto print_string;
print_string:
align = 0;
if (st.nlen > st.prec)
st.nlen = st.prec;
if (st.width > st.nlen)
align = st.width - st.nlen;
if ((st.flags & FLAGS_LEFT) == 0)
for (; align > 0; --align)
*dst++ = st.filled;
for (i = 0; i < st.nlen; ++i)
*dst++ = st.ptrout[i];
for (; align > 0; --align)
*dst++ = st.filled;
goto repeat;
finsh:
*dst++ = 0;
return 0;
}
int myprintf(const char *fmt, ...)
{
int res;
va_list ap;
char buff[256];
va_start(ap, fmt);
res = myvsprintf(buff, fmt, ap);
va_end(ap);
myputs(buff);
return res;
}
int mysprintf(char *s, const char *fmt, ...)
{
int res;
va_list ap;
va_start(ap, fmt);
res = myvsprintf(s, fmt, ap);
va_end(ap);
return res;
}









