简短回答:是的,完全可以同时实现你的两种解决方案。
如果您想支持所有数据类型和格式,printf函数会相当复杂。但是,写出能够输出字符串或整数的代码并在几个不同的进制下运行并不难(大多数人只需要十进制和十六进制,但是有了十进制和十六进制后,八进制可能只需要另外3-4行代码)。
通常,printf的编写方式如下:
int printf(const char *fmt, ...)
{
int ret;
va_list args;
va_start(args, fmt)
ret = do_xprintf(outputfunc, NULL, fmt, args);
va_end(args);
return ret;
}
然后do_xprintf()
为所有变体(如printf,sprintf,fprintf等)完成所有繁重的工作
int do_xprintf(void (*outputfunc)(void *extra, char c), void *extra, const char *fmt, va_list args)
{
char *ptr = fmt;
while(1)
{
char c = *ptr++;
if (c == '%')
{
c = *ptr++;
switch(c)
{
case 's':
char *str = va_arg(args, const char *);
while(*str)
{
count++;
outputfunc(extra, *str);
str++;
}
break;
case 'x':
base = 16;
goto output_number;
case 'd':
base = 10;
output_number:
int i = va_arg(args, int);
break;
default:
count++;
outputfunc(extra, c);
break;
}
else
count++;
outputfunc(extra, c);
}
return count;
}
现在,您只需要填写以上代码的一些部分并编写一个outputfunc()函数,将其输出到串行端口即可。
请注意这只是粗略的草图,我相信代码中可能会有一些错误 - 如果您想支持浮点数或“宽度”,则需要做更多的工作......
(关于额外参数的说明 - 对于FILE *
输出,应该是文件指针;对于sprintf
,您可以传递缓冲区和缓冲区中的位置等结构体信息)