02.printf

作者: 柏666 | 来源:发表于2019-05-31 01:09 被阅读0次

    typedef char * va_list;

            //便于移植

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

            //以int的长度,进行四字节对齐。

    #define va_start(ap, v) ( ap = (va_list)&v + _INTSIZEOF(v) )

            //使ap指向第一个可变参数地址。(va_list)&v得到起始参数的地址。加上_INTSIZEOF(v) 表示第一个可变参数地址。

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

            //用逗号表达式,返回ap指向的值。逗号表达式第一句,表示移动指针ap到下一个变量的地址。

    #define va_end(ap)      ( ap = (va_list)0 )

            //释放指针。

    unsigned char hex_tab[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};


    int printf(const char *fmt, ...)

    {

            va_list ap;

            va_start(ap, fmt);

            my_printf(fmt, ap);

            va_end(ap);

            return 0;

    }


    static int my_printf(const char *fmt, va_list ap)

    {

        char lead=' ';

        int  maxwidth=0;

        for(; *fmt != '\0'; fmt++)

        {

            //判断输出数字格式的位数,以便显示时添加‘0’.如果lead不为空,则需要添加显示

            lead=' ';

            maxwidth=0;

            if (*fmt != '%')//直接依次输出

            {

                    outchar(*fmt);

                    continue;

            }

            else//next

            {

                    fmt++;

            }

            //format : %08d, %8d,%d,%u,%x,%f,%c,%s

            if(*fmt == '0')

            {

                    lead = '0';

                    fmt++;

            }

            while(*fmt >= '0' && *fmt <= '9')

            {

                    maxwidth *=10;

                    maxwidth += (*fmt - '0');

                    fmt++;

            }

            switch (*fmt)

            {

                    case 'd': out_num(va_arg(ap, int), 10, lead, maxwidth); break;

                    case 'o': out_num(va_arg(ap, unsigned int),  8, lead, maxwidth); break;

                    case 'u': out_num(va_arg(ap, unsigned int), 10, lead, maxwidth); break;

                    case 'x': out_num(va_arg(ap, unsigned int), 16, lead, maxwidth); break;

                    case 'c': outchar(va_arg(ap, int)); break;

                    case 's': outstring(va_arg(ap, char *)); break;  

                    default: outchar(*fmt); break;

            }

        }

        return 0;

    }


    //使用硬件等输出设备,输出字符串。与硬件规格书对应
    int outchar(int c)

    {

            while (!(UTRSTAT0 & (1<<2)));

            UTXH0 = (unsigned char)c;

            return 0;

    }

    int outstring(const char *s)

    {

            while (*s != '\0') 

            {

                    while (!(UTRSTAT0 & (1<<2)));

                    UTXH0 = (unsigned char)c;

            }

            return 0;

    }


    #define MAX_NUMBER_BYTES 128

    //long:防止益处。divide:除数。lead:格式的开头是否需要添加'0'。maxwidth:需要添加多少个'0'。

    static int out_num(long input, int divide,char lead,int maxwidth)

    {

            unsigned long num = 0;//确保输出正数。

            char buf[MAX_NUMBER_BYTES];

            char *out_string = buf + sizeof(buf);//从末尾往前输出

            int str_idx = 0;

            int pre_str_idx = 0;

    //字符串结束符

            *(--out_string) = '\0';

    //修正

            if (input < 0)    num = -input;

            else    num = input;

    //按进制做除法。取余数作为输出字符。

            do {

                    *(--out_string) = hex_tab[num % divide];

                    str_idx++;

            }while ((num /= divide) != 0);

    //在前面填充格式'0'

            if (maxwidth && str_idx < maxwidth)

            {

                    for (pre_str_idx=maxwidth-str_idx; pre_str_idx; pre_str_idx--)

                    *(--out_string) = lead;

            }

    //判断正负

            if (input < 0)    *(--out_string) = '-';

            return outstring(out_string);

    }

    相关文章

      网友评论

          本文标题:02.printf

          本文链接:https://www.haomeiwen.com/subject/tgdntctx.html