Pregunta Cómo escribir mi propio printf () en C?


En realidad, estoy tratando de escribir mi propio printf() en C usando varags. Pero no estoy obteniendo la solución correcta para esto. ¿Puede alguien ayudarme?


8
2017-11-14 19:07


origen


Respuestas:


Antes de la implementación de la función printf () tenemos que ocuparnos de un problema inusual, que son los argumentos variables. Como sabemos que printf puede tomar muchos argumentos además de la cadena.       Entonces, tenemos que usar una biblioteca estándar llamada stdarg.h para manejar este problema de argumento variable. En este contexto de implementación, no es necesario aprender toda la biblioteca stdarg.h porque usamos algunas funciones macro de esta biblioteca que es comprensible directamente por nuestro programa C.

Aquí está la fuente del código que explica agradable y rápido

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

void Myprintf(char *,...);              //Our printf function
char* convert(unsigned int, int);       //Convert integer number into octal, hex, etc.


int main() 
{ 
    Myprintf(" WWW.FIRMCODES.COM \n %d", 9); 

    return 0;
} 


void Myprintf(char* format,...) 
{ 
    char *traverse; 
    unsigned int i; 
    char *s; 

    //Module 1: Initializing Myprintf's arguments 
    va_list arg; 
    va_start(arg, format); 

    for(traverse = format; *traverse != '\0'; traverse++) 
    { 
        while( *traverse != '%' ) 
        { 
            putchar(*traverse);
            traverse++; 
        } 

        traverse++; 

        //Module 2: Fetching and executing arguments
        switch(*traverse) 
        { 
            case 'c' : i = va_arg(arg,int);     //Fetch char argument
                        putchar(i);
                        break; 

            case 'd' : i = va_arg(arg,int);         //Fetch Decimal/Integer argument
                        if(i<0) 
                        { 
                            i = -i;
                            putchar('-'); 
                        } 
                        puts(convert(i,10));
                        break; 

            case 'o': i = va_arg(arg,unsigned int); //Fetch Octal representation
                        puts(convert(i,8));
                        break; 

            case 's': s = va_arg(arg,char *);       //Fetch string
                        puts(s); 
                        break; 

            case 'x': i = va_arg(arg,unsigned int); //Fetch Hexadecimal representation
                        puts(convert(i,16));
                        break; 
        }   
    } 

    //Module 3: Closing argument list to necessary clean-up
    va_end(arg); 
} 

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

10
2018-02-18 10:29



Si tienes algo de tiempo y eres realmente curioso, podrías estudiar la versión de GNU libc: Ver printf, que a su vez usa vprintf, que usa vfprintf


6
2017-11-14 19:17



La página man de Linux va_start (3) da muy buenos ejemplos de cómo escribir tales funciones (mucho más simple, pero en general todos los ladrillos principales están ahí). También podría examinar casi cualquier implementación de libstdc.


3
2017-11-14 20:28



Hay al menos dos libros con buenas explicaciones de cómo printf()se puede escribir la función de formateo similar (y completar ejemplos de trabajo):


2
2017-11-15 14:24



Esta respuesta puede ayudarte para entender cómo escribir funciones variadas. Tenga en cuenta que no se realiza ninguna comprobación de errores / límites, no se establecen atributos para indicar al compilador qué tipo de argumentos pueden ser adecuados, no se obtiene ningún beneficio con el solo uso de printf ().

Puede ser o no el ejemplo que estás buscando.

El fragmento relevante (ampliado un poco aquí):

#include <stdarg.h>
void _printf(FILE *out, va_list ap)
{
    vfprintf(out, fmt, ap);
}

void printf(const char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    _printf(stdout, ap);
    va_end(ap);
}

Nota: hacer que estos devuelvan el correcto tipo (entero con signo) se deja como un ejercicio para el lector. Esto se parece bastante a la tarea para mí, solo estoy tratando de superar cualquier punto difícil de usar va_start y va_end, además de mostrar que una va_list se puede pasar a las funciones auxiliares para evitar la duplicación de código en tantas implementaciones de casi la misma cosa.

Recomiendo mirar la implementación del sub sistema de impresión BSD (o incluso glibc). También puede consultar uclibc, dietlibc, etc.


0
2017-11-15 14:41