C 如何将复合文字用于`fprintf()`具有任意基数的多个格式化数字?
我想将多个数字转换成某种表示形式,然后使用C 如何将复合文字用于`fprintf()`具有任意基数的多个格式化数字?,c,c99,literals,compound-literals,C,C99,Literals,Compound Literals,我想将多个数字转换成某种表示形式,然后使用*printf()说明符的标志、宽度和精度。首选是避免全局或静态缓冲区。关键问题似乎是如何为每个转换后的数字提供char[] fprintf(ostream, "some_format", foo(int_a, base_x), foo(int_b, base_y), ...); 如何使用C11复合文字来解决此问题? 如何使用C99(或更高版本)复合文字来解决此问题 C99 C11引入了复合文本,它不仅允许复杂的初始化结构,而且还允许“串联”变量 代码
*printf()
说明符的标志、宽度和精度。首选是避免全局或静态
缓冲区。关键问题似乎是如何为每个转换后的数字提供char[]
fprintf(ostream, "some_format", foo(int_a, base_x), foo(int_b, base_y), ...);
如何使用C11复合文字来解决此问题?如何使用C99(或更高版本)复合文字来解决此问题 C99 C11引入了复合文本,它不仅允许复杂的初始化结构,而且还允许“串联”变量 代码可以调用一个转换函数,并在每次函数调用时传入一个新的缓冲区
(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);
}
Ref:有许多答案,但没有一个答案允许进行上述简单的内存管理(无静态
),并访问fprintf()
标记宽度、精度和使用数字的全部范围
这是一个答案。注意:我断言返回值仍然在范围内,因为“……它的生命周期从进入与其关联的块开始,一直到该块的执行以任何方式结束。(输入封闭块或调用函数将暂停但不结束当前块的执行)。”C11dr§6.2.46@chux当前位置我认为你是对的,但是范围和寿命是不同的概念。一个对象有一个生命周期;标识符有一个作用域。与生命周期不同,作用域可以是不连续的。是的,是的,是的,这个答案('的例子)说明了为什么我们应该喜欢复合文字!;-)@这是故意的。复合文本没有“临时生存期”。6.2.4/8是指由函数的值返回的结构(例如,
foo().x=5;
)@m.m.:是的,chux关于复合文本是左值的有用观察,我发现了这一点。因此,非左值数组文字是不可能的,因为函数不能返回数组。(此外,复合文字不能是VLA,因此它们的生存期可以从块的开头开始。)为什么只使用C11?它同样适用于C99,也可以用C99解决。你是说你想用%s
而不是%d
或其他什么?M.M使用%s
或%d
或其他什么。我不想扼杀新奇的想法。@alk Q&A根据您的正确观察进行了修改。
base10: 0 base2: 0 base36:0 0
base10: 25 base2:11001 base36:P 25
base10:4294967295 base2:11111111111111111111111111111111 base36:1Z141Z3 4294967295