printf函数简洁实现
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
int My_putchar(int ch)
{
HalSerial_UARTWrite((uint8 *)&ch, 1);
return ch;
}
char* My_itoa(int value,char str[],int radix)
{
char temp[33];
char *tp = temp;
int i;
unsigned v;
int sign;
char *sp;
if(radix > 36 || radix < 1)
return 0;
sign = (radix == 10 && value < 0); //十进制负数
if(sign)
v = -value;
else
v = (unsigned)value;
while(v || tp == temp) //转化操作
{
i = v % radix;
v = v / radix;
if(i < 10)
*tp++ = i + '0';
else
*tp++ = i + 'A' - 10;
}
if(str == 0)
str = (char*)malloc((tp - temp) + sign + 1);
sp = str;
if(sign) //是负数的话把负号先加入数组
*sp++ = '-';
while(tp > temp)
*sp++ = *--tp;
*sp = 0;
return str;
}
int printf(const char *fmt, ...)
{
const char *s;
int d;
char buf[16];
va_list ap;
va_start(ap, fmt);
while (*fmt) {
if (*fmt != '%') {
My_putchar(*fmt++);
continue;
}
switch (*++fmt) {
case 's':
s = va_arg(ap, const char *);
for ( ; *s; s++) {
My_putchar(*s);
}
break;
case 'd':
d = va_arg(ap, int);
My_itoa(d, buf, 10);
for (s = buf; *s; s++) {
My_putchar(*s);
}
break;
case 'X':
d = va_arg(ap, int);
My_itoa(d, buf, 16);
for (s = buf; *s; s++) {
My_putchar(*s);
}
break;
/* Add other specifiers here... */
default:
My_putchar(*fmt);
break;
}
fmt++;
}
va_end(ap);
return 1; /* Dummy return value */
}
但是,上面的这个函数在一些很小的芯片上,依然跑不起来,比如,
CC2541单片机,程序使用的是CLIB,所以,不但对printf不支持,连可变参数 va_list va_start 都不完整支持,
这个时候,就只能使用 sprintf 大法了,如下:
注意:打印缓存要使用全局变量,因为很多便宜的单片机,堆栈一不小心就溢出了,这样打印用的局部数组,最容易溢出了。
extern char g_buf[];
#define printbase(...) do {sprintf(g_buf, __VA_ARGS__); HalSerial_UARTWrite_Str(g_buf);} while (0)
#define print_str(...) printbase(__VA_ARGS__)
char g_buf[100];