嵌入式操作系统---打印函数(printf/sprintf)的实现


https://blog.csdn.net/u010961173/article/details/79769747

格式化输出函数:printf/sprintf/fprintf/snprintf等等

一、打印函数简介

作用:将“给定的内容”按照“指定的格式”输出到“指定目标内”。

打印函数的基本格式:

 

char print_buf[BUF_SIZE];
void printf(const char *fmt, ...)
{
    va_list ap;//定义一个指针变量
    unsigned int i;
 
    va_start (ap, fmt);
    i = vsprintf (print_buf, sizeof(print_buf),fmt, ap);
    va_end (args);
 
    __put_char (print_buf,i);
}

 

printf(const char *fmt,...)是一个可变参数函数,第一个参数为字符串,后面是格式化输出参数列表。

c语言中函数的参数都是压进栈里的,可变参数函数必须有一个参数表示参数的个数,才能让编译器知道要压进栈多少参数,以及函数返回时弹出多少参数,printf(char *fmt,...)实现这个功能的是fmt字符串,里面有多少'%',就代表后面有多少个参数,所以我们必须提取出fmt字符串中'%'的个数,以及针对'%'后面不同的字符来处理参数。

 

const char *fmt定义了一个只读字符指针;“...”表示printf的参数是可变的;

 

va_list ap:定义一个字符型指针变量

 

va_start(argv,i):初始化argv

 

c=va_arg(argv,int):在已知变量的情况下,获得下一个变参变量

 

va_end(argv):结束变参变量操作

 

其中,__put_char()将字符逐个打印到串口输出寄存器中。

void __put_char(char *p,int num){
while(*p&&num--){
*(volatile unsigned int *)0xd0000020=*p++;
};
}

 

二、打印函数的实现

 

1、变参函数的实现(宏定义)

(1)va_list

typedef char * va_list;
va_list       ap;        //定义一个指针类型

(2)va_start(ap,fmt) 

#define va_start(ap,fmt) ( ap = (va_list)&fmt + _INTSIZEOF(fmt) )

ap指向函数栈中变参列表第一个参数的首地址;

____________________________

|___________________________|

|                      argn                              |

|                      ........                              |

|                      arg0                              |<----ap(sizeof(int)大小对齐)

|                      fmt                                 |

|                      pc                                  |

|___________________________|

 

注意:传给宏va_start的参数fmt是可变参数列表中的前一个参数,ap指向变参列表中第一个参数地址。

注意:函数参数压栈时,参数的入栈顺序是从右向左,出栈时是从左向右。函数调用时,先把若干个参数都压入栈中,再压fmt,最后压pc,这样一来,栈顶指针偏移便找到了fmt,通过fmt中的%占位符,取得后面参数的个数,从而正确取得所有参数。

 

#define _INTSIZEOF(n)   ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )

 

计算int类型按4字节(int占4字节)对齐后的结果。通过使用_INTSIZEOF(n),可以根据一个变量的类型计算变量在内存中占用的字节数,从而正确定位参数在内存的位置。

对于short、char类型的数据,因为不满一个int类型的内存空间,所以按照int类型对齐;

(3)va_arg(ap,type)

#define va_arg(ap,type) ( *(type *)((ap += _INTSIZEOF(type)) - _INTSIZEOF(type)) )

指针变量ap本身指向变参列表中的下一个参数地址,va_arg取出的是当前参数的值

(4)va_end(ap)

#define va_end(ap)    ( ap = (va_list)0 )

ap指向空

2、vsprintf(char *buf, const char *fmt, va_list args)函数实现

函数功能:将变量列表args中的参数按照fmt中规定的格式保存到临时缓存buf中。

