所以我有一个 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-tag 类型是节点的类型,并且节点的标签嵌入在同一个 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;
};