⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vsprintf.c

📁 一个printf的实现源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    * 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 (* buffer == '0' ) 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

int vsprintf( char * buf, const char * fmt, va_list args )
{
    int len;
    unsigned long num;
    int i, base;
    char * str;
    char * s;

    int flags;            // Flags to number()

    int field_width;      // Width of output field
    int precision;        // Min. # of digits for integers; max number of chars for from string
    int qualifier;        // 'h', 'l', or 'L' for integer fields

    for ( str = buf; * fmt; fmt ++)
    {
        if (* fmt != '%' )
        {
            * str ++ = * fmt;
            continue;
        }

        // Process flags
        flags = 0;
    repeat:
        fmt ++; // This also skips first '%'
        switch (* fmt )
        {
            case '-': flags |= LEFT; goto repeat;
            case '+': flags |= PLUS; goto repeat;
            case ' ': flags |= SPACE; goto repeat;
            case '#': flags |= SPECIAL; goto repeat;
            case '0': flags |= ZEROPAD; goto repeat;
        }

        // 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 (* fmt == 'h' || * fmt == 'l' || * fmt == 'L' )
        {
            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':
            s = va_arg( args, char *);
            if (! s ) s = "<NULL>";
            len = strnlen( s, precision );
            if (!( flags & LEFT )) while ( len < field_width --) * str ++ = ' ';
            for ( i = 0; i < len; ++ i ) * str ++ = * s ++;
            while ( len < field_width --) * str ++ = ' ';
            continue;

        case 'p':
            if ( field_width == - 1 )
            {
                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 ( qualifier == 'l' )
            {
                long * ip = va_arg( args, long *);
                * ip = ( str - buf );
            }
            else
            {
                int * ip = va_arg( args, int *);
                * ip = ( str - buf );
            }
            continue;

        case 'A':
            flags |= LARGE;

        case 'a':
            if ( qualifier == 'l' )
                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;

        case 'x':
            base = 16;
            break;

        case 'd':
        case 'i':
            flags |= SIGN;

        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;
        }

        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 int );

        str = number( str, num, base, field_width, precision, flags );
    }

    * 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;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -