本帖最后由 ufbycd 于 2018-9-1 14:10 编辑
看到有人写了分享贴,吓我一跳,以为是分享printf实现!进去一看却不是!还是我来吧!
[mw_shl_code=c,true]
/*
BYTE_OUT is the only external dependency for this file,
if you have a working BYTE_OUT, leave it commented out.
If not, uncomment the define below and
replace outbyte(c) by your own function call.
#define BYTE_OUT(c) outbyte(c)
*/
#include "serial.h"
#include <stdarg.h>
#define BYTE_OUT(c) Serial_PutChar(c)
#define SUPPOR_LONG_LONG 0
#define PRINT_FLOAT_AGINST_DOUBLE 0
#if ! PRINT_FLOAT_AGINST_DOUBLE
# undef SUPPOR_LONG_LONG
# define SUPPOR_LONG_LONG 1
#endif
struct _mbuf
{
int isSizeLimited;
size_t size;
char *data;
};
static int printchar(struct _mbuf *sbuf, int c)
{
if (sbuf)
{
if (sbuf->isSizeLimited)
{
if (sbuf->size < 1)
return -1;
else if (sbuf->size == 1)
{
*(sbuf->data) = ' ';
sbuf->size = 0;
return 1;
}
}
*(sbuf->data) = (char) c;
sbuf->data += 1;
sbuf->size -= 1;
}
else
{
BYTE_OUT((uint8_t)c);
}
return 1;
}
#define PAD_RIGHT 1
#define PAD_ZERO 2
static int prints(struct _mbuf *sbuf, const char *string, int width, int pad)
{
register int pc = 0, padchar = ' ';
if (width > 0)
{
register int len = 0;
register const char *ptr;
for (ptr = string; *ptr; ++ptr)
++len;
if (len >= width)
width = 0;
else
width -= len;
if (pad & PAD_ZERO)
padchar = '0';
}
if (!(pad & PAD_RIGHT))
{
for (; width > 0; --width)
{
printchar(sbuf, padchar);
++pc;
}
}
for (; *string; ++string)
{
printchar(sbuf, *string);
++pc;
}
for (; width > 0; --width)
{
printchar(sbuf, padchar);
++pc;
}
return pc;
}
/* the following should be enough for 32 bit int */
#define PRINT_BUF_LEN 24
static int printInt(struct _mbuf *sbuf, int value, int ary, int sg, int width,
int pad, int letbase)
{
char print_buf[PRINT_BUF_LEN];
register char *str;
register int t, neg = 0, pc = 0;
register unsigned int u = value;
if (value == 0)
{
print_buf[0] = '0';
print_buf[1] = ' ';
return prints(sbuf, print_buf, width, pad);
}
if (sg && (ary == 10) && (value < 0))
{
neg = 1;
u = -value;
}
str = print_buf + PRINT_BUF_LEN - 1;
*str = ' ';
while (u)
{
t = u % ary;
if (t >= 10)
t += letbase - '0' - 10;
*--str = t + '0';
u /= ary;
}
if (neg)
{
if (width && (pad & PAD_ZERO))
{
printchar(sbuf, '-');
++pc;
--width;
}
else
{
*--str = '-';
}
}
return pc + prints(sbuf, str, width, pad);
}
#if SUPPOR_LONG_LONG
static int printLongLongInt(struct _mbuf *sbuf, long long int value, int ary,
int sg, int width, int pad, int letbase)
{
char print_buf[PRINT_BUF_LEN];
register char *str;
register int t, neg = 0, pc = 0;
register unsigned long long int u = value;
if (value == 0)
{
print_buf[0] = '0';
print_buf[1] = ' ';
return prints(sbuf, print_buf, width, pad);
}
if (sg && ary == 10 && value < 0)
{
neg = 1;
u = -value;
}
str = print_buf + PRINT_BUF_LEN - 1;
*str = ' ';
while (u)
{
t = u % ary;
if (t >= 10)
t += letbase - '0' - 10;
*--str = t + '0';
u /= ary;
}
if (neg)
{
if (width && (pad & PAD_ZERO))
{
printchar(sbuf, '-');
++pc;
--width;
}
else
{
*--str = '-';
}
}
return pc + prints(sbuf, str, width, pad);
}
#else
# define printLongLongInt(sbuf, value, ary, sg, width, pad, letbase) 0
#endif
#if ! PRINT_FLOAT_AGINST_DOUBLE
static int printDouble(struct _mbuf *sbuf, double value, int ary, int width,
int precision, int pad, int letbase)
{
int num;
long long int llvalue, lli;
unsigned long long ull;
int i;
num = 0;
llvalue = (long long int) value;
num += printLongLongInt(sbuf, llvalue, ary, 1, width, pad, letbase);
printchar(sbuf, '.');
num += 1;
lli = 1;
for (i = 0; i < precision; i++)
{
lli *= 10;
}
value -= (double)llvalue;
llvalue = (long long int) (value * lli); // 加 0.5 作四舍五入
ull = (llvalue > 0) ? llvalue : -llvalue;
num += printLongLongInt(sbuf, ull, ary, 1, precision, PAD_ZERO, letbase);
return num;
}
#else
static int printFloat(struct _mbuf *sbuf, float value, int ary, int width, int precision, int pad, int letbase)
{
int num;
int32_t llvalue, lli;
uint32_t uli;
int i;
num = 0;
llvalue = (int32_t) value;
num += printInt(sbuf, llvalue, ary, 1, width, pad, letbase);
printchar(sbuf, '.');
num += 1;
lli = 1;
for(i = 0; i < precision; i++)
{
lli *= 10;
}
value -= llvalue;
llvalue = (int32_t) (value * lli);
uli = (llvalue > 0) ? llvalue : - llvalue;
num += printInt(sbuf, uli, ary, 1, precision, PAD_ZERO, letbase);
return num;
}
#endif
/**
* @brief A format specifier follows this prototype:
* %[flags][width][.precision][length]specifier
*
* @param out
* @param format
* @param args
* @return
*/
static int print(struct _mbuf *sbuf, const char *format, va_list args)
{
register int width, precision, pad;
register int num = 0;
char scr[2];
char c, *pchar;
enum _length
{
_normal = 0, _short, _short_short, _long, _long_long
} length;
for (; *format != 0; ++format)
{
if (*format != '%')
{
printchar(sbuf, *format);
++num;
}
else if (format[1] == '%')
{
printchar(sbuf, '%');
++format;
++num;
}
else
{
++format;
width = 0;
precision = 0;
length = _normal;
pad = 0;
c = *format;
if (c == ' ')
break;
/* parse flags */
switch (c)
{
case '-':
pad = PAD_RIGHT;
++format;
break;
case '+':
case '#':
++format;
break;
case '0':
pad |= PAD_ZERO;
++format;
break;
}
/* Parse width */
while ((*format >= '0') && (*format <= '9'))
{
width *= 10;
width += *format - '0';
++format;
}
/* Parse precision */
if (*format == '.')
{
++format;
while ((*format >= '0') && (*format <= '9'))
{
precision *= 10;
precision += *format - '0';
++format;
}
}
else
{
precision = 6;
}
/* parse length */
switch (*format)
{
case 'l':
if (format[1] == 'l')
{
length = _long_long;
++format;
}
else
length = _long;
++format;
break;
case 'h':
if (format[1] == 'h')
format += 2;
break;
case 'L':
case 'j':
case 'z':
case 't':
++format;
break;
}
int letbase;
if (*format >= 'a')
letbase = 'a';
else
letbase = 'A';
/* parse specifier */
switch (*format)
{
case 's':
pchar = (char *) va_arg(args, int);
num += prints(sbuf, pchar ? pchar : "(null)", width, pad);
break;
case 'd':
if (length == _long_long)
num += printLongLongInt(sbuf, va_arg(args, long long int),
10, 1, width, pad, letbase);
else if (length == _long)
num += printInt(sbuf, va_arg(args, long int), 10, 1, width,
pad, letbase);
else
num += printInt(sbuf, va_arg(args, int), 10, 1, width, pad,
letbase);
break;
case 'x':
case 'X':
if (length == _long_long)
num += printLongLongInt(sbuf,
va_arg(args, long long int), 16, 0, width,
pad, letbase);
else if (length == _long)
num += printInt(sbuf, va_arg(args, long int), 16,
0, width, pad, letbase);
else
num += printInt(sbuf, va_arg(args, int), 16, 0,
width, pad, letbase);
break;
case 'u':
case 'p':
if (length == _long_long)
num += printLongLongInt(sbuf,
va_arg(args, long long int), 10, 0, width,
pad, letbase);
else if (length == _long)
num += printInt(sbuf, va_arg(args, long int), 10,
0, width, pad, letbase);
else
num += printInt(sbuf, va_arg(args, int), 10, 0,
width, pad, letbase);
break;
case 'o':
if (length == _long_long)
num += printLongLongInt(sbuf,
va_arg(args, long long int), 8, 0, width,
pad, letbase);
else if (length == _long)
num += printInt(sbuf, va_arg(args, long int), 8, 0,
width, pad, letbase);
else
num += printInt(sbuf, va_arg(args, int), 8, 0,
width, pad, letbase);
break;
case 'c':
/** @note char are converted to int then pushed on the stack */
scr[0] = (char) va_arg(args, int);
scr[1] = ' ';
num += prints(sbuf, scr, width, pad);
break;
case 'f':
case 'F':
case 'e':
case 'E':
case 'g':
case 'G':
#if PRINT_FLOAT_AGINST_DOUBLE
num += printFloat(sbuf, va_arg(args, float), 10, width, precision, pad, letbase);
#else
num += printDouble(sbuf, va_arg(args, double), 10, width,
precision, pad, letbase);
#endif
break;
}
}
}
if (sbuf)
printchar(sbuf, ' ');
va_end(args);
return num;
}
int printf (const char *format, ...)
{
int ret;
va_list args;
va_start(args, format);
ret = print(NULL, format, args);
va_end(args);
return ret;
}
int vprintf(const char *format, va_list args)
{
return print(NULL, format, args);
}
int sprintf(char *out, const char *format, ...)
{
va_list args;
struct _mbuf mybuf =
{ 0, (size_t) -1, out };
va_start(args, format);
return print(&mybuf, format, args);
}
int vsprintf(char *out, const char *format, va_list args)
{
struct _mbuf mybuf =
{ 0, (size_t) -1, out };
return print(&mybuf, format, args);
}
int snprintf(char *out, unsigned int size, const char *format, ...)
{
va_list args;
struct _mbuf mybuf =
{ 1, size, out };
va_start(args, format);
return print(&mybuf, format, args);
}
int puts(const char *s)
{
int i;
char c;
c = *s++;
for (i = 0; c != ' '; i++)
{
BYTE_OUT((uint8_t)c);
c = *s++;
}
BYTE_OUT('
');
return i + 1;
}
[/mw_shl_code]
因为感觉C库的printf体积比自己实现的要大挺多,所以实际工程项目都是用这个printf实现。
不用屏蔽原来的重定向,如果不屏蔽就有输出,说明还是链接到C库里的printf了
一周热门 更多>