我想将多个数字转换为某种表达形式,然后使用*printf()
格式指示符的标志、宽度和精度。最好避免使用全局或static
缓冲区。关键问题似乎是如何为每个转换后的数字提供一个char[]
?
fprintf(ostream, "some_format", foo(int_a, base_x), foo(int_b, base_y), ...);
如何使用C99(或更高版本)的复合字面量来解决这个问题?请注意,不再使用C11。
我想将多个数字转换为某种表达形式,然后使用*printf()
格式指示符的标志、宽度和精度。最好避免使用全局或static
缓冲区。关键问题似乎是如何为每个转换后的数字提供一个char[]
?
fprintf(ostream, "some_format", foo(int_a, base_x), foo(int_b, base_y), ...);
C99 引入了复合字面量(compound literals),它不仅允许复杂的初始化结构,还允许“内联”变量。
代码可以调用转换函数并传递一个新缓冲区 (char [UTOA_BASE_N]){0}
给每个函数调用,从而使函数能够返回同一缓冲区,该缓冲区现在已写入所需的内容且仍在其生命周期中。返回的字符串然后使用"%s"
说明符可用的各种标志、宽度和精度打印出来。
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
// Maximum buffer size needed
#define UTOA_BASE_N (sizeof(unsigned)*CHAR_BIT + 1)
char *utoa_base(char *s, unsigned x, unsigned base) {
s += UTOA_BASE_N - 1;
*s = '\0';
if (base >= 2 && base <= 36) {
do {
*(--s) = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[x % base];
x /= base;
} while (x);
}
return s;
}
#define TO_BASE(x,b) utoa_base((char [UTOA_BASE_N]){0} , (x), (b))
void test(unsigned x) {
printf("base10:%10u base2:%5s base36:%s ", x, TO_BASE(x, 2), TO_BASE(x, 36));
printf("%lu\n", strtoul(TO_BASE(x, 36), NULL, 36));
}
int main(void) {
test(0);
test(25);
test(UINT_MAX);
}
输出
base10: 0 base2: 0 base36:0 0
base10: 25 base2:11001 base36:P 25
base10:4294967295 base2:11111111111111111111111111111111 base36:1Z141Z3 4294967295
参考:有没有printf转换器可以以二进制格式打印?有很多答案,但它们都不允许像上面那样简单地进行内存管理(没有static
),并且可以使用fprintf()
标志宽度、精度和使用数字的全部范围。
这是一个自问自答的答案。
foo().x = 5;
)。 - M.M
%s
而不是%d
或其他吗? - M.M"%s"
,"%d"
或其他格式。我不想扼杀新颖的想法。 - chux - Reinstate Monica