Chinaunix首页 | 论坛 | 博客
  • 博客访问: 519226
  • 博文数量: 96
  • 博客积分: 2102
  • 博客等级: 上尉
  • 技术积分: 1695
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-11 22:12
文章分类

全部博文(96)

文章存档

2014年(2)

2012年(94)

分类: C/C++

2012-04-30 10:01:37

对于参数都产生格式化输出函数的实现都使用到了变参结构类型:va_list;
int  vsprintf(char *buf, const char *fmt, va_list args) :其中args 已经通过va_start宏进行赋值了。

int  printf(const char * fmt ,[argument]): 利用vsprintf()函数获得要输出的字符串和输出字符串的字符的个数,并且将字符串送到标准输出句柄stdout 。

int cprintf(const char * fmt, [argument]) :和printf()一样也利用了vsprintf(),但是他将输出的字符串送到了控制台上。

int fprintf(FILE * stream , char *fmt , [argument]) :同上,此外将输出字符串送到了文件句柄。

printf前面加上'v'表示参数是从va_args数组的args中接收的。
printf前面加上's'字符则表示将以null结束的字符送到字符串buf(保证buf有足够的空间将字符串存储)中。

## printf() :是一般程序员编程使用的输出函数。
     printk():是内核使用的打印函数。对于printk重新编写的主要原因是因为在内核中不能使用专用于的用户模式fs  段寄存器,需要首先保存它。该函数首先使用vsprintf()对参数进行格式化处理,然后保存了fs段寄存器的情况下调用tty_write()进行信息的打印。
 
printf()的实现:
         对于prinf来讲主要涉及到了:变参函数、对于数据变形、添加格式符号、含有浮点数的变换。
         对于变参的处理主要是对三个宏的处理:在C标准库的srtdarg.h 已经将三个宏 va_start , va_arg , va_end 进行了解释和应用。
         对于数据变形主要使用的是数对于基数的除法、取余、存储和读出。
         添加格式符号主要是对格式位的处理。例如 flags | SIGN的处理,此时各个宏值的标志为是在128的各个位只用一个1,用于方便标识。
                                #define LEFT_DQ 1
                                #define SIGN_DATA 2
                                #define ZERO_BQ  4
                                #define KONG_BQ  8
                                #define FORMAT_X 16
                                #define SIGN 32
                               #define SMALL 64
       对于含有浮点数处理方法主要是对于精确位数的处理。其中最重要的是对于math.h中函数“:double mod(double value , double & iptr 《整数部分》) :获取函数的整数部分、小数部分。

local.h

  1. #ifndef _LOCAL_H
  2. #define _LOCAL_H
  3. #include<stdarg.h>
  4. #define MAX 960
  5. #define INF 67676

  6. #define TRUE 1
  7. #define FALSE 0

  8. #define LEFT_DQ 1
  9. #define SIGN_DATA 2
  10. #define ZERO_BQ 4
  11. #define KONG_BQ 8
  12. #define FORMAT_X 16
  13. #define SIGN 32
  14. #define SMALL 64




  15. int printfexe(char * str, ...);
  16. int deal_string (char * str, va_list ap,char buff[]);
  17. int is_digit(char ch);
  18. char * number_to(int num ,int base, int flags,int width, char fnhl,char *p);


  19. #endif

