Reputation: 3140
I'm trying to write a recursive function for printing a tree-like structure. What I want to do is roughly as follows. Assume form
is a function that takes the same arguments as printf
, but returns the formatted string instead of printing it; Node
is the struct that the structure is built from, with a val
slot storing an unsigned long.
char* vals(Node* u) {
if (leaf(u)) {
return form("%lu", u->val);
} else {
return form("%s, %s", vals(u->left), vals(u->right);
}
}
I'm not sure how to write this, as I've not been able to find a function similar to form
.
Upvotes: 1
Views: 2106
Reputation: 241761
As it happens, I have an implementation (two implementations, actually) of that function here at line 77 or so. It's just a simple wrapper designed to make calling the function easier; there are more efficient solutions but it doesn't usually make much difference.
/* 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, ...);
The first one relies on vasprintf
, which is a non-standard function which is part of 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;
}
The second one relies on vsnprintf
, which is a Posix-standard interface but was incorrectly implemented in some older standard C library implementations (glibc
until version 2.0.6, for example.)
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;
}
Feel free to use them as you need them. They're not particularly profound.
For gcc (and, I think, clang), you can declare the function as:
char* concatf(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
which will enable the compiler to check the validity of the format string, as it does with printf
Upvotes: 3
Reputation: 206607
I would suggest creating two form
functions, one for the leaf nodes and the other for the non-leaf nodes.
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);
}
}
Upvotes: 0
Reputation: 17710
You're probably looking for asprintf
? Note that you should also free
previously received allocated strings once you have used them and they are no longer needed (i.e. between the asprintf that uses them and the return, so you'll need an intermediate variable).
Upvotes: 1