1

したがって、Node オブジェクトの抽象構文ツリーがあります。各 Node には、任意の数の子ノードと、 std::map 構造を介して Node に添付された情報の一口である任意の数のタグがあります。ここで、構文ツリー全体を 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" として出力します。ただし、このループは最後の要素をスキップすることがあります。このループの直後の行がタグの数を出力する方法に注目してください。2 つのタグが存在する場合、最初のタグのみが実際に表示されます。2枚目が表示されないのはなぜですか?

編集:マークBが質問に答えました。何がうまくいかなかったのかについての正確な説明については、彼の答えを読んでください。彼は、これが getTags() の定義であると精神的に推測しました。

std::map<std::string,std::string> getTags()
{   
    return tags;
};

これに変更する(アンパサンドを追加する)とうまくいきました:

std::map<std::string,std::string> & getTags()
{   
    return tags;
};
4

2 に答える 2

6

私は精神的なデバッグ スキルを使用して、getTags()(実際のコンテナーへの参照ではなく) コンテナーを値で返すことを提案します。そのため、ノードbeginendノードは別の一時コンテナーを参照します。その時点で、元の一時コンテナーがなくなっているため、反復に何が起こっても公平なゲームです。

于 2013-01-30T14:29:59.177 に答える
0

マークはおそらく正しい。

別の可能性は、そのマップを破損したことです。マップに入った後でキーを編集することで言います。

于 2013-01-30T14:43:03.003 に答える