一个移植十分方便的类似printf函数

一个十分便于移植的类似printf函数,已测试通过。只需要实现SendChar()函数,把你要外发的字符(比如:发送到串口,显示屏等)写在这里即可。里面部分使用Renasas的源码,在这里尊重其版权。供大家使用,也请尊重我个人的辛勤汗水哈~
源码如下:
/*-----------------------------------------------------------------------------
warning:(float and signed values no supported,this text base on keil's _print_out(copyright by renasas))


FUNCTION: smp_printf,smp_sprintf:
int smp_printf(const char *format, ...);
int smp_sprintf(char *s, const char *format, ...);
-----------------------
DESCRIPTION: Simplified printf and sprintf. (float and signed values no supported)


Only you need to do,is to code 'void SendChar(unsigned char c)' out. 
'SendChar()' is used for smp_printf.Have a good time!^_^
-----------------------
Author:Zhong Kunjiang.
Tel:15280402009.
email:164844595@qq.com.
All right reserved.
-----------------------------------------------------------------------------*/
#include <stdarg.h>
/*---------------------------------------------------------------------------*/


void SendChar(unsigned char c)
{
//add your code here to send a char to your output device.^_^








}
/*----------------------------------------------------------------------------*/
#ifndef NULL
#define NULL 0
#endif


enum { UI, UH, UL, SI, SH, SL };
enum { LEFT_SPACE, PREFIX, ZERO_PAD, VALUE_TXT, RIGHT_SPACE, OUT_DONE};


static const struct
{
  char c[2];
  char size;
} prefix[]=
{
  {{0,0},0},      /* 0: default, no prefix */
  {{'-',0},1},    /* 1: minus sign */
  {{'+',0},1},    /* 2: plus sign */
  {{' ',0},1},    /* 3: space */
  {{'0','x'},2},  /* 4: hex 0x */
  {{'0','X'},2},  /* 5: hex 0X */
};


/* Function Prototypes */
int _print_out(char *s, const char *format, va_list sp);


int smp_sprintf(char *s, const char *format, ...)
{
  int return_count;
  va_list sp;


  va_start(sp, format);


  return_count = _print_out(s, format, sp);
  va_end(sp);
  return (return_count);
}


int smp_printf(const char *format, ...)
{
  int return_count;
  va_list sp;


  va_start(sp, format);
  return_count = _print_out(NULL, format, sp);
  va_end(sp);
  return (return_count);
}


