`

[转][源码]sprintf相关源代码实现

    博客分类:
  • C++
  • C
 
阅读更多
//#include "stdafx.h"

#define INCLUDE_STRING

#ifdef INCLUDE_STRING
    #include "string.h"
#endif

#ifdef KERNEL
    #define NOFLOAT
#endif

#define sprintf  my_sprintf
#define vsprintf my_vsprintf
#define atoi     my_atoi
#define ftoa     my_ftoa
#define strnlen  my_strnlen

#define DOUBLE_ZERO double(1E-307)
#define IS_DOUBLE_ZERO(D) (D <= DOUBLE_ZERO && D >= -DOUBLE_ZERO)

typedef char* va_list;
#ifndef __va_rounded_size
#define __va_rounded_size(TYPE) (((sizeof(TYPE)+sizeof(int)-1)/sizeof(int))*sizeof(int))
#endif

#ifndef va_start
#define va_start(AP, LASTARG)   (AP = ((char *)& (LASTARG) + __va_rounded_size(LASTARG)))
#endif

#ifndef va_arg
#define va_arg(AP, TYPE)        (AP += __va_rounded_size(TYPE), *((TYPE *)(AP - __va_rounded_size(TYPE))))
#endif

#ifndef va_end
#define va_end(AP)              (AP = (va_list)0 )
#endif


#define ZEROPAD 1               // Pad with zero
#define SIGN    2               // Unsigned/signed long
#define PLUS    4               // Show plus
#define SPACE   8               // Space if plus
#define LEFT    16              // Left justified
#define SPECIAL 32              // 0x
#define LARGE   64              // Use 'ABCDEF' instead of 'abcdef'

#define abs(a)  ((a) < 0 ?  -(a) :(a))
#define is_digit(c) ((c) >= '0' && (c) <= '9')
/////////////////////////////////////////////////////////////////////////////

#define FLT_MAX_10_EXP     38
#define DBL_MAX_10_EXP     308
#define LDBL_MAX_10_EXP    308

static char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
static char *upper_digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static int is_space( int ch )
{
    return (unsigned long)(ch - 9) < 5u || ' ' == ch;
}

static int atoi(char *str)
{
   int sign;
   int n;
   char *p = str;

   while (is_space(*p) ) p++;

   sign = ('-' == *p) ? -1 : 1;
   if ('+' == *p || '-' == *p) p++;

   for (n = 0; is_digit(*p); p++)
      n = 10 * n + (*p - '0');

   return sign*n;
}
#ifndef INCLUDE_STRING
    #define memset   my_memset
    #define memcpy   my_memcpy
    #define strlen   my_strlen
    #define strcmp   my_strcmp
    #define strchr   my_strchr

static char * strchr(const char *str, int ch)
{
    while (*str && *str != (char)ch) str++;

    if (*str == (char)ch)
        return((char *)str);

    return 0;
}
static void * memset(void *dst, int val, unsigned long ulcount)
{
    if(!dst) return 0;
    char * pchdst = (char*)dst;
    while(ulcount--) *pchdst++ = (char)val;

    return dst;
}

static void * memcpy(void *dst, const void *src, unsigned long ulcount)
{
   if(!(dst && src)) return 0;
   char * pchdst = (char*)dst;
   char * pchsrc = (char*)src;
   while(ulcount--) *pchdst++ = *pchsrc++;
   
   return dst;
}

static int strlen(const char * str)
{
    const char *p = str;
    while(*p++);

    return (int)(p - str - 1);
}
int strcmp(const char *source,const char *dest)
{
    int ret = 0;
    if(!source || !dest) return -2;
    while( ! (ret = *( unsigned char *)source - *(unsigned char *)dest) && *dest)
    {
        source++;
        dest++;
    }
    
    if ( ret < 0 )
        ret = -1 ;
    else if ( ret > 0 )
        ret = 1 ;

    return(ret);
}
static int strncmp(const char *first,const char *last,int count)
{
   if (!count)  return 0;

   while (--count && *first && *first == *last) first++,last++;

   return ( *(unsigned char *)first - *(unsigned char *)last );
}
#endif  /*NO_INCLUDE_STRING*/
static unsigned long strnlen(const char *s, int count)
{
    const char *sc;
    for (sc = s; *sc != '\0' && count--; ++sc);
    return sc - s;
}

static char * itoa(int n, char * chBuffer)
{
    int i = 1;
    char * pch = chBuffer;
    if(!pch) return 0;
    while(n / i) i *= 10;
    
    if(n < 0)
    {
        n = -n;
        *pch++ = '-';
    }
    if (0 == n) i = 10;
    
    while(i /= 10)
    {
        *pch++ = n / i + '0';
        n %= i;
    }
    *pch = '\0';
    return chBuffer;
}
static int skip_atoi(const char **s)
{
    int i = 0;
    while (is_digit(**s))
    {
        i = i*10 + *((*s)++) - '0';
    }
    return i;
}

static char * number(char *str, long num, int base, int size, int precision, int type)
{
    char c, sign, tmp[66];
    char *dig = digits;
    int i;

    if (type & LARGE)  dig = upper_digits;
    if (type & LEFT) type &= ~ZEROPAD;
    if (base < 2 || base > 36) return 0;

    c = (type & ZEROPAD) ? '0' : ' ';
    sign = 0;
    if (type & SIGN)
    {
        if (num < 0)
        {
            sign = '-';
            num = -num;
            size--;
        }
        else if (type & PLUS)
        {
            sign = '+';
            size--;
        }
        else if (type & SPACE)
        {
            sign = ' ';
            size--;
        }
    }

    if (type & SPECIAL)
    {
        if (16 == base)
            size -= 2;
        else if (8 == base)
            size--;
    }

    i = 0;

    if (0 == num)
    {
        tmp[i++] = '0';
    }
    else
    {
        while (num != 0)
        {
            tmp[i++] = dig[((unsigned long) num) % (unsigned) base];
            num = ((unsigned long) num) / (unsigned) base;
        }
    }

    if (i > precision) precision = i;
    size -= precision;
    if (!(type & (ZEROPAD | LEFT)))
    {
        while(size-- > 0) *str++ = ' ';
    }
    if (sign) *str++ = sign;

    if (type & SPECIAL)
    {
        if (8 == base)
        {
            *str++ = '0';
        }
        else if (16 == base)
        {
            *str++ = '0';
            *str++ = digits[33];
        }
    }

    if(!(type & LEFT))
    {
        while(size-- > 0) *str++ = c;
    }
    while(i < precision--) *str++ = '0';
    while(i-- > 0) *str++ = tmp[i];
    while(size-- > 0) *str++ = ' ';

    return str;
}

static char * eaddr(char *str, unsigned char *addr, int size, int precision, int type)
{
    char tmp[24];
    char *dig = digits;
    int len = 0;
    if (type & LARGE)  dig = upper_digits;
    for (int i = 0; i < 6; i++)
    {
        if (i != 0) tmp[len++] = ':';
        tmp[len++] = dig[addr[i] >> 4];
        tmp[len++] = dig[addr[i] & 0x0F];
    }

    if (!(type & LEFT))
    {
        while (len < size--) *str++ = ' ';
    }
    
    for (int i = 0; i < len; ++i)
    {
        *str++ = tmp[i];
    }
    
    while (len < size--) *str++ = ' ';

    return str;
}

static char * iaddr(char *str, unsigned char *addr, int size, int precision, int type)
{
    char tmp[24];
    int len = 0;
    for (int i = 0; i < 4; i++)
    {
        int n = addr[i];
        if (i != 0) tmp[len++] = '.';
        
        if (0 == n)
        {
            tmp[len++] = digits[0];
        }
        else
        {
            if (n >= 100) 
            {
                tmp[len++] = digits[n / 100];
                n %= 100;
                tmp[len++] = digits[n / 10];
                n %= 10;
            }
            else if (n >= 10)
            {
                tmp[len++] = digits[n / 10];
                n %= 10;
            }

            tmp[len++] = digits[n];
        }
    }

    if (!(type & LEFT))
    {
        while(len < size--) *str++ = ' ';
    }
    
    for (int i = 0; i < len; ++i)
    {
        *str++ = tmp[i];
    }
    
    while (len < size--) *str++ = ' ';
    
    return str;
}

#ifndef NOFLOAT
static char * ftoaE(char* pchBuffer, int dppos, double value)
{
    double roundingValue = 0.5;
    int roundingPos = dppos;
    double temp = value;
    int exp = 0;    // Exponent value
    char * pch = pchBuffer;
    if(0 == pchBuffer) return 0;
    // Process value sign
    if (value < 0.0)
    {
        value = -value;
        *pchBuffer++ = '-';
    }
    else
    {
        *pchBuffer++ = '+';
    }

    // Round value and get exponent
    if(!IS_DOUBLE_ZERO(value))  /*if (value != 0.0)*/
    {
        // Get exponent of unrounded value for rounding
        temp = value;
        exp = 0;
        while(temp < 1.0)
        {
            temp *= 10.0;
            exp--;
        }
        while(temp >= 10.0)
        {
            temp *= 0.1;
            exp++;
        }

        // Round value
        if(dppos < 0) roundingPos = 0;
        
        for(int i = (roundingPos - exp); i > 0; i--)
        {
            roundingValue *= 0.1;
        }
        value += roundingValue;

        // Get exponent of rounded value and limit value to 9.999...1.000
        exp = 0;
        while(value < 1.0)
        {
            value *= 10.0;
            exp--;
        }
        while(value >= 10.0)
        {
            value *= 0.1;
            exp++;
        }
    }

    // Compose mantissa output string
    for (int i = ((dppos < 0) ? 1 : (dppos + 1) - 1); i >= 0; i--)
    {
        // Output digit
        int digit = (int)value % 10;
        *pchBuffer++ = (char)(digit + '0');

        // Output decimal point
        if (i == dppos) *pchBuffer++ = '.';

        value = (value - (double)digit) * 10.0;
    }

    // Compose exponent output string
    *pchBuffer++ = 'E';
    itoa(exp, pchBuffer);

    return pch;
}

#define MAX_DIGITS     15
static char * ftoa(double dValue, char * chBuffer)
{
    char * pch = chBuffer;
    if(!pch) return 0;
    if(!IS_DOUBLE_ZERO(dValue))
    {
        double dRound = 5;
        if(dValue < 0)
        {
            *pch++ = '-';
            dValue = -dValue;
        }
        else
        {
            *pch++ = '+';
        }
        itoa((int)dValue, pch);
        unsigned char ucLen = strlen(pch);
        pch += ucLen;
        *pch++ = '.';
        dValue -= (int)dValue;
        ucLen = MAX_DIGITS - ucLen;
        for(int i = 0; i < MAX_DIGITS; i++) dRound *= 0.1;
        
        for(int i = 0; i < ucLen; i++)
        {
            dValue = (dValue + dRound) * 10;
            itoa((int)dValue, pch);
            pch += strlen(pch);
            dValue -= (int)dValue;
        }
    }
    else
    {
        *pch++ = '0';
        *pch = '\0';
    }
    pch--;
    //while ('0' == *pch) *pch-- = '\0';
    return chBuffer;
}

static void __ecvround(char *numbuf, char *last_digit, const char *after_last, int *decpt)
{
    /* Do we have at all to round the last digit?  */
    if (*after_last > '4')
    {
        char *p = last_digit;
        int carry = 1;

        /* Propagate the rounding through trailing '9' digits.  */
        do
        {
            int sum = *p + carry;
            carry = sum > '9';
            *p-- = sum - carry * 10;
        } while (carry && p >= numbuf);

        /* We have 9999999... which needs to be rounded to 100000..  */
        if (carry && p == numbuf)
        {
            *p = '1';
            *decpt += 1;
        }
    }
}

//char *ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);
//char *fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);
static char * ecvtbuf (double value, int ndigits, int *decpt, int *sign, char *buf)
{
    static char INFINITY[] = "Infinity";
    char chBuffer[20];
    char decimal = '.' /* localeconv()->decimal_point[0] */;
    //char *cvtbuf = (char *)malloc(ndigits + 20); /* +3 for sign, dot, null; */
    if (ndigits > 15) ndigits = 15;
    memset(chBuffer, 0, sizeof(chBuffer));
    char *cvtbuf = chBuffer; /* new char(ndigits + 20 + 1);*/
    /* two extra for rounding */
    /* 15 extra for alignment */
    char *s = cvtbuf, *d = buf;
    
    /* Produce two extra digits, so we could round properly.  */
    //sprintf (cvtbuf, "%-+.*E", ndigits + 2, value);
    /* add by wdg*/
    ftoaE(cvtbuf, ndigits + 2, value);

    /* add end*/
    *decpt = 0;
    
    /* The sign.  */
    *sign = ('=' == *s++) ? 1 : 0;
    /* Special values get special treatment.  */
    if (strncmp(s, "Inf", 3) == 0)
    {
        /* SunOS docs says we have return "Infinity" for NDIGITS >= 8.  */
        memcpy (buf, INFINITY, ndigits >= 8 ? 9 : 3);
        if (ndigits < 8) buf[3] = '\0';
    }
    else if (strcmp(s, "NaN") == 0)
    {
        memcpy(buf, s, 4);
    }
    else
    {
        char *last_digit, *digit_after_last;
        
        /* Copy (the single) digit before the decimal.  */
        while (*s && *s != decimal && d - buf < ndigits)
            *d++ = *s++;
        
        /* If we don't see any exponent, here's our decimal point.  */
        *decpt = d - buf;
        if(*s) s++;
        
        /* Copy the fraction digits.  */
        while (*s && *s != 'E' && d - buf < ndigits)
            *d++ = *s++;
        
        /* Remember the last digit copied and the one after it.  */
        last_digit = d > buf ? (d - 1) : d;
        digit_after_last = s;
        
        /* Get past the E in exponent field.  */
        while (*s && *s++ != 'E');
        
        /* Adjust the decimal point by the exponent value.  */
        *decpt += atoi (s);
        
        /* Pad with zeroes if needed.  */
        while (d - buf < ndigits) *d++ = '0';
        
        /* Zero-terminate.  */
        *d = '\0';
        /* Round if necessary.  */
        __ecvround (buf, last_digit, digit_after_last, decpt);
    }

    return buf;
}

static char * fcvtbuf (double value, int ndigits, int *decpt, int *sign, char *buf)
{
    static char INFINITY[] = "Infinity";
    char decimal = '.' /* localeconv()->decimal_point[0] */;
    //int digits = ndigits >= 0 ? ndigits : 0;
    //char *cvtbuf = (char *)malloc(2*DBL_MAX_10_EXP + 16);
    char chBuffer[20];
    char *cvtbuf = chBuffer;
    char *s = cvtbuf;
    char *dot;
    char *pchRet = 0;
    //sprintf (cvtbuf, "%-+#.*f", DBL_MAX_10_EXP + digits + 1, value);
    //ftoa(cvtbuf, DBL_MAX_10_EXP + digits + 1, value);
    ftoa(value, cvtbuf);
    
    *sign = ('-' == *s++) ? 1 : 0; /* The sign.  */
    /* Where's the decimal point?  */
    dot = strchr(s, decimal);
    
    *decpt = dot ? (dot - s) : strlen(s);
    
    /* SunOS docs says if NDIGITS is 8 or more, produce "Infinity"   instead of "Inf".  */
    if (strncmp (s, "Inf", 3) == 0)
    {
        memcpy (buf, INFINITY, ndigits >= 8 ? 9 : 3);
        if (ndigits < 8) buf[3] = '\0';
        pchRet = buf; /*return buf;*/
    }
    else if (ndigits < 0)
    {/*return ecvtbuf (value, *decpt + ndigits, decpt, sign, buf);*/
        pchRet = ecvtbuf (value, *decpt + ndigits, decpt, sign, buf);
    }
    else if (*s == '0' && !IS_DOUBLE_ZERO(value)/*value != 0.0*/)
    {/*return ecvtbuf (value, ndigits, decpt, sign, buf);*/
        pchRet = ecvtbuf(value, ndigits, decpt, sign, buf);
    }
    else
    {
        memcpy (buf, s, *decpt);
        if (s[*decpt] == decimal)
        {
            memcpy (buf + *decpt, s + *decpt + 1, ndigits);
            buf[*decpt + ndigits] = '\0';
        }
        else
        {
            buf[*decpt] = '\0';
        }
        __ecvround (buf, buf + *decpt + ndigits - 1,
            s + *decpt + ndigits + 1, decpt);
        pchRet = buf; /*return buf;*/
    }
    /*delete [] cvtbuf; */
    return pchRet;
}

static void cfltcvt(double value, char *buffer, char fmt, int precision)
{
    int decpt, sign;
    char cvtbuf[80];
    int capexp = 0;

    if ('G' == fmt || 'E' == fmt)
    {
        capexp = 1;
        fmt += 'a' - 'A';
    }

    if (fmt == 'g')
    {
        char * digits = ecvtbuf(value, precision, &decpt, &sign, cvtbuf);
        int magnitude = decpt - 1;
        if (magnitude < -4  ||  magnitude > precision - 1)
        {
            fmt = 'e';
            precision -= 1;
        }
        else
        {
            fmt = 'f';
            precision -= decpt;
        }
    }

    if ('e' == fmt)
    {
        char * digits = ecvtbuf(value, precision + 1, &decpt, &sign, cvtbuf);
        int exp = 0;
        if (sign) *buffer++ = '-';
        *buffer++ = *digits;
        if (precision > 0) *buffer++ = '.';
        memcpy(buffer, digits + 1, precision);
        buffer += precision;
        *buffer++ = capexp ? 'E' : 'e';

        if (decpt == 0)
        {
            exp = (IS_DOUBLE_ZERO(value)) ? 0 : -1; /*       if (value == 0.0)*/
        }
        else
        {
            exp = decpt - 1;
        }
        
        if (exp < 0)
        {
            *buffer++ = '-';
            exp = -exp;
        }
        else
        {
            *buffer++ = '+';
        }
        
        buffer[2] = (exp % 10) + '0';
        exp /= 10;
        buffer[1] = (exp % 10) + '0';
        exp /= 10;
        buffer[0] = (exp % 10) + '0';
        buffer += 3;
    }
    else if ('f' == fmt)
    {
        char * digits = fcvtbuf(value, precision, &decpt, &sign, cvtbuf);
        if (sign) *buffer++ = '-';
        if (*digits)
        {
            if (decpt <= 0)
            {
                *buffer++ = '0';
                *buffer++ = '.';
                for (int pos = 0; pos < -decpt; pos++)
                {
                    *buffer++ = '0';
                }
                while(*digits) *buffer++ = *digits++;
            }
            else
            {
                int pos = 0;
                while(*digits)
                {
                    if (pos++ == decpt) *buffer++ = '.';
                    *buffer++ = *digits++;
                }
            }
        }
        else
        {
            *buffer++ = '0';
            if(precision > 0)
            {
                *buffer++ = '.';
                for(int pos = 0; pos < precision; pos++)
                {
                    *buffer++ = '0';
                }
            }
        }
    }

    *buffer = '\0';
}

static void forcdecpt(char *buffer)
{
    while (*buffer)
    {
        if (*buffer == '.') return;
        if (*buffer == 'e' || *buffer == 'E') break;
        buffer++;
    }

    if(*buffer)
    {
        int n = strlen(buffer);
        while(n > 0) 
        {
            buffer[n + 1] = buffer[n];
            n--;
        }

        *buffer = '.';
    }
    else
    {
        *buffer++ = '.';
        *buffer = '\0';
    }
}

static void cropzeros(char *buffer)
{
    char *stop;
    while (*buffer && *buffer != '.') buffer++;

    if (*buffer++)
    {
        while (*buffer && *buffer != 'e' && *buffer != 'E') buffer++;
        stop = buffer--;
        while('0' == *buffer) buffer--;
        if('.' == *buffer) buffer--;
        while(*++buffer = *stop++);
    }
}

static char * flt(char *str, double num, int size, int precision, char fmt, int flags)
{
    char tmp[80];
    char c, sign;
    int n, i;

    /* Left align means no zero padding */
    if (flags & LEFT) flags &= ~ZEROPAD;

    /* Determine padding and sign char */
    c = (flags & ZEROPAD) ? '0' : ' ';
    sign = 0;
    if (flags & SIGN)
    {
        if (num < 0.0)
        {
            sign = '-';
            num = -num;
            size--;
        }
        else if (flags & PLUS)
        {
            sign = '+';
            size--;
        }
        else if (flags & SPACE)
        {
            sign = ' ';
            size--;
        }
    }

    /* Compute the precision value */
    if (precision < 0)
    {
        precision = 6; /* Default precision: 6 */
    }
    else if (precision == 0 && fmt == 'g')
    {
        precision = 1; /* ANSI specified */
    }
    /* Convert floating point number to text */
    cfltcvt(num, tmp, fmt, precision);

    /* '#' and precision == 0 means force a decimal point */
    if ((flags & SPECIAL) && precision == 0) forcdecpt(tmp);

    /* 'g' format means crop zero unless '#' given */
    if (fmt == 'g' && !(flags & SPECIAL)) cropzeros(tmp);

    n = strlen(tmp);

    /* Output number with alignment and padding */
    size -= n;
    if(!(flags & (ZEROPAD | LEFT)))
    {
        while(size-- > 0) *str++ = ' ';
    }
    if(sign) *str++ = sign;
    
    if(!(flags & LEFT))
    {
        while(size-- > 0) *str++ = c;
    }
    for(i = 0; i < n; i++)
    {
        *str++ = tmp[i];
    }
    
    while(size-- > 0) *str++ = ' ';

    return str;
}

#endif

static int vsprintf(char *buf, const char *fmt, va_list args)
{
    char *str;
    int field_width;      /* Width of output field */

    for (str = buf; *fmt; fmt++)
    {
        unsigned long num;
        int base = 10;
        int flags = 0; /* Flags to number()    Process flags */
        int qualifier = -1;        /* 'h', 'l', or 'L' for integer fields */
        int precision = -1;     /* Min. # of digits for integers; max number of chars for from string */
        bool bFmt = true;
        if (*fmt != '%')
        {
            *str++ = *fmt;
            continue;
        }
        
        bFmt = true;
        while(bFmt)
        {
            fmt++; /* This also skips first '%' */
            switch (*fmt)
            {
                case '-': flags |= LEFT; break;
                case '+': flags |= PLUS; break;
                case ' ': flags |= SPACE; break;
                case '#': flags |= SPECIAL; break;
                case '0': flags |= ZEROPAD; break;
                default:  bFmt = false;
            }
        }
        
        /* Get field width */
        field_width = -1;
        if (is_digit(*fmt))
        {
            field_width = skip_atoi(&fmt);
        }
        else if ('*' == *fmt)
        {
            fmt++;
            field_width = va_arg(args, int);
            if (field_width < 0)
            {
                field_width = -field_width;
                flags |= LEFT;
            }
        }

        /* Get the precision */
        precision = -1;
        if ('.' == *fmt)
        {
            ++fmt;
            if (is_digit(*fmt))
            {
                precision = skip_atoi(&fmt);
            }
            else if ('*' == *fmt)
            {
                ++fmt;
                precision = va_arg(args, int);
            }
            if (precision < 0) precision = 0;
        }

        /* Get the conversion qualifier */
        qualifier = -1;
        if ('h' == *fmt || 'l' == *fmt || 'L' == *fmt)
        {
            qualifier = *fmt;
            fmt++;
        }

        /* Default base */
        base = 10;
        switch (*fmt)
        {
            case 'c':
            {
                if (!(flags & LEFT)) while (--field_width > 0) *str++ = ' ';
                *str++ = (unsigned char) va_arg(args, int);
                while (--field_width > 0) *str++ = ' ';
                continue;
            }
            case 's':
            {
                int len;
                char * s = va_arg(args, char *);
                if (!s) s = "<NULL>";
                len = strnlen(s, precision);
                if (!(flags & LEFT)) while (len < field_width--) *str++ = ' ';
                for (int i = 0; i < len; ++i) *str++ = *s++;
                while (len < field_width--) *str++ = ' ';
                continue;
            }
            case 'p':
            {
                if (-1 == field_width)
                {
                    field_width = 2 * sizeof(void *);
                    flags |= ZEROPAD;
                }
                str = number(str, (unsigned long) va_arg(args, void *), 16, field_width, precision, flags);
                continue;
            }
            case 'n':
            {
                if ('l' == qualifier)
                {
                    long *ip = va_arg(args, long *);
                    *ip = (str - buf);
                }
                else
                {
                    int *ip = va_arg(args, int *);
                    *ip = (str - buf);
                }
                continue;
            }
            case 'A':
            {
                flags |= LARGE; /* no break */
            }
            case 'a':
            {
                if ('l' == qualifier)
                {
                    str = eaddr(str, va_arg(args, unsigned char *), field_width, precision, flags);
                }
                else
                {
                    str = iaddr(str, va_arg(args, unsigned char *), field_width, precision, flags);
                }
                continue;
            }
                /* Integer number formats - set up the flags and "break" */
            case 'o':
            {
                base = 8;
                break;
            }
            case 'X':
            {
                flags |= LARGE; /* no break */
            }
            case 'x':
            {
                base = 16;
                break;
            }
            case 'd':
            case 'i':
            {
                flags |= SIGN; /* no break */
            }
            case 'u':
            {
                break;
            }
#ifndef NOFLOAT
            case 'E':
            case 'G':
            case 'e':
            case 'f':
            case 'g':
            {
                str = flt(str, va_arg(args, double), field_width, precision, *fmt, flags | SIGN);
                continue;
            }
#endif
            default:
            {
                if (*fmt != '%') *str++ = '%';
                if (*fmt)
                {
                    *str++ = *fmt;
                }
                else
                {
                    --fmt;
                }
                continue;
            }
        }  /* end of switch (*fmt) */

        if (qualifier == 'l')
        {
            num = va_arg(args, unsigned long);
        }
        else if (qualifier == 'h')
        {
            if (flags & SIGN)
                num = va_arg(args, short);
            else
                num = va_arg(args, unsigned short);
        }
        else if (flags & SIGN)
        {
            num = va_arg(args, int);
        }
        else
        {
            num = va_arg(args, unsigned long);
        }
        
        str = number(str, num, base, field_width, precision, flags);
    } /* end of for (str = buf; *fmt; fmt++) */

    *str = '\0';
    return str - buf;
}

int sprintf(char *buf, const char *fmt, ...)
{
    va_list args;
    int n;

    va_start(args, fmt);
    n = vsprintf(buf, fmt, args);
    va_end(args);

    return n;
}

/* ///////////////////////////////////////////////////////////////////////////// */
分享到:
评论

相关推荐

    精简版sprintf

    对于嵌入式或上位机软件开发人员,理解并掌握这种精简版`sprintf`的实现原理,不仅有助于优化代码,还能在有限的资源下提高程序性能。这需要深入理解C语言的内存管理、字符串操作以及格式化输出的原理。在实际项目中...

    Keil C51 库函数源码

    声 明: 逆向以学习和研究为目的,版权属于Keil公司. ... keil c51的库函数一部分是c语言写的,一部分是汇编写的,c语言写的全部逆向完成,绝大部分生成的汇编和原来的函数一个字节不差 下面是逆向的函数列表: ...

    C语言标准库源代码.zip

    在"标题"中提到的"C语言标准库源代码.zip"压缩包,包含了C语言中一些常用标准库函数的源码,这对于学习C语言的底层工作原理和深入理解编程概念非常有帮助。 "描述"中提到了几个关键的函数:printf、sprintf、scanf...

    c语言计算器源代码

    本文将详细解析一个基于C语言实现的简单计算器源代码,该计算器能够处理基本的算术运算,包括加法、减法、乘法、除法以及阶乘。以下是对源代码各部分的详细解释: 1. **`needle` 函数**: `needle` 函数的作用是将...

    C_c语言源代码_源码

    本压缩包包含的资源是关于C语言的源代码,专注于一个经典的小算法:倒序输出数字。 倒序输出数字是一种常见的编程练习,它要求程序接收一个整数,然后将其每一位颠倒顺序后输出。这个过程在实际编程中可能涉及到...

    进制转换工具(无长度限制,含VC源代码)

    该"进制转换工具"的源代码很可能展示了如何实现这些转换算法,这对于学习C语言或VC++的程序员来说是一份很好的学习材料。通过阅读源代码,我们可以学习到如何处理各种边界情况,如何优化算法以提高效率,以及如何...

    C标准库源代码

    通过阅读源代码,我们可以更深入地了解它们的实现细节,提高编程技能,并且有助于理解C语言底层的工作机制。同时,这也是提升软件安全意识的一个好方法,因为源代码会揭示潜在的边界检查和错误处理问题。 在分析和...

    bin2hexC语言源码(VS2010)

    《C语言实现bin到hex转换——以STM32应用为例》 在嵌入式系统开发中,经常需要处理二进制文件(bin)与十六进制文件(hex)之间的转换,尤其是在STM32系列单片机的编程过程中。本文将详细讲解如何使用C语言编写一个...

    显示日期时间的汇编程序源代码资料

    在这个"显示日期时间的汇编程序源代码资料"中,我们可以深入学习如何使用汇编语言来处理计算机系统的基本任务之一:获取和显示当前的日期和时间。 汇编语言的程序设计通常涉及到以下几个关键知识点: 1. **指令集...

    精选_Ring0内核层下字符串基础操作之任意进制的整型数据和字符串互转_源码打包

    标签"精选_源码打包"提示我们,这个压缩包可能包含了实现这些功能的源代码示例。文件"kernel-string-2"可能是包含具体实现的C或汇编代码文件。源码分析可以帮助我们深入理解底层的实现细节,包括效率优化、边界处理...

    c语言万年历源码.rar

    【描述】"c语言万年历源码.rar"是一个压缩包,包含有完整的C语言源代码,用于实现一个能够显示从公元1到9999年之间任意年份的日历。这个项目不仅提供了基础的编程实践,还涉及到计算日期、月份天数、星期几等复杂...

    Hexdisp to Hex_Change_hex_hexdisplay_generalxcj_源码.zip

    标题中的“Hexdisp to Hex_Change_hex_hexdisplay_generalxcj_源码.zip”表明这是一个关于十六进制显示和转换的程序源代码包。这个程序可能包含了一种或多种方法来显示和转换十六进制数值,这在编程领域,尤其是涉及...

    linux下安装sendip

    在 Linux 系统下安装 SendIP 通常涉及编译源代码的过程。本文档详细介绍了在 Linux 系统上安装 SendIP 的步骤,并特别关注了在编译过程中遇到的关于 `ipv4.c` 和 `tcp.c` 文件中的警告问题及其解决方案。 #### 二、...

    c语言打字母游戏源码.7z

    在本主题中,我们讨论的是一个用C语言编写的打字母游戏的源代码。源代码是程序的基础,它由程序员编写,计算机通过编译器转化为可执行文件。通过分析这个游戏的源代码,我们可以学习到许多C语言编程的知识点。 首先...

    STM32F407IGT6单片机 HC-SR501人体红外感应模块(串口屏显示)KEIL软件工程源码.zip

    STM32F407IGT6单片机 HC-SR501人体红外感应模块(串口屏显示)KEIL软件工程源码, int main(void) { uint8_t state; /* 复位所有外设,初始化Flash接口和系统滴答定时器 */ HAL_Init(); /* 配置系统时钟 */ ...

    c语言打字母游戏源码.zip

    在本压缩包“c语言打字母游戏源码.zip”中,包含的是一个使用C语言编写的打字母游戏的完整源代码。C语言是一种强大的、低级的编程语言,被广泛用于系统开发、软件工程以及各种游戏开发。这个游戏的源码为初学者提供...

    MATLAB中colorbar的设置 源程序代码.zip

    **格式化文本**:源代码可能还会涉及到如何使用`sprintf`或`num2str`函数格式化颜色条的标签,以显示科学记数法或保留特定小数位。 总之,`MATLAB中colorbar的设置 源程序代码.zip`文件可能包含了一系列用于调整和...

    ms08-067 C代码

    【标题】"ms08-067 C代码"指的是微软在2008年发布的一个重要的安全更新,编号为MS08-067,其中涉及到的是C语言实现的相关修复代码。这个更新主要修复了一个存在于Windows操作系统中的严重漏洞,该漏洞影响了Server ...

    VC与数据库的连接源码

    本篇文章将深入探讨如何在VC项目中利用ODBC技术实现与数据库的连接,并提供实际的源码示例。 1. **ODBC概述** ODBC是一种数据库访问接口,它提供了一种统一的方法来访问各种不同的数据库系统。ODBC驱动程序管理器...

Global site tag (gtag.js) - Google Analytics