#include <stdio.h>
#include <stdarg.h>
/*
可变参数实现printf
使用putchar()函数作为输出
思路:
通过遍历固定参数format从中提取出,可变参数类型
然后使用putchar()函数输出对应参数值
*/
/*
@ 使用递归用putchar()函数输出整数
@ 在函数void printf_demo4(const char *format, ...)中调用
*/
void printf_int(int tmp)
{
if (tmp > 9)
{
printf_int(tmp / 10);
}
putchar(tmp % 10 + '0');
}
/*
@实现功能,输入十进制或者十六进制可以打印出二进制数据
@通过位操作,当高位不为0时开始进行输出
*/
void printf_binary(int tmp)
{
char flag = 0;
int ret = 0;
char tmp_sizeof = sizeof(tmp);//先判断出输入数据是几位数据
for (int i = 0; i < tmp_sizeof * 8; i++)
{
if (tmp_sizeof == 4)
{
ret = 0x80000000 & tmp;
if (ret != 0)
{
putchar(1 + '0');
flag = 1;
}
else if ((flag == 1) && !ret)
{
putchar(0 + '0');
}
tmp <<= 1;
}
else if (tmp_sizeof == 2)
{
ret = 0x8000 & tmp;
if (ret != 0)
{
putchar(1 + '0');
flag = 1;
}
else if ((flag == 1) && !ret)
{
putchar(0 + '0');
}
tmp <<= 1;
}
else
{
ret = 0x80 & tmp;
if (ret != 0)
{
putchar(1 + '0');
flag = 1;
}
else if ((flag == 1) && !ret)
{
putchar(0 + '0');
}
tmp <<= 1;
}
}
}
/*
@实现功能,输入十进制或者十六进制可以打印出二进制数据
@通过位操作,当高位不为0时开始进行输出
*/
void printf_hex(int tmp)
{
/*标志位 判断前面半字是否有0*/
char flag = 0;
/*储存移位后的结果*/
int ret = 0;
/*得出输入的字节数 先判断出输入数据是几位数据
在c++中可使用auto实现区分 这里主要用于单片机不加区分
*/
char tmp_sizeof = sizeof(tmp);
/*根据不同字节数据 判断改移动多少位*/
char Move_Bit[4] = { 0,12,28 };
/*用作循环*/
int i = 0;
putchar('0');
putchar('X');
for (int i = 0; i <tmp_sizeof * 2; i++)
{
/*从高四位取数 从高四位取数,*/
ret = 0xf0000000 & tmp;
ret = ret >> Move_Bit[tmp_sizeof - 2];
/*储存半字对应的十六进制数*/
int j = 0;
j += ((ret >> 3) & 0x1) * 8;
j += ((ret >> 2) & 0x1) * 4;
j += ((ret >> 1) & 0x1) * 2;
j += ((ret >> 0) & 0x1) * 1;
/*数据判断输出*/
switch (j)
{
case 15:
putchar('F');
flag = 1;
break;
case 14:
putchar('E');
flag = 1;
break;
case 13:
putchar('D');
flag = 0;
break;
case 12:
putchar('C');
flag = 1;
break;
case 11:
putchar('B');
flag = 1;
break;
case 10:
putchar('A');
flag = 1;
break;
default:
/*不输出前面为0的半字*/
if ((flag == 1) || j)
{
putchar(j + '0');
flag = 1;
}
break;
}
tmp <<= 4;
}
}
/*
使用普通方法实现用putchar()函数输出整形数据
示例,存在局限性,不适用
*/
void printf_int_(void)
{
int tmp = 1239;
char Q_tmp = 0;
char B_tmp = 0;
char S_tmp = 0;
char G_tmp = 0;
Q_tmp = tmp / 1000;
B_tmp = tmp % 1000 / 100;
S_tmp = tmp % 100 / 10;
G_tmp = tmp % 10;
if (Q_tmp)
{
putchar(Q_tmp + '0');
}
if (B_tmp || Q_tmp)
{
putchar(B_tmp + '0');
}
if (S_tmp || B_tmp || Q_tmp)
{
putchar(S_tmp + '0');
}
if (1)
{
putchar(G_tmp + '0');
}
}
/*
@ 可变参数实现printf
@ 实现 %c:字符输出
%d:整形数据输出
%s:字符串输出
增加实现二进制输出:
增加格雷码输出:
增加BCD码输出:
*/
void my_printf(const char *format, ...)
{
va_list arg_ptr;
va_start(arg_ptr, format);
while (*format != '\0')
{
if (*format == '%' && (*(format + 1) == 's'))
{
char *tmp = NULL;
tmp = va_arg(arg_ptr, char*);
while (*tmp != '\0')
{
putchar(*tmp);
tmp++;
}
format++;
}
else if (*format == '%' && (*(format + 1) == 'c'))
{
char tmp = 0;
tmp = va_arg(arg_ptr, char);
putchar(tmp);
format++;
}
else if (*format == '%' && (*(format + 1) == 'd'))
{
int tmp = 0;
tmp = va_arg(arg_ptr, int);
printf_int(tmp);
format++;
}
else if (*format == '%' && (*(format + 1) == 'b'))
{
int tmp = 0;
tmp = va_arg(arg_ptr, int);
printf_binary(tmp);
format++;
}
else if (*format == '%' && (*(format + 1) == 'X'))
{
int tmp = 0;
tmp = va_arg(arg_ptr, int);
printf_hex(tmp);
format++;
}
else if (*format == '/' && (*(format + 1) == 'n'))
{
putchar('\n');
}
else
{
putchar(*format);
}
format++;
}
va_end(arg_ptr);
return;
}