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

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

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

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

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

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

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

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

 #include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<stdarg.h> #define N 110
#define eps 1e-16
#define INF 1e9
#define PRECISION 30 int maxx(int x,int y){return x>y ? x:y;}
void swapp(char *x,char *y){char t;t=*x;*x=*y;*y=t;}
int find_int_type(int int_type,char ch);
void change_int_type_to_char(int x,int int_type,char *s,int *sl,int *minus);
void print_int_regardless_type(char *s,int *sl,int minus,int Justify_type,int min_width,int precision);
void print_int(int x,int Justify_type,int min_width,int precision,int int_type);
void print_string(char *s,int Justify_type,int min_width,int precision);
int is_g_or_G(char double_type){return (double_type == 'g' || double_type=='G');}
void rounding_off(char *s,int *sl,int *ml,int precision);
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);
void print_double_f(char *s,int sl,int ml,int minus,int Justify_type,int min_width,int precision);
void print_double(double x,int Justify_type,int min_width,int precision,char double_type);
int myprintf(const char *format,...); int main()
{
// freopen("a.out","w",stdout);
int a=;
double b=9.9734567;
int count=;
myprintf("%\n");
myprintf("%15e%15e\n",-0.0000123,123.123);printf("%15e%15e\n",-0.0000123,123.123);
myprintf("%f\n",0.0000123);printf("%f\n",0.0000123);
myprintf("%.1E\n",b);printf("%.1E\n",b);
myprintf("%e\n",0.0000123);printf("%e\n",0.0000123);
myprintf("%15.8g\n",0.000012346789);printf("%15.8g\n",0.0000123456789);
myprintf("%5d%10d\n",a,a);printf("%5d%10d\n",a,a);
myprintf("%10.5d%10.5d\n",a,a);printf("%10.5d%10.5d\n",a,a);
myprintf("%15.10hd%15.10ld\n",count,count);printf("%15.10hd%15.10ld\n",count,count);
myprintf("%5o\n",a);printf("%5o\n",a);
myprintf("%f\n",b);printf("%f\n",b);
myprintf("%15f%20.10f\n",-b,-b);printf("%15f%20.10f\n",-b,-b);
myprintf("%15g\n",0.0000123);printf("%15g\n",0.0000123);
myprintf("%15e%15E%15g%15g\n",-b,b,b,0.0000123);printf("%15e%15E%15g%15g\n",-b,b,b,0.0000123);
myprintf("%15g\n",0.0000123);printf("%15g\n",0.0000123);
myprintf("%-15.10x%10.10X\n",count);printf("%-15.10x%10.10X\n",count);
myprintf("%10.5s\n%c\n","asdfghjkl",'a');printf("%10.5s\n%c\n","asdfghjkl",'a');
myprintf("\x41\101 \\ \r\n");printf("\x41\101 \\ \r\n");
unsigned int d = ;
myprintf("%.10u\n",d);printf("%.10u\n",d);
int *p;
myprintf("%p\n",p);printf("%p\n",p);
return ;
} int find_int_type(int int_type,char ch)
{
if(ch=='d' || ch=='i') return int_type;
if(ch=='o') return ;
if(ch=='x') return ;
if(ch=='X') return ;
if(ch=='u') return int_type+;
} void change_int_type_to_char(int x,int int_type,char *s,int *sl,int *minus)
{
*sl=;
switch(int_type)
{
case :{//int
int y=(int)x;if(y<) *minus=,y=-y;
while(y) s[(*sl)++]=(y%)+'',y/=;
break;
}
case :{//unsigned int
unsigned int y=(unsigned int)x;
while(y) s[(*sl)++]=(y%)+'',y/=;
break;
}
case :{//short
short int y=(short int)x;if(y<) *minus=,y=-y;
while(y) s[(*sl)++]=(y%)+'',y/=;
break;
}
case :{//unsigned short
unsigned short int y=(unsigned short int)x;
while(y) s[(*sl)++]=(y%)+'',y/=;
break;
}
case :{//long int
long int y=(long int )x;if(y<) *minus=,y=-y;
while(y) s[(*sl)++]=(y%)+'',y/=;
break;
}
case :{//unsigned long int
unsigned long int y=(unsigned long int)y;
while(y) s[(*sl)++]=(y%)+'',y/=;
break;
}
case :{//o
int y=(int )x;
while(y) s[(*sl)++]=(y%)+'',y/=;
break;
}
case :{//x
int y=(int)x;
while(y) s[(*sl)++]=((y%)>=) ? (y%)-+'a' : (y%)+'',y/=;
break;
}
case :{//X
int y=(int)x;
while(y) s[(*sl)++]=((y%)>=) ? (y%)-+'A' : (y%)+'',y/=;
break;
}
}
} void print_int_regardless_type(char *s,int *sl,int minus,int Justify_type,int min_width,int precision)
{
while(precision<INF && *sl<precision) s[(*sl)++]='';
if(minus) s[(*sl)++]='-';
int space=min_width-*sl; if(Justify_type==)//right
for(int i=;i<=space;i++) putchar(' ');
for(int i=(*sl)-;i>=;i--) putchar(s[i]);
if(Justify_type==)//left
for(int i=;i<=space;i++) putchar(' ');
} void print_int(int x,int Justify_type,int min_width,int precision,int int_type)
{
int minus=(x<) ? :;
char *s=(char *)malloc(N*sizeof(char));
int *sl=(int *)malloc(sizeof(int));
change_int_type_to_char(x,int_type,s,sl,&minus);
print_int_regardless_type(s,sl,minus,Justify_type,min_width,precision);
free(s);
free(sl);
} void print_string(char *s,int Justify_type,int min_width,int precision)
{
int sl=strlen(s);
if(sl > precision) sl=precision;
int space=min_width-sl; if(Justify_type==)//right
for(int i=;i<=space;i++) putchar(' ');
for(int i=;i<sl;i++) putchar(s[i]);
if(Justify_type==)//left
for(int i=;i<=space;i++) putchar(' ');
} void rounding_off(char *s,int *sl,int *ml,int precision)//四舍五入
{
if(s[(*ml)+precision]<='') return;
s[(*ml)+precision-]++;
for(int i=(*ml)+precision-;i>=;i--) s[i-]+=(s[i]-'')/,s[i]=(s[i]-'')%+'';
if(s[]>'')
{
(*sl)++;(*ml)++;
for(int i=(*ml)+precision;i>=;i--) s[i]=s[i-];
s[]=(s[]-'')/+'';
s[]=(s[]-'')%+'';
}
} 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)
{
int space=min_width-(minus++precision+++);
if(precision) space--;//'.' if(Justify_type==)//right
for(int i=;i<=space;i++) putchar(' ');
if(minus) putchar('-');
putchar(s[]);
if(precision) putchar('.');
for(int i=;i<=precision;i++)
{
if(i>=sl && is_g_or_G(double_type)) break;
putchar((i<sl) ? s[i] : '');
}
putchar(is_g_or_G(double_type) ? double_type+'e'-'g' : double_type);
if(exponent>=) putchar('+');
else putchar('-'),exponent*=-;
putchar(exponent/+'');putchar((exponent/)%+'');putchar(exponent%+'');
if(Justify_type==)//left
for(int i=;i<=space;i++) putchar(' ');
} void print_double_f(char *s,int sl,int ml,int minus,int Justify_type,int min_width,int precision)
{
int space=min_width-(minus+ml+precision);
if(precision) space--;//'.'
if(Justify_type==)//right
for(int i=;i<=space;i++) putchar(' ');
if(minus) putchar('-');
for(int i=;i<ml;i++) putchar(s[i]);
if(precision) putchar('.');
for(int i=ml;i<=ml-+precision;i++) putchar((i<sl) ? s[i]:'');
if(Justify_type==)//left
for(int i=;i<=space;i++) putchar(' ');
} //m.ddddd
void print_double(double x,int Justify_type,int min_width,int precision,char double_type)
{
if(precision==INF) precision=;
int zero=(fabs(x) < eps);
int minus=(x<) ? :;x=fabs(x);
char *s=(char *)malloc(N*sizeof(char));
int sl=,ml=,y=(int)x;x-=y;
if(y==) s[sl++]='';
while(y) s[sl++]=y%+'',y/=;
for(int i=;i<=(sl-)/;i++) swapp(&s[i],&s[sl--i]);
ml=sl;
while(sl<=ml+PRECISION) s[sl++]=(int)(x*)+'',x=x*-(int)(x*);
//f
if(double_type=='f')
{
rounding_off(s,&sl,&ml,precision);
print_double_f(s,sl,ml,minus,Justify_type,min_width,precision);
}
else//e E g G
{
int st=,ssl=,exponent=ml-;
char *ss=(char *)malloc(N*sizeof(char));
while(!zero && s[st]=='') st++,exponent--,s[sl++]='';
for(int i=st;i<sl;i++) ss[ssl++]=s[i]; if(double_type=='e' || double_type=='E' ||
(is_g_or_G(double_type) && (exponent < - || exponent >=precision)))
{
ml=;
if(is_g_or_G(double_type))
{
if(precision) precision--,ssl--;
while(precision && ss[ml+precision-]=='') precision--;
}
int mml=;
rounding_off(ss,&ssl,&mml,precision);
if(mml==) exponent++;
print_double_e_or_E(ss,ssl,exponent,minus,Justify_type,min_width,precision,double_type);
}
else
{
precision-=ml;sl-=ml;
rounding_off(s,&sl,&ml,precision);
while(precision && s[ml+precision-]=='') precision--;
print_double_f(s,sl,ml,minus,Justify_type,min_width,precision);
}
free(ss);
}
free(s);
} int myprintf(const char *format,...)
{
char ch;
int arg_int;
double arg_double;
char *arg_str;
void *arg_p;
va_list ap;
va_start(ap,format); while((ch = *format++)!='\0')
{
if(ch!='%') {putchar(ch);continue;}
//ch = '%' *format = '\0'
if(*format=='\0' || *format=='%') {putchar('%');continue;} int Justify_type=,min_width=,precision=INF,int_type=,ok=;
if(*format=='-') Justify_type=,format++;
while(*format>='' && *format<='') min_width=min_width*+*format-'',format++;
if(*format=='.')
{
format++;precision=;
while(*format>='' && *format<='') precision=precision*+*format-'',format++;
}
if(*format=='h') int_type=,format++;
if(*format=='l') int_type=,format++; if(*format=='d' || *format=='i' || *format=='o' || *format=='x' || *format=='X' || *format=='u')
{
ok=;arg_int=va_arg(ap,int);
print_int(arg_int,Justify_type,min_width,precision,find_int_type(int_type,*format));
}
if(*format=='c')
{
ok=;arg_int=va_arg(ap,int);
putchar(arg_int);
}
if(*format=='s')
{
ok=;arg_str=va_arg(ap,char *);
print_string(arg_str,Justify_type,min_width,precision);
}
if(*format=='f' || *format=='e' || *format=='E' || *format=='g' || *format=='G')
{
ok=;arg_double=va_arg(ap,double);
print_double(arg_double,Justify_type,min_width,precision,*format);
}
if(*format=='p')
{
ok=;arg_p=va_arg(ap,void *);
arg_int=(int)arg_p;
precision=;//默认地址为8位,若机器地址不为8位可更改此处。
print_int(arg_int,Justify_type,min_width,precision,);
}
if(!ok) {putchar('%');format--;}//ch=='%'
format++;
}
va_end(ap);
}

