printf的学习

首先从网上找到了glibc的标准库的内容,找到了里面的printf.c的函数实现
int
__printf (const char *format, ...)
{
  va_list arg;
  int done;

  va_start (arg, format);
  done = vfprintf (stdout, format, arg);
  va_end (arg);

  return done;
}

以前一直没有仔细看这个函数,她的返回值是一个整型,(其实就是返回成功在现实屏上输出的字符个数);她带有。。。额。。。不知道该说几个参数,第一个参数是一个字符串类型的指针常量(相当于一个数组的开头),然后是省略号...;这是变参的表示方法,表示我们具体有几个参数不确定,参数的个数是由第一个参数决定的(即第一个参数里面的内容可以决定后面一共有几个参数);

然后是   va_list arg;这一句,包含在头文件里面,这是一种变参列表的类型,可以用来保存字符串中的字符和变量之间的关系

接下来是
va_start (arg, format);
done = vfprintf (stdout, format, arg);
va_end (arg);
其中 va_start (arg, format);是把字符串format里面的内容提取参数到arg变参列表里面
done = vfprintf (stdout, format, arg);这里是调用另外一个现实函数vsprintf,把arg包含变参列表的内容以format格式输出到stdout(标准输出,PC上默认是电脑屏幕)
va_end (arg);结束转化

这是标准库里的实现,但是我们才使用嵌入式的时候还可以做一些改动,把标注输出到屏幕改成输出到UART串口上;
为了避免移植的时候要包括很多不知道的函数和头文件(一个没有包含就会出错,相互调用的太多了),所以就参考了网上以为大牛的博客,他是自己写了一个pritnf函数,亲测在linux ubuntu 15.10下可用

先贴上他的代码(其中我加了点注释和对效果的检查)
#include
#include

int my_printf(const char* string,...);

int main()
{
int x;

my_printf("the x is :%d\n", x);

my_printf("hello world!\n");

return 0;
}

int my_printf(const char* string,...)
{

char buffer[BUFSIZ];//Be tolerant with my_printf, never try to jump ovet the band of the buffer -- buffer overflow

int temp = 0;
va_list arg;

char* p_string = NULL;
char* p_buffer = buffer;
char* p_temp   = NULL;

int counter = 0; //the value is to return the numbers of the characters put into the 'puts' succeessfully (can be ignored)
int number   = 0;
int foo     = 0;

va_start(arg,string);

for(counter = 0,p_string = string;*(p_string) != '\0';)
{
switch(*p_string)
{
case '%':
p_string++;

switch(*p_string)
{
case 'd': //the value is a number

temp = va_arg(arg,int);

foo = temp;

while(foo)
{
number++;
counter++;
foo /= 10;
}

foo = temp;

while(number)
{
*(p_buffer+number-1) = (foo);
foo /= 10;
number--;
}

p_buffer += number;
break;

case 'c': //the value is a character
temp = va_arg(arg,int);
*(p_buffer++) = temp;
break;

case 's': //the value is a string of characters
p_temp = va_arg(arg,char*);

while(p_temp != NULL)
{
*(p_buffer++) = *(p_temp++);
counter++;
}
break;

default:
break;

}
break;

default:
        *(p_buffer++) = *(p_string++);
        counter++;
}
  }

va_end(arg);

p_buffer = NULL;

puts(buffer);

return counter;
}

下面说说具体思路,同标准库的printf,首先进行参数列表的提取,然后判断接下来的字符是否代表参数,如果是参数则改变原来的字符串,判断完整个字符串后(字符串长度可能会改变),则结束参量转换,最后把得到的 新的字符串用其它方式输出,比如可以用串口,或者其它的print显示函数。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值