实现自己的printf函数

在嵌入式开发中,常常会通过串口打印一些信息到PC终端,这就需要实现自己的printf函数,下面介绍打印函数print的实现。
print.h

#ifndef     __PRINT_H_
#define    __PRINT_H_

void    print(char* fmt, ...);
void    printch(char ch);
void    printdec(int dec);
void    printflt(double flt);
void    printbin(int bin);
void    printhex(int hex);
void    printstr(char* str);

#define console_print(ch)    putchar(ch)

#endif    /*#ifndef __PRINT_H_*/

上面print函数为全功能的打印函数,可以实现类似printf的功能,printch实现单个字符的打印、printdec实现十进制格式数字的打印,printflt实现浮点数的打印,printbin实现二进制格式数字的打印,printhex实现十六进制格式数字的打印,printstr实现字符串的打印,console_print函数是串口单字符打印函数的宏定义,这里暂时用PC终端单字符打印函数putchar代替。在实际嵌入式环境下,替换成串口单字符打印函数即可。
print.c

#include <stdio.h>
#include <stdarg.h>
#include "print.h"

int main(void)
{
    print("print: %c\n", 'c');
    print("print %d\n", 1234567);
    print("print: %f\n", 1234567.1234567);
    print("print: %s\n", "string test");
    print("print: %b\n", 0x12345ff);
    print("print: %x\n", 0xabcdef);
    print("print: %%\n");
    return 0;
}

void    print(char* fmt, ...)
{
    double vargflt = 0;
    int  vargint = 0;
    char* vargpch = NULL;
    char vargch = 0;
    char* pfmt = NULL;
    va_list vp;

    va_start(vp, fmt);
    pfmt = fmt;

    while(*pfmt)
    {
        if(*pfmt == '%')
        {
            switch(*(++pfmt))
            {
                
                case 'c':
                    vargch = va_arg(vp, int); 
                    /*    va_arg(ap, type), if type is narrow type (char, short, float) an error is given in strict ANSI
                        mode, or a warning otherwise.In non-strict ANSI mode, 'type' is allowed to be any expression. */
                    printch(vargch);
                    break;
                case 'd':
                case 'i':
                    vargint = va_arg(vp, int);
                    printdec(vargint);
                    break;
                case 'f':
                    vargflt = va_arg(vp, double);
                    /*    va_arg(ap, type), if type is narrow type (char, short, float) an error is given in strict ANSI
                        mode, or a warning otherwise.In non-strict ANSI mode, 'type' is allowed to be any expression. */
                    printflt(vargflt);
                    break;
                case 's':
                    vargpch = va_arg(vp, char*);
                    printstr(vargpch);
                    break;
                case 'b':
                case 'B':
                    vargint = va_arg(vp, int);
                    printbin(vargint);
                    break;
                case 'x':
                case 'X':
                    vargint = va_arg(vp, int);
                    printhex(vargint);
                    break;
                case '%':
                    printch('%');
                    break;
                default:
                    break;
            }
            pfmt++;
        }
        else
        {
            printch(*pfmt++);
        }
    }
    va_end(vp);
}

void    printch(char ch)
{
    console_print(ch);
}

void    printdec(int dec)
{
    if(dec==0)
    {
        return;
    }
    printdec(dec/10);
    printch( (char)(dec%10 + '0'));
}

void    printflt(double flt)
{
    int icnt = 0;
    int tmpint = 0;
    
    tmpint = (int)flt;
    printdec(tmpint);
    printch('.');
    flt = flt - tmpint;
    tmpint = (int)(flt * 1000000);
    printdec(tmpint);
}

void    printstr(char* str)
{
    while(*str)
    {
        printch(*str++);
    }
}

void    printbin(int bin)
{
    if(bin == 0)
    {
        printstr("0b");
        return;
    }
    printbin(bin/2);
    printch( (char)(bin%2 + '0'));
}

void    printhex(int hex)
{
    if(hex==0)
    {
        printstr("0x");
        return;
    }
    printhex(hex/16);
    if(hex < 10)
    {
        printch((char)(hex%16 + '0'));
    }
    else
    {
        printch((char)(hex%16 - 10 + 'a' ));
    }
}

编译执行结果如下:

print: c
print: 1234567
print: 1234567.123456
print: string test
print: 0b1001000110100010111111111
print: 0xabcdef
print: %
如上所示,print函数实现了类似printf的功能。




评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值