如何在C中编写自己的printf()?

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

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

这是代码源,它解释得很好而且快速

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

如果你有时间并且非常好奇,你可以学习GNU libc的版本:请参阅printf ,而printf又使用vprintf,它使用vfprintf

Linux va_start(3)手册页提供了编写此类函数的非常好的示例(更简单但通常所有主要的砖都在那里)。 您还可以检查几乎所有libstdc实现。

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

  • Plauger,’ 标准C图书馆 ‘
  • Hanson,’ C接口和实现 ‘

这个答案可以帮助您了解如何编写可变参数函数。 注意,没有进行错误/边界检查,没有设置任何属性来告诉编译器哪种参数可能是合适的,没有实现仅使用printf()的好处。

它可能是也可能不是您正在寻找的示例。

相关的片段(在这里扩展了一下):

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

注意:使这些返回正确的类型(有符号整数)留给读者练习。 这看起来很像我的家庭作业,我只是想让你超越使用va_start和va_end的任何关键点,并且显示可以将va_list传递给辅助函数以避免在如此多的几乎相同的实现中复制代码事情。

我强烈建议查看BSD(甚至glibc)printf子系统实现。 你也可以看看uclibc,dietlibc等。