2010-05-11 77 views
5

在C中,有可能在sprintf函數中使用遞歸嗎?出於某種原因,我得到的,當我做一個分割故障:C:sprintf和遞歸

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

回答

10

你越來越細分,因爲out未初始化不是遞歸的原因。你應該爲它分配一些內存,例如

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

你的意思是分配沒有初始化 - out的說明值並不重要只是一些內存空間 – Mark 2010-05-11 18:43:37

6

你沒有分配任何內存爲out,所以你寫入的隨機內存位置。這個算法在前面看起來有點不穩定 - 你怎麼知道要爲out分配多少空間 - 你知道樹上的一些大小邊界嗎?

+0

哦......謝謝你的答案。那麼......我明白這個問題(我認爲sprintf負責分配內存)......但我不知道如何解決它。在Java中它簡單地是 public String toString(){ if(isExternal()) return name +「:」+ distance; else return「(」+ l.toString()+「:」+ r.toString +「)」; } – Suugaku 2010-05-11 18:49:17

3

發佈的代碼具有未定義的行爲。遞歸拋開你說:

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

換句話說,你正試圖輸出到一個未初始化的指針,這是不確定的行爲,因此是毫無意義的。

如果你問,我可以在遞歸函數中使用sprintf將信息添加到緩衝區,答案可能但不容易。每次遞歸調用都必須保留一個緩衝區,並且每個調用都會更新緩衝區的索引。