自己实现一个printf函数

在ARM嵌入式开发环境中,串口一般使用ARM PL011的uart实现,uart的实现原理就是实现了一个8bits宽度,32深度的fifo,不停的往屏幕输出一个byte,一个byte。这个就是硬件的实现,那么软件是怎么实现打印 高级程序语言中定义的char,short,int,long,float,string呢?这个就是软件实现的技巧了,今天我来实现一个printf函数,当然我现在的环境是x86平台,嵌入式开发环境就是替换x86下的putchar函数罢了。

硬件平台:x86环境   编译器环境:MinGW 

实现如下:

print_cui.h:

 #ifndef     __PRINT_H_
 #define    __PRINT_H_


 #include <stdio.h>
 #include <stdarg.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_cui.c:

#include "print_cui.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' ));
    }
}


运行结果:


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值