int _print_out(char *s, const char *format, va_list sp)
{
  int total = 0;


  char tmp_buf[12];                         /* maximum tmp_buf usage is 12 in %d */


  /* Loop through format string */
  while ( *format )                         /* loop till hit NULL */
  {
    unsigned char tmp_char, index, out_state;
    unsigned char left_justify = 0;         /* set default to right justify */
    unsigned char prefix_select = 0;        /* set default prefix to none */
    int  min_width = 0;            /* set default field min_width to 0 */
    int  precision = 0;            /* set default precision to 0 */
    unsigned char size_type = UI;           /* set default type to unsigned int */
    char const * str_ptr = tmp_buf;    /* set default string source to buffer */


    union
    {
      unsigned long UL;
      signed long SL;
    } value;


    int str_len = 0;
    tmp_buf[0] = 0;


    if ( *format == '%' )                   /* start of escape characters */
    {
      out_state = PREFIX;
      do
      {
        format++;                           /* point to next character */


        /* Decode the flags */
        switch (*format)
        {
          case '0':
            precision = -1;                 /* if precision not explicitly set, this will zero fill min_width */
            break;
          case '#':
            prefix_select = 4;              /* exact prefix will be determined during type decode */
            break;
          case '+':
            prefix_select = 2;              /* this will be overriden if number is negative */
            break;
          case ' ':
            prefix_select = 3;              /* this will be overriden if number is negative */
            break;
          case '-':
            left_justify = 1;               /* left justification */
            break;
          default:
            out_state = OUT_DONE;           /* no flags left */
            break;
          }
        } while( out_state != OUT_DONE );


      /* check for minimum width */
      index = 0;
      while ( (*format >= '0') && (*format <= '9') )
      {
        min_width = (min_width * index * 10) + (*format - '0');
        index++;
        format++;
      }


      /* check for precision */
      if (*format == '.')
      {
        format++;
        index = 0;
        while ( (*format >= '0') && (*format <= '9') )
        {
          precision = (precision * index * 10) + (*format - '0');
          index++;
          format++;
        }
      }


      /* check for size specifier */
      switch(*format)
      {
        case 'h':
          size_type = UH;
          format++;
          break;
        case 'l':
          size_type = UL;
          format++;
          break;
        default:
          break;
      }




      /* check which type of varaible to print */
      switch(*format)
      {
        case '%':
        {
          /* output a '%' */
          tmp_buf[0] = '%';
          tmp_buf[1] = 0;
          str_len = 1;
          break;
        }
        
        case 'c':
        {
          /* output a single character */
          tmp_buf[0] = (char)va_arg(sp, int);
          tmp_buf[1] = 0;
          str_len = 1;
          break;
        }


        case 'd':
        case 'i':
          size_type += SI;
          /* flow through to decimal processing */


        case 'u':
        {
          /* output decimal value from stack */
          static const unsigned long base10[] = {1000000000,100000000,10000000,1000000,100000,10000,1000,100,10,1};


          /* convert all data types to long to ease later processing */
          switch (size_type)
          {
            default:
            case UI:
              value.UL = (unsigned long)va_arg(sp, unsigned int);
              break;


            case SI:
              value.SL = (signed long)va_arg(sp, signed int);
              break;


            case UH:
              value.UL = (unsigned long)(unsigned short)va_arg(sp, unsigned int);
              break;


            case SH:
              value.SL = (signed long)(signed short)va_arg(sp, signed int);
              break;


            case UL:
            case SL:
              value.UL = va_arg(sp, unsigned long);
              break;
          }


          /* convert signed values to positive as necessary and set prefix appropriately */
          if (size_type >= SI)
          {
            if (value.SL < 0)
            {
              value.SL = -value.SL;
              prefix_select = 1;
            }
          }


          /* write out decimal values to buffer...after suppressing zeros */
          for (index = 0; index < 10; index++)
          {
            tmp_char = (unsigned char)(value.UL/base10[index]);
            value.UL -= tmp_char * base10[index];
            tmp_buf[str_len] = tmp_char + '0';
            if ((tmp_char != 0) || (str_len !=0))
              str_len++;
          }


          if (str_len == 0)
            str_len = 1; /* if value was zero, we need to increment length */
          
          tmp_buf[str_len] = 0;
          break;
        }


        case 'X':
          if (prefix_select != 0) prefix_select++;
          /* fall through to processing */
        case 'x':  
        {
          /* output hex value from stack */
          static const char ascii_table_lower[] = "0123456789abcdef";
          static const char ascii_table_upper[] = "0123456789ABCDEF";
          static const char hex_shift[] = { 28, 24, 20, 16, 12, 8, 4, 0};


          /* convert all data types to long to ease later processing */
          switch (size_type)
          {
            default:
            case UI:
            case SI:
              value.UL = (unsigned long)va_arg(sp, unsigned int);
              break;


            case UH:
            case SH:
              value.UL = (unsigned long)(unsigned short)va_arg(sp, unsigned int);
              break;


            case UL:
            case SL:
              value.UL = va_arg(sp, unsigned long);
              break;
          }




          /* write out hex values to buffer...after suppressing initial zeros */
          for (index = 0; index < 8; index++)
          {
            tmp_char = (unsigned char)(value.UL >> hex_shift[index]) & 0x0F;
            tmp_buf[str_len] = (*format == 'x') ? ascii_table_lower[tmp_char] : ascii_table_upper[tmp_char];
            if ((tmp_char != 0) || (str_len !=0))
              str_len++;
          }


          if (str_len == 0)
            str_len = 1; /* if value was zero, we need to increment length */
          
          tmp_buf[str_len] = 0;
          break;
        }


        case 's':
        case 'S':
        {
          /* Add string from stack */
          char const * t_str_ptr;


          str_ptr = t_str_ptr = va_arg(sp, char *);
          while(*t_str_ptr)    /* find string length */
          {
            str_len++;
            t_str_ptr++;
          }
          break;
        }


        default:
        {
          /* non-processed format...inform user and try not to crash */
          static const char err_msg[]="!!NG!!";
          static const char err_fmt[]=" ";


          str_ptr = err_msg;
          str_len = (int)sizeof(err_msg)-1;
          format=err_fmt;
          
          break;
        }
      } /* switch end */
    } /* escape processing end */
    else
    {
      /* pass through Standard ASCII */
      index = 0;
      if( *format == '\n')    /* Add CR to LF */
        tmp_buf[str_len++] = '\r';


      tmp_buf[str_len++] = *format;
      tmp_buf[str_len] = 0;
    }


/*
if numeric format
    default precision = 0
    if width specified set precision to width-prefix size if zero pad
    if precision specified set precision to it
    set precision to str_len if str_len is greater


    space = min_width - precision - prefix size if greater than zero
    if left justify, space to right, else space to left, 
if string format
    if precision > 0, use to truncate string
 */    
    out_state=LEFT_SPACE;


    /* if precision is -1, field has been requested to zero pad */
    if (precision == -1)
      precision = min_width - prefix[prefix_select].size;


    if ((precision > 0) && (*format == 's'))
    {
      /* requesting string truncation... */
      if (str_len > precision)
        str_len = precision;


      /* zero precision to prevent zero padding */
      precision = 0;
    }


    /* precision now equals number of zero pads */
    precision = precision - str_len;


    /* min_width now equals number of spaces to add...left_justify will control at beginning or end of min_width */
    min_width = (min_width - str_len) - prefix[prefix_select].size;
    min_width -= (precision > 0) ? precision : 0;


    do
    {
      tmp_char = 0;


      switch (out_state)
      {
        case LEFT_SPACE:
        {
          if ((min_width > 0) && (left_justify == 0))
          {
            tmp_char = ' ';
            min_width--;
          }
          else
          {
            /* advance state */
            index = 0;
            out_state = PREFIX;
          }
          break;
        }
        case PREFIX:
        {
          tmp_char = prefix[prefix_select].c[index++];
          if (index >= prefix[prefix_select].size)
          {
            /* advance state */
            out_state = ZERO_PAD;
          }
          break;
        }
        case ZERO_PAD:
        {
          if (precision > 0)
          {
            tmp_char = '0';
            precision--;
          }
          else
          {
            /* advance state */
            precision = 0;
            out_state = VALUE_TXT;
          }
          break;
        }
        case VALUE_TXT:
        {
          tmp_char = str_ptr[precision++];    /* use precision for indexing because is type "int" */
          if (precision >= str_len)
          {
            /* advance state */
            out_state = RIGHT_SPACE;
          }
          break;
        }
        case RIGHT_SPACE:
        {
          if (min_width > 0)
          {
            tmp_char = ' ';
            min_width--;
          }
          else
          {
            /* advance state */
            out_state = OUT_DONE;
          }
          break;
        }
        default:
        {
          /* output complete */
          out_state = OUT_DONE;
          break;
        }
      }


      if (tmp_char != 0)
      {
        if(s != NULL)
          *s++ = tmp_char;
        else
          (void)SendChar(tmp_char);
        total++;
      }


    }
    while (out_state!=OUT_DONE);


    format++;
  }   /* while format */


  /* Insert NULL at the end of the string */
  if(s != NULL)
    *s = 0;


  return total;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寒江独钓2009

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值