我将如何在 C 中编写自己的新格式说明符?
How would I write my own new format specifier in C?
是否可以用 C 编写新的格式说明符?例如,假设 %g 是一个格式说明符,它以 A.B.C.D 格式从等效的无符号整数打印 ip 地址。
int ip_addr = Some integer
printf("ip address = %g", ip_addr);
输出:以A.B.C.D格式打印IP地址
虽然您可以编写一个包装函数,它将接受 %g
并依次调用 printf
.
,但您不能更改标准库函数
您将不得不重新实现 printf 函数(更准确地说是它的格式解析函数)。你可以做的是将 printf 包装在一个支持 ip 地址的函数中,或者这样做:
#define FMT_IP "%d.%d.%d.%d"
#define FMT_IP_ARG(ip) getA(ip), getB(ip), getC(ip), getD(ip)
其中 getX 函数或宏获取表示 IP 地址的给定整数的 X 部分。
然后:
printf("ip address = " FMT_IP "\n", FMT_IP_ARG(ip));
添加新说明符涉及 re-writing printf()
或制作您自己的函数来处理新说明符以及 printf()
并调用它。这两种方法都很难。
另一种方法是使用 "%s"
并编写您自己的函数来形成字符串。
对于 C99 或更高版本,使用复合文字来形成所需的缓冲区 space。
#include <stdio.h>
#define MYIP_N 16
#define MYIP(ip) myip((char [MYIP_N]){""}, (ip))
char *myip(char *dest, int ip) {
snprintf(dest, MYIP_N, "%d.%d.%d.%d", (ip >> 24) & 255, (ip >> 16) & 255,
(ip >> 8) & 255, (ip >> 0) & 255);
return dest;
}
int main(void) {
int ip1 = 0x01020304;
int ip2 = 0x05060708;
printf("%s %s\n", MYIP(ip1), MYIP(ip2));
return 0;
}
输出
1.2.3.4 5.6.7.8
这适用于 printf()
或 fprintf()
、sprintf()
,甚至 puts()
puts(MYIP(ip1));
1.2.3.4
我会选择 ,它简单且便携,前提是您知道需要多大的临时缓冲区。
但是,如果您使用的是 GNU 库 (glibc),则可以使用新的说明符扩展 printf
。强烈建议您使用 upper-case 字母作为格式代码,因为几乎所有 lower-case 格式代码都在使用,其余的可能会被未来的 C/Posix 标准使用。该工具记录在 glibc manual.
中
基于 GNU 工具,为 BSD 库编写了一个类似的 pretty-much-compatible 工具。显然,它在 Mac OS X 上可用,尽管我不能保证这一事实。我确实在 xprintf(3) and xprintf(5).
的 Apple on-line 手册页中找到了它
上面链接的文档中有示例。
是否可以用 C 编写新的格式说明符?例如,假设 %g 是一个格式说明符,它以 A.B.C.D 格式从等效的无符号整数打印 ip 地址。
int ip_addr = Some integer
printf("ip address = %g", ip_addr);
输出:以A.B.C.D格式打印IP地址
虽然您可以编写一个包装函数,它将接受 %g
并依次调用 printf
.
您将不得不重新实现 printf 函数(更准确地说是它的格式解析函数)。你可以做的是将 printf 包装在一个支持 ip 地址的函数中,或者这样做:
#define FMT_IP "%d.%d.%d.%d"
#define FMT_IP_ARG(ip) getA(ip), getB(ip), getC(ip), getD(ip)
其中 getX 函数或宏获取表示 IP 地址的给定整数的 X 部分。
然后:
printf("ip address = " FMT_IP "\n", FMT_IP_ARG(ip));
添加新说明符涉及 re-writing printf()
或制作您自己的函数来处理新说明符以及 printf()
并调用它。这两种方法都很难。
另一种方法是使用 "%s"
并编写您自己的函数来形成字符串。
对于 C99 或更高版本,使用复合文字来形成所需的缓冲区 space。
#include <stdio.h>
#define MYIP_N 16
#define MYIP(ip) myip((char [MYIP_N]){""}, (ip))
char *myip(char *dest, int ip) {
snprintf(dest, MYIP_N, "%d.%d.%d.%d", (ip >> 24) & 255, (ip >> 16) & 255,
(ip >> 8) & 255, (ip >> 0) & 255);
return dest;
}
int main(void) {
int ip1 = 0x01020304;
int ip2 = 0x05060708;
printf("%s %s\n", MYIP(ip1), MYIP(ip2));
return 0;
}
输出
1.2.3.4 5.6.7.8
这适用于 printf()
或 fprintf()
、sprintf()
,甚至 puts()
puts(MYIP(ip1));
1.2.3.4
我会选择
但是,如果您使用的是 GNU 库 (glibc),则可以使用新的说明符扩展 printf
。强烈建议您使用 upper-case 字母作为格式代码,因为几乎所有 lower-case 格式代码都在使用,其余的可能会被未来的 C/Posix 标准使用。该工具记录在 glibc manual.
基于 GNU 工具,为 BSD 库编写了一个类似的 pretty-much-compatible 工具。显然,它在 Mac OS X 上可用,尽管我不能保证这一事实。我确实在 xprintf(3) and xprintf(5).
的 Apple on-line 手册页中找到了它上面链接的文档中有示例。