2010-05-11 22 views
5

En C, ¿es posible usar la recursión dentro de la función sprintf? Por alguna razón, me sale un error de segmentación cuando lo hago:C: sprintf y recursión

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; 
} 

Respuesta

10

Usted está recibiendo segmento porque out no se ha inicializado, no debido a la recursividad. Debería asignarle memoria, p. Ej.

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

Quiere decir asignado no inicializado - el valor de declarar de fuera no importa solo un poco de espacio de memoria – Mark

6

Usted no asignó ninguna memoria para out, por lo que está escrito en una posición de memoria aleatoria. Este algoritmo parece un poco inestable en ese frente. ¿Cómo sabrá cuánto espacio asignar para out? ¿Conoce algunos límites de tamaño en el árbol?

+0

ohh ... Gracias por la respuesta. Bueno ... Entiendo el problema (pensé que sprintf se encargó de asignar la memoria) ... Pero no sé cómo resolverlo. En Java era simplemente public String toString() { if (isExternal()) return name + ":" + distance; else return "(" + l.toString() + ":" + r.toString + ")"; } – Suugaku

3

El código publicado tiene un comportamiento indefinido. recursividad a un lado usted está diciendo:

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

En otras palabras, están tratando de salida a un puntero no inicializado, que es un comportamiento indefinido, y por lo tanto no tiene sentido.

Si está preguntando, ¿puedo usar sprintf en una función recursiva para agregar información a un búfer, la respuesta es posible, pero no fácil. Debería mantener un búfer fuera de cada llamada recursiva y también un índice para el búfer que actualizaría cada llamada.