2011-12-29 34 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