• 手写简化版printf函数


    2019.02.01更新:经同学提醒,myprintf函数应有返回值为输出的字符数。

    期末的大作业,手写一个myprintf函数,支持如下一些操作。

    也就是  % -(负号控制左右对齐) 数(控制字段宽). 数(控制精度) ?(字符,控制类型) 

    我实现的话就是按上面的实现的,说一下这个简化版存在的问题(简化的地方):

    1)%d %i %o %x %X %u %c 这些都默认后面输入的是int,所以long long其实没有用。

    2)支持最大精度<=30,如果有需要请更改PRECISION

    myprintf默认四舍五入(rounding_off函数实现)

    如果发现错误,请指出,谢谢大家啦!

      1 #include<stdio.h>
      2 #include<stdlib.h>
      3 #include<string.h>
      4 #include<math.h>
      5 #include<stdarg.h>
      6 
      7 #define N 110
      8 #define eps 1e-16
      9 #define INF 1e9
     10 #define PRECISION 30
     11 
     12 int maxx(int x,int y){return x>y ? x:y;}
     13 void swapp(char *x,char *y){char t;t=*x;*x=*y;*y=t;}
     14 int find_int_type(int int_type,char ch);
     15 void change_int_type_to_char(int x,int int_type,char *s,int *sl,int *minus);
     16 void print_int_regardless_type(char *s,int *sl,int minus,int Justify_type,int min_width,int precision);
     17 void print_int(int x,int Justify_type,int min_width,int precision,int int_type);
     18 void print_string(char *s,int Justify_type,int min_width,int precision);
     19 int is_g_or_G(char double_type){return (double_type == 'g' || double_type=='G');}
     20 void rounding_off(char *s,int *sl,int *ml,int precision);
     21 void print_double_e_or_E(char *s,int sl,int exponent,int minus,int Justify_type,int min_width,int precision,char double_type);
     22 void print_double_f(char *s,int sl,int ml,int minus,int Justify_type,int min_width,int precision);
     23 void print_double(double x,int Justify_type,int min_width,int precision,char double_type);
     24 int myprintf(const char *format,...);
     25 
     26 
     27 int main()
     28 {
     29     // freopen("a.out","w",stdout);
     30     int a=123;
     31     double b=9.9734567;
     32     int count=123456789;
     33     myprintf("%
    ");
     34     myprintf("%15e%15e
    ",-0.0000123,123.123);printf("%15e%15e
    ",-0.0000123,123.123);
     35     myprintf("%f
    ",0.0000123);printf("%f
    ",0.0000123);
     36     myprintf("%.1E
    ",b);printf("%.1E
    ",b);
     37     myprintf("%e
    ",0.0000123);printf("%e
    ",0.0000123);
     38     myprintf("%15.8g
    ",0.000012346789);printf("%15.8g
    ",0.0000123456789);
     39     myprintf("%5d%10d
    ",a,a);printf("%5d%10d
    ",a,a);
     40     myprintf("%10.5d%10.5d
    ",a,a);printf("%10.5d%10.5d
    ",a,a);
     41     myprintf("%15.10hd%15.10ld
    ",count,count);printf("%15.10hd%15.10ld
    ",count,count);
     42     myprintf("%5o
    ",a);printf("%5o
    ",a);
     43     myprintf("%f
    ",b);printf("%f
    ",b);
     44     myprintf("%15f%20.10f
    ",-b,-b);printf("%15f%20.10f
    ",-b,-b);
     45     myprintf("%15g
    ",0.0000123);printf("%15g
    ",0.0000123);
     46     myprintf("%15e%15E%15g%15g
    ",-b,b,b,0.0000123);printf("%15e%15E%15g%15g
    ",-b,b,b,0.0000123);
     47     myprintf("%15g
    ",0.0000123);printf("%15g
    ",0.0000123);
     48     myprintf("%-15.10x%10.10X
    ",count);printf("%-15.10x%10.10X
    ",count);
     49     myprintf("%10.5s
    %c
    ","asdfghjkl",'a');printf("%10.5s
    %c
    ","asdfghjkl",'a');
     50     myprintf("x41101 \ 
    ");printf("x41101 \ 
    ");
     51     unsigned int d = 123456;
     52     myprintf("%.10u
    ",d);printf("%.10u
    ",d);
     53     int *p;
     54     myprintf("%p
    ",p);printf("%p
    ",p);
     55     return 0;
     56 }
     57 
     58 int find_int_type(int int_type,char ch)
     59 {
     60     if(ch=='d' || ch=='i') return int_type;
     61     if(ch=='o') return 6;
     62     if(ch=='x') return 7;
     63     if(ch=='X') return 8;
     64     if(ch=='u') return int_type+1;
     65 }
     66 
     67 void change_int_type_to_char(int x,int int_type,char *s,int *sl,int *minus)
     68 {
     69     *sl=0;
     70     switch(int_type)
     71     {
     72         case 0:{//int
     73             int y=(int)x;if(y<0) *minus=1,y=-y;
     74             while(y) s[(*sl)++]=(y%10)+'0',y/=10;
     75             break;
     76         }
     77         case 1:{//unsigned int
     78             unsigned int y=(unsigned int)x;
     79             while(y) s[(*sl)++]=(y%10)+'0',y/=10;
     80             break;
     81         }
     82         case 2:{//short
     83             short int y=(short int)x;if(y<0) *minus=1,y=-y;
     84             while(y) s[(*sl)++]=(y%10)+'0',y/=10;
     85             break;
     86         }
     87         case 3:{//unsigned short
     88             unsigned short int y=(unsigned short int)x;
     89             while(y) s[(*sl)++]=(y%10)+'0',y/=10;
     90             break;
     91         }
     92         case 4:{//long int
     93             long int y=(long int )x;if(y<0) *minus=1,y=-y;
     94             while(y) s[(*sl)++]=(y%10)+'0',y/=10;
     95             break;
     96         }
     97         case 5:{//unsigned long int
     98             unsigned long int y=(unsigned long int)y;
     99             while(y) s[(*sl)++]=(y%10)+'0',y/=10;
    100             break;
    101         }
    102         case 6:{//o
    103             int y=(int )x;
    104             while(y) s[(*sl)++]=(y%8)+'0',y/=8;
    105             break;
    106         }
    107         case 7:{//x
    108             int y=(int)x;
    109             while(y) s[(*sl)++]=((y%16)>=10) ? (y%16)-10+'a' : (y%16)+'0',y/=16;
    110             break;
    111         }
    112         case 8:{//X
    113             int y=(int)x;
    114             while(y) s[(*sl)++]=((y%16)>=10) ? (y%16)-10+'A' : (y%16)+'0',y/=16;
    115             break;
    116         }
    117     }
    118 }
    119 
    120 void print_int_regardless_type(char *s,int *sl,int minus,int Justify_type,int min_width,int precision)
    121 {
    122     while(precision<INF && *sl<precision) s[(*sl)++]='0';
    123     if(minus) s[(*sl)++]='-';
    124     int space=min_width-*sl;
    125 
    126     if(Justify_type==1)//right
    127         for(int i=1;i<=space;i++) putchar(' ');
    128     for(int i=(*sl)-1;i>=0;i--) putchar(s[i]);
    129     if(Justify_type==0)//left
    130         for(int i=1;i<=space;i++) putchar(' ');
    131 }
    132 
    133 void print_int(int x,int Justify_type,int min_width,int precision,int int_type)
    134 {
    135     int minus=(x<0) ? 1:0;
    136     char *s=(char *)malloc(N*sizeof(char));
    137     int *sl=(int *)malloc(sizeof(int));
    138     change_int_type_to_char(x,int_type,s,sl,&minus);
    139     print_int_regardless_type(s,sl,minus,Justify_type,min_width,precision);
    140     free(s);
    141     free(sl);
    142 }
    143 
    144 void print_string(char *s,int Justify_type,int min_width,int precision)
    145 {
    146     int sl=strlen(s);
    147     if(sl > precision) sl=precision;
    148     int space=min_width-sl;
    149 
    150     if(Justify_type==1)//right
    151         for(int i=1;i<=space;i++) putchar(' ');
    152     for(int i=0;i<sl;i++) putchar(s[i]);
    153     if(Justify_type==0)//left
    154         for(int i=1;i<=space;i++) putchar(' ');
    155 }
    156 
    157 void rounding_off(char *s,int *sl,int *ml,int precision)//四舍五入
    158 {
    159     if(s[(*ml)+precision]<='4') return;
    160     s[(*ml)+precision-1]++;
    161     for(int i=(*ml)+precision-1;i>=1;i--) s[i-1]+=(s[i]-'0')/10,s[i]=(s[i]-'0')%10+'0';
    162     if(s[0]>'9')
    163     {
    164         (*sl)++;(*ml)++;
    165         for(int i=(*ml)+precision;i>=1;i--) s[i]=s[i-1];
    166         s[0]=(s[1]-'0')/10+'0';
    167         s[1]=(s[1]-'0')%10+'0';
    168     }
    169 }
    170 
    171 void print_double_e_or_E(char *s,int sl,int exponent,int minus,int Justify_type,int min_width,int precision,char double_type)
    172 {
    173     int space=min_width-(minus+1+precision+1+1+3);
    174     if(precision) space--;//'.'
    175 
    176     if(Justify_type==1)//right
    177         for(int i=1;i<=space;i++) putchar(' ');
    178     if(minus) putchar('-');
    179     putchar(s[0]);
    180     if(precision) putchar('.');
    181     for(int i=1;i<=precision;i++) 
    182     {
    183         if(i>=sl && is_g_or_G(double_type)) break;
    184         putchar((i<sl) ? s[i] : '0');
    185     }
    186     putchar(is_g_or_G(double_type) ? double_type+'e'-'g' : double_type);
    187     if(exponent>=0) putchar('+');
    188     else putchar('-'),exponent*=-1;
    189     putchar(exponent/100+'0');putchar((exponent/10)%10+'0');putchar(exponent%10+'0');
    190     if(Justify_type==0)//left
    191         for(int i=1;i<=space;i++) putchar(' ');
    192 }
    193 
    194 void print_double_f(char *s,int sl,int ml,int minus,int Justify_type,int min_width,int precision)
    195 {
    196     int space=min_width-(minus+ml+precision);
    197     if(precision) space--;//'.'
    198     if(Justify_type==1)//right
    199          for(int i=1;i<=space;i++) putchar(' ');
    200     if(minus) putchar('-');
    201     for(int i=0;i<ml;i++) putchar(s[i]);
    202     if(precision) putchar('.'); 
    203     for(int i=ml;i<=ml-1+precision;i++) putchar((i<sl) ? s[i]:'0');
    204     if(Justify_type==0)//left
    205         for(int i=1;i<=space;i++) putchar(' ');
    206 }
    207 
    208 //m.ddddd
    209 void print_double(double x,int Justify_type,int min_width,int precision,char double_type)
    210 {
    211     if(precision==INF) precision=6;
    212     int zero=(fabs(x) < eps);
    213     int minus=(x<0) ? 1:0;x=fabs(x);
    214     char *s=(char *)malloc(N*sizeof(char));
    215     int sl=0,ml=0,y=(int)x;x-=y;
    216     if(y==0) s[sl++]='0';
    217     while(y) s[sl++]=y%10+'0',y/=10;
    218     for(int i=0;i<=(sl-1)/2;i++) swapp(&s[i],&s[sl-1-i]);
    219     ml=sl;
    220     while(sl<=ml+PRECISION) s[sl++]=(int)(x*10)+'0',x=x*10-(int)(x*10);
    221     //f
    222     if(double_type=='f')
    223     {
    224         rounding_off(s,&sl,&ml,precision);
    225         print_double_f(s,sl,ml,minus,Justify_type,min_width,precision);
    226     }
    227     else//e E g G
    228     {
    229         int st=0,ssl=0,exponent=ml-1;
    230         char *ss=(char *)malloc(N*sizeof(char));
    231         while(!zero && s[st]=='0') st++,exponent--,s[sl++]='0';
    232         for(int i=st;i<sl;i++) ss[ssl++]=s[i];
    233 
    234         if(double_type=='e' || double_type=='E' || 
    235           (is_g_or_G(double_type) && (exponent < -4 || exponent >=precision)))
    236         {
    237             ml=1;
    238             if(is_g_or_G(double_type)) 
    239             {
    240                 if(precision) precision--,ssl--;
    241                 while(precision && ss[ml+precision-1]=='0') precision--;
    242             }
    243             int mml=1;
    244             rounding_off(ss,&ssl,&mml,precision);
    245             if(mml==2) exponent++;
    246             print_double_e_or_E(ss,ssl,exponent,minus,Justify_type,min_width,precision,double_type);
    247         }
    248         else
    249         {
    250             precision-=ml;sl-=ml;
    251             rounding_off(s,&sl,&ml,precision);
    252             while(precision && s[ml+precision-1]=='0') precision--;
    253             print_double_f(s,sl,ml,minus,Justify_type,min_width,precision);
    254         }
    255         free(ss);
    256     }
    257     free(s);
    258 }
    259 
    260 int myprintf(const char *format,...)
    261 {
    262     char ch;
    263     int arg_int;
    264     double arg_double;
    265     char *arg_str;
    266     void *arg_p;
    267     va_list ap;
    268     va_start(ap,format);
    269     
    270     while((ch = *format++)!='')
    271     {
    272         if(ch!='%') {putchar(ch);continue;}
    273         //ch = '%'  *format = '' 
    274         if(*format=='' || *format=='%') {putchar('%');continue;}
    275 
    276         int Justify_type=1,min_width=0,precision=INF,int_type=0,ok=0;
    277         if(*format=='-') Justify_type=0,format++;
    278         while(*format>='0' && *format<='9') min_width=min_width*10+*format-'0',format++;
    279         if(*format=='.')
    280         {
    281             format++;precision=0;
    282             while(*format>='0' && *format<='9') precision=precision*10+*format-'0',format++;
    283         }
    284         if(*format=='h') int_type=2,format++;
    285         if(*format=='l') int_type=4,format++;
    286         
    287         if(*format=='d' || *format=='i' || *format=='o' || *format=='x' || *format=='X' || *format=='u')
    288         {
    289             ok=1;arg_int=va_arg(ap,int);
    290             print_int(arg_int,Justify_type,min_width,precision,find_int_type(int_type,*format));
    291         }
    292         if(*format=='c')
    293         {
    294             ok=1;arg_int=va_arg(ap,int);
    295             putchar(arg_int);
    296         }
    297         if(*format=='s')
    298         {
    299             ok=1;arg_str=va_arg(ap,char *);
    300             print_string(arg_str,Justify_type,min_width,precision);
    301         }
    302         if(*format=='f' || *format=='e' || *format=='E' || *format=='g' || *format=='G')
    303         {
    304             ok=1;arg_double=va_arg(ap,double);
    305             print_double(arg_double,Justify_type,min_width,precision,*format);
    306         }
    307         if(*format=='p')
    308         {
    309             ok=1;arg_p=va_arg(ap,void *);
    310             arg_int=(int)arg_p;
    311             precision=8;//默认地址为8位,若机器地址不为8位可更改此处。
    312             print_int(arg_int,Justify_type,min_width,precision,8);            
    313         }
    314         if(!ok) {putchar('%');format--;}//ch=='%' 
    315         format++;
    316     }
    317     va_end(ap);
    318 }
  • 相关阅读:
    vsphere中虚机的cpu热插拔和内存热添加
    vsphere storage appliance工作原理和实施
    vmware产品框架-计算中心,5.1更新等
    vcenter建立cluster
    vcenter 5.1安装亲历
    openfiler在esxi下的安装配置
    升级华为s2016
    ubuntu下配置华为交换机s2016
    Fibre Channel address weaknesses
    vsphere HA内幕变化
  • 原文地址:https://www.cnblogs.com/KonjakJuruo/p/10199078.html
Copyright © 2020-2023  润新知