代码之家  ›  专栏  ›  技术社区  ›  Andrei0408

printf自定义实现中的错误

c
  •  0
  • Andrei0408  · 技术社区  · 4 年前

    %pd ,其中p是要打印的字符数。

    #include <stdio.h>
    #include <ctype.h>
    #include <stdarg.h>
    #include <stdlib.h>
    
    void print(char *, ...);
    char *convert(unsigned int, int);
    char *to_lower(unsigned int, int);
    unsigned int count_digits(unsigned int);
    
    int main()
    {
        char str[12]="World";
        char c='A';
        int n = 5, x= 1011, y = 12, z = 5, t = 10;
    
        print("Hello s c |%s| |%c| 5 |%d| 5 some random %X %x %b %o words\n", str, c, n, x, y, z, t);
        print("%5d\n", y);
    
    }
    
    void print(char *format, ...)
    {
        int num, precision = 0, nDigits, i, temp;
        char *num_deca;
    
        va_list lst;
        va_start(lst, format);
    
        while(*format != '\0')
        {
            if(*format != '%')
            {
                putchar(*format);
                format++;
                continue;
            }
    
            format++;
    
            if(isdigit(*format))
            {
                temp = atoi(format);
                precision = precision*10+temp;
                //precision = atoi(format);
                format++;
                continue;
            }
    //      format++;
    
            switch(*format)
            {
                case 'c':
                    putchar(va_arg(lst, int)); 
                    break;
                case 'd':
                    num = (va_arg(lst, int));
                    //nDigits = count_digits(num);
    
                    if(num > 0)
                    {
                        num_deca = convert(num, 10);
                        nDigits = count_digits(num);
                        for(i = 0; i < (precision - nDigits); i++)
                        {
                            putchar(' ');
                        }
                        fputs(num_deca, stdout);
    
                       // fputs(convert(num,10), stdout);
                    }
                    else
                    {
                        num = -num;
                        putchar('-');
                        fputs(convert(num,10), stdout);
                    }
                    break;
                case 's':
                    fputs(va_arg(lst, char *), stdout);
                    break;
                case 'X':
                    num = va_arg(lst, int);
                    fputs(convert(num,16), stdout);
                    break;
                case 'x':
                    num = va_arg(lst, int);
                    fputs(to_lower(num,16), stdout);
                    break;
                case 'b':
                    num = va_arg(lst, int);
                    fputs(convert(num,2), stdout);
                    break;
                case 'o':
                    num = va_arg(lst, int);
                    fputs(convert(num,8), stdout);
                    break;
            }
    
            format++;
        }
    
        va_end(lst);
    }
    
    char *convert(unsigned int num, int base) 
    { 
        static char Representation[]= "0123456789ABCDEF";
        static char buffer[50]; 
        char *ptr; 
    
        ptr = &buffer[49]; 
        *ptr = '\0'; 
    
        do 
        { 
            *--ptr = Representation[num%base]; 
            num /= base; 
        }while(num != 0); 
    
        return(ptr); 
    }
    
    char *to_lower(unsigned int num, int base) 
    {
        static char Representation[]= "0123456789abcdef";
        static char buffer[50];
        char *ptr;
    
        ptr = &buffer[49];
        *ptr = '\0';
    
        do
        {
            *--ptr = Representation[num%base]; 
            num /= base; 
        }while(num != 0); 
    
        return(ptr); 
    }
    
    unsigned int count_digits(unsigned int n)
    {
        unsigned int counter = 0;
    
        while(n != 0)
        {
            n = n/10;
            counter++;
        }
    
        return counter;
    }
    
    
    Output: Hello s c |World| |A| 5 |5| 5 some random 3F3 c 101 12 words
    d
    

    %5d% 应该是空格12(因为12只有2个数字)。我计算了参数的位数,并使用了一个for循环,该循环一直持续到精度和位数之间的差值,但是程序不再将d视为格式说明符的一部分,只打印字母“d”。知道为什么吗?

    1 回复  |  直到 4 年前
        1
  •  2
  •   Ion Larrañaga    4 年前

    问题是打印每个字符直到找到“%”。如果找到“%”,则转到下一个字符并对其进行处理。但是,如果下一个字符是数字,则可以修改精度并在循环的开头加上“continue”。当重新启动循环时,下一个字符(a'd')不是“%”,所以它只是按原样打印。您应该有一个变量来告诉您是否仍在处理序列,或者在结束对完整序列的处理(“%5d”)之前不转到循环的开头。