手写简化版printf函数的更多相关文章

  1. 依据ECMA规范,手写一个bind函数

    Function.prototype.bind 函数,参见ECMA规范地址 如题,这次来实现一个boundFunction函数,不挂载在Function.prototype上,而是一个单独声明的函数. ...

  2. 【OpenCV学习笔记】之六 手写图像旋转函数---万丈高楼平地起

    话说,平凡之处显真格,这一点也没错!  比如,对旋转图像进行双线性插值,很简单吧?  可,对我,折腾了大半天,也没有达到预期效果!  尤其是三个误区让我抓瞎好久: 1,坐标旋转公式.   这东西,要用 ...

  3. 手写事件代理函数 (Delegated function)

    ‘手写 ’ 这个词 ,面试是不是听过无数遍呢 ! 今天我们来手写一个这样的事件委托函数 => function( parent, selector, type ,  handle)  {} 你需 ...

  4. 前端面试手写代码——JS函数柯里化

    目录 1 什么是函数柯里化 2 柯里化的作用和特点 2.1 参数复用 2.2 提前返回 2.3 延迟执行 3 封装通用柯里化工具函数 4 总结和补充 1 什么是函数柯里化 在计算机科学中,柯里化(Cu ...

  5. cs224d 作业 problem set2 (一) 用tensorflow纯手写实现sofmax 函数,线性判别分析,命名实体识别

    Hi Dear Today we will use tensorflow to implement the softmax regression and linear classifier algor ...

  6. 手写Function.bind函数

    if(!Function.prototype.bind){ Function.prototype.bind = function(oThis){ if(typeof this !=="fun ...

  7. 手写简化版SpringBoot

    Springboot项目全部依赖注解的,web工程是如何启动的 1 首先引入了Tomcat依赖,然后用java代码启动Tomcat容器,默认Tomcat版本是8.5版本 2 Tomcat是实现了ser ...

  8. 手写map, filter函数

    function map(arr, fn) { let newArr = []; for (let i = 0; i < arr.length; i++) { newArr[i] = fn(ar ...

  9. 22 道高频 JavaScript 手写面试题及答案

    实现防抖函数(debounce) 防抖函数原理:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时. 那么与节流函数的区别直接看这个动画实现即可. 手写简化版: // 防抖函数 cons ...

随机推荐

  1. typescript 不用import?

    如果你想用ts文件,而又不想import,export,怎么办呢? 感谢开发者提供的工具.    https://github.com/domchen/typescript-plus.   感想: 仅 ...

  2. NLP & AI

    NLP & AI Anaconda The Most Popular Python Data Science Platform https://www.anaconda.com/what-is ...

  3. html template & iframe

    html template & iframe https://bbs.csdn.net/topics/390123946 据说可以利用某些浏览器bug绕过跨域限制,可以也研究下; 由于浏览器对 ...

  4. Delphi报的错误

    引入单元时提示Unit 'Unit1' already uses all the units in the project. 可能是没有添加环境变量造成的,需要手动输入代码引用单元. 和Environ ...

  5. oracle 恢复误删数据

    快照  select * from sys_info as of timestamp to_Date('2014-04-08 15:28:00', 'yyyy-mm-dd hh24:mi:ss')   ...

  6. Nagios通过企业微信报警

    主要分两部分进行: 注册企业微信,自建应用,获取与发送消息相关的信息: 编写调用微信API脚本(bash),配置Nagios微信报警: 一.企业微信 1.注册企业微信:https://work.wei ...

  7. 【Cf #291 B】R2D2 and Droid Army(二分,线段树)

    因为题目中要求使连续死亡的机器人最多,令人联想到二分答案. 考虑如何检验这之中是否存在一段连续的长度为md的区间,其中花最多k步使得它们都死亡. 这个条件等价于区间中m个最大值的和不超过k. 枚举起点 ...

  8. 洛谷 P1685 游览 解题报告

    P1685 游览 题目描述 顺利通过了黄药师的考验,下面就可以尽情游览桃花岛了! 你要从桃花岛的西头开始一直玩到东头,然后在东头的码头离开.可是当你游玩了一次后,发现桃花岛的景色实在是非常的美丽!!! ...

  9. 项目管理---git----遇到问题------.gitignore不起作用

    情况 在管理一个版本库时,有时候不想要管理某些文件,这个时候我就把这个问价写到.gitignore文件中,这样应该就可以将这个文件忽略,不再进行·版本管理了,但是经常出现的情况是:将这些文件名写到其中 ...

  10. 单点登录(十三)-----实战-----cas4.2.X登录启用mongodb验证方式完整流程

    我们在之前的文章中中已经讲到了正确部署运行cas server 和 在cas client中配置. 在此基础上 我们去掉了https的验证,启用了http访问的模式. 单点登录(七)-----实战-- ...