c - 如何清空 GLib 树?

标签 c glib

为了清空 GLib 树,必须首先遍历树并填充所有找到的键的列表。然后可以使用 g_tree_remove 函数清空树。问题是我不确定如何从遍历函数中填充列表。这是我试过的

#include <stdio.h>
#include <stdlib.h>
#include <glib.h>

//Prototypes
gint treeCompareFunction (const gchar* a, const gchar* b, gpointer self);
gboolean traverseTree(gpointer key, gpointer value, gpointer data);

int main()
{
    GTree* tree = g_tree_new_full ((GCompareDataFunc) treeCompareFunction, NULL, NULL, NULL);
    // Insert data into the tree
    g_tree_insert (tree, "key 1", "val 1");
    g_tree_insert (tree, "key 2", "val 2");
    g_tree_insert (tree, "key 3", "val 3");

    GSList* list = NULL;
    // Try to get all the keys of the tree in a list
    g_tree_foreach (tree, (GTraverseFunc)traverseTree, list);
    printf ("List size after tree traversal: %"  G_GUINT32_FORMAT "\n", g_slist_length(list));
    //TODO empty the tree
    return 0;
}

gint treeCompareFunction (const gchar* a, const gchar* b, gpointer self) {
    return g_strcmp0(a, b);
}

gboolean traverseTree(gpointer key, gpointer value, gpointer data) {
 data = g_slist_append(data, key);
 printf ("List size in traversal function: %"  G_GUINT32_FORMAT "\n", g_slist_length(data));
 return FALSE;
}

输出是

List size in traversal function: 1
List size in traversal function: 1
List size in traversal function: 1
List size after tree traversal: 0

我如何获取列表中的所有键然后清空树?

最佳答案

您需要传递一个指向您的GSList* 的指针,而不是GSList* 本身,否则遍历函数将修改指向列表头部的局部指针,不是指向 main() 中列表头部的指针。

GSList *list = NULL;
g_tree_foreach (tree, (GTraverseFunc)traverseTree, &list);
…

gboolean traverseTree(gpointer key, gpointer value, gpointer data) {
 GSList *out_list = data;
 *out_list = g_slist_append(*out_list, key);
 printf ("List size in traversal function: %"  G_GUINT32_FORMAT "\n", g_slist_length(*out_list));
 return FALSE;
}

另外,请注意,使用 g_slist_append() 迭代追加到链表将为您提供 O(N^2) 性能,而 g_slist_length() 需要 O( N) 次。总体而言,使用指针数组会更容易、更高效:

GPtrArray *items_to_remove = g_ptr_array_sized_new (g_tree_nnodes (tree));
g_tree_foreach (tree, (GTraverseFunc)traverseTree, items_to_remove);
…

gboolean traverseTree(gpointer key, gpointer value, gpointer data) {
 GPtrArray *items_to_remove = data;
 g_ptr_array_add(items_to_remove, key);
 printf ("List size in traversal function: %u\n", items_to_remove->len);
 return FALSE;
}

关于c - 如何清空 GLib 树?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50334530/

相关文章:

c - 使用 sprintf 构建字符串时出现的问题

cmake - 在 CMake 中使用 GLib2 的推荐方法是什么

c - 为什么我们必须在这个字符串函数c 中进行malloc?

c - 在c中的链表中的某个位置插入节点

c - LLVM Pass 插入一个外部函数调用到 LLVM 位码

c++ - libsoup客户端的简单例子

c - 用于稀疏、惰性、不可变数组的线程安全缓存

c - sprintf 会删除它上次写入缓冲区时添加的最后一个空字符吗?

c - 数组类型和使用 malloc 分配的数组之间的区别

c - 为什么 GTK 4 报告 "assertion ' GTK_IS_WIDGET(部件 )' failed"?