2012-07-02 39 views
2

创建带有一些附加功能的snprintf()版本的最简单方法是什么?例如附加的格式说明符可以重复指定次数的以下转换?例如,像%6a%-3x这样的东西将接受参数列表中的char*参数,并且如果这指向字符串"My test string"将打印"4d 79 20 74 65 73 74 "。关联的参数总是一个指向相应类型数组的指针。创建printf的自定义版本

这是代码来解释格式说明符和可变长度参数列表(其类型取决于格式字符串中的格式说明符),我希望有一些帮助,以避免重新发明轮子。

这需要使用普通的老式C语言,因为它必须使用Microchip的PIC C30编译器进行编译。

谢谢 - 罗文

+13

[下载开源实现](http://www.gnu.org/software/libc/download.html)'printf'并对其进行破解。 –

+0

@JonathonReinhart然后被迫释放你为这个项目编写的所有其他代码,因为它是一个“派生工作”。绝对没有人可以反对!这就是说,对于OP来说,还有更多的宽松许可的stdio/libc在那里;如果没有别的,只需从其中一个BSD变体中抽取一个。 – tbert

+0

伙计们,如果你真的认为hacking printf是正确的方法,你真的需要检查vsprintf。 –

回答

2

vsprintf是你在找什么。它可以让你编写自己的类似sprintf的函数,它接受可变数量的参数,然后让你在进行调用之前做你需要的。

这里是我用它来实现自己的printf到USB端点在嵌入式设备中的例子:

#include <stdarg.h> 
void uprintf(char *fmt, ...) { 
    va_list args; 
    va_start(args, fmt); 
    vsprintf(str_buffer, fmt, args); 
    usb_write(str_buffer); 
    va_end(args); 
} 

在你的情况,你可以“拦截”的格式调用vsprintf,字符串并将自己的语法扩展为适当的格式说明符语法,然后将新的格式说明符和变量arg列表传递到vsprintf

void your_printf(char *fmt, ...) { 
    char new_fmt_string[1024]; /* make sure you allocate enough space */ 
    va_list args; 

    /* here, do your transformation on the fmt string */ 

    va_start(args, new_fmt_string); 
    vsprintf(str_buffer, new_fmt_string, args); 

    /* now take your fully formatted string and do something with it */ 

    /* then clean up */ 
    va_end(args); 
} 
+0

但是没有便携的方式来转换例如const char(*)[3]'到'%-3x%-3x%-3x'的一个好参数列表。 – aschepler

+0

我只是给了他他所要求的:这是'代码来解释格式说明符'和'可变长度参数列表',我想帮助一些,以避免重新发明轮子。 :-) –

1

最简单的方法可能不是你想要的答案,但它可能是最实际的解决方案:不要这样做。

取而代之,创建您自己的写入缓冲区的输出函数。

// print count bytes from buf into s, but take up no more than n-1 bytes 
// returns how many bytes were (or would be) printed 
int snprint_hex (char *s, size_t n, const char *buf, size_t count) { 
    //... 
} 

您的代码会更清楚,你将不必实现神秘的解析代码来处理所有的printf格式说明。