对于参数都产生格式化输出函数的实现都使用到了变参结构类型: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 《整数部分》)
:获取函数的整数部分、小数部分。
- #ifndef _LOCAL_H
- #define _LOCAL_H
- #include<stdarg.h>
- #define MAX 960
- #define INF 67676
- #define TRUE 1
- #define FALSE 0
- #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
- int printfexe(char * str, ...);
- int deal_string (char * str, va_list ap,char buff[]);
- int is_digit(char ch);
- char * number_to(int num ,int base, int flags,int width, char fnhl,char *p);
- #endif
- #include"local.h"
- #include<stdio.h>
- #include<string.h>
- #include<stdarg.h>
- #include<stdlib.h>
- #include<math.h>
- //没有自己处里
- int main()
- {
-
- // printfexe("-AS=%3s Ac = %c \n","okk",'c');
- // printfexe("-af=%3lf",8.4);
- // printfexe("ao = o\n",11);
- // printfexe("ao = %#3o\n",11);
- // printf("ao = %#3o\n",11);
- // printfexe("Ae = %e\n",8677.444);
- printfexe("Ae = %e\n",0.008677444);
- // printfexe("Ap = %p\n",8);
- return 0;
- }
- int printfexe(char * str, ...)
- {
- int count =0;
- char buff[MAX];
- va_list ap ;//变参的类型
- va_start(ap,str);
- count = deal_string(str,ap,buff);//buff用于存储最后变换的结果,str用于存储已知的字符串,ap用于存储记录变参的指针
- va_end(ap);
- puts(buff);
- return count;//最后生成的字符的个数
- }
- int deal_string(char * str,va_list ap , char buff[])
- {
-
- char *p, fnhl;
- int flags,width, prec;
- p = buff;
- for(p= buff;*str;str++)
- {
- if( *str !='%' ) {
- *p++ = *str;
- continue;
- }
- flags = 0;
- repeat:
- switch(*(++str)){//可以重复出现
- case '-'://用于表示左对齐
- flags |= LEFT_DQ;
- goto repeat;
- case '+':
- flags |= SIGN_DATA;
- goto repeat;
- case '0':
- flags |= ZERO_BQ;
- goto repeat;
- case ' ':
- flags |= KONG_BQ;
- goto repeat;
- case '#':
- flags |= FORMAT_X;
- goto repeat;
- default:
- break;
- }
- while(is_digit(*str)>0)//对于该函数对此调用浪费时间和空间,可以使用宏
- {
- if(*str =='0'&& width==0)//width=0表示达到0n中的0的位置
- flags = ZERO_BQ;
- width = width*10+*str-'0';
- str++;
- }
- fnhl = 'h';//默认为4个字节。
- if(*str == 'l' || *str == 'L' || *str == 'h')
- fnhl = *str++;
- switch(*str)
- {
- case 'i':
- printf("i\n");
- case 'd':
- printf("d\n");
- flags |=SIGN;
- case 'u':
- printf("u\n");
- p= number_to(va_arg(ap,unsigned long),10,flags,width,fnhl,p);//10进制变换,有符号,即最高位表示符号。
- break;
- case 'o':
- printf("o\n");
- p= number_to(va_arg(ap,unsigned long),8,flags,width,fnhl,p);//10进制变换,有符号,即最高位表示符号。
- break;
- case 'p':
- flags |= FORMAT_X;
- printf("p\n");
- case 'x':
- printf("x\n");
- flags |=SMALL;
- p = number_to(va_arg(ap,unsigned long),16,flags,width,fnhl,p);
- break;
- case 'X':
- printf("X\n");
- flags &=(~SMALL);
- p = number_to(va_arg(ap,unsigned long),16,flags,width,fnhl,p);
- break;
- case 'f':
- printf("f\n");
- double iptr,fptr;
- int num[MAX],in=0;
- long ff;
- fptr = modf(va_arg(ap,double),&iptr);
- if(!( flags&LEFT_DQ))
- while(width-->0)
- *p ++ =' ';
- ff = (long) iptr;
- while(ff>0) {
- num[in++] = ff % 10;
- ff=ff/10;
- }
- while(--in>=0)
- *p++=num[in]+'0';
- *p++ = '.';
- if(fnhl=='l' || fnhl=='L')
- in = 11;
- else
- in = 8;
-
- ff = (long)(fptr*pow(10,in));
- printf("ff = %ld fptr = %lf\n",ff,fptr*10);
- while(ff) {
- *p++ = ff/pow(10,--in)+'0';
- ff = ff %(int)pow(10,in);
- }
- if (flags&LEFT_DQ)
- while(width-->0)
- *p ++ =' ';
- break;
- case 'e':
- printf("e\n");
- double iptr1,fptr1;
- int in1=0,e;
- long ff1;
-
- fptr1 = modf(va_arg(ap,double),&iptr1);
- printf("%lf %lf",fptr1,iptr1);
- if(!( flags&LEFT_DQ))
- while(width-->0)
- *p ++ =' ';
- ff1 = (long) iptr1;
- if(ff1>0) {
- while(1)
- {
- if(ff1 / (int)(pow(10,++in1))<=0)
- break;
- }
- printf("e = %d \n",e);
- e = --in1;
- *p++='0'+ff1/(int)(pow(10,e));
- *p++='.';
- while(ff1) {
- ff1 = ff1 % (int)(pow(10,--in1));
- *p++ ='0'+ff1/(int)(pow(10,in1));
- }
- ff1 = (long)fptr1*10;
- *p++='0'+ ff1;//处理来小数点的后面的第一位
- } else
- {
- printf("else");
- in1 =0;
- while(1) {
- if(fptr1 * pow(10,++in1)>=1.0000)
- break;
- }
- e = -(in1);
- ff1 = (long)(fptr1*pow(10,in1));
- *p ++ = '0'+ff1;
- *p++='.';
- }
- if(fnhl == 'l' || fnhl=='L')
- in1 = 11;
- else
- in1 = 8;
- ff1 =(long)(fptr1*(int)pow(10,in1));
- while(ff1) {
- ff1 = ff1 %(int)pow(10,--in1+e);
- *p++ = ff1/pow(10,in1+e-1)+'0';
- }
- *p++='e';
- flags = flags&~LEFT_DQ;
- if(e>0)
- *p++ = '+';
- else
- *p++ = '-';
- p = number_to( fabs(e),10,flags,width,fnhl,p);
- break;
- case 'E':
- case 's':
- printf("s\n");
- if(!( flags&LEFT_DQ))
- while(width-->0)
- *p ++ =' ';
- char *s = va_arg(ap,char*);
- while(*s)
- *p++ = *s++;
- if (flags&LEFT_DQ)
- while(width-->0)
- *p ++ =' ';
- break;
- case 'c':
- printf("c\n");
- if(!( flags&LEFT_DQ))
- while(width-->0)
- *p ++ =' ';
- *p++ = (unsigned char)va_arg(ap,int);
- if (flags&LEFT_DQ)
- while(width-->0)
- *p ++ =' ';
- break;
- default:
- if(*str == '%')
- *p++ = *str;
- }
- }
- *p = 0;
- return p-buff;
- }
- int is_digit(char ch)
- {
- if(ch >='0' && ch <='9')
- return TRUE;
- return FALSE;
- }
- char * number_to(int num, int base, int flags, int width, char fnhl, char *p)
- {
- char *num_a = "0123456789abcdefx";
- char c,op='0';
- char ls[MAX]={0};
- int in = MAX-1;
- c = (flags & ZERO_BQ ? '0':' ');
- if(flags &SMALL ==0)
- num_a = "0123456789ABCDEFX";
- if(base<=0)
- { printf("error: base <=0");
- return NULL;
- }
- if(num<=0){
- if(flags&SIGN) {
- num = -num;
- op = '-';
- } else {
- if(fnhl=='L' || fnhl =='l')
- num = pow(2,63)+num;
- else
- num = pow(2,31)+num;
- }
- }
- printf("num = %d\n",num);
- if(num ==0)
- ls[in++]=0;
- else
- while(num){
- ls[in--] = num_a[abs(numse)];
- num = num /base;
- }
- if( base == 16 || base == 8 )
- if(flags&FORMAT_X)
- {
- if(base ==16)
- ls[in--]=num_a[16];
- ls[in--]='0';
- }
- if(op=='-')
- ls[in]=op;
- else
- in+=1;
- if(width >0)
- {
- if(flags&LEFT_DQ)//左对齐只存在在右侧补‘ ’
- {
- while(in<MAX)
- *p++ = ls[in++];
- while(width-->0)
- *p++ = ' ';
- }
- else//右对齐中存在在左侧补0还是补‘ ’
- {
- while(width-->0)
- *p++ = c;
- while(in<MAX)
- *p++ = ls[in++];
- }
- }
- else{
- while(in<MAX)
- *p++ = ls[in++];
- }
- return p;
- }
编译命令: gcc printfexe.c -lm -o printfexe
结果:
阅读(3212) | 评论(0) | 转发(0) |