/***********************************************
* 文件名: myPrintf.c
* 文件功能: 使用putchar函数模拟printf函数的功能
* 编辑人: 王廷云
* 编辑时间: 2017-10-14
* 修改时间: 2018-1-12
************************************************/
#include <stdio.h>
#include <stdarg.h>
/* 功能函数声明 */
void myPrintf(char *s, ...); // 需要实现的目标函数
void printNum(unsigned long num, int base); // 通用数字打印函数
void printDeci(int dec); // 打印十进制数
void printOct(unsigned oct); // 打印八进制数
void printHex(unsigned hex); // 打印十六进制数
void printAddr(unsigned long addr); // 打印地址
void printStr(char *str); // 打印字符串
void printFloat(double f); // 打印浮点数
/*
* 程序从主函数开始
* 思路:
* ->实现功能类似于printf函数的myPrintf函数
* ->支持字符,字符串,十进制整数,八进制整数,
* 十六进制整数,浮点数,地址的打印
*/
int main(int argc, char **argv)
{
/* 用于测试的变量 */
unsigned int a = 255; // 整数
float f = 10.000; // 浮点数
char c = 'z'; // 字符
char *s = "this is a string"; // 字符串
int *p = &a; // 地址
/* 这是printf函数的结果 */
printf("printf >>> 十进制:%d 八进制:%o 十六进制:%x\n", a, a, a);
printf("printf >>> 字符:'%c' 字符串:%s 浮点数:%f\n", c, s, f);
printf("printf >>> 地址:%p\n\n", p);
/* 这是myPrintf函数的结果 */
printf("myPrintf >>> 十进制:%d 八进制:%o 十六进制:%x\n", a, a, a);
printf("myPrintf >>> 字符:'%c' 字符串:%s 浮点数:%f\n", c, s, f);
printf("myPrintf >>> 地址:%p\n", p);
return 0;
}
/*
* 函数名: myPrintf
* 函数功能: 打印格式字符串
* 参数: 1. 包含格式符的字符串地址 2.可变参
* 返回值: 无
*/
void myPrintf(char *s, ...)
{
int i = 0;
/* 可变参第一步 */
va_list va_ptr;
/* 可变参第二部 */
va_start(va_ptr, s);
/* 循环打印所有格式字符串 */
while (s[i] != '\0')
{
/* 普通字符正常打印 */
if (s[i] != '%')
{
putchar(s[i++]);
continue;
}
/* 格式字符特殊处理 */
switch (s[++i]) // i先++是为了取'%'后面的格式字符
{
/* 根据格式字符的不同来调用不同的函数 */
case 'd': printDeci(va_arg(va_ptr,int));
break;
case 'o': printOct(va_arg(va_ptr,unsigned int));
break;
case 'x': printHex(va_arg(va_ptr,unsigned int));
break;
case 'c': putchar(va_arg(va_ptr,int));
break;
case 'p': printAddr(va_arg(va_ptr,unsigned long));
break;
case 'f': printFloat(va_arg(va_ptr,double));
break;
case 's': printStr(va_arg(va_ptr,char *));
break;
default : break;
}
i++; // 下一个字符
}
/* 可变参最后一步 */
va_end(va_ptr);
}
/*
* 函数名: printNum()
* 函数功能: 通用数字打印函数可以把整型值打印成
* 10进制数,8进制数,2进制数,16进制数
* 参数: 1.需要打印的整数,无符号长整型是为了兼容
* 地址格式打印; 2.打印的进制
* 返回值: 无
*/
void printNum(unsigned long num, int base)
{
/* 递归结束条件 */
if (num == 0)
{
return;
}
/* 继续递归 */
printNum(num/base, base);
/* 逆序打印结果 */
putchar("0123456789abcdef"[num%base]);
}
/*
* 函数名: printDeci
* 函数功能: 打印十进制数
* 参数: 十进制整数
* 返回值: 无
*/
void printDeci(int dec)
{
int num;
/* 处理有符号整数为负数时的情况 */
if (dec < 0)
{
putchar('-');
dec = -dec; // 该操作存在溢出风险:最小的负数没有对应的正数
}
/* 处理整数为时0的情况 */
if (dec == 0)
{
putchar('0');
return;
}
else
{
printNum(dec, 10); // 打印十进制数
}
}
/*
* 函数名: printOct
* 函数功能: 打印八进制整数
* 参数: 无符号整数
* 返回值: 无
*/
void printOct(unsigned oct)
{
if (oct == 0) // 处理整数为0的情况
{
putchar('0');
return;
}
else
{
printNum(oct,8); // 打印8进制数
}
}
/*
* 函数名: printHex
* 函数功能: 打印十六进制整数
* 参数: 无符号整数
* 返回值: 无
*/
void printHex(unsigned hex)
{
if (hex == 0) // 处理整数为0的情况
{
putchar('0');
return;
}
else
{
printNum(hex,16); // 打印十六进制数
}
}
/*
* 函数名: printAddr
* 函数功能: 打印地址
* 参数: 待打印的地址
* 返回值: 无
*/
void printAddr(unsigned long addr)
{
/* 打印前导"0x" */
putchar('0');
putchar('x');
/* 打印地址:格式和十六进制一样 */
printNum(addr, 16);
}
/*
* 函数名: printStr
* 函数功能: 打印字符串
* 参数: 字符串地址
* 返回值: 无
*/
void printStr(char *str)
{
int i = 0;
while (str[i] != '\0')
{
putchar(str[i++]);
}
}
/*
* 函数名: printFloat
* 函数功能: 打印浮点数
* 参数: 待打印浮点数
* 返回值: 无
*/
void printFloat(double f)
{
int temp;
/* 先打印整数部分 */
temp = (int)f;
printNum(temp,10);
/* 分隔点 */
putchar('.');
/* 打印小数部分 */
f -= temp;
if (f == 0)
{
/* 浮点型数据至少六位精度 */
for (temp = 0; temp < 6; temp++)
{
putchar('0');
}
return;
}
else
{
temp = (int)(f*1000000);
printNum(temp,10);
}
}
【C语言】之实现 printf 函数功能
最新推荐文章于 2024-06-03 14:23:37 发布