Comment créer un tableau de structures en C?

100

J'essaie de créer un tableau de structures où chaque structure représente un corps céleste.

Je n'ai pas beaucoup d'expérience avec les structures, c'est pourquoi j'ai décidé d'essayer de les utiliser au lieu de tout un tas de tableaux. Cependant, je continue à rencontrer de nombreuses erreurs différentes. J'ai essayé d'implémenter les techniques que j'ai vues sur divers threads et sur StackOverflow (comme Array of structs en C et C - initialize array of structs ), mais elles n'étaient pas toutes applicables.

Plus d'informations pour ceux qui ont lu jusqu'ici: Je n'ai besoin de rien de tout cela pour être dynamique, je connais / définit la taille de tout à l'avance. J'ai également besoin que ce soit un tableau global car j'y accède dans plusieurs méthodes différentes qui ont défini des arguments (c'est-à-dire les méthodes GLUT).

Voici comment je définis la structure dans mon en-tête:

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

J'ai une liste d'autres variables globales que je définis avant de définir l'intérieur de la structure, et l'une d'elles est le tableau de cette structure (en gros, si je ne suis pas trop clair dans mon discours brumeux, la ligne ci-dessous est au-dessus des éléments ci-dessus):

struct body bodies[n];

Juste pour que vous le sachiez, nc'est quelque chose que j'ai légitimement défini (ie #define n 1).

J'utilise ce tableau dans plusieurs méthodes différentes, mais la plus simple et la moins encombrante est une forme simplifiée de mon main. Ici, j'initialise toutes les variables dans chacune des structures, juste pour définir les variables avec certitude avant de les modifier d'une manière ou d'une autre:

  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;
 }

L'erreur actuelle à laquelle je suis confronté est celle nbody.c:32:13: error: array type has incomplete element typeoù la ligne 32 est l'endroit où je crée le tableau des structures.

Une dernière précision, par en-tête j'entends l'espace ci-dessus int main(void)mais dans le même *.cfichier.

Amndeep7
la source
Eh bien, cela fonctionne bien pour moi. Ne déclarez-vous pas struct body bodies[n];avant la struct body {}déclaration?
Jack
Notez que l'utilisation de tableaux de longueur variable peut souvent causer des bogues mystérieux ou des plantages lorsque la taille du tableau dépasse la taille de la pile du programme sur votre système (ce qui est complètement hors de votre contrôle en tant que programmeur). Il vaut mieux utiliser malloc () pour ce genre de chose.
adrian

Réponses:

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;
}

cela fonctionne très bien. votre question n'était pas très claire d'ailleurs, alors faites correspondre la mise en page de votre code source avec ce qui précède.

nims
la source
De plus, j'ai une question sur le placement entre la déclaration du type struct et ensuite en faire une instance - j'ai une structure différente, une dont j'ai défini le contenu ci - dessous où j'en fais d'abord une instance (juste une cette fois, pas un tableau), alors pourquoi cela n'a-t-il pas fait la série massive d'erreurs? Cela a très bien fonctionné, ce qui m'a amené à penser que ma tentative de création d'un tableau aurait dû fonctionner également, mais cette fois, cela n'a pas fonctionné. Aussi, merci pour votre réponse, cela a fonctionné.
Amndeep7
1
Salut, .... 59 J'aime? Je n'ai pas vu les tableaux de struct, je ne vois que les tableaux de variables de frappé ...
12

Je pense que vous pourriez aussi l'écrire de cette façon. Je suis également étudiant, donc je comprends votre combat. Réponse un peu tardive mais ok.

#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];
Christakitos
la source
11

Donc, pour tout mettre ensemble en utilisant 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);
}
Dounchan
la source
8
Votre ligne malloc devrait-elle avoir numStudents * sizeof (STUDENT)?
Todd
@Todd Il vaut mieux ne pas le faire. sizeof *studentsc'est la même chose et ce ne sera pas mal si l'ÉTUDIANT change un jour.
trentcl
@trentcl Il a alloué de la mémoire pour {numStudents} nombre de pointeurs. Pas des structures, mais des pointeurs. La taille du pointeur est le plus souvent de 4 octets, tandis que la taille de la structure est de 20 octets. 20 octets est un nombre divisible par 4, donc aucun remplissage n'est nécessaire et la structure est stockée tous les 20 octets à partir de l'adresse de départ. Cela ne fonctionne que parce que vous allouez de la mémoire pour un seul cas particulier. Sinon, d'autres mallocs pourraient écraser la mémoire de vos structures, car elle n'est pas allouée et vous avez dépassé la mémoire de vos élèves.
John Smith
3
@JohnSmith Vous vous trompez; relisez-le. sizeof *studentsest la taille de ce qui est pointé , c'est- à -dire sizeof(STUDENT)non sizeof(STUDENT*). Vous faites exactement l'erreur contre laquelle l' ptr = malloc(num * sizeof *ptr)idiome est censé se prémunir. Vérifiez-le ici (notez que le serveur, comme la plupart des PC modernes, a des pointeurs de 8 octets donc les tailles sont 8 et 32 ​​au lieu de 4 et 20).
trentcl
@trentcl Merci pour l'explication. J'ai été confus par la syntaxe du pointeur de déréférencement dans sa propre initialisation. Je dirais que c'est une solution un peu déroutante, mais certainement plus compacte.
John Smith
8

bouge toi

struct body bodies[n];

à après

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

Reste tout va bien.

vrk001
la source
6

Une autre façon d'initialiser un tableau de structures consiste à initialiser explicitement les membres du tableau. Cette approche est utile et simple s'il n'y a pas trop de membres de structure et de tableau.

Utilisez le typedefspécificateur pour éviter de réutiliser l' structinstruction à chaque fois que vous déclarez une variable struct:

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

Déclarez ensuite votre tableau de structures. L'initialisation de chaque élément va de pair avec la déclaration:

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}};

Pour répéter, c'est une solution plutôt simple et directe si vous n'avez pas trop d'éléments de tableau et de grands membres de structure et si, comme vous l'avez dit, vous n'êtes pas intéressé par une approche plus dynamique. Cette approche peut également être utile si les membres de la structure sont initialisés avec des variables enum nommées (et pas seulement des nombres comme l'exemple ci-dessus), ce qui donne au lecteur de code un meilleur aperçu de l'objectif et de la fonction d'une structure et de ses membres dans certains applications.

Abdel Aleem
la source
1
Aime ça! Réponse sympa et simple 👍
Ethan
1

Cette erreur signifie que le compilateur n'est pas en mesure de trouver la définition du type de votre struct avant la déclaration du tableau de structs, puisque vous dites que vous avez la définition de la structure dans un fichier d'en-tête et que l'erreur est nbody.clà vous devriez vérifier si vous incluez correctement le fichier d'en-tête. Vérifiez les vôtres #includeet assurez-vous que la définition de la structure est effectuée avant de déclarer une variable de ce type.

David
la source
Je doute que OP signifie en-tête comme fichier d'en-tête, comme il l'a écrit, "la ligne ci-dessous est au-dessus de la substance ci-dessus" avant la déclaration de tableau de structure qui est dans son fichier nbody.c. Attendons qu'il se réveille et dissipe le doute.
nims
@nims est correct, par en-tête, je voulais dire la zone au-dessus de la maindéclaration.
Amndeep7
1

Solution utilisant des pointeurs:

#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;
}
Aider Bean
la source