printfexe.c

  1. #include"local.h"
  2. #include<stdio.h>
  3. #include<string.h>
  4. #include<stdarg.h>
  5. #include<stdlib.h>
  6. #include<math.h>
  7. //没有自己处里
  8. int main()
  9. {
  10.    
  11. // printfexe("-AS=%3s Ac = %c \n","okk",'c');
  12. // printfexe("-af=%3lf",8.4);
  13. // printfexe("ao = o\n",11);
  14. // printfexe("ao = %#3o\n",11);
  15. // printf("ao = %#3o\n",11);
  16. // printfexe("Ae = %e\n",8677.444);
  17.     printfexe("Ae = %e\n",0.008677444);
  18. // printfexe("Ap = %p\n",8);
  19.     return 0;
  20. }

  21. int printfexe(char * str, ...)
  22. {
  23.     int count =0;
  24.     char buff[MAX];
  25.     va_list ap ;//变参的类型
  26.     va_start(ap,str);
  27.     count = deal_string(str,ap,buff);//buff用于存储最后变换的结果,str用于存储已知的字符串,ap用于存储记录变参的指针
  28.     va_end(ap);
  29.     puts(buff);

  30.     return count;//最后生成的字符的个数
  31. }
  32. int deal_string(char * str,va_list ap , char buff[])
  33. {
  34.    
  35.     char *p, fnhl;
  36.     int flags,width, prec;
  37.     p = buff;

  38.     for(p= buff;*str;str++)
  39.     {
  40.         if( *str !='%' ) {
  41.             *p++ = *str;
  42.             continue;
  43.         }
  44.     flags = 0;
  45.     repeat:
  46.         switch(*(++str)){//可以重复出现
  47.             case '-'://用于表示左对齐
  48.                 flags |= LEFT_DQ;
  49.                 goto repeat;
  50.             case '+':
  51.                 flags |= SIGN_DATA;
  52.                 goto repeat;
  53.             case '0':
  54.                 flags |= ZERO_BQ;
  55.                 goto repeat;
  56.             case ' ':
  57.                 flags |= KONG_BQ;
  58.                 goto repeat;
  59.             case '#':
  60.                 flags |= FORMAT_X;
  61.                 goto repeat;
  62.             default:
  63.                 break;
  64.         }
  65.         while(is_digit(*str)>0)//对于该函数对此调用浪费时间和空间,可以使用宏
  66.         {
  67.             if(*str =='0'&& width==0)//width=0表示达到0n中的0的位置
  68.                  flags = ZERO_BQ;
  69.             width = width*10+*str-'0';
  70.             str++;
  71.         }
  72.         fnhl = 'h';//默认为4个字节。
  73.         if(*str == 'l' || *str == 'L' || *str == 'h')
  74.             fnhl = *str++;
  75.         switch(*str)
  76.         {
  77.             case 'i':
  78.                 printf("i\n");
  79.             case 'd':
  80.                 printf("d\n");
  81.                 flags |=SIGN;
  82.             case 'u':
  83.                 printf("u\n");
  84.                 p= number_to(va_arg(ap,unsigned long),10,flags,width,fnhl,p);//10进制变换,有符号,即最高位表示符号。
  85.                 break;
  86.             case 'o':
  87.                 printf("o\n");
  88.                 p= number_to(va_arg(ap,unsigned long),8,flags,width,fnhl,p);//10进制变换,有符号,即最高位表示符号。
  89.                 break;
  90.             case 'p':
  91.                 flags |= FORMAT_X;
  92.                 printf("p\n");
  93.             case 'x':
  94.                 printf("x\n");
  95.                 flags |=SMALL;
  96.                 p = number_to(va_arg(ap,unsigned long),16,flags,width,fnhl,p);
  97.                 break;
  98.             case 'X':
  99.                 printf("X\n");
  100.                 flags &=(~SMALL);
  101.                 p = number_to(va_arg(ap,unsigned long),16,flags,width,fnhl,p);
  102.                 break;
  103.             case 'f':
  104.                 printf("f\n");
  105.                 double iptr,fptr;
  106.                 int num[MAX],in=0;
  107.                 long ff;
  108.                 fptr = modf(va_arg(ap,double),&iptr);
  109.                 if(!( flags&LEFT_DQ))
  110.                     while(width-->0)
  111.                         *p ++ =' ';
  112.                 ff = (long) iptr;
  113.                 while(ff>0) {
  114.                      num[in++] = ff % 10;
  115.                      ff=ff/10;
  116.                 }
  117.                 while(--in>=0)
  118.                     *p++=num[in]+'0';
  119.                 *p++ = '.';
  120.                 if(fnhl=='l' || fnhl=='L')
  121.                     in = 11;
  122.                 else
  123.                     in = 8;
  124.                
  125.                 ff = (long)(fptr*pow(10,in));
  126.                 printf("ff = %ld fptr = %lf\n",ff,fptr*10);
  127.                 while(ff) {
  128.                     *p++ = ff/pow(10,--in)+'0';
  129.                      ff = ff %(int)pow(10,in);
  130.                 }
  131.                 if (flags&LEFT_DQ)
  132.                     while(width-->0)
  133.                         *p ++ =' ';
  134.                 break;
  135.             case 'e':
  136.                 printf("e\n");
  137.                 double iptr1,fptr1;
  138.                 int in1=0,e;
  139.                 long ff1;
  140.                
  141.                 fptr1 = modf(va_arg(ap,double),&iptr1);

  142.                 printf("%lf %lf",fptr1,iptr1);
  143.                 if(!( flags&LEFT_DQ))
  144.                     while(width-->0)
  145.                         *p ++ =' ';
  146.                 ff1 = (long) iptr1;

  147.                 if(ff1>0) {
  148.                     while(1)
  149.                     {
  150.                         if(ff1 / (int)(pow(10,++in1))<=0)
  151.                             break;
  152.                     }
  153.                     printf("e = %d \n",e);
  154.                     e = --in1;
  155.                     *p++='0'+ff1/(int)(pow(10,e));
  156.                     *p++='.';
  157.                     while(ff1) {
  158.                     ff1 = ff1 % (int)(pow(10,--in1));
  159.                     *p++ ='0'+ff1/(int)(pow(10,in1));
  160.                     }

  161.                     ff1 = (long)fptr1*10;
  162.                     *p++='0'+ ff1;//处理来小数点的后面的第一位
  163.                 } else
  164.                 {
  165.                     printf("else");
  166.                     in1 =0;
  167.                     while(1) {
  168.                         if(fptr1 * pow(10,++in1)>=1.0000)
  169.                             break;
  170.                     }

  171.                     e = -(in1);
  172.                     ff1 = (long)(fptr1*pow(10,in1));

  173.                     *p ++ = '0'+ff1;
  174.                     *p++='.';
  175.                 }
  176.                 if(fnhl == 'l' || fnhl=='L')
  177.                     in1 = 11;
  178.                 else
  179.                     in1 = 8;
  180.                 ff1 =(long)(fptr1*(int)pow(10,in1));
  181.                 while(ff1) {
  182.                      ff1 = ff1 %(int)pow(10,--in1+e);
  183.                     *p++ = ff1/pow(10,in1+e-1)+'0';
  184.                 }
  185.                 *p++='e';
  186.                 flags = flags&~LEFT_DQ;
  187.                 if(e>0)
  188.                     *p++ = '+';
  189.                 else
  190.                     *p++ = '-';
  191.                 p = number_to( fabs(e),10,flags,width,fnhl,p);
  192.                 break;
  193.             case 'E':
  194.             case 's':
  195.                 printf("s\n");
  196.                 if(!( flags&LEFT_DQ))
  197.                     while(width-->0)
  198.                         *p ++ =' ';
  199.                 char *s = va_arg(ap,char*);
  200.                 while(*s)
  201.                     *p++ = *s++;
  202.                 if (flags&LEFT_DQ)
  203.                     while(width-->0)
  204.                         *p ++ =' ';
  205.                 break;
  206.             case 'c':
  207.                 printf("c\n");
  208.                 if(!( flags&LEFT_DQ))
  209.                     while(width-->0)
  210.                         *p ++ =' ';
  211.                 *p++ = (unsigned char)va_arg(ap,int);
  212.                 if (flags&LEFT_DQ)
  213.                     while(width-->0)
  214.                         *p ++ =' ';
  215.                 break;
  216.             default:
  217.                 if(*str == '%')
  218.                     *p++ = *str;
  219.         }


  220.     }
  221.     *p = 0;
  222.     return p-buff;
  223. }

  224. int is_digit(char ch)
  225. {
  226.     if(ch >='0' && ch <='9')
  227.         return TRUE;
  228.     return FALSE;
  229. }
  230. char * number_to(int num, int base, int flags, int width, char fnhl, char *p)
  231. {
  232.     char *num_a = "0123456789abcdefx";
  233.     char c,op='0';
  234.     char ls[MAX]={0};
  235.     int in = MAX-1;


  236.     c = (flags & ZERO_BQ ? '0':' ');



  237.     if(flags &SMALL ==0)
  238.         num_a = "0123456789ABCDEFX";

  239.     if(base<=0)
  240.     { printf("error: base <=0");
  241.         return NULL;
  242.     }

  243.     if(num<=0){
  244.         if(flags&SIGN) {
  245.             num = -num;
  246.             op = '-';
  247.         } else {
  248.             if(fnhl=='L' || fnhl =='l')
  249.                 num = pow(2,63)+num;
  250.             else
  251.                 num = pow(2,31)+num;
  252.         }
  253.     }
  254.     printf("num = %d\n",num);
  255.     if(num ==0)
  256.         ls[in++]=0;
  257.     else
  258.             while(num){
  259.                 ls[in--] = num_a[abs(numse)];
  260.             num = num /base;
  261.         }

  262.     if( base == 16 || base == 8 )
  263.         if(flags&FORMAT_X)
  264.             {
  265.                 if(base ==16)
  266.                     ls[in--]=num_a[16];
  267.                 ls[in--]='0';
  268.             }
  269.     if(op=='-')
  270.         ls[in]=op;
  271.     else
  272.         in+=1;
  273.     if(width >0)
  274.     {
  275.         if(flags&LEFT_DQ)//左对齐只存在在右侧补‘ ’
  276.         {
  277.             while(in<MAX)
  278.                 *p++ = ls[in++];
  279.             while(width-->0)
  280.                 *p++ = ' ';
  281.         }
  282.         else//右对齐中存在在左侧补0还是补‘ ’
  283.         {
  284.             while(width-->0)
  285.             *p++ = c;
  286.             while(in<MAX)
  287.                 *p++ = ls[in++];
  288.         }
  289.     }
  290.     else{
  291.             while(in<MAX)
  292.                 *p++ = ls[in++];
  293.     }

  294.     return p;
  295. }
编译命令: gcc printfexe.c -lm -o printfexe

结果:




阅读(3143) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~