int vsprintf(char *buf, canst char *fmt, va_list args) 
{
    unsigned NUM_TYPE num;
    int base;
    char*str;
    int flags;
    int field_width;
    int Precision;
    int qualifier;
    str = bUf;
 
    for (; *fmt ; ++fmt) 
    {
        if (* fmt ! = ' % ' )
        {
            *str++ = *fmt;
            continue;
        }
 
        /* process flags */
        flags = 0;
        repeat:
        ++fmt;/* skip first "%" */
 
        switch(*fmt)
        {
            case '- ' : flags |= LEFT;goto repeat;
            case '+ ' : flags |= PLUS;goto repeat;
            ...
        }
        ...
        base = 10;
 
        switch (*fmt){
        case 'c':
            ...
            *str++ (unsigned char)va_arg(args,int);
            ...
        continue;
 
 
        case 's':
            str = string(str,va_arg(args, char *),field_width,precision,flags);
        continue;
        ...
 
        case ' X ' :
            base = 16;
        break;
 
        case 'd':
 
 
        case ' i '
            flags |= SIGN;
 
        case 'u':
            break;
 
        default:
            * str++ ='%';
        if (*fmt)
            *str++ = *fmt;
        else
            --fmt ;
            continue;
        }
        str = number (str, num, base, field_width, precision, flags) ;
 
    }
    *str == '\0';
 
    return str-buf;
}

 

三、实现自己的打印函数

int vsnprintf(char *buf, int size, const char *fmt, va_list args){
    int num;
    char *str, *end, c,*s;
    int read;
    unsigned int spec=0;

    str = buf;//临时缓存buf首地址
    end = buf + size;//临时缓存buff结束地址

    if (end < buf) {
        end = ((void *)-1);
        size = end - buf;
    }

    while (*fmt) {
        const char *old_fmt = fmt;//保存原来fmt的格式的首地址

        read = <strong><span style="color:#ff0000;">format_decode</span></strong>(fmt, &spec);//判断参数的格式,保存到spec中,read为当前参数在字符串中的指针偏移
        fmt += read;//指针偏移到本参数格式的下一位字符的地址

        if((FORMAT_TYPE(spec))==FORMAT_TYPE_NONE){
            int copy = read;
            if (str < end) {
                if (copy > end - str)//防止buff空间不足越界
                    copy = end - str;
                    memcpy(str, old_fmt, copy);//原样拷贝到buff中
            }
            str += read;//更新字符偏移


        }else if(spec&FORMAT_FLAG_WIDTH){
            //do nothing
        }else if(FORMAT_TYPE(spec)==FORMAT_TYPE_CHAR){//字符类型,直接拷贝
            c = (unsigned char) va_arg(args, int);
            if (str < end)
                *str = c;
            ++str;
        }else if(FORMAT_TYPE(spec)==FORMAT_TYPE_STR){//字符串类型,直接拷贝
            s = (char *) va_arg(args, char *);
            while(str<end&&*s!='\0'){
                *str++=*s++;
            }
        }else{//数值型,进行转换
            if(FORMAT_TYPE(spec)==FORMAT_TYPE_INT){
                num = va_arg(args, int);
            }else if(FORMAT_TYPE(spec)==FORMAT_TYPE_ULONG){
                num = va_arg(args, unsigned long);
            }else if(FORMAT_TYPE(spec)==FORMAT_TYPE_LONG){
                num = va_arg(args, long);
            }else if(FORMAT_TYPE(spec)==FORMAT_TYPE_SIZE_T){
                num = va_arg(args, int);
            }else if(FORMAT_TYPE(spec)==FORMAT_TYPE_USHORT){
                num = (unsigned short) va_arg(args, int);
            }else if(FORMAT_TYPE(spec)==FORMAT_TYPE_SHORT){
                num = (short) va_arg(args, int);
            }else{
                num = va_arg(args, unsigned int);
            }
                str=<strong><span style="color:#ff0000;">number</span></strong>(str,num,spec&FORMAT_BASE_MASK,spec);
        }
    }
    if (size > 0) {
        if (str < end)
            *str = '\0';
        else
            end[-1] = '\0';
    }
    return str-buf;
}

