1

私はCの初心者です..構造体と配列の場合に動的メモリ割り当てがどのように機能するかを理解しようとしています..たとえば、次のようなコードがあります..

struct Person
{
    int id;
    char *name;
    char *place;
};

struct Database
{ 
    struct Person *data_rows;
};

文字配列の名前と場所の両方に動的にメモリを割り当てたい..および struct data_rows の配列..そのサイズを入力として取得..理想的には、割り当ての順序と同じための適切な構文はどうあるべきですか? ありがとう。

4

3 に答える 3

2

さて、「明らかに」最初に「struct Database」を入力する必要があります。

struct Database MyDatabase;

MyDatabase.data_rows=malloc(sizeof(MyDatabase.data_rows[0])*NumberOfPeople);

malloc() の失敗をチェックしなかったという事実を無視すると、これにより、すべて初期化されていない「struct Person」の配列が得られます。したがって、ほとんどの場合、それらを初期化する必要があります。

int i;
for (i=0; i<NumberOfPeople; i++)
{
   struct Person* MyPerson;

   MyPerson=&MyDatabase.data_rows[i];
   MyPerson->id=i;
   MyPerson->name=malloc(...);
   /* Do something to store the name in MyPerson->name */
   MyPerson->place=malloc(...);
   /* Do something to store the place in MyPerson->name */
}

ここで問題になるのは、malloc に付けた "..." です。固定サイズを使用すれば簡単ですが、構造体を次のように宣言することもできます

struct Person
{
    int id;
    char name[100];
    char place[200];
};

基本的に、名前の長さがどうあるべきかわからないので、「...」と入力しました。

また、「id」が何であるかを推測しました。配列インデックスを使用することは、実際にはやや無意味です:-)

もちろん、今すべてを行う必要はありません。名前を設定してポインターを NULL に置き、ファイルからデータを読み取るときなど、後でそれらを埋めることができます。または、どのフィールドが初期化され、どのフィールドが初期化されていないかをコードが常に「認識」していると確信している場合は、ここでまったく初期化しないこともできます。

于 2012-07-08T11:59:57.150 に答える
1

関数を作成することを強くお勧めします。これperson_newによりperson_free、構造体のメモリ管理が処理されます。

struct Person* person_new(char *name, char* place) {
  struct Person* person = malloc(sizeof(struct Person));

  person->name = strdup(name);
  person->place = strdup(place);

  return person;
}

void person_free(struct Person* person) {
  free(person->name);
  free(person->place);
  free(person);
}
于 2012-07-08T12:03:26.183 に答える
0

最善の方法は、構造体をクラスに変換することです。以下は構造体に対しても機能します...

次のように、Database と Person でコンストラクタとデストラクタを定義します。

struct Person
{
    Person(){
        name = new char[256];
        place = new char[256]; 
    };
    ~Person(){
       delete name; 
       delete place;
    }

    int id;
    char *name;
    char *place;
};

struct Database
{ 
    Database(int nPersons){
       data_rows = new Person[nPersons]; 
    };
    ~Database(){
       delete data_rows;
    };
    struct Person *data_rows;
};

または、コンストラクタとデストラクタなしでこれを行い、コード内ですべてのものを順番に割り当てることができますが、これは非常に醜い方法です!

なので:

Database myData;
myData.data_rows = new Persons[40];
for(int i=0; i < 40; i++){
   myData.data_rows[i].name = new char[256];
   myData.data_rows[i].place = new char[256];
}

data_rows[i]-> *(data_rows + i)は、ポインタのアドレスを i 回シフトしてから逆参照するだけであることに注意してください。

于 2012-07-08T12:03:18.277 に答える