2011-12-29 65 views
2

我想寫一段代碼,我正在做的一種樹,如果一個節點不存在,我想拋出顯示哪個節點不存在的例外。即:C++ cout和字符指針,我失去了指針

Trie t = Trie(); 
try { 
    t.get('a'); 
} catch(NoSuchNode e) { 
    cout << e.what() << endl; 
} 

這個代碼應該只是做什麼,如果節點存在,否則打印給出的錯誤,這是我的異常代碼(我使用std ::例外,因爲這似乎是個好主意):

class NoSuchNode : public std::exception 
{ 
private: 
    char *_node_name; 
public: 
    NoSuchNode(const char *node_name) { _node_name = new char(*node_name); } 
    virtual const char* what() const throw() 
    { 
     std::stringstream ss; 
     ss << "There exists no node for: " << _node_name << "."; 
     const std::string& tmp = ss.str(); 
     return tmp.c_str(); 
    } 
}; 

而且,它的工作原理應該如此,valgrind不會在無效讀取時給出任何錯誤,所以這很好,我想呢?現在我的問題,我用此溶液來之前我剛改:

_node_name = new char(*node_name); 

到:

_node_name = node_name; 

,這樣我就不需要爲它分配更多的空間。問題在於,有時它並沒有真正打印任何好的數據,有時甚至會打印出一個字符,甚至更多。不是我真正期待的。此外,valgrind抱怨說,我讀過我可以使用的記憶。爲什麼是這樣?我敢打賭,如果std :: string只是得到一個指向char的指針,它認爲它是一個以空字符結尾的字符串,因此試圖從內存的開始讀取,直到找到空字符?這是否正確,解決這個問題的正確方法是什麼?我應該只是通過價值傳遞數據,因爲我幾乎在做?

加入: 每個節點只能容納一個字符,只有一個字符而沒有其他字符。所以我沒有字符串可以這麼說。

所以事實證明我真正感興趣的是如何處理char *輸入流。 感謝您的答案!

如果在我的代碼中有其他錯誤,並且您有時間請告訴我!

在此先感謝!

回答

3

new char(*node_name)分配對應於node_name的第一個字符的單個字符。不是一個字符串。當你使用它像一個NULL結尾的C字符串時,終止字節丟失,你會得到垃圾。

char *對於std :: cout和其他流是特殊的,因爲它意味着「以null結尾的C字符串」。你必須解引用它(<< *_node_name <<),或者像hmjd建議的那樣,只需使用一個字符(char node_name)。

當您在不重新分配的情況下使用node_name時,運行時指針所指的空間在您需要時已經消失。你不擁有指向內存,所以你應該立即使用或複製。

一般來說,編寫自己的異常類並不容易,需要考慮很多。在你的情況下,只需從std::logic_errorstd::runtime_error派生,並讓他們處理字符串。

+0

這正是我想要的,每個節點上只有一個字符。 – lfxgroove 2011-12-29 11:39:16

+1

@Anton,然後只用'char'而不是'char *'。 – hmjd 2011-12-29 11:40:07

+1

@Anton:'char *'對於std :: cout和其他流是特殊的,因爲它意味着「以null結尾的C字符串」。您必須對其進行解引用,或者像hmjd所示,只需使用一個「char」。 – thiton 2011-12-29 11:45:24

2

爲什麼你根本用指針?您的節點名稱是一個單獨的char,按此處理。

class NoSuchNode : public std::exception 
{ 
private: 
    char _node_name; 
public: 
    NoSuchNode(char node_name) : _node_name(node_name) { } 
    virtual const char* what() const throw() 
    { 
     std::stringstream ss; 
     ss << "There exists no node for: " << _node_name << "."; 
     const std::string& tmp = ss.str(); 
     return tmp.c_str(); 
    } 
}; 

(。我用初始化代替在構造函數中分配這是一個通用的最佳實踐)

+0

好的,補充說,謝謝! – lfxgroove 2011-12-29 11:44:55

2

這不是一個好主意,返回 回報tmp.c_str(); ,因爲tmp.c_str()返回一個指向內存位置的指針,從函數返回後它將被釋放。

+0

哦,我不知道,我應該只是使用類似:'char ret = *(tmp.c_str());'而不是? – lfxgroove 2011-12-29 16:52:35