j'essaie d'utiliser les fonctions B-Tree qu'offre Glib mais je rencontre quelques petits soucis.
En fait, j'ajoute des valeurs à la chaine dans un B-Tree et quand je lookup ces valeurs, elles ont disparues... seule reste la dernière ajoutée...
voilà mon code :
#include <glib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
GTree * redirected_connections;
int main(int argc, char **argv)
{
redirected_connections = g_tree_new((GCompareDataFunc)strcmp);
int i;
for (i=1; i < 250; i++)
{
int value = (i * i);
gchar intkey[4];
snprintf(intkey,4, "%d", i);
gchar intval[6];
snprintf(intval,6, "%d", value);
fprintf(stdout, "add %s:%s\n",intkey, intval );
g_tree_insert(redirected_connections, intkey, intval);
}
for (i=1;i<250;i++)
{
gchar intkey[4];
snprintf(intkey,4, "%d", i);
fprintf(stdout, "check value %s:%s\n", intkey, g_tree_lookup(redirected_connections, intkey));
}
gint numberofnodes = g_tree_nnodes(redirected_connections);
fprintf(stdout, "# of nodes : %d\n",numberofnodes);
g_tree_destroy (redirected_connections);
}
Il se compile chez moi avec la ligne
gcc -Wall -o test_b-tree test_b-tree.c `pkg-config --cflags --libs glib-2.0`
Je ne comprend pas pourquoi il m'écrase toutes les autres valeurs, il devrait ajouter une feuille à l'arbre à chaque fois et le ré-équilibrer... au lieu de celà, on dirait qu'il écrase l'arbre
J'ai fait le même type de code avec les Hash Tables de Glib et ça marche parfaitement...
Une idée d'où vient mon erreur ?
# normal
Posté par mathieu mathieu (site web personnel) . Évalué à 3.
ici tu ne fais ton traitement que sur le même pointeur!
tu devrais soit faire un malloc pour chaque element ou alors faire un tableau!
[^] # Re: normal
Posté par jve (site web personnel) . Évalué à 1.
Je dois avouer que je suis un peu pommé, n'étant pas particulièrement développeur (enfin, comme tout le monde quoi)
je me suis rabattu sur les hash table, plus simples à utiliser et qui me semblent bien rapides pour ce que je fait... mais je doit avouer que le sentiment face au B-Tree m'irrite :p
et sur le net, pas d'exemple, que des liens vers la doc officielle...
Donc au final, si t'avais un exemple de code, ca m'intéresse ;)
[^] # Re: normal
Posté par ecyrbe . Évalué à 3.
cependant voici un exemple pour que ton application fonctionne :
#include <glib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
GTree * redirected_connections;
int main(int argc, char **argv)
{
redirected_connections = g_tree_new_full((GCompareDataFunc)strcmp,NULL,(GDestroyNotify)free,(GDestroyNotify)free);
int i;
for (i=1; i < 250; i++)
{
int value = (i * i);
gchar* intkey = (gchar*)malloc(sizeof(gchar)*4);
snprintf(intkey,4, "%d", i);
gchar* intval = (gchar*)malloc(sizeof(gchar)*6);
snprintf(intval,6, "%d", value);
fprintf(stdout, "add %s:%s\n",intkey, intval );
g_tree_insert(redirected_connections, intkey, intval);
}
for (i=1;i<250;i++)
{
gchar intkey[4];
snprintf(intkey,4, "%d", i);
fprintf(stdout, "check value %s:%s\n", intkey, g_tree_lookup(redirected_connections, intkey));
}
gint numberofnodes = g_tree_nnodes(redirected_connections);
fprintf(stdout, "# of nodes : %d\n",numberofnodes);
g_tree_destroy (redirected_connections);
}
[^] # Re: normal
Posté par liberforce (site web personnel) . Évalué à 3.
Ce sera vrai avec des GNode, des GSList, des GList, etc... C'est à toi de créer la mémoire qui stocke tes données, le boulot des GTree, GNode, et. c'est juste de pouvoir retrouver cette mémoire.
Donc commence par installer devhelp qui t'aidera à trouver les fonctions que tu veux.
Ensuite, si tu remplaces tes tableaux de gchar par des gchar * que tu fais pointer à de la mémoire alloué sur le tas (heap) et pas sur la pile (stack) comme tu le faisais, bin ça marchera.
Ainsi par exemple:
Devient:
N'oublie pas que cette mémoire allouée, tu dois dois la désallouer quand tu n'en as plus besoin, pour éviter les "célèbres" fuites mémoire (memory leak). Utilise g_free pour cela.
[^] # Re: normal
Posté par ecyrbe . Évalué à 2.
Pour la désallocation, dans mon exemple, je lui dit d'utiliser g_tree_new_all qui permet de spécifier le destructeur pour la clé et le contenu, du coup c'est automatique, il n'aura pas besoin de désallouer à la mano.
par contre faudra remplacer free par g_free ...
[^] # Re: normal
Posté par liberforce (site web personnel) . Évalué à 3.
[^] # Re: normal
Posté par jve (site web personnel) . Évalué à 1.
[^] # Re: normal
Posté par liberforce (site web personnel) . Évalué à 2.
Ah, si tu veux encore plus utiliser la glib, avec les facilités qu'elle propose, tu peux remplacer les fprintf(stdout,...) par g_print par exemple.
Je ne peux que t'enjoindre à lire la documentation de la glib, dont les opérations sur les chaines de caractères, qui fourmillent de fonctions plus agréables que celles de la lib standard du C:
http://developer.gnome.org/doc/API/2.0/glib/glib-String-Util(...)
[^] # Re: normal
Posté par jve (site web personnel) . Évalué à 1.
En partie grâce au livre "C en action" de Yves Mettier, très pratique pour les codeux du dimanche comme moi... (formation secu info, pas du tout dev)
Le soucis, c'est les deadlines qui m'oblige à passer des étapes régulièrement et donc m'empêche de prendre le temps de réapprendre (encore qu'il y ais plus à apprendre qu'a ré-apprendre :p).
Bref, le B-Tree se remplit correctement maintenant, mais pour le nettoyer, si j'ai bien compris, il faut parcourir les branches et feuilles avec "traverse", lister dans un tableau de pointeur (GPtrArray ?) les keys que l'on veut supprimer pour, dans un second temps, appeler "remove" sur ces clés
j'ai bon ?
[^] # Re: normal
Posté par ecyrbe . Évalué à 2.
cette fonction te crée un b-tree vide, tu lui donne en paramètre les fonctions chargées de désallouer la mémoire pour toi.
pour désallouer la mémoire d'une chaine de caractère, tu fait appel à g_free(memoire_a_desallouer). donc pour qu'il te désalloue la mémoire allouée pour des chaines de caractère pour la clé et les données, tu fais :
g_tree_new_full(strcmp,NULL,g_free,g_free);
quand tu fera appel à g_tree_destroy(), pour chaque noeuds il videra la mémoire pour toi.
[^] # Re: normal
Posté par jve (site web personnel) . Évalué à 0.
je souhaite supprimer des entrées du tableau selon un critère sur la valeur de l'entrée
je l'ai fait, et ca marche, il faut parcourir le tableau avec g_tree_traverse qui appel une fonction pour chaque valeur
dans cette fonction, j'enregistre la clé si mon critère match
et une fois que g_tree_traverse est terminé, je supprime les valeurs matchées
il semblerait que ca fonctionne proprement ;)
[^] # Re: normal
Posté par ecyrbe . Évalué à 3.
Tu fais appel à quoi? si tu fait appel à g_tree_remove, ça fait aussi appel tout seul aux fonctions de desallocation mémoire si tu utilise g_tree_new_full() pour créer ton arbre.
d'ailleurs c'est explicitement écrit dans la doc des g_tree...
donc, qu'est-ce qui est faux dans ce que j'ai dit?
[^] # Re: normal
Posté par jve (site web personnel) . Évalué à 1.
J'ai besoin de traverser l'arbre pour tester des valeurs et supprimer des feuilles en fonctions de ces valeurs.
Donc oui j'utilise g_tree_remove qui appel les destructeurs listés dans g_tree_new_full, mais je doit faire cela APRES avoir parcouru l'arbre en entier
ze purpose of my question, c'était de savoir si j'utilisais la bonne méthode ;)
j'utilise les 3 fonctions suivantes :
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.