如何用C编写我自己的printf()?

如何用C编写我自己的printf()?,c,libc,C,Libc,实际上,我正试图使用varags在C中编写自己的printf()。但是我没有得到正确的解决方案。有人能帮我吗?如果您有时间并且非常好奇,您可以研究GNU libc的版本: 请参阅,它反过来使用vprintf,它使用Linux va_start(3)手册页提供了编写此类函数的非常好的示例(简单得多,但通常所有主要模块都在那里)。您还可以检查几乎所有的libstdc实现。至少有两本书很好地解释了如何编写类似printf()的格式化函数(以及完整的工作示例): 普劳格 “汉森” 了解如何编写可变函数

实际上,我正试图使用varags在C中编写自己的
printf()
。但是我没有得到正确的解决方案。有人能帮我吗?

如果您有时间并且非常好奇,您可以研究GNU libc的版本:
请参阅,它反过来使用vprintf,它使用Linux va_start(3)手册页提供了编写此类函数的非常好的示例(简单得多,但通常所有主要模块都在那里)。您还可以检查几乎所有的libstdc实现。

至少有两本书很好地解释了如何编写类似printf()的格式化函数(以及完整的工作示例):

  • 普劳格
  • “汉森”
了解如何编写可变函数。注意,没有进行错误/边界检查,没有设置属性来告诉编译器什么样的参数可能是合适的,仅仅使用printf()没有任何好处

它可能是,也可能不是你正在寻找的例子

相关的代码片段(此处展开):

#包括
void\u printf(文件*out,va\u列表ap)
{
vfprintf(输出、fmt、ap);
}
void printf(常量字符*fmt,…)
{
va_列表ap;
va_启动(ap、fmt);
_printf(标准输出,美联社);
va_端(ap);
}
注意:让这些返回正确的类型(带符号整数)留给读者作为练习。对我来说,这看起来很像家庭作业,我只是想让你克服使用va_start和va_end的任何症结,并说明可以将va_列表传递给助手函数,以避免在几乎相同的东西的这么多实现中重复代码


我强烈建议查看BSD(甚至glibc)printf子系统的实现。您还可以查看uclibc、dietlibc等。

在实现printf()函数之前,我们必须处理不寻常的问题,即变量参数。正如我们所知,printf可以接受字符串之外的许多参数。 因此,我们必须使用一个名为stdarg.h的标准库来处理这个变量参数问题。在这个实现上下文中,我们不需要学习整个stdarg.h库,因为我们使用了这些库的一些宏函数,这些函数可以被我们的C程序直接理解

#包括
#包括
void Myprintf(字符*,…)//printf函数
字符*转换(无符号整数,整数)//将整数转换成八进制、十六进制等。
int main()
{ 
Myprintf(“WWW.FIRMCODES.COM\n%d”,9);
返回0;
} 
void Myprintf(字符*格式,…)
{ 
字符*遍历;
无符号整数i;
char*s;
//模块1:初始化Myprintf的参数
va_列表参数;
va_开始(参数,格式);
对于(遍历=格式;*遍历!='\0';遍历++)
{ 
而(*遍历!=“%”)
{ 
putchar(*导线测量);
遍历++;
} 
遍历++;
//模块2:获取和执行参数
开关(*横向)
{ 
案例“c”:i=va_arg(arg,int);//Fetch char参数
普查尔(一);
打破
案例“d”:i=va_arg(arg,int);//获取十进制/整数参数

如果(I)您在编写printf函数或使用varargs方面有问题?您可能想进一步说明您的问题所在。您是否知道stdarg.h
?您是否不知道如何使用它,或者您在解析格式字符串时遇到问题?告诉新手C程序员阅读GNU代码?不要太残忍:-)@ValentinGolev:基本代码可能很简单,但有些代码使用数百个指针、大量数据结构和大量奇怪的运算符来将长代码放在一行中,这将是非常困难的。特别是对于初学者。如果你想体验一下,试着阅读大量GNU代码。
#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);
}
#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); 
}