1

問題文 :ユーザーが、構造内に格納する必要があるデータを提供します。私が受け取るこのデータは、ユーザーが動的にデータを追加できるデータ構造になっています。

要件:このデータを構造体の「内部」に連続し て格納する方法が必要です。

例えば。ユーザーが、保存する必要がある文字列を渡すことができるとします。だから私はこのようなものを書きました:

void pushData( string userData )
{
    struct 
    {
       string junk;
    } data;

    data.junk = userData;
}

問題 :この種のストレージを実行すると、文字列は POD ではないため、実際のデータは実際には構造の「内部」に格納されません。ベクトルまたはリストを受け取ったときにも同様の問題が発生します。

次に、次のようなことができます:

void pushData( string userData )
{
    struct 
    {
       char junk[100];
    } data;    

    // Copy userdata into array junk
}

これは構造の「内部」にデータを保存しますが、ユーザーが提供できる文字列のサイズに上限を設定することはできません。

誰かがいくつかのアプローチを提案できますか?

PS:シリアル化可能性について何か読んだことがありますが、私の場合に役立つかどうかははっきりとわかりませんでした。それが前進する方法である場合、誰かがそれをどのように進めるかについて考えを与えることができますか?


編集 :

  1. いいえ、これは宿題ではありません。
  2. メッセージ キューを介してこの種の構造を渡すことができる実装を作成しました。POD では問題なく動作しますが、動的データも渡すように拡張する必要があります。

これは、メッセージ キューがデータを取得する方法です。

私。ポインターを与えて、データを読み取って転送するサイズを伝えます。

ii. 単純な古いデータ型の場合、データは構造体内に格納されます。この構造体のメッセージ キューへのポインターを他のプロセスに簡単に渡すことができます。

iii. ただし、ベクター/文字列/リストなどの場合、実際のデータは構造内にないため、この構造のポインターを渡すと、メッセージキューは実際のデータではなく、内部に格納されるポインターを渡しますこの構造。

これこれを見ることができます。私は似たようなことを達成しようとしています。

4

4 に答える 4

3
void pushData( string userData )
{
    struct Data
    {
       char junk[1];
    };

    struct Data* data = malloc(userData.size() + 1);
    memcpy(data->junk, userData.data(), userData.size());
    data->junk[userData.size()] = '\0'; // assuming you want null termination
}

ここでは長さ 1 の配列を使用していますが、malloc を使用して構造体を割り当てているため、実際には任意のサイズにすることができます。

于 2013-03-07T05:11:24.237 に答える
1

表面上はかなり人工的な制約がいくつかありますが、質問に答えるには:単一structの変数に可変量のデータを含めることは不可能です...最も近いのは、最終メンバーを言うことです。そのchar [1]ような構造体を可変サイズのヒープ領域の開始、および配列のインデックス付けがチェックされないという事実を使用して、その文字を超えてメモリにアクセスします。この手法について学ぶには、http ://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html (または John Zwinck が投稿した回答)を参照してください。

別のアプローチは、たとえばtemplate <size_t N> struct X { char data_[size]; };ですが、各インスタンス化は個別の構造体型になり、実行時に必要なすべてのサイズを事前にインスタンス化することはできません (上限が必要ないと言った場合)。できたとしても、データが大きくなるにつれてさまざまなインスタンス化を処理するコードを作成することは、コードの肥大化と同様に悪夢のようです。

ある場所に文字列メンバーがあり、別の場所にデータがある構造を持つことは、ほとんどの場合、上記のハッカーよりも望ましいことです。

うまくいけばそれほどワイルドではない推測をすると、一般的なバイナリブロックの読み取り/書き込みで、開始アドレスとサイズに基づいてオブジェクトをシリアル化することに関心があると思います...? もしそうなら、どこかから現在のデータサイズを見つける必要があるため、目標が満たされていても問題があります. 可変長データをヒープに組み込む構造体固有のシリアル化ルーチンを作成することは、はるかに有望です。

于 2013-03-07T05:14:39.693 に答える
0

簡単な解決策: データの max_size (例: 1000) を見積もり、pushData が複数回呼び出されたときにメモリ リークを防止します (空きメモリと新しいサイズのメモリを malloc する場合 -> フラグメント メモリ)。

#define MAX_SIZE 1000
void pushData( string userData )
{
 struct Data
 {
   char junk[MAX_SIZE];
 };


memcpy(data->junk, userData.data(), userData.size());
data->junk[userData.size()] = '\0'; // assuming you want null termination
}
于 2013-03-07T05:45:26.117 に答える
0

John Zwinckが述べたように....動的メモリ割り当てを使用して問題を解決できます。

void pushData( string userData )
{
    struct Data
    {
       char *junk;
    };

    struct Data *d = calloc(sizeof(struct data), 1);
    d->junk = malloc(strlen(userData)+1);
    strcpy(d->junk, userdata);
}
于 2013-03-07T05:48:47.243 に答える