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; }