所以我有一个Node对象的抽象语法树。每个节点都有任意数量的子节点以及任意数量的标签,这些标签是通过std :: map结构附加到节点的信息的花絮。现在我想以类似XML的格式打印整个语法树。为此我使用了这个函数:
int __ostreamNode_indent = 0;
std::ostream & operator << ( std::ostream & ss, Node* n )
{
for( int i = 0 ; i < __ostreamNode_indent ; ++i )
ss << " ";
ss << "<" << n->getSymbolType() << " ";
for( std::map<std::string,std::string>::iterator itr = n->getTags().begin() ; itr != n->getTags().end() ; ++itr )
{
ss << itr->first << "=\"" << itr->second << "\" ";
}
ss << "numtags=" << n->getTags().size() << " ";
if( n->getChildren().size() == 0 )
ss << "/";
ss << ">" << std::endl;
__ostreamNode_indent++;
for( unsigned int i = 0 ; i != n->getChildren().size() ; ++i )
{
ss << n->getChildren().at(i);
}
__ostreamNode_indent--;
if( n->getChildren().size() != 0 )
{
for( int i = 0 ; i < __ostreamNode_indent ; ++i )
ss << " ";
ss << "</" << n->getSymbolType() << ">" << std::endl;
}
return ss;
}
结构正是我想要的方式:XML标签类型是节点的类型,节点的标签嵌入在同一XML开口标签中。子节点位于开始和结束标记之间。这是一个例子:
<block line="0" numtags=2 >
<funcdef line="0" numtags=2 >
<identifier line="0" col="13" value="main" numtags=3 />
<expressionunion line="0" numtags=2 >
<identifier line="0" col="16" value="a" numtags=3 />
<identifier line="0" col="19" value="b" numtags=3 />
</expressionunion>
<assignment line="1" numtags=2 >
<identifier line="1" col="5" value="c" numtags=3 />
<numel line="1" numtags=2 >
<solveunder line="1" numtags=2 >
<identifier line="1" col="11" value="a" numtags=3 />
<identifier line="1" col="16" value="b" numtags=3 />
</solveunder>
</numel>
</assignment>
<return line="2" numtags=2 >
<power line="2" numtags=2 >
<identifier line="2" col="12" value="c" numtags=3 />
<identifier line="2" col="14" value="b" numtags=3 />
</power>
</return>
</funcdef>
</block>
此示例还演示了此问题。我用行
迭代所有标签 for( std::map<std::string,std::string>::iterator itr = n->getTags().begin() ; itr != n->getTags().end() ; ++itr )
{
ss << itr->first << "=\"" << itr->second << "\" ";
}
并将它们输出为key =“value”。但是,有时这个循环会跳过最后一个元素。请注意紧跟此循环后的行如何输出标记数。当存在两个标签时,实际只显示第一个标签。为什么不显示第二个?
编辑:马克B回答了这个问题;阅读他的答案,以确切解释出现了什么问题。他精神上猜测这是getTags()的定义:
std::map<std::string,std::string> getTags()
{
return tags;
};
将其更改为此(添加&符号)可以解决问题:
std::map<std::string,std::string> & getTags()
{
return tags;
};
答案 0 :(得分:6)
我将使用我的通灵调试技巧并建议getTags()
按值返回容器(而不是对实际容器的引用),因此begin
和{{1} } nodes指的是不同的临时容器。在那时,无论迭代发生了什么,都是合理的游戏,因为最初的临时容器已经消失了。
答案 1 :(得分:0)
另一种可能性是你破坏了这张地图。通过在地图中编辑密钥来说。