format_decode(fmt, &spec);//判断参数的格式,保存到spec中,read为当前参数在字符串中的指针偏移 fmt += read;//指针偏移到本参数格式的下一位字符的地址 if((FORMAT_TYPE(spec))==FORMAT_TYPE_NONE){ int copy = read; if (str < end) { if (copy > end - str)//防止buff空间不足越界 copy = end - str; memcpy(str, old_fmt, copy);//原样拷贝到buff中 } str += read;//更新字符偏移 }else if(spec&FORMAT_FLAG_WIDTH){ //do nothing }else if(FORMAT_TYPE(spec)==FORMAT_TYPE_CHAR){//字符类型,直接拷贝 c = (unsigned char) va_arg(args, int); if (str < end) *str = c; ++str; }else if(FORMAT_TYPE(spec)==FORMAT_TYPE_STR){//字符串类型,直接拷贝 s = (char *) va_arg(args, char *); while(str<end&&*s!='\0'){ *str++=*s++; } }else{//数值型,进行转换 if(FORMAT_TYPE(spec)==FORMAT_TYPE_INT){ num = va_arg(args, int); }else if(FORMAT_TYPE(spec)==FORMAT_TYPE_ULONG){ num = va_arg(args, unsigned long); }else if(FORMAT_TYPE(spec)==FORMAT_TYPE_LONG){ num = va_arg(args, long); }else if(FORMAT_TYPE(spec)==FORMAT_TYPE_SIZE_T){ num = va_arg(args, int); }else if(FORMAT_TYPE(spec)==FORMAT_TYPE_USHORT){ num = (unsigned short) va_arg(args, int); }else if(FORMAT_TYPE(spec)==FORMAT_TYPE_SHORT){ num = (short) va_arg(args, int); }else{ num = va_arg(args, unsigned int); } str=number(str,num,spec&FORMAT_BASE_MASK,spec); } } if (size > 0) { if (str < end) *str = '\0'; else end[-1] = '\0'; } return str-buf; }

 

(1)format_decode函数

作用:判断格式化的符号及类型;

flags:第0字节:若为数值,作为数值基数;
           第1字节:格式类型,字符,整形,长整型,短整型等;
           第2字节:若为数值,表示数值符号;

int format_decode(const char *fmt,unsigned int *flags){
    const char *start = fmt;
 
    *flags &= ~FORMAT_TYPE_MASK;
    *flags |= FORMAT_TYPE_NONE;
    for (; *fmt ; ++fmt) {
        if (*fmt == '%')
        break;
    }
 
    if (fmt != start || !*fmt)
        return fmt - start;
 
    do{
        fmt++;
        switch(*fmt){
            case 'l':
                SET_FORMAT_FLAG(*flags,FORMAT_FLAG_WIDTH);
                break;
            default:
                break;
        }
    }while(0);
    
    SET_FORMAT_BASE(*flags,FORMAT_BASE_D);
    switch (*fmt) {
        case 'c':
            SET_FORMAT_TYPE(*flags,FORMAT_TYPE_CHAR);
            break;
 
        case 's':
            SET_FORMAT_TYPE(*flags,FORMAT_TYPE_STR);
            break;
 
        case 'o':
            SET_FORMAT_BASE(*flags,FORMAT_BASE_O);
            SET_FORMAT_TYPE(*flags,FORMAT_TYPE_UINT);
            break;
 
        case 'x':
        case 'X':
            SET_FORMAT_BASE(*flags,FORMAT_BASE_X);
            SET_FORMAT_TYPE(*flags,FORMAT_TYPE_UINT);
            break;
 
        case 'd':
        case 'i':
            SET_FORMAT_TYPE(*flags,FORMAT_TYPE_INT);
            SET_FORMAT_BASE(*flags,FORMAT_BASE_D);
            break;
        case 'u':
            SET_FORMAT_TYPE(*flags,FORMAT_TYPE_UINT);
            SET_FORMAT_BASE(*flags,FORMAT_BASE_D);
            break;
 
    default:
        break;
    }
    return ++fmt-start;//参数偏移的字节数
}
SET_FORMAT_FLAG(*flags,FORMAT_FLAG_WIDTH);
                break;
            default:
                break;
        }
    }while(0);
    
    SET_FORMAT_BASE(*flags,FORMAT_BASE_D);
    switch (*fmt) {
        case 'c':
            SET_FORMAT_TYPE(*flags,FORMAT_TYPE_CHAR);
            break;

        case 's':
            SET_FORMAT_TYPE(*flags,FORMAT_TYPE_STR);
            break;

        case 'o':
            SET_FORMAT_BASE(*flags,FORMAT_BASE_O);
            SET_FORMAT_TYPE(*flags,FORMAT_TYPE_UINT);
            break;

        case 'x':
        case 'X':
            SET_FORMAT_BASE(*flags,FORMAT_BASE_X);
            SET_FORMAT_TYPE(*flags,FORMAT_TYPE_UINT);
            break;

        case 'd':
        case 'i':
            SET_FORMAT_TYPE(*flags,FORMAT_TYPE_INT);
            SET_FORMAT_BASE(*flags,FORMAT_BASE_D);
            break;
        case 'u':
            SET_FORMAT_TYPE(*flags,FORMAT_TYPE_UINT);
            SET_FORMAT_BASE(*flags,FORMAT_BASE_D);
            break;

    default:
        break;
    }
    return ++fmt-start;//参数偏移的字节数
}

