1

Could anybody show me how my implementation of printf or scanf using va_start, va_end, va_arg and syscalls read/write should look?

I have something like this:

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

How can I eliminate putchar and use read/write?

Cel Skeggs
  • 1,827
  • 21
  • 38
Mark
  • 13
  • 4
  • See [What should `main()` return in C and C++?](http://stackoverflow.com/questions/204476/) Also, the standard version of `puts()` outputs a newline after the string; you probably need to use `fputs(..., stdout)` to output only what is in the string. Or show the implementation of `puts()`. – Jonathan Leffler Jun 01 '15 at 18:59

1 Answers1

1

Here's the easy way to do this:

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

This will write out the given character to stdout, without using the C standard library's IO functions. Don't mix this with the C standard library's IO functions, however, as this probably won't work.

As I said, this is somewhat naive: this solution will work, but you should think about the following cases for a robust solution:

  • What if the syscall returns early (with a return value of zero)? This can happen when a signal is received.
  • What if the write syscall fails? You should check the return value.
  • It's inefficient to write every character one-character-at-a-time. You should consider buffering your output.
Cel Skeggs
  • 1,827
  • 21
  • 38