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

 

 

 

 

posted on 2020-07-03 11:10  lizhuohui  阅读(74)  评论(0编辑  收藏  举报

导航