SET_FORMAT_FLAG(*flags,FORMAT_FLAG_WIDTH); break; default: break; } }while(0); SET_FORMAT_BASE(*flags,FORMAT_BASE_D); switch (*fmt) { case 'c': SET_FORMAT_TYPE(*flags,FORMAT_TYPE_CHAR); break; case 's': SET_FORMAT_TYPE(*flags,FORMAT_TYPE_STR); break; case 'o': SET_FORMAT_BASE(*flags,FORMAT_BASE_O); SET_FORMAT_TYPE(*flags,FORMAT_TYPE_UINT); break; case 'x': case 'X': SET_FORMAT_BASE(*flags,FORMAT_BASE_X); SET_FORMAT_TYPE(*flags,FORMAT_TYPE_UINT); break; case 'd': case 'i': SET_FORMAT_TYPE(*flags,FORMAT_TYPE_INT); SET_FORMAT_BASE(*flags,FORMAT_BASE_D); break; case 'u': SET_FORMAT_TYPE(*flags,FORMAT_TYPE_UINT); SET_FORMAT_BASE(*flags,FORMAT_BASE_D); break; default: break; } return ++fmt-start;//参数偏移的字节数 }

(2)number函数

函数功能:根据类型进行数值转换

char *number(char *str, int num,int base,unsigned int flags){
    int i=0;
    int sign=0;
 
    if(FORMAT_SIGNED(flags)&&(signed int)num<0){
        sign=1;
        num=~num+1;
    }
 
    do{
        numbers[i++]=digits[do_div(num,base)];
    }while(num!=0);
    
 
    if(FORMAT_BASE(flags)==FORMAT_BASE_O){
        numbers[i++]='0';
    }else if(FORMAT_BASE(flags)==FORMAT_BASE_X){
        numbers[i++]='x';
        numbers[i++]='0';
    }else if(FORMAT_BASE(flags)==FORMAT_BASE_B){
        numbers[i++]='b';
        numbers[i++]='0';
    }
    if(sign)
        numbers[i++]='-';
 
    while (i-- > 0)
            *str++ = numbers[i];
    return str;
}

 

嵌入式操作系统---打印函数(printf/sprintf)的实现

 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010961173/article/details/79769747

格式化输出函数:printf/sprintf/fprintf/snprintf等等

一、打印函数简介

作用:将“给定的内容”按照“指定的格式”输出到“指定目标内”。

打印函数的基本格式:

  1.  
    char print_buf[BUF_SIZE];
  2.  
    void printf(const char *fmt, ...)
  3.  
    {
  4.  
    va_list ap; //定义一个指针变量
  5.  
    unsigned int i;
  6.  
     
  7.  
    va_start (ap, fmt);
  8.  
    i = vsprintf (print_buf, sizeof(print_buf),fmt, ap);
  9.  
    va_end (args);
  10.  
     
  11.  
    __put_char (print_buf,i);
  12.  
    }

