2010-05-11 6 views
5

En C, est-il possible d'utiliser la récursivité dans la fonction sprintf? Pour une raison quelconque, je reçois une erreur de segmentation quand je le fais:C: sprintf et récursion

inline char *TreeNode_toString(const TreeNode *node) 
{ 
    char *out; 

    if(TreeNode_isExternal(node)) // If the node has no children... 
    { 
    sprintf(out, "%s:%.2f", node->name, node->distance); 
    } 
    else // The node is strictly binary, so it will have two non-null children 
    { 
    char *l = TreeNode_toString(node->l); // l = left child 
    char *r = TreeNode_toString(node->r); // r = right child 
    sprintf(out, "(%s,%s):%.2f", l, r, node->distance); 
    } 

    return out; 
} 

Répondre

10

Vous obtenez le segment parce out n'est pas initialisé, non pas à cause de la récursivité. Vous devriez lui allouer de la mémoire, par ex.

inline char *TreeNode_toString(const TreeNode *node) 
{ 
    char *out = malloc(4096); // <-- allocate 

    ... 

    char *l = TreeNode_toString(node->l); 
    char *r = TreeNode_toString(node->r); 
    snprintf(out, 4096, "(%s,%s):%.2f", l, r, node->distance); 
    // ^-- please use snprintf to avoid buffer overflow, thanks. 
    free(l); // <-- remember to free 
    free(r); // <-- remember to free 
    } 

    return out; 
} 
+0

Vous voulez dire non alloué - la valeur de sortie ne compte pas seulement de l'espace mémoire – Mark

6

Vous n'avez pas Allouer mémoire pour out, de sorte que vous écrivez dans un emplacement de mémoire vive. Cet algorithme semble un peu fragile sur ce front - comment saurez-vous combien d'espace allouer pour out - connaissez-vous des limites de taille sur l'arbre?

+0

ohh ... Merci pour la réponse. Eh bien ... je comprends le problème (je pensais que Sprintf s'occupait de l'allocation de la mémoire) ... Mais je ne sais pas comment le résoudre. En Java, il était simplement public Chaîne toString() { if (isExternal()) return name + ":" + distance; sinon return "(" + l.toString() + ":" + r.toString + ")"; } – Suugaku

3

Le code tel que publié a un comportement indéfini. récursion de côté, vous dites:

char * out; 
sprintf(out, "%s:%.2f", node->name, node->distance); 

En d'autres termes, vous essayez de sortie à un pointeur non initialisé, ce qui est un comportement non défini, et est donc dénuée de sens.

Si vous demandez, puis-je utiliser sprintf dans une fonction récursive pour ajouter des informations à un tampon, la réponse est peut-être, mais pas facilement. Vous devriez maintenir un tampon hors chaque appel récursif et aussi un index au tampon que chaque appel mettrait à jour.