Cで構造体の配列をどのように作成しますか?


100

私は各構造体が天体を表す構造体の配列を作ろうとしています。

私は構造体の経験があまりないため、配列全体ではなく構造体を使用することにしました。ただし、さまざまなエラーが何度も発生します。Iは、(例えば、Iは、様々なスレッド上とStackOverflowの上で見たことの技術を実装しようとしたCにおける構造体の配列及び-構造体の初期化配列Cがないそれらのすべては、適用可能でした)。

ここまで読んだ人のための詳細情報:動的である必要はありません。すべてのサイズを事前に知っている/定義しています。引数が定義されているいくつかの異なるメソッド(GLUTメソッドなど)でこれにアクセスするため、これもグローバル配列である必要があります。

これは、ヘッダーで構造体を定義する方法です。

struct body
{
    double p[3];//position
    double v[3];//velocity
    double a[3];//acceleration
    double radius;
    double mass;
};

構造体の内部を定義する前に定義している他のグローバル変数のリストがあり、それらの1つはこの構造体の配列です(基本的に、霧の中で話すのが不明確な場合は、下の行上記のものの上にあります):

struct body bodies[n];

ちょうどあなたが知ってnいるように、私が正当に定義したものです(つまり#define n 1)。

私はいくつかの異なる方法でこの配列を使用していますが、最も簡単で最もスペースを消費しない方法は、私のメインの単純化された形式です。ここで、各構造体のすべての変数を初期化します。何らかの方法で変数を変更する前に、変数を確実に設定します。

  int a, b;
 for(a = 0; a < n; a++)
 {
        for(b = 0; b < 3; b++)
        {
            bodies[a].p[b] = 0;
            bodies[a].v[b] = 0;
            bodies[a].a[b] = 0;
        }
        bodies[a].mass = 0;
        bodies[a].radius = 1.0;
 }

私が直面している現在のエラーはnbody.c:32:13: error: array type has incomplete element type、32行目で構造体の配列を作成しているところです。

最後に、ヘッダーとint main(void)は、同じ*.cファイル内の上のスペースを意味します。


まあ、それは私にとってはうまくいきます。宣言のstruct body bodies[n];前にstruct body {}宣言しませんか?
ジャック

可変長配列を使用すると、配列のサイズがシステム上のプログラムのスタックサイズ(プログラマーとして完全に制御できない)を超えると、不可解なバグやクラッシュを引き起こす可能性があることに注意してください。この種のものにはmalloc()を使用することをお勧めします。
エイドリアン

回答:


107
#include<stdio.h>
#define n 3
struct body
{
    double p[3];//position
    double v[3];//velocity
    double a[3];//acceleration
    double radius;
    double mass;
};

struct body bodies[n];

int main()
{
    int a, b;
     for(a = 0; a < n; a++)
     {
            for(b = 0; b < 3; b++)
            {
                bodies[a].p[b] = 0;
                bodies[a].v[b] = 0;
                bodies[a].a[b] = 0;
            }
            bodies[a].mass = 0;
            bodies[a].radius = 1.0;
     }

    return 0;
}

これは正常に動作します。ちなみにあなたの質問はあまり明確ではなかったので、ソースコードのレイアウトを上記に合わせてください。


また、私は構造体タイプの宣言と実際にそれのインスタンスを作成する間の配置について質問があります-私は最初にインスタンスを作成する以下のコンテンツを定義した別の構造体を持っています(ちょうど1つ今回は配列ではありません)、それでなぜこれが大量のエラーを発生させなかったのですか?それはうまくいったので、配列を作るという私の試みもうまくいくはずだと私は思いましたが、今回はうまくいきませんでした。また、ご回答いただきありがとうございます。
Amndeep7

1
こんにちは.... 59いいね?構造体の配列は表示されませんでした。

12

そのように書いてもいいと思います。私も学生なので、あなたの苦労を理解しています。少し遅い応答ですが大丈夫です。

#include<stdio.h>
#define n 3

struct {
    double p[3];//position
    double v[3];//velocity
    double a[3];//acceleration
    double radius;
    double mass;
}bodies[n];

11

したがって、次のコマンドを使用してすべてをまとめmalloc()ます。

int main(int argc, char** argv) {
    typedef struct{
        char* firstName;
        char* lastName;
        int day;
        int month;
        int year;

    }STUDENT;

    int numStudents=3;
    int x;
    STUDENT* students = malloc(numStudents * sizeof *students);
    for (x = 0; x < numStudents; x++){
        students[x].firstName=(char*)malloc(sizeof(char*));
        scanf("%s",students[x].firstName);
        students[x].lastName=(char*)malloc(sizeof(char*));
        scanf("%s",students[x].lastName);
        scanf("%d",&students[x].day);
        scanf("%d",&students[x].month);
        scanf("%d",&students[x].year);
    }

    for (x = 0; x < numStudents; x++)
        printf("first name: %s, surname: %s, day: %d, month: %d, year: %d\n",students[x].firstName,students[x].lastName,students[x].day,students[x].month,students[x].year);

    return (EXIT_SUCCESS);
}

8
malloc行にnumStudents * sizeof(STUDENT)が必要ですか?
トッド14

@トッドそれはしない方がいいです。sizeof *students同じことであり、もし学生がたまたま変わったとしてもそれは間違いないでしょう。
trentcl 2016年

@trentcl彼は{numStudents}個のポインタにメモリを割り当てました。構造ではなく、ポインタ。ポインタサイズは通常4バイトですが、構造体のサイズは20バイトです。20バイトは4で割り切れる数なので、パディングは必要なく、構造は開始アドレスから20バイトごとに格納されます。特定の1つの場合にのみメモリを割り当てるため、これは機能します。そうでない場合、他のmallocが割り当てられておらず、学生のメモリをオーバーフローしたため、構造体のメモリを上書きする可能性があります。
John Smith、

3
@JohnSmithあなたは間違っています。もう一度読んでください。sizeof *students指すもののサイズです。つまりsizeof(STUDENT)、ではありませんsizeof(STUDENT*)。あなたはptr = malloc(num * sizeof *ptr)イディオムが守るべきことになっている正確な間違いを犯しています。ここで確認してください(ほとんどの最新のPCと同様に、サーバーには8バイトのポインターがあるため、サイズは4および20ではなく8および32です)。
trentcl

@trentcl説明ありがとうございます。独自の初期化でポインターを逆参照する構文に混乱しました。少しわかりにくいですが、間違いなくもっとコンパクトなソリューションです。
John Smith、

8

動く

struct body bodies[n];

後へ

struct body
{
    double p[3];//position
    double v[3];//velocity
    double a[3];//acceleration
    double radius;
    double mass;
};

残りはすべて正常に見えます。


6

構造体の配列を初期化する別の方法は、配列メンバーを明示的に初期化することです。このアプローチは、構造体と配列のメンバーが多すぎない場合に便利でシンプルです。

typedef指定子を使用structして、構造体変数を宣言するたびにステートメントを再利用しないようにします。

typedef struct
{
    double p[3];//position
    double v[3];//velocity
    double a[3];//acceleration
    double radius;
    double mass;
}Body;

次に、構造体の配列を宣言します。各要素の初期化は、宣言に沿って行われます。

Body bodies[n] = {{{0,0,0}, {0,0,0}, {0,0,0}, 0, 1.0}, 
                  {{0,0,0}, {0,0,0}, {0,0,0}, 0, 1.0}, 
                  {{0,0,0}, {0,0,0}, {0,0,0}, 0, 1.0}};

繰り返しますが、これは、配列要素や構造体メンバーが多すぎず、前述のように、より動的なアプローチに興味がない場合は、かなり単純で簡単なソリューションです。このアプローチは、構造体のメンバーが名前付き列挙型変数(上記の例のような数値だけでなく)で初期化されている場合にも役立ちます。これにより、コードリーダーは構造とその特定のメンバーの目的と機能の概要をよりよく理解できます。アプリケーション。


1
これが大好き!ニースと簡単な答え👍
イーサン

1

あなたはヘッダファイルに構造体の定義を持って言っているとエラーがでているので、コンパイラは、構造体の配列の宣言の前に、構造体の型の定義を見つけることができないという旨のエラー手段nbody.cその後、ヘッダーファイルが正しく含まれているかどうかを確認する必要があります。をチェックし、#includeその型の変数を宣言する前に、構造体の定義が完了していることを確認してください。


彼が書いたように、OPはヘッダーファイルとしてのヘッダーを意味するのではないかと疑っています。彼が目を覚まして疑問を解消するのを待ちましょう。
nims

@nimsは正しいmainです。ヘッダーとは、ステートメントの上の領域のことです。
Amndeep7

1

ポインタを使用した解決策:

#include<stdio.h>
#include<stdlib.h>
#define n 3
struct body
{
    double p[3];//position
    double v[3];//velocity
    double a[3];//acceleration
    double radius;
    double *mass;
};


int main()
{
    struct body *bodies = (struct body*)malloc(n*sizeof(struct body));
    int a, b;
     for(a = 0; a < n; a++)
     {
            for(b = 0; b < 3; b++)
            {
                bodies[a].p[b] = 0;
                bodies[a].v[b] = 0;
                bodies[a].a[b] = 0;
            }
            bodies[a].mass = 0;
            bodies[a].radius = 1.0;
     }

    return 0;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.