模拟实现printf函数

时间:2021-06-29 19:23:53

模拟实现 printf()函数


如果要想解决这个问题 ,就要 知道一个知识点 ,可变参数列表  ,
可变参数列表是通过宏来实现的,这些宏定义于stdarg.h头文件中,它是标准库的一部分。这个头文件声明
个类型va_list 和三个宏va_start、va_arg和va_end。
转到定义处 查看一下这几个宏和类型 
typedef char *  va_list;

#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

#define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )

#define _crt_va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

#define _crt_va_end(ap)      ( ap = (va_list)0 )
从上 面可以看出  va_list 表示的是 一个 char*的指针 
#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
_INSIZEOF( n) 表示 的 是将 一个类型 如果该类型的空间字节数为"1 2 3 4"  都将它进位 为4字节 
                                                              如果该类型的空间字节数为"5 6 7 8 " 都将它进位 为8字节 
#define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
表示的是 将 ap跳过第一个参数 v ,指向下一个 
#define _crt_va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
表示的是 要计算的参数,但是此时的 ap指向的是下一个参数,这样就可以为下一个参数的使用做好基础
#define _crt_va_end(ap)      ( ap = (va_list)0 )
结束 后 将 ap  赋值为 \0;
下面是我写的一个简单 的printf()函数 
代码实现
#define  _CRT_SECURE_NO_WARENINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<stdarg.h>
void  Puts(const char *src)//我自己定义的puts 函数 输出时不会输出‘\n’
{
	while(*src)
	{
		putchar(*src);
		src++;
	}
}
void My_printf(const char *src,...)
{
	va_list arg;
	va_start(arg,src);
	while(*src)//判断 字符串是否 结束 
	{
		if(*src =='s')
		{ 
			Puts(va_arg(arg,char*));//在这块不能使用puts()函数 ,因为会多输出一个 '\n'
		}
		else if(*src == 'c')
		{
			 putchar(va_arg(arg,char));
		}
		else   //如果不是类型名 就 原型输出
			putchar(*src);
		src++;
	}
	va_end(arg);
}
int main()
{
	My_printf("s\n ccc.\n","hello",'b','i','t');
	system("pause");
	return 0 ;
}