实际上,我正在尝试printf()
使用 varags 在 C 中编写自己的代码。但我没有得到正确的解决方案。谁能帮我吗?
6 回答
在实现 printf() 函数之前,我们必须处理不寻常的问题,即变量参数。我们知道 printf 可以接受除字符串之外的许多参数。所以我们必须使用一个名为 stdarg.h 的标准库来处理这个变量参数问题。在这个实现上下文中,我们不需要学习整个 stdarg.h 库,因为我们使用了这些库的一些宏函数,这些宏函数可以直接被我们的 C 程序理解。
#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);
}
Linux va_start(3) 手册页提供了编写此类函数的非常好的示例(更简单,但通常所有主要的砖块都在那里)。您也可以检查几乎所有的 libstdc 实现。
这个答案可能会帮助您了解如何编写可变参数函数。请注意,没有进行错误/边界检查,没有设置属性来告诉编译器什么样的参数可能是合适的,与仅使用 printf() 相比没有任何好处。
它可能是也可能不是您正在寻找的示例。
相关的片段(在这里扩展了一点):
#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);
}
注意:使这些返回正确的类型(有符号整数)留给读者练习。这对我来说很像家庭作业,我只是想让你克服使用 va_start 和 va_end 的任何症结,并表明可以将 va_list 传递给辅助函数以避免在许多几乎相同的实现中重复代码事物。
我强烈建议查看 BSD(甚至 glibc)printf 子系统实现。您还可以查看 uclibc、dietlibc 等。
它仅适用于“%s”格式说明符。但我认为这仍然有用
void printf(char* str, ...)
{
char* s;
va_list vl;
va_start(vl, str);
for (char* ptr = str; *ptr != '\0'; ptr++)
{
if (*ptr == '%')
{
ptr++;
s = va_arg(vl, char*);
while (*s != '\0')
putchar(*s++);
}
putchar(*ptr);
}
va_end(vl);
}
int main()
{
char str[60] = "String Array is initialized";
printf("abcd %s abcd \n", str);
printf("It work!\n");
}