我正在尝试编写一个用于打印树状结构的递归函数。我想做的大致如下。假设form
是一个与printf
采用相同参数的函数,但返回格式化的字符串而不是打印它; Node
是构建结构的结构,val
槽存储无符号长整数。
char* vals(Node* u) {
if (leaf(u)) {
return form("%lu", u->val);
} else {
return form("%s, %s", vals(u->left), vals(u->right);
}
}
我不知道如何写这个,因为我找不到与form
类似的功能。
答案 0 :(得分:1)
您可能正在寻找asprintf
?请注意,在使用它们之后,您还应该free
以前收到分配的字符串,并且不再需要它们(即在使用它们的asprintf和返回之间,因此您需要一个中间变量)。
答案 1 :(得分:1)
碰巧,我在第77行左右有一个函数here的实现(实际上是两个实现)。它只是一个简单的包装器,旨在使函数调用更容易;有更有效的解决方案,但它通常没有太大的区别。
/* Like GNU asprintf, but returns the resulting string buffer;
* it is the responsibility of the caller to freee the buffer
*/
char* concatf(const char* fmt, ...);
第一个依赖于vasprintf
,这是一个非标准函数,它是Gnu glibc
的一部分:
char* concatf(const char* fmt, ...) {
va_list args;
char* buf = NULL;
va_start(args, fmt);
int n = vasprintf(&buf, fmt, args);
va_end(args);
if (n < 0) { free(buf); buf = NULL; }
return buf;
}
第二个依赖于vsnprintf
,它是一个Posix标准接口,但在一些较旧的标准C库实现中被错误地实现(例如,glibc
直到版本2.0.6。)
char* concatf(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
char* buf = NULL;
int n = vsnprintf(NULL, 0, fmt, args);
va_end(args);
if (n >= 0) {
va_start(args, fmt);
buf = malloc(n+1);
if (buf) vsnprintf(buf, n+1, fmt, args);
va_end(args);
}
return buf;
}
随意使用它们。他们并不是特别深刻。
对于gcc(我认为是clang),你可以将函数声明为:
char* concatf(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
这将使编译器能够检查格式字符串的有效性,就像使用printf
答案 2 :(得分:0)
我建议创建两个form
函数,一个用于叶节点,另一个用于非叶节点。
char* formLeaf(Node* u) {
char leafRet[100];
sprintf(leafRet,"%lu", u->val);
return strdup(leafRet);
}
char* vals(Node* u);
char* formNonLeaf(Node* u) {
char* left = vals(u->left);
char* right = vals(u->left);
char* ret = malloc(strlen(left) + strlen(right) + 3);
sprintf(ret, "%s, %s", left, right);
free(left);
free(right);
return ret;
}
char* vals(Node* u) {
if (leaf(u)) {
return formLeaf(u);
} else {
return formNonLeaf(u);
}
}