2

プログラムの背景: ユーザーはstring、動詞と名詞の 2 つの単語のみを入力できます。この文字列を a にトークン化し、許可された動詞のaおよび許可された名詞の avectorと比較tokens[0]します。vectortokens[1]vector

現在、特定の名詞に対して特定の動詞のみを実行できるようにする方法を見つけようとしています。たとえば、"take book" と書くと、それが許可されているというメッセージ (または何でも) が表示されますが、"take door" と書くとそうではありません。これまで、考えられる動詞ごとに値を持つclassオブジェクトを作成しました (たとえば、 内で、 whichまたはforを作成できます)。boolclass ObjectObject bookm_take = truefalseObject door

ただし、これらのオブジェクトをユーザー入力に関連付けるのに問題があります。たとえば、次のようなことができるようにしたいと考えてい
ます。 2) プログラムは、入力に受け入れ可能な単語が含まれているかどうかを (個別に) チェックします。 3)オブジェクトに対して実行可能なアクションの bool 値を取得する関数であると見なし、プログラムは を取得し、 の場合は実行します(例: )。このようにして、すべてのオプションを手動で検討して、、、などの無限のリストを作成することなく、すべての正当な動詞と名詞で使用できる に1 つのサイクルのみを含めることができます。tokens[0]tokens[1]

getstat()tokens[1].getstat(tokens[0])truetokens[0].tokens[1]()book.take()ifmain()ifelse if

これがまったく混乱している場合は申し訳ありません。変数をオブジェクト名として使用できないことはわかっていますが、動詞と名詞のすべての組み合わせと一致を考慮するサイクル内でサイクルを実行するよりも、これを行うためのより良い方法があると確信しています。現時点ではそれぞれ 3 つほど試していますが、これが機能するようになったら拡張する予定です。可能性のあるすべての動詞と名詞を複数回ハードコーディングする必要がある場合、すべての変更を追跡するのは悪夢です。ソースコード。(また、ソース全体を投稿できなくて申し訳ありません。今は非常に長いファイルです!) 正しい方向へのヘルプ/ヒントをありがとう!

4

3 に答える 3

2

この種のものには、virtualメソッドまたは C++11std::functionとラムダのいずれかを使用して、ランタイム ポリモーフィズムを使用できます。

明らかに、「トークン」システムを再設計する必要があります。


仮想メソッドの例:

struct Object
{ 
    virtual void onTake() { }
    virtual void onOpen() { }
};

struct Door : public Object 
{
    bool open{false};
    void onTake() override { say("I can't take the door!"); }
    void onOpen() override { say("The door is now open."); open = true; }
};

struct Book : public Object
{
    void onTake() override { say("I put the book in my backpack."); }
    void onOpen() override { say("I open the book. All the pages are blank."); }
};

C++11 ラムダの例:

struct Object
{ 
    std::function<void()> onTake, onOpen;
};

struct Door : public Object 
{
    bool open{false};
    Door() 
    {
        onTake = []{ say("I can't take the door!"); };
        onOpen = []{ say("The door is now open."); open = true; };
    }
};

struct Book : public Object
{
    Book() 
    {
        onTake = []{ say("I put the book in my backpack."); };
        onOpen = []{ say("I open the book. All the pages are blank."); };
    }
};

// You can also avoid creating new classes
Object bananaPrototype; 
bool eaten{false};
bananaPrototype.onTake = []{ say("I put the banana in my backpack."); };
bananaPrototype.onOpen = [eaten] mutable 
{ say("I eat the banana. Yum."); eaten = true; };
于 2013-09-29T14:38:53.843 に答える
0

コードが見えないような些細なケースでアドバイスをするのは難しいですが、私が理解している限り、ハードコードのアプローチをやめることを検討したほうがよいでしょう book.take()。より一般的なコードを書いてみてください。少なくともbook.action(actions::kTake).

于 2013-09-29T14:43:38.653 に答える
0

あなたが言うように、tokens[0].tokens[1]()あなたが望むことをしません-プログラムが実行されているとき、関数と変数の名前は利用できません。

マップを使用してみることができます。objectsオブジェクト名のキーを持つマップである可能性があります。値 ( objects[token[0]]) は、必要なことを行うための関数 ( ) である他のマップになりますobjects[token[0]][token[1]]

次に例を示します。

#include <unordered_map>
#include <string>
#include <iostream>

using namespace std;

void read_fn()
{
    cout << "You read the book";
}

int main()
{
    unordered_map <string, unordered_map <string, void (*)()>> lookup;

    unordered_map <string, void (*)()> book_lookup;

    book_lookup["read"] = read_fn;
    lookup["book"] = book_lookup;

    lookup["book"]["read"]();
}
于 2013-09-29T14:44:30.500 に答える