使用va_start,va_end va_arg和syscalls实现printf

时间:2015-01-12 22:41:32

标签: c printf system-calls

有人可以告诉我使用printfscanfva_start和系统调用读/写的va_endva_arg的实现方式应该如何?

我有这样的事情:

#include <stdio.h>
#include <stdarg.h>

char *translate(unsigned int, int);

void myprintf(char * frmt,...){
    char *pointer;
    int iterator;
    char *s;
    va_list argp;
    va_start(argp, frmt);
    pointer=frmt;

    for(pointer=frmt; *pointer!='\0';pointer++){
        if(*pointer!='%'){
            putchar(*pointer);
            continue;
        }
        pointer++;

        switch(*pointer){       
        case 'd':
            iterator=va_arg(argp,int);
            if(iterator<0){
                iterator=-iterator;
                putchar('-');
            }
            puts(translate(iterator,10));
            break;
        case 's':
            s=va_arg(argp,char *);
            puts(s);
            break;
        //case 'b': b=va_arg(argp, );;break;
        case 'x':
            unsigned=va_arg(argp, unsigned int);
            puts(translate(unsigned,16));
            break;
        case '%':
            putchar('%');
            break;
        }
    }
    va_end(argp);   
}

char *translate(unsigned int num, int base){
    static char buff[33];
    char *ptr;
    ptr=&buff[sizeof(buff)-1];
    *ptr='\0';
    do{
        *--ptr="0123456789abcdef"[num%base];
        num/=base;
    } while(num!=0);

    return(ptr);
}

void main(){
    void myprintf(char *,...);
    char *translate(unsigned int, int);
    int iterator=65;
    char str[]="przyklad";
    myprintf("\njbleble%s%d%x",str,iterator,iterator);
}

如何消除putchar并使用读/写?

1 个答案:

答案 0 :(得分:1)

这是执行此操作的简便方法:

#define FD_STDOUT 1
void putchar(int c) {
    char ch = c;
    write(FD_STDOUT, &ch, 1);
}

这将把给定的字符写出到stdout,而不使用C标准库的IO函数。但是,不要将它与C标准库的IO函数混合使用,因为这可能不起作用。

正如我所说,这有些天真:这个解决方案可行,但您应该考虑以下案例以获得强大的解决方案:

  • 如果系统调用提前返回(返回值为零)怎么办?收到信号时可能会发生这种情况。
  • 如果write系统调用失败怎么办?你应该检查返回值。
  • 一次一个字符地写每个字符是低效的。您应该考虑缓冲输出。