printf(const char *fmt,...)是一个可变参数函数,第一个参数为字符串,后面是格式化输出参数列表。
c语言中函数的参数都是压进栈里的,可变参数函数必须有一个参数表示参数的个数,才能让编译器知道要压进栈多少参数,以及函数返回时弹出多少参数,printf(char *fmt,...)实现这个功能的是fmt字符串,里面有多少'%',就代表后面有多少个参数,所以我们必须提取出fmt字符串中'%'的个数,以及针对'%'后面不同的字符来处理参数。

const char *fmt定义了一个只读字符指针;“...”表示printf的参数是可变的;

va_list ap:定义一个字符型指针变量

va_start(argv,i):初始化argv

c=va_arg(argv,int):在已知变量的情况下,获得下一个变参变量

va_end(argv):结束变参变量操作

其中,__put_char()将字符逐个打印到串口输出寄存器中。

void __put_char(char *p,int num){
while(*p&&num--){
*(volatile unsigned int *)0xd0000020=*p++;
};
}

二、打印函数的实现

1、变参函数的实现(宏定义)

(1)va_list

  1.  
    typedef char * va_list;
  2.  
    va_list ap; //定义一个指针类型

(2)va_start(ap,fmt) 

#define va_start(ap,fmt) ( ap = (va_list)&fmt + _INTSIZEOF(fmt) )

ap指向函数栈中变参列表第一个参数的首地址;

____________________________
|___________________________|
|                      argn                              |
|                      ........                              |
|                      arg0                              |<----ap(sizeof(int)大小对齐)
|                      fmt                                 |
|                      pc                                  |
|___________________________|

注意:传给宏va_start的参数fmt是可变参数列表中的前一个参数,ap指向变参列表中第一个参数地址。
注意:函数参数压栈时,参数的入栈顺序是从右向左,出栈时是从左向右。函数调用时,先把若干个参数都压入栈中,再压fmt,最后压pc,这样一来,栈顶指针偏移便找到了fmt,通过fmt中的%占位符,取得后面参数的个数,从而正确取得所有参数。

#define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )

计算int类型按4字节(int占4字节)对齐后的结果。通过使用_INTSIZEOF(n),可以根据一个变量的类型计算变量在内存中占用的字节数,从而正确定位参数在内存的位置。

对于short、char类型的数据,因为不满一个int类型的内存空间,所以按照int类型对齐;

(3)va_arg(ap,type)

#define va_arg(ap,type) ( *(type *)((ap += _INTSIZEOF(type)) - _INTSIZEOF(type)) )

指针变量ap本身指向变参列表中的下一个参数地址,va_arg取出的是当前参数的值

(4)va_end(ap)

#define va_end(ap) ( ap = (va_list)0 )

ap指向空

 

2、vsprintf(char *buf, const char *fmt, va_list args)函数实现

