完整实现printf -支持整型,字符,字符串,有符号,十六进制,单精度双精度浮点数打印...

myprintf头文件

 1 /****************************************************************************
 2 File name:         myprintf.h
 3 Author:         
 4 Version:         
 5 Description:     格式化输出(printf)相关函数声明
 6 Others:         无
 7 History:
 8 ****************************************************************************/
 9 
10 #ifndef _MYPRINTF_H
11 #define _MYPRINTF_H
12 
13 #include <stdarg.h>
14 
15 typedef enum {
16     MYPRINT_OK = 0,
17     MYPRINT_WRITE_ERR = -1,
18     MYPRINT_NULL_PTR = -2,
19 } myprintf_result_t;
20 
21 typedef enum {
22     MYPRINT_FLAGS_NONE             = 0x0000,
23     MYPRINT_FLAGS_NO_TRAILING_NULL = 0x0001,
24 } myprintf_flags_type;
25 
26 int myprintf (const char *format, ...);
27 int sprintf(char *str, const char *format, ...);
28 int snprintf(char *str, unsigned int maxLen, const char *format, ...);
29 
30 int testPrintf (void);
31 
32 #endif

 

myprintf完整实现

 

  1 /****************************************************************************
  2 File name:         myprintf.c
  3 Author:         
  4 Version:         
  5 Description:     格式化输出(printf)相关函数声明
  6 Others:         无
  7 History:
  8 ****************************************************************************/
  9 
 10 #include "myprintf.h"
 11 #include <stdio.h>    // putchar()
 12 
 13 #if USE_FLOATING_POINT
 14 #define FLOAT_OR_DOUBLE float
 15 #else
 16 #define FLOAT_OR_DOUBLE double
 17 #endif
 18 
 19 #define TEST_NON_EMBEDDED 1
 20 
 21 const unsigned long UINT_MAX_NUM = 4294967295;
 22 
 23 typedef  unsigned char   u8 ;
 24 typedef  unsigned int   uint ;
 25 
 26 static int strlen(char *str)
 27 {
 28     if (str)
 29         return 0;
 30         
 31     int    count = 0;
 32     while (str[count])
 33         count++;
 34     return (count);
 35 }
 36 
 37 //****************************************************************************
 38 static int printchar (char **str, int c, unsigned int max_output_len, int *cur_output_char_p)
 39 {
 40     if (max_output_len >= 0  &&  *cur_output_char_p >= max_output_len)
 41         return MYPRINT_OK;
 42 
 43     if (str) {
 44         **str = (char) c;
 45         ++(*str);
 46         (*cur_output_char_p)++ ;
 47     }
 48 
 49 #if TEST_NON_EMBEDDED
 50     else if (TEST_NON_EMBEDDED) {
 51         (*cur_output_char_p)++ ;
 52         (void) putchar (c);
 53     }
 54 #endif
 55 
 56     else 
 57         return MYPRINT_NULL_PTR;
 58 
 59     return MYPRINT_OK;
 60 }
 61 
 62 
 63 //****************************************************************************
 64 //  This version returns the length of the output string.
 65 //  It is more useful when implementing a walking-string function.
 66 //****************************************************************************
 67 static const FLOAT_OR_DOUBLE round_nums[8] = {
 68         0.5,
 69         0.05,
 70         0.005,
 71         0.0005,
 72         0.00005,
 73         0.000005,
 74         0.0000005,
 75         0.00000005
 76 };
 77 
 78 static unsigned FloatOrDoubleToStr(char *outbfr, FLOAT_OR_DOUBLE flt_or_dbl, unsigned dec_digits, int use_leading_plus)
 79 {
 80     static char local_bfr[128] ;
 81     char *output = (outbfr == 0) ? local_bfr : outbfr ;
 82 
 83     //*******************************************
 84     //  extract negative info
 85     //*******************************************
 86     if (flt_or_dbl < 0.0) {
 87         *output++ = '-' ;
 88         flt_or_dbl *= -1.0 ;
 89     } else {
 90         if (use_leading_plus) {
 91             *output++ = '+' ;
 92         }
 93     }
 94 
 95     //  handling rounding by adding .5LSB to the floating-point data
 96     if (dec_digits < 8) {
 97         flt_or_dbl += round_nums[dec_digits] ;
 98     }
 99 
100     //**************************************************************************
101     //  construct fractional multiplier for specified number of digits.
102     //**************************************************************************
103     uint mult = 1 ;
104     uint idx ;
105     for (idx=0; idx < dec_digits; idx++)
106         mult *= 10 ;
107 
108     uint wholeNum = (uint) flt_or_dbl ;
109     uint decimalNum = (uint) ((flt_or_dbl - wholeNum) * mult);
110 
111     //*******************************************
112     //  convert integer portion
113     //*******************************************
114     char tbfr[40] ;
115     idx = 0 ;
116     while (wholeNum != 0) {
117         tbfr[idx++] = '0' + (wholeNum % 10) ;
118         wholeNum /= 10 ;
119     }
120 
121     if (idx == 0) {
122         *output++ = '0' ;
123     } else {
124         while (idx > 0) {
125             *output++ = tbfr[idx-1] ; 
126             idx-- ;
127         }
128     }
129     if (dec_digits > 0) {
130         *output++ = '.' ;
131 
132         //*******************************************
133         //  convert fractional portion
134         //*******************************************
135         idx = 0 ;
136         while (decimalNum != 0) {
137             tbfr[idx++] = '0' + (decimalNum % 10) ;
138             decimalNum /= 10 ;
139         }
140         //  pad the decimal portion with 0s as necessary;
141         //  We wouldn't want to report 3.093 as 3.93, would we??
142         while (idx < dec_digits) {
143             tbfr[idx++] = '0' ;
144         }
145 
146         if (idx == 0) {
147             *output++ = '0' ;
148         } else {
149             while (idx > 0) {
150                 *output++ = tbfr[idx-1] ;
151                 idx-- ;
152             }
153         }
154     }
155     *output = 0 ;
156 
157     //  prepare output
158     output = (outbfr == 0) ? local_bfr : outbfr ;
159 
160     return strlen(output) ;
161 }
162 
163 //****************************************************************************
164 #define  PAD_RIGHT   1
165 #define  PAD_ZERO    2
166 
167 static int prints (char **out, const char *string, int width, int pad,
168                      unsigned int max_output_len, int *cur_output_char_p)
169 {
170     register int pc = 0, padchar = ' ';
171     if (width > 0) {
172         int len = 0;
173         const char *ptr;
174         for (ptr = string; *ptr; ++ptr)
175             ++len;
176         if (len >= width)
177             width = 0;
178         else
179             width -= len;
180         if (pad & PAD_ZERO)
181             padchar = '0';
182     }
183     if (!(pad & PAD_RIGHT)) {
184         for (; width > 0; --width) {
185             int result = printchar ( out, padchar, max_output_len, cur_output_char_p);
186             if (result <0)
187                 return result;
188             ++pc;
189         }
190     }
191     for (; *string; ++string) {
192         int result = printchar (out, *string, max_output_len, cur_output_char_p);
193         if (result < 0)
194             return result;
195         ++pc;
196     }
197     for (; width > 0; --width) {
198         int result = printchar ( out, padchar, max_output_len,cur_output_char_p);
199         if (result < 0) 
200             return result;
201         ++pc;
202     }
203     return pc;
204 }
205 
206 //****************************************************************************
207 /* the following should be enough for 32 bit int */
208 #define PRINT_BUF_LEN 12
209 static int printi (char **out, int i, uint base, int sign, int width, int pad,
210                      int letbase, unsigned int max_output_len,
211                      int *cur_output_char_p, int use_leading_plus)
212 {
213     char print_buf[PRINT_BUF_LEN];
214     char *s;
215     int t, neg = 0, pc = 0;
216     unsigned u = (unsigned) i;
217     if (i == 0) {
218         print_buf[0] = '0';
219         print_buf[1] = '\0';
220         return prints ( out, print_buf, width, pad, max_output_len, cur_output_char_p);
221     }
222     if (sign && base == 10 && i < 0) {
223         neg = 1;
224         u = (unsigned) -i;
225     }
226     //  make sure print_buf is NULL-term
227     s = print_buf + PRINT_BUF_LEN - 1;
228     *s = '\0';
229 
230     while (u) {
231         t = u % base;  // Signed-unsigned mix with divide
232         if (t >= 10)
233             t += letbase - '0' - 10;
234         *--s = (char) t + '0';
235         u /= base;  // Signed-unsigned mix with divide
236     }
237     if (neg) {
238         if (width && (pad & PAD_ZERO)) {
239             int result = printchar (out, '-', max_output_len, cur_output_char_p);
240             if (result < 0)
241                 return result;
242             ++pc;
243             --width;
244         }
245         else {
246             *--s = '-';
247         }
248     } else {
249         if (use_leading_plus) {
250             *--s = '+';
251         }
252     }
253     int result = prints (out, s, width, pad, max_output_len, cur_output_char_p);
254     if (result <0) {
255         return result;
256     } else {
257         return pc + result;
258     }
259 }
260 
261 //****************************************************************************
262 static int print (char **out, unsigned int flags, 
263                 unsigned int max_output_len, const char *format, va_list vargs)
264 {
265     int post_decimal ;
266     int width, pad ;
267     unsigned dec_width = 6 ;
268     int pc = 0;
269     char scr[2];
270     int cur_output_char = 0;
271     int *cur_output_char_p = &cur_output_char;
272     int use_leading_plus = 0 ;  //  start out with this clear
273 
274     max_output_len--; // make room for a trailing '\0'
275     for (; *format != 0; ++format) {
276         if (*format == '%') {
277             dec_width = 6 ;
278             ++format;
279             width = pad = 0;
280             if (*format == '\0')
281                 break;
282             if (*format == '%')
283                 goto out_lbl;
284             if (*format == '-') {
285                 ++format;
286                 pad = PAD_RIGHT;
287             }
288             if (*format == '+') {
289                 ++format;
290                 use_leading_plus = 1 ;
291             }
292             while (*format == '0') {
293                 ++format;
294                 pad |= PAD_ZERO;
295             }
296             post_decimal = 0 ;
297             if (*format == '.'  ||
298                     (*format >= '0' &&  *format <= '9')) {
299 
300                 while (1) {
301                     if (*format == '.') {
302                         post_decimal = 1 ;
303                         dec_width = 0 ;
304                         format++ ;
305                     } else if ((*format >= '0' &&  *format <= '9')) {
306                         if (post_decimal) {
307                             dec_width *= 10;
308                             dec_width += (uint) (u8) (*format - '0');
309                         } else {
310                             width *= 10;
311                             width += *format - '0';
312                         }
313                         format++ ;
314                     } else {
315                         break;
316                     }
317                 }
318             }
319             if (*format == 'l')
320                 ++format;
321             if (*format == 'h')
322                 ++format;
323             switch (*format) {
324             case 's':
325             {
326                 char *s = va_arg(vargs, char*);
327                 int result = prints (out, s ? s : "(null)", width, pad, max_output_len, cur_output_char_p);
328                 if (result<0) 
329                     return result;
330                 pc += result;
331                 use_leading_plus = 0 ;  //  reset this flag after printing one value
332             }
333             break;
334             
335             case 'd':
336             {
337                 int result = printi (out, va_arg(vargs, int), 10, 1, width, pad, 'a',
338                                      max_output_len, cur_output_char_p, use_leading_plus);
339                 if (result<0) 
340                     return result;
341                 pc += result;
342 
343                 use_leading_plus = 0 ;  //  reset this flag after printing one value
344             }
345             break;
346             
347             case 'x':
348             {
349                 int result = printi (out, va_arg(vargs, int), 16, 0, width, pad, 'a', 
350                                     max_output_len, cur_output_char_p, use_leading_plus);
351                 if (result<0) 
352                     return result;
353                 pc += result;
354                 use_leading_plus = 0 ;  //  reset this flag after printing one value
355             }
356             break;
357             
358             case 'X':
359             {
360                 int result = printi (out, va_arg(vargs, int), 16, 0, width, pad, 'A', 
361                                     max_output_len, cur_output_char_p, use_leading_plus);
362                 if (result<0) 
363                     return result;
364                 pc += result;
365                 use_leading_plus = 0 ;  //  reset this flag after printing one value
366             }
367             break;
368             
369             case 'p':
370             case 'u':
371             {
372                 int result = printi (out, va_arg(vargs, int), 10, 0, width, pad, 'a', 
373                             max_output_len, cur_output_char_p, use_leading_plus);
374                 use_leading_plus = 0 ;  //  reset this flag after printing one value
375                 if (result<0) 
376                     return result;
377                 pc += result;
378             }
379             break;
380             
381             case 'c':
382             {
383                 /* char are converted to int then pushed on the stack */
384                 scr[0] = (char)va_arg(vargs,int);
385                 scr[1] = '\0';
386                 int result = prints (out, scr, width, pad, max_output_len, cur_output_char_p);
387                 if (result<0) 
388                     return result;
389                 pc += result;
390                 use_leading_plus = 0 ;  //  reset this flag after printing one value
391             }
392             break;
393 
394             case 'f':
395             {
396                 double d = va_arg(vargs,double);
397                 FLOAT_OR_DOUBLE flt_or_dbl = d;
398                 char bfr[81];
399                 FloatOrDoubleToStr(bfr, flt_or_dbl, dec_width, use_leading_plus);
400                 int result = prints (out, bfr, width, pad, max_output_len, cur_output_char_p);
401                 if (result<0) 
402                     return result;
403                 pc += result;
404                 use_leading_plus = 0 ;  //  reset this flag after printing one value
405             }
406             break;
407 
408             default: {
409                 int result = printchar (out, '%', max_output_len, cur_output_char_p);
410                 if (result<0) 
411                     return result;
412                 ++pc;
413 
414                 result = printchar (out, *format, max_output_len, cur_output_char_p);
415                 if (result<0) 
416                     return result;
417                 ++pc;
418 
419                 use_leading_plus = 0 ;  //  reset this flag after printing one value
420             }
421                 break;
422             }
423         } else {
424             out_lbl: {
425                 int result = printchar (out, *format, max_output_len, cur_output_char_p);
426                 if (result<0) 
427                     return result;
428                 ++pc;
429             }
430         }
431     }  //  for each char in format string
432 
433     max_output_len++; // make room for a trailing '\0'
434 
435     if (!(flags & MYPRINT_FLAGS_NO_TRAILING_NULL)) {
436         if (out) 
437             **out = '\0';
438         else
439             return MYPRINT_NULL_PTR;
440     }
441 
442     return pc;
443 }
444 
445 int myprintf (const char *format, ...)
446 {
447     va_list vargs;
448     va_start(vargs,format);
449     int result = print (0, MYPRINT_FLAGS_NONE, UINT_MAX_NUM, format, vargs);
450     va_end(vargs);
451     return result;
452 }  
453 
454 int sprintf(char *str, const char *format, ...)
455 {
456     va_list vargs;
457     va_start(vargs,format);
458 
459     int charCnt = print(&str, MYPRINT_FLAGS_NONE, UINT_MAX_NUM, format, vargs);
460 
461     va_end(vargs);
462 
463     return charCnt;
464 }
465 
466 int snprintf(char *str, unsigned int maxLen, const char *format, ...)
467 {
468     va_list vargs;
469     va_start(vargs,format);
470 
471     int charCnt = print(&str, MYPRINT_FLAGS_NONE, (unsigned int)maxLen, format, vargs);
472 
473     va_end(vargs);
474 
475     return charCnt;
476 }
477 
478 //****************************************************************************
479 int testPrintf (void)
480 {
481     int slen ;
482     char *ptr = "Hello world!";
483     char *np = 0;
484     char buf[128];
485     char buf2[10];
486 
487     myprintf ("\n");
488     myprintf ("ptr=%s, %s is null pointer, char %c='a'\n", ptr, np, 'a');
489     myprintf ("hex %x = ff, hex02=%02x\n", 0xff, 2);   //  hex handling
490     myprintf ("signed %d = %uU = 0x%X\n", -3, -3, -3);   //  int formats
491     myprintf ("%d %s(s) with %%\n", 0, "message");
492 
493     slen = sprintf (buf, "justify: left=\"%-10s\", right=\"%10s\"\n", "left", "right");
494     myprintf ("[len=%d] %s", slen, buf);
495 
496     sprintf(buf, "     padding (pos): zero=[%04d], left=[%-4d], right=[%4d]\n", 3, 3, 3) ;
497     myprintf ("%s", buf);
498 
499     //  test walking string builder
500     slen = 0 ;
501     slen += sprintf(buf+slen, "padding (neg): zero=[%04d], ", -3) ;   //lint !e845
502     slen += sprintf(buf+slen, "left=[%-4d], ", -3) ;
503     slen += sprintf(buf+slen, "right=[%4d]\n", -3) ;
504     myprintf ("[%d] %s", slen, buf);
505 
506     //#ifdef USE_FLOATING_POINT
507     myprintf("+ format: int: %+d, %+d, float: %+.1f, %+.1f, reset: %d, %.1f\n", 3, -3, 3.0f, -3.0f, 3, 3.0);
508     sprintf (buf, "%.3f is a float, %.2f is with two decimal places\n", 3.345f, 3.345f);
509     myprintf ("%s", buf);
510     myprintf("\n");
511     //#else // USE_DOUBLES
512     myprintf("+ format: int: %+d, %+d, double: %+.1f, %+.1f, reset: %d, %.1f\n", 3, -3, 3.0, -3.0, 3, 3.0);
513     sprintf (buf, "%.3f is a double, %.2f is with two decimal places\n", 3.345, 3.345);
514     myprintf ("%s", buf);
515     //#endif
516 
517     sprintf (buf, "multiple unsigneds: %u %u %2u %X\n", 15, 5, 23, 0xB38F) ;
518     myprintf ("%s", buf);
519 
520     sprintf (buf, "multiple chars: %c %c %c %c\n", 'a', 'b', 'c', 'd') ;
521     myprintf ("%s", buf);
522 
523     //#ifdef USE_FLOATING_POINT
524     myprintf("\nFloats:\n");
525     sprintf (buf, "multiple floats: %f %.1f %2.0f %.2f %.3f %.2f [%-8.3f]\n",
526             3.45f, 3.93f, 2.45f, -1.1f, 3.093f, 13.72f, -4.382f) ;
527     myprintf ("%s\n", buf);
528     
529     sprintf (buf, "float special cases: %f %.f %.0f %2f %2.f %2.0f\n",
530             3.14159, 3.14159, 3.14159, 3.14159, 3.14159, 3.14159) ;
531     myprintf ("%s\n", buf);
532     
533     sprintf (buf, "rounding floats: %.1f %.1f %.3f %.2f [%-8.3f]\n",
534             3.93f, 3.96f, 3.0988f, 3.999f, -4.382f) ;
535     myprintf ("%s\n", buf);
536 
537     //#else // USE_DOUBLES
538     myprintf("\nDoubles:\n");
539     sprintf (buf, "multiple doubles: %f %.1f %2.0f %.2f %.3f %.2f [%-8.3f]\n",
540             3.45, 3.93, 2.45, -1.1, 3.093, 13.72, -4.382) ;
541     myprintf ("%s", buf);
542     sprintf (buf, "double special cases: %f %.f %.0f %2f %2.f %2.0f\n",
543             3.14159, 3.14159, 3.14159, 3.14159, 3.14159, 3.14159) ;
544     myprintf ("%s", buf);
545     sprintf (buf, "rounding doubles: %.1f %.1f %.3f %.2f [%-8.3f]\n",
546             3.93, 3.96, 3.0988, 3.999, -4.382) ;
547     myprintf ("%s", buf);
548     //#endif
549     myprintf("\n");
550 
551     //  test case from our Yagarto ARM9 problem
552     char *cmd = "adc_vref " ;
553     float fvalue = -3.0031290 ;
554     sprintf (buf, "%s%.7f", cmd, (double) fvalue);
555     myprintf("%s\n", buf);
556     
557     myprintf("int: %d\n", 10101);
558     myprintf("signed int: %u\n", -1);
559     myprintf("hex: 0x%x\n", 16);
560     myprintf("ptr: 0x%p\n", fvalue);
561     myprintf("str: %s\n", cmd);
562     myprintf("float: %.6f\n", fvalue);
563     myprintf("char: %c\n", 'A');
564 
565     return 0;
566 }
567 
568 int main(void)
569 {
570     testPrintf();
571     
572     return 0;
573 }

 

转载于:https://www.cnblogs.com/iczelion/p/6151922.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值