プレーンテキストファイルを解析することにより、データ構造を生成します

StackOverflow https://stackoverflow.com/questions/799558

  •  18-09-2019
  •  | 
  •  

質問

私はそれが簡単に自分がゲームのさまざまな側面(文字/舞台/衝突データのようなもの)を変更できるようにすること書いているゲームファイルパーサーを書きました。例えば、私はこのような文字クラスを持っているかもしれません。

class Character
{
public:
    int x, y; // Character's location
    Character* teammate;
}

私は、ファイルからC ++

に似た構文を持つデータ構造を読み込むために私のパーサを設定しました
Character Sidekick
{
    X = 12
    Y = 0
}

Character AwesomeDude
{
    X = 10
    Y = 50
    Teammate = Sidekick
}

これは、2つのデータ構造を作成し、キーの文字列は、私は(この場合はサイドキックとAwesomeDudeで)それを与えた任意の名前であるmap<std::string, Character*>、それらを配置します。私のパーサがクラスへのポインタを見つけると、チームメイトのポインタのように、それはそのデータ構造体へのポインタを取得するためにマップにルックアップするために十分にスマートです。問題は、それがまだ文字マップに配置されていなかったので、私はAwesomeDudeする相棒のチームメイトを宣言することができないということです。

私はまだマップに追加されていない私のデータ構造の参照オブジェクトを持つことができるように、私はこの問題を解決するための最良の方法を見つけようとしています。私は、(a)のデータ構造を宣言するか、(b)のパーサは二回、一度空のデータ構造体へのポインタを持つマップと二度目にを投入するために、ファイルを読んでいる転送する機能を追加していると考えることができる2つの最も簡単な解決策通過し、それらを記入します。

(A)との問題は、私は、クラスを呼び出すためにどのコンストラクタを決めることができ、私は前方に何かを宣言した場合、私はコンストラクタが混乱することができ、データの残りの部分から離れて持っている必要があるだろうということです。 (B)との問題は、私は自分のファイルにサイドキックとAwesomeDudeを宣言したいかもしれないということです。時々私は、Aから読み取るファイルのリストを取得したい場合がありますが、私は、(これはそれほど悪くないです私は推測する私のパーサはむしろちょうど1時より読み取るためにファイルのリストを取ることができるようにする必要があるだろうファイル)。 (b)は、コンストラクタ自体の後半で宣言されたデータ構造を使用することができないという欠点がありますが、私はそれは大きな問題はないと思う。

どっちがより良いアプローチのように聞こえますか?私は考えていない第三の選択肢はありますか? /私はこれは私が自分自身を与えたいどの機能に基づいて、やや主観的であると仮定しますが、任意の入力は大歓迎です - :...そこには、ポインタ参照または結合か何かでこれにいくつかの巧妙な解決策であるべきように思えます。

役に立ちましたか?

解決

あなたが参照を最初に遭遇したときに、単に参考として保管します。その後、あなたは「後で解決する必要があるの参照」のリストには、文字、または参照、または何を置くことができます。

ファイルが実行された場合、参照を持っており、それらを解決するものを介して実行ます。

他のヒント

さて、あなたは番目のオプションを求めました。あなたは、XMLを使用する必要はありませんが、あなたは次のような構造に従うならば、あなたのデータ構造を構築するためにSAXパーサーを使用することは非常にシンプルになります。

いずれにしても、代わりにチームメイトを参照するのは、各文字が(この場合はブルーチーム)チームを参照します。これは、循環参照の問題を分離します。ちょうどあなたが文字の前にチームをリストにしてください。

<team>Blue</team>

<character>
    <name>Sidekick</name>
    <X>12</X>
    <Y>0</Y>
    <teamref>Blue</teamref>
</character>

<character>
    <name>Sidekick</name>
    <X>10</X>
    <Y>50</Y>
    <teamref>Blue</teamref>
</character>

個人的に、私は)Bで行くと思います。パーサとバリデータクラス、同じデータ構造上で動作の両方にコードを分割します。パーサーは今のあなたの構造の実際のポインタのヌルを残して、データ構造を充填し、そのテキスト名など任意のオブジェクト参照を格納し、ファイルを読み込んで解析します。

あなたがファイルをロードし終わったら、「本物」のポインタに埋め、検証し、任意の参照を解決するためにValidatorクラスを使用します。あなたはこれらのルックアップがいいと速く作るためにあなたのデータを構造化する方法を検討することになるでしょう。

ウィルは、私が書くとしていたまさに述べました。ただ、未解決の参照を持つリストか何かをキープます。

そして、あなたはファイルを読み終えたら、未解決の参照がある場合、エラーをスローすることを忘れないでください= P

の代わりに、あなたのマップに文字オブジェクトを格納する、文字のプロキシを格納します。オブジェクトがロードされたとき、プロキシは、より実際の文字オブジェクトへのポインタを含むことになります。文字::チームメイトの種類は、このプロキシタイプに変更されます。あなたのマップになっていない参照して読んだとき、あなたはプロキシを作成し、プロキシを使用しています。あなたはすでにマップ内の空のプロキシを持っている文字をロードすると、新しくロードされた文字を移入。また、すべての参照文字がロードされたとき、あなたは知っているので、あなたがマップを持っているどのように多くの空のプロキシを追跡するためにカウンタを追加することもできます。

間接の別の層が....それは常により簡単に、より遅くプログラミング行います。

1つのオプションは、義務を逆にするだろう。地図参照を埋めるために責任がある。

template<T> class SymbolMap // I never could rememeber C++ template syntax
{
   ...

   /// fill in target with thing name
   /// if no name yet, add it to the list of thing that will be name
   void Set(T& target, std::string name);

   /// define name as target
   /// go back and fill in anything that needs to be name
   void Define(T target, std::string name);

   /// make sure everything is resolved
   ~SymbolMap()
}

セマンティクスを移動/値とよく対話しないであろうことが、私はあまりないことを疑います。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top