函数功能:将变量列表args中的参数按照fmt中规定的格式保存到临时缓存buf中。

  1.  
    int vsprintf(char *buf, canst char *fmt, va_list args)
  2.  
    {
  3.  
    unsigned NUM_TYPE num;
  4.  
    int base;
  5.  
    char*str;
  6.  
    int flags;
  7.  
    int field_width;
  8.  
    int Precision;
  9.  
    int qualifier;
  10.  
    str = bUf;
  11.  
     
  12.  
    for (; *fmt ; ++fmt)
  13.  
    {
  14.  
    if (* fmt ! = ' % ' )
  15.  
    {
  16.  
    *str++ = *fmt;
  17.  
    continue;
  18.  
    }
  19.  
     
  20.  
    /* process flags */
  21.  
    flags = 0;
  22.  
    repeat:
  23.  
    ++fmt; /* skip first "%" */
  24.  
     
  25.  
    switch(*fmt)
  26.  
    {
  27.  
    case '- ' : flags |= LEFT; goto repeat;
  28.  
    case '+ ' : flags |= PLUS; goto repeat;
  29.  
    ...
  30.  
    }
  31.  
    ...
  32.  
    base = 10;
  33.  
     
  34.  
    switch (*fmt){
  35.  
    case 'c':
  36.  
    ...
  37.  
    *str++ ( unsigned char)va_arg(args, int);
  38.  
    ...
  39.  
    continue;
  40.  
     
  41.  
     
  42.  
    case 's':
  43.  
    str = string(str,va_arg(args, char *),field_width,precision,flags);
  44.  
    continue;
  45.  
    ...
  46.  
     
  47.  
    case ' X ' :
  48.  
    base = 16;
  49.  
    break;
  50.  
     
  51.  
    case 'd':
  52.  
     
  53.  
     
  54.  
    case ' i '
  55.  
    flags |= SIGN;
  56.  
     
  57.  
    case 'u':
  58.  
    break;
  59.  
     
  60.  
    default:
  61.  
    * str++ = '%';
  62.  
    if (*fmt)
  63.  
    *str++ = *fmt;
  64.  
    else
  65.  
    --fmt ;
  66.  
    continue;
  67.  
    }
  68.  
    str = number (str, num, base, field_width, precision, flags) ;
  69.  
     
  70.  
    }
  71.  
    *str == '\0';
  72.  
     
  73.  
    return str-buf;
  74.  
    }

三、实现自己的打印函数

int vsnprintf(char *buf, int size, const char *fmt, va_list args){
	int num;
	char *str, *end, c,*s;
	int read;
	unsigned int spec=0;

	str = buf;//临时缓存buf首地址
	end = buf + size;//临时缓存buff结束地址

	if (end < buf) {
		end = ((void *)-1);
		size = end - buf;
	}

	while (*fmt) {
		const char *old_fmt = fmt;//保存原来fmt的格式的首地址

		read = <strong><span style="color:#ff0000;">format_decode</span></strong>(fmt, &spec);//判断参数的格式,保存到spec中,read为当前参数在字符串中的指针偏移
		fmt += read;//指针偏移到本参数格式的下一位字符的地址

		if((FORMAT_TYPE(spec))==FORMAT_TYPE_NONE){
			int copy = read;
			if (str < end) {
				if (copy > end - str)//防止buff空间不足越界
					copy = end - str;
					memcpy(str, old_fmt, copy);//原样拷贝到buff中
			}
			str += read;//更新字符偏移


		}else if(spec&FORMAT_FLAG_WIDTH){
			//do nothing
		}else if(FORMAT_TYPE(spec)==FORMAT_TYPE_CHAR){//字符类型,直接拷贝
			c = (unsigned char) va_arg(args, int);
			if (str < end)
				*str = c;
			++str;
		}else if(FORMAT_TYPE(spec)==FORMAT_TYPE_STR){//字符串类型,直接拷贝
			s = (char *) va_arg(args, char *);
			while(str<end&&*s!='\0'){
				*str++=*s++;
			}
		}else{//数值型,进行转换
			if(FORMAT_TYPE(spec)==FORMAT_TYPE_INT){
				num = va_arg(args, int);
			}else if(FORMAT_TYPE(spec)==FORMAT_TYPE_ULONG){
				num = va_arg(args, unsigned long);
			}else if(FORMAT_TYPE(spec)==FORMAT_TYPE_LONG){
				num = va_arg(args, long);
			}else if(FORMAT_TYPE(spec)==FORMAT_TYPE_SIZE_T){
				num = va_arg(args, int);
			}else if(FORMAT_TYPE(spec)==FORMAT_TYPE_USHORT){
				num = (unsigned short) va_arg(args, int);
			}else if(FORMAT_TYPE(spec)==FORMAT_TYPE_SHORT){
				num = (short) va_arg(args, int);
			}else{
				num = va_arg(args, unsigned int);
			}
				str=<strong><span style="color:#ff0000;">number</span></strong>(str,num,spec&FORMAT_BASE_MASK,spec);
		}
	}
	if (size > 0) {
		if (str < end)
			*str = '\0';
		else
			end[-1] = '\0';
	}
	return str-buf;
}format_decode(fmt, &spec);//判断参数的格式,保存到spec中,read为当前参数在字符串中的指针偏移
		fmt += read;//指针偏移到本参数格式的下一位字符的地址

		if((FORMAT_TYPE(spec))==FORMAT_TYPE_NONE){
			int copy = read;
			if (str < end) {
				if (copy > end - str)//防止buff空间不足越界
					copy = end - str;
					memcpy(str, old_fmt, copy);//原样拷贝到buff中
			}
			str += read;//更新字符偏移


		}else if(spec&FORMAT_FLAG_WIDTH){
			//do nothing
		}else if(FORMAT_TYPE(spec)==FORMAT_TYPE_CHAR){//字符类型,直接拷贝
			c = (unsigned char) va_arg(args, int);
			if (str < end)
				*str = c;
			++str;
		}else if(FORMAT_TYPE(spec)==FORMAT_TYPE_STR){//字符串类型,直接拷贝
			s = (char *) va_arg(args, char *);
			while(str<end&&*s!='\0'){
				*str++=*s++;
			}
		}else{//数值型,进行转换
			if(FORMAT_TYPE(spec)==FORMAT_TYPE_INT){
				num = va_arg(args, int);
			}else if(FORMAT_TYPE(spec)==FORMAT_TYPE_ULONG){
				num = va_arg(args, unsigned long);
			}else if(FORMAT_TYPE(spec)==FORMAT_TYPE_LONG){
				num = va_arg(args, long);
			}else if(FORMAT_TYPE(spec)==FORMAT_TYPE_SIZE_T){
				num = va_arg(args, int);
			}else if(FORMAT_TYPE(spec)==FORMAT_TYPE_USHORT){
				num = (unsigned short) va_arg(args, int);
			}else if(FORMAT_TYPE(spec)==FORMAT_TYPE_SHORT){
				num = (short) va_arg(args, int);
			}else{
				num = va_arg(args, unsigned int);
			}
				str=number(str,num,spec&FORMAT_BASE_MASK,spec);
		}
	}
	if (size > 0) {
		if (str < end)
			*str = '\0';
		else
			end[-1] = '\0';
	}
	return str-buf;
}

(1)format_decode函数

作用:判断格式化的符号及类型;

flags:第0字节:若为数值,作为数值基数;
           第1字节:格式类型,字符,整形,长整型,短整型等;
           第2字节:若为数值,表示数值符号;

  1.  
    int format_decode(const char *fmt,unsigned int *flags){
  2.  
    const char *start = fmt;
  3.  
     
  4.  
    *flags &= ~FORMAT_TYPE_MASK;
  5.  
    *flags |= FORMAT_TYPE_NONE;
  6.  
    for (; *fmt ; ++fmt) {
  7.  
    if (*fmt == '%')
  8.  
    break;
  9.  
    }
  10.  
     
  11.  
    if (fmt != start || !*fmt)
  12.  
    return fmt - start;
  13.  
     
  14.  
    do{
  15.  
    fmt++;
  16.  
    switch(*fmt){
  17.  
    case 'l':
  18.  
    SET_FORMAT_FLAG(*flags,FORMAT_FLAG_WIDTH);
  19.  
    break;
  20.  
    default:
  21.  
    break;
  22.  
    }
  23.  
    } while( 0);
  24.  
     
  25.  
    SET_FORMAT_BASE(*flags,FORMAT_BASE_D);
  26.  
    switch (*fmt) {
  27.  
    case 'c':
  28.  
    SET_FORMAT_TYPE(*flags,FORMAT_TYPE_CHAR);
  29.  
    break;
  30.  
     
  31.  
    case 's':
  32.  
    SET_FORMAT_TYPE(*flags,FORMAT_TYPE_STR);
  33.  
    break;
  34.  
     
  35.  
    case 'o':
  36.  
    SET_FORMAT_BASE(*flags,FORMAT_BASE_O);
  37.  
    SET_FORMAT_TYPE(*flags,FORMAT_TYPE_UINT);
  38.  
    break;
  39.  
     
  40.  
    case 'x':
  41.  
    case 'X':
  42.  
    SET_FORMAT_BASE(*flags,FORMAT_BASE_X);
  43.  
    SET_FORMAT_TYPE(*flags,FORMAT_TYPE_UINT);
  44.  
    break;
  45.  
     
  46.  
    case 'd':
  47.  
    case 'i':
  48.  
    SET_FORMAT_TYPE(*flags,FORMAT_TYPE_INT);
  49.  
    SET_FORMAT_BASE(*flags,FORMAT_BASE_D);
  50.  
    break;
  51.  
    case 'u':
  52.  
    SET_FORMAT_TYPE(*flags,FORMAT_TYPE_UINT);
  53.  
    SET_FORMAT_BASE(*flags,FORMAT_BASE_D);
  54.  
    break;
  55.  
     
  56.  
    default:
  57.  
    break;
  58.  
    }
  59.  
    return ++fmt-start; //参数偏移的字节数
  60.  
    }
SET_FORMAT_FLAG(*flags,FORMAT_FLAG_WIDTH);
				break;
			default:
				break;
		}
	}while(0);
	
	SET_FORMAT_BASE(*flags,FORMAT_BASE_D);
	switch (*fmt) {
		case 'c':
			SET_FORMAT_TYPE(*flags,FORMAT_TYPE_CHAR);
			break;

		case 's':
			SET_FORMAT_TYPE(*flags,FORMAT_TYPE_STR);
			break;

		case 'o':
			SET_FORMAT_BASE(*flags,FORMAT_BASE_O);
			SET_FORMAT_TYPE(*flags,FORMAT_TYPE_UINT);
			break;

		case 'x':
		case 'X':
			SET_FORMAT_BASE(*flags,FORMAT_BASE_X);
			SET_FORMAT_TYPE(*flags,FORMAT_TYPE_UINT);
			break;

		case 'd':
		case 'i':
			SET_FORMAT_TYPE(*flags,FORMAT_TYPE_INT);
			SET_FORMAT_BASE(*flags,FORMAT_BASE_D);
			break;
		case 'u':
			SET_FORMAT_TYPE(*flags,FORMAT_TYPE_UINT);
			SET_FORMAT_BASE(*flags,FORMAT_BASE_D);
			break;

	default:
		break;
	}
	return ++fmt-start;//参数偏移的字节数
}

 

 

 

(2)number函数

函数功能:根据类型进行数值转换

  1.  
    char *number(char *str, int num,int base,unsigned int flags){
  2.  
    int i= 0;
  3.  
    int sign= 0;
  4.  
     
  5.  
    if(FORMAT_SIGNED(flags)&&( signed int)num< 0){
  6.  
    sign= 1;
  7.  
    num=~num+ 1;
  8.  
    }
  9.  
     
  10.  
    do{
  11.  
    numbers[i++]=digits[do_div(num,base)];
  12.  
    } while(num!= 0);
  13.  
     
  14.  
     
  15.  
    if(FORMAT_BASE(flags)==FORMAT_BASE_O){
  16.  
    numbers[i++]= '0';
  17.  
    } else if(FORMAT_BASE(flags)==FORMAT_BASE_X){
  18.  
    numbers[i++]= 'x';
  19.  
    numbers[i++]= '0';
  20.  
    } else if(FORMAT_BASE(flags)==FORMAT_BASE_B){
  21.  
    numbers[i++]= 'b';
  22.  
    numbers[i++]= '0';
  23.  
    }
  24.  
    if(sign)
  25.  
    numbers[i++]= '-';
  26.  
     
  27.  
    while (i-- > 0)
  28.  
    *str++ = numbers[i];
  29.  
    return str;
  30.  
    }

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM