-1

私はこの構造を作成しました:

struct xlsmain {
    vector<sub_parts> sb;
    string name;        
}

struct sub_parts {
    vector<pio_parts> pio;
    string name_pio;
    string direction;
    string partition;
}

struct pio_parts {
    string pio_name;
    vector<report_specs> report;
}

struct report_specs {
    string name; 
    vector<string> value;
}

struct xlsmain* interface = new xlsmain[100];

すべての要素が階層的に関連付けられているため、ネストが必要です。私が今直面している問題は、この構造体に値を入力する方法です。

編集:push_back()毎回別の構造を宣言する必要があるため、使用するのは好きではありません。たとえば、サブ パーツを xlsmain に追加する場合は、変数を宣言する必要があります。

sub_parts sb1;

次に、使用できるようになるまで、この構造体に値をフィードする必要があります。

interface[i].sb.push_back(sb1);

さらに、ネスティングが含まれる場合は、次のような構造sb1も多数作成する必要があります。これにより、構造体に単一の値を入力するためだけに、多数の変数を作成する必要が生じます。

4

2 に答える 2

0

オプションは、ベクトルの代わりに std::map を使用することです。その後、次のようなことができます

xmlsmain["some element"].sb["some other"].direction = "up";

このようにして、要素「some element」と「some other」が自動的に作成されます。

于 2012-10-19T07:25:38.853 に答える
0

push_back()編集前は、 「複雑すぎる」という懸念が明確ではありませんでした。(あなたもメソッドの名前が気に入らなかったような気がします... またはそのような奇妙なことですか?)

提起された新しい問題に対処しようとします。ただし、標準ライブラリstringvectorクラスを使用していても、構造自体が C++ の利点を得られていないことを繰り返します。

コンストラクタ、デストラクタ、またはメソッドがありません。これらは、これらのクラスのクライアントがより単純で抽象的なコードを記述できるようにする「魔法の」動作でデータ オブジェクトを「生き生きとさせる」ための基盤です。これは、唯一の「クライアント」が独自のコードにすぎない場合でも役立ちます。

次のようなコードがあったとします。

pio_parts pp;
pp.pio_name = "this string will be stored in the name";
pp.report.push_back(someReport);
pp.report.push_back(anotherReport);

次のように、構造体にコンストラクターとメソッドを追加する場合:

struct pio_parts {
    string pio_name;
    vector<report_specs> report;

    pio_parts(string newName) {
         pio_name = newName;
    }

    void addReport(report_specs newSpecs) {
         report.push_back(newSpecs);
    }
};

次に、上記のコードはより適切になります。

pio_parts pp ("this string will be stored in the name");
pp.addReport(someReport);
pp.addReport(anotherReport);

pio_partsとはいえ、実際には、追加するデータ メンバーの名前を知らなくても済むようになっただけです。代わりにメソッド名を覚えるようになりました。少しタイピングを節約できますが、push_back()ほぼ同じでした。

ただし、ベクトルに追加するだけでなく、内部で実行する必要がある関連操作がさらにある場合はaddReport()、そのすべてのコードを配置する場所ができました。そうすれば、あなたのクラスのユーザーは、レポートを追加するために必要な簿記について心配する必要がなくなります...彼らはただそれが行われるように頼むだけです! また、呼び出しがないため、呼び出している人がリストがベクトルに格納されていることを知るpush_back()必要がなくなりました。addReport()

class意図的に、参照、コピー構築、スマート ポインター、メンバー初期化構文、またはvsの詳細を掘り下げようとはしませんでしたstruct。奥が深すぎる言語です。できるだけ早く時間を取り、Bjarne Stroustrup によるこの短い論文を注意深く読んでください。

新しい言語としての標準 C++ の学習


ここで、もう 1 つの懸念事項に取り掛かります。まず第一に、関数に渡すために C++ で変数の名前付きインスタンスを作成する必要はありません。次のように書き換えることができます。

sub_parts sb1;
interface[i].sb.push_back(sb1);

...代わりに:

interface[i].sb.push_back(sub_parts ());

この場合、オブジェクトが空で構築されているため、特に役に立ちません...つまり、役に立たないものをプッシュしただけです。ただし、コンストラクターがオブジェクトを満たすパラメーターを受け取った場合は問題ありません。次のように配列を構築することもできます。

コンストラクターが 2 つ以上の引数を必要とするオブジェクトの配列を初期化するにはどうすればよいですか?

しかし、コンストラクターが (あなたのように) ハードコーディングされたリストを受け取る場合、軟膏には少しハエがありました。C++ では、コーディングした値で通常の配列を直接初期化できますが、通常の配列を渡すと、その長さ情報が失われます。ベクトルの方が良いでしょうが、ハードコードされた値で初期化するのは面倒です:

ハードコーディングされた要素で std::vector を初期化する最も簡単な方法は何ですか?

書かなければならないことについて、あなたがしたのとほぼ同じ不満を人々が持っていたことがわかります。

std::vector<int> ints;

ints.push_back(10);
ints.push_back(20);
ints.push_back(30);

その投稿にはいくつかの回避策がリストされていますが、最先端のコンパイラ (おそらくあなたが使用しているものではない) がサポートされています:

std::vector<int> ints = {10, 20, 30};

それらがあれば、「ネストされた」スタイルの構築を非常に簡単に行うことができます。


最後の注意として、以前のコメントで、生の配列とベクトルについて具体的に質問しているように見えました。あなたのinterface場合、ほぼ確実にベクトルが必要です。ここに落とし穴があります: 生の配列で使用するには、 (通常の だけでなく)new xlsmain[100]を実行することを覚えておく必要があります。delete[] interfacedelete interface

C++ の delete と delete[] 演算子

いずれにせよ、C++ にも realloc がないことに注意してください。それが動的に割り当てていた理由である場合は、その考えを忘れてください。

インターフェースをベクトルにするだけで、このようなトラブルから身を守ることができます。必要に応じてサイズを変更できます。また、いわゆる「マジック ナンバー」をプログラムにハードコーディングする必要もありません。

于 2012-10-19T07:00:22.990 に答える