📄 printf.c
字号:
/* vprintf.c * * (C) Copyright Apr 15 1995, Edmond J. Breen. * ALL RIGHTS RESERVED. * This code may be copied for personal, non-profit use only. * */#include <stdio.h>#include <ctype.h>#include <string.h>#include <stdlib.h>#include <math.h>#include <stdarg.h>#include "stdliblocal.h"static int charin_(char **buf){ int ch; ch = **buf; *buf += 1; if(!ch) ch = EOF; return ch;}static int charback_(int ch, char **buf){ *buf -= 1; return ch;}static int charout_(int c, char **buf){ char *s; s = *buf; *s++ = c; *s = 0; *buf = s; return 1;}int _Uprintf(int (*output)(), void *arg, const char *fmt, va_list ap){ /*_UPRINTF * Orginally developed from James Hendrix's Small C tools. * * (c) Edmond J.Breen (March, 1995). * ALL RIGHTS RESERVED. * * Purpose: To perform formatted printing to a function. * It performs a superset of printf type * operations. * * _UPRINTF RECOGNISES: * FLAGS: * -, +, 0 and #. * plus ! and | (see below). * * CONVERSION CHARACTERS: * d, i, o, x, X, u, c, s, * f, e, E, g, G, p, n, % * plus b (see below). * * LENGTH MODIFIES: * l, L, and h. * * The WIDTH and or the PRECISION can be set indirectly * via * as specified by K&R. * * _UPRINTF EXTRA FEATURES. * NEW FLAGS: * FLAG WHAT IT SPECIFIES * | Centre justification. * ! Used with floating point numbers. * It specifies, if possible, that the * number will be centred with respect * to the decimal point. * If used with non floating point * numbers or the floating point number * does not contain a decimal point, * the ! flag is equivalent to |. * NEW CONVERSION CHARACTER: * CHARACTER WHAT IT SPECIFIES * b int, unsigned binary notation. */ int v; static char str[128]; char *sptr, lseen,Lseen; int left, right, centre, maxchr, pad, len, width, sign, dprec, mod, prec,dot,gotfloat; v = 0; while(*fmt) { if(*fmt != '%') { (*output)(*fmt,arg); ++fmt;++v; continue; } else if(*++fmt =='%') { (*output)(*fmt++,arg); ++v; continue; } pad = ' '; centre = len = right = left = 0; gotfloat = dot = sign = mod = 0; Lseen = lseen = dprec = 0; while(*fmt) { /* collect in any order */ if(*fmt == '-') left = 1; else if(*fmt == '0') pad = '0'; else if(*fmt == '+') sign = 1; else if(*fmt == '#') mod = 1; else if(*fmt == '|') centre = 1; else if(*fmt == '!') centre = 1, dot = 1; else break; ++fmt; } if(isdigit(*fmt)) { width = atoi(fmt); while(isdigit(*fmt)) ++fmt; } else if(*fmt == '*') { width = va_arg(ap,int); fmt++; } else width = -1; if(*fmt == '.') { if(*++fmt == '*') { maxchr = va_arg(ap,int); fmt++; } else { maxchr = atoi(fmt); while(isdigit(*fmt)) ++fmt; } } else maxchr = -1; switch(*fmt) { /* check for length modifier*/ case 'h': fmt++;break; case 'l': lseen = 1; fmt++;break; case 'L': Lseen = 1; fmt++;break; } sptr = str; switch(*fmt++) { case 'c': sptr[0] = (char)va_arg(ap,int); sptr[1] = 0; break; case 'b': if(lseen) ultoa(va_arg(ap,long),sptr,2); else utoa(va_arg(ap,int),sptr,2); break; case 'i': case 'd': if(lseen) ltoa(va_arg(ap,long),sptr,10); else itoa(va_arg(ap,int),sptr,10); dprec=1; break; case 'u': if(lseen) ultoa(va_arg(ap,unsigned long),sptr,10); else utoa(va_arg(ap,unsigned),sptr,10); dprec=1; break; case 'o': if(mod) *sptr = '0'; if(lseen)ltoa(va_arg(ap,long),&sptr[mod],8); else itoa(va_arg(ap,int),&sptr[mod],8); dprec = 1; break; case 's': sptr = va_arg(ap,char*); break; case 'x': case 'X': if(mod) { *sptr = '0', sptr[1] = *(fmt-1); mod++; } if(lseen)ultoa(va_arg(ap,long),&sptr[mod],16); else utoa(va_arg(ap,int),&sptr[mod],16); if(*(fmt-1) == 'X') { while(*sptr) { *sptr = toupper(*sptr); sptr++; } sptr = str; } dprec = 1; break; case 'e': case 'E': case 'g': case 'G': case 'f': { int trunc = 0; char type = *(fmt-1),c; double d; gotfloat = 1; if(maxchr < 0) prec = 6; else prec = maxchr,maxchr = -1; if(Lseen) d = va_arg(ap,double); else d = va_arg(ap,double); if(type == 'g' || type == 'G') { double ex; if(d !=0) ex = log10(d < 0? -d:d); else ex = 1; if(ex < -4 || ex >= prec) c = type - 2; else c = 'f'; trunc = 1; } else c = type; if(mod) { if(!prec) prec = 1; trunc = 0; } sptr = fftoa(d,str, prec, c,trunc); } break; case 'n': *va_arg(ap,int*) = v; continue; case 'p': ultoa((long)va_arg(ap,long*),sptr,16); break; default: (*output)(*(fmt-1),arg); while(*fmt) { (*output)(*fmt++,arg); ++v; } return v; } if(!len && sptr) len = strlen(sptr); if(sign) len += (*sptr == '-' ? 0: 1); if(dprec && maxchr >=0) { dprec = maxchr; pad = '0'; }else dprec = 0; if(maxchr > -1 && maxchr<len) len = maxchr; if(width>len) width = width -len; else if(dprec > len) width = dprec - len; else width = 0; if(centre) { left = (right = width >> 1) + (width%2); if(dot && gotfloat) { int d = 0,c; while(sptr[d] && sptr[d] != '.') d++; if(sptr[d] == '.') { c = (width + len)/2; if(sign && sptr[0] != '-') d++; if(c-d > 0) right = c-d; else right = 0; if(width - right > 0) left = width - right; else left = 0; } } } else if(!left) right = width; else left = width; if(sign && !left && pad == '0') { if(*sptr != '-') { (*output)('+',arg); ++v;len--; } sign = 0; } while(right--) {(*output)(pad,arg); ++v;} if(sign && *sptr != '-') {(*output)('+',arg);len--;++v;} while(len--) {(*output)(*sptr++,arg);++v;} while(left--) {(*output)(pad,arg);++v;} } return v;}int printf_(const char *fmt,...){ int rtn; va_list ap; /*ap =*/ va_start(ap,fmt); rtn = _Uprintf(fputc,stdout,fmt,ap); va_end(ap); return rtn;}int fprintf(FILE *fp, const char *fmt, ...){ int rtn; va_list ap; va_start(ap,fmt); rtn = _Uprintf(fputc,fp,fmt,ap); va_end(ap); return rtn;}int sprintf(char *str, const char *fmt, ...){ int rtn; va_list ap; va_start(ap,fmt); rtn = _Uprintf(charout_,&str,fmt,ap); va_end(ap); return rtn;}int vfprintf(FILE *fp, const char *fmt,va_list ap){ int rtn; rtn = _Uprintf(fputc,fp,fmt,ap); return rtn;}int vsprintf(char *str, const char *fmt,va_list ap){ int rtn; rtn = _Uprintf(charout_,&str,fmt,ap); return rtn;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -