Come si crea un array di strutture in C?


100

Sto cercando di creare un array di strutture in cui ogni struttura rappresenta un corpo celeste.

Non ho molta esperienza con le strutture, motivo per cui ho deciso di provare a usarle invece di un intero gruppo di array. Tuttavia, continuo a incorrere in numerosi errori diversi. Ho provato a implementare le tecniche che ho visto su vari thread e su StackOverflow (come Array of structs in C e C - initialize array of structs ), tuttavia non tutte erano applicabili.

Ulteriori informazioni per chi ha letto fin qui: non ho bisogno di niente di tutto questo per essere dinamico, conosco / definisco la dimensione di tutto in anticipo. Ho anche bisogno che questo sia un array globale poiché accedo a questo in diversi metodi diversi che hanno argomenti definiti (cioè metodi GLUT).

Ecco come sto definendo la struttura nella mia intestazione:

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

Ho un elenco di altre variabili globali che sto definendo prima di definire l'interno della struttura, e una di questeèl'array di questa struttura (in pratica, se sono troppo poco chiaro nel mio parlare appannato, la riga sotto è al di sopra delle cose sopra):

struct body bodies[n];

Solo così sai, nè qualcosa che ho legittimamente definito (cioè #define n 1).

Uso questo array in diversi metodi, ma il più semplice e che occupa meno spazio è una forma semplificata del mio main. Qui inizializzo tutte le variabili in ciascuna delle strutture, solo per impostare le variabili per certo prima di modificarle in qualche modo:

  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'errore corrente che sto affrontando è nbody.c:32:13: error: array type has incomplete element typedove la riga 32 è dove sto creando l'array degli struct.

Un'ultima precisazione, per intestazione intendo lo spazio sopra int main(void)ma nello stesso *.cfile.


Bene, funziona bene per me. Non stai dichiarando struct body bodies[n];prima della struct body {}dichiarazione?
Jack

Si noti che l'utilizzo di array di lunghezza variabile può spesso causare bug misteriosi o arresti anomali quando la dimensione dell'array supera la dimensione dello stack del programma sul sistema (che è completamente fuori dal controllo di un programmatore). È meglio usare malloc () per questo genere di cose.
Adrian

Risposte:


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

questo funziona bene. la tua domanda non era molto chiara, quindi abbina il layout del tuo codice sorgente con quanto sopra.


Inoltre, ho una domanda sul posizionamento tra la dichiarazione del tipo di struttura e poi effettivamente crearne un'istanza: ho una struttura diversa, una di cui ho definito il contenuto di seguito dove ne creo prima un'istanza (solo una questa volta, non un array), quindi perché questo non ha fatto la massiccia serie di errori? Ha funzionato perfettamente, il che mi ha portato a pensare che anche il mio tentativo di creare un array avrebbe dovuto funzionare, ma questa volta non ha funzionato. Inoltre, grazie per la tua risposta, ha funzionato.
Amndeep7

1
Ciao, .... 59 mi piace? Non ho visto array di struct, vedo solo array di variabili da colpiti ...

12

Penso che potresti scriverlo anche in questo modo. Sono anche uno studente quindi capisco la tua lotta. Risposta un po 'in ritardo ma 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];

11

Quindi, per mettere tutto insieme usando 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
La tua linea malloc dovrebbe avere numStudents * sizeof (STUDENT)?
Todd

@Todd È meglio non farlo. sizeof *studentsè la stessa cosa e non sarebbe sbagliato se lo STUDENTE dovesse mai cambiare.
trentcl

@trentcl Ha allocato memoria per {numStudents} quantità di puntatori. Non strutture, ma puntatori. La dimensione del puntatore è solitamente di 4 byte, mentre la dimensione della struttura è di 20 byte. 20 byte è un numero divisibile per 4, quindi non è necessario alcun riempimento e la struttura viene memorizzata su ogni 20 byte dall'indirizzo iniziale. Funziona solo perché si alloca la memoria solo per un caso particolare. Altrimenti altri mallocs potrebbero sovrascrivere la memoria delle tue strutture, perché non è allocata e hai sovraccaricato la memoria dello studente.
John Smith

3
@JohnSmith Ti sbagli; leggilo di nuovo. sizeof *studentsè la dimensione di ciò a cui punta , cioè sizeof(STUDENT)no sizeof(STUDENT*). Stai commettendo l'errore esatto da cui il ptr = malloc(num * sizeof *ptr)linguaggio dovrebbe guardarsi. Controllalo qui (nota che il server, come la maggior parte dei PC moderni, ha puntatori a 8 byte, quindi le dimensioni sono 8 e 32 invece di 4 e 20).
trentcl

@trentcl Grazie per la spiegazione. Sono stato confuso dalla sintassi del puntatore di dereferenziazione nella sua inizializzazione. Direi che è una soluzione un po 'confusa, ma decisamente più compatta.
John Smith,

8

mossa

struct body bodies[n];

a dopo

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

Il resto sembra tutto a posto.


6

Un altro modo per inizializzare un array di strutture consiste nell'inizializzare esplicitamente i membri dell'array. Questo approccio è utile e semplice se non ci sono troppi membri di struct e array.

Usa lo typedefspecificatore per evitare di riutilizzare l' structistruzione ogni volta che dichiari una variabile struct:

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

Quindi dichiara il tuo array di strutture. L'inizializzazione di ogni elemento va di pari passo con la dichiarazione:

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

Per ripetere, questa è una soluzione piuttosto semplice e diretta se non hai troppi elementi array e membri di grandi dimensioni e se, come hai affermato, non sei interessato a un approccio più dinamico. Questo approccio può essere utile anche se i membri della struttura sono inizializzati con variabili enum denominate (e non solo numeri come l'esempio sopra), per cui fornisce al lettore di codice una migliore panoramica dello scopo e della funzione di una struttura e dei suoi membri in certi applicazioni.


1
Ama questo! Risposta bella e semplice 👍
Ethan

1

Questo errore significa che il compilatore non è in grado di trovare la definizione del tipo della tua struttura prima della dichiarazione dell'array di strutture, poiché stai dicendo che hai la definizione della struttura in un file di intestazione e l'errore è in nbody.callora dovresti controllare se stai includendo correttamente il file di intestazione. Controlla i tuoi #includee assicurati che la definizione della struttura sia eseguita prima di dichiarare qualsiasi variabile di quel tipo.


Dubito che OP significhi header come file di intestazione, come ha scritto, "la riga sotto è sopra la roba sopra" prima della dichiarazione di array della struttura che è nel suo file nbody.c. Aspettiamo che si svegli e chiarisca il dubbio.
nims

@nims è corretto, per intestazione intendevo l'area sopra la maindichiarazione.
Amndeep7

1

Soluzione utilizzando i puntatori:

#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;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.