Что бы это ни стоило, возможно, вы используете не тот язык программирования :) То, что вы намеревались написать, это в значительной степени C ++, где это будет:
traverse(node, [node,h]{ print(node, h); });
Тогда traverse будет шаблонная функция, так что вы не обязаны передавать только один вид функции, но вместо этого можете передавать любой функтор (вызываемый объект, например, класс, реализующий оператор вызова):
template <typename Fun> void traverse(node_t *, Fun &&f);
Но вы используется указатель на функцию, поскольку он C, а указатель на функцию не похож на замыкание в C ++: он не может содержать параметров. Таким образом, передача параметров на вас. Я представляю, что аргумент FILE*
действительно исходит из узла? Это дерево каталогов, которое вы пытаетесь представить?
typedef struct {
node_t **children; // null-terminated array of child node pointers
const char *name;
} node_t;
typedef void (*cnode_observer_t)(const node_t *, int level, void *);
void ctraverse_level(const node_t *node, int level, void *extra,
cnode_observer_t cobserver)
{
cobserver(node, extra);
node_t **child = node->children;
++level;
while (*child) {
ctraverse_level(*child++, level, extra, cobserver);
}
}
void ctraverse(const node_t *node, void *extra, cnode_observer_t cobserver) {
ctraverse_level(node, 0, extra, cobserver);
}
void node_printer(const node_t *node, int level, void *file) {
assert(node && file);
FILE *f = file;
fprintf(f, "%*c%s\n", level, ' ', node->name);
}
void test(const node_t *node, FILE *file) {
ctraverse(node, file, node_printer);
}
Для полноты картины, вот как это будет выглядеть в C ++:
struct Node {
std::vector<Node> children;
std::string name;
};
template <typename Obs>
void ctraverse(const Node &node, F fun, int level = 0) {
fun(node, level);
++level;
for (auto &n : node.children) {
ctraverse(n, fun);
}
}
void test(const Node &node, std::ostream &out) {
traverse(node, [&](auto &node, int level) {
out << setw(level) << setfill(' ') << " " << node.name << '\n';
});
}