¿Cómo se hace una matriz de estructuras en C?

100

Estoy tratando de hacer una serie de estructuras donde cada estructura representa un cuerpo celeste.

No tengo tanta experiencia con estructuras, por lo que decidí intentar usarlas en lugar de un montón de matrices. Sin embargo, sigo encontrándome con numerosos errores diferentes. Intenté implementar las técnicas que he visto en varios subprocesos y en StackOverflow (como Matriz de estructuras en C y C - inicializar matriz de estructuras ), sin embargo, no todas eran aplicables.

Más información para los que han leído hasta aquí: No necesito nada de esto para ser dinámico, sé / defino el tamaño de todo de antemano. También necesito que esto sea una matriz global ya que estoy accediendo a esto en varios métodos diferentes que tienen argumentos definidos (es decir, métodos GLUT).

Así es como estoy definiendo la estructura en mi encabezado:

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

Tengo una lista de otras variables globales que estoy definiendo antes de definir el interior de la estructura, y una de ellas es la matriz de esta estructura (básicamente, si no estoy muy claro en mi discurso empañado, la línea de abajo está por encima de lo anterior):

struct body bodies[n];

Para que lo sepas, nes algo que he definido legítimamente (es decir #define n 1).

Utilizo esta matriz en varios métodos diferentes, pero el más fácil y que consume menos espacio es una forma simplificada de mi archivo main. Aquí inicializo todas las variables en cada una de las estructuras, solo para establecer las variables con certeza antes de modificarlas de alguna manera:

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

El error actual al que me enfrento es nbody.c:32:13: error: array type has incomplete element typedonde la línea 32 es donde estoy haciendo la matriz de estructuras.

Una última aclaración, por cabecera me refiero al espacio de arriba int main(void)pero en el mismo *.carchivo.

Amndeep7
fuente
Bueno, me funciona bien. ¿No estás declarando struct body bodies[n];antes de la struct body {}declaración?
Jack
Tenga en cuenta que el uso de matrices de longitud variable a menudo puede causar errores misteriosos o bloqueos cuando el tamaño de la matriz excede el tamaño de la pila del programa en su sistema (que está completamente fuera de su control como programador). Es mejor usar malloc () para este tipo de cosas.
Adrian

Respuestas:

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

esto funciona bien. Por cierto, su pregunta no fue muy clara, así que haga coincidir el diseño de su código fuente con el anterior.

nims
fuente
Además, tengo una pregunta sobre la ubicación entre la declaración del tipo de estructura y luego hacer una instancia de ella: tengo una estructura diferente, una en la que definí el contenido a continuación, donde primero hago una instancia de ella (solo una esta vez, no una matriz), entonces, ¿por qué esto no cometió una serie masiva de errores? Funcionó bien, lo que me llevó a pensar que mi intento de hacer una matriz debería haber funcionado también, pero esta vez no funcionó. Además, gracias por tu respuesta, funcionó.
Amndeep
1
Hola ... ¿59 me gusta? No vi matrices de estructura, solo veo matrices de variables de golpeado ...
12

Creo que también podrías escribirlo de esa manera. También soy estudiante, así que entiendo tu lucha. Respuesta un poco tardía pero bien.

#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
fuente
11

Entonces, para ponerlo todo junto 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);
}
Dounchan
fuente
8
¿Debe su línea malloc tener numStudents * sizeof (ESTUDIANTE)?
Todd
@Todd Es mejor no hacerlo. sizeof *studentses lo mismo y no estará mal si el ESTUDIANTE cambia alguna vez.
trentcl
@trentcl Ha asignado memoria para {numStudents} cantidad de punteros. No estructuras, sino punteros. El tamaño del puntero suele ser de 4 bytes, mientras que el tamaño de la estructura es de 20 bytes. 20 bytes es un número divisible por 4, por lo que no se necesita relleno y la estructura se almacena cada 20 bytes desde la dirección de inicio. Solo funciona porque asigna memoria para un solo caso en particular. De lo contrario, otros mallocs podrían sobrescribir la memoria de sus estructuras, porque no está asignada y ha desbordado la memoria de su estudiante.
John Smith
3
@JohnSmith Estás equivocado; Leelo de nuevo. sizeof *studentses el tamaño de lo que se apunta , es decir sizeof(STUDENT), no sizeof(STUDENT*). Estás cometiendo el error exacto del que ptr = malloc(num * sizeof *ptr)se supone que debe protegerse el idioma. Compruébelo aquí (tenga en cuenta que el servidor, como la mayoría de las PC modernas, tiene punteros de 8 bytes, por lo que los tamaños son 8 y 32 en lugar de 4 y 20).
trentcl
@trentcl Gracias por la explicación. Me confundió la sintaxis de desreferenciar el puntero en su propia inicialización. Yo diría que es una solución un poco confusa, pero definitivamente más compacta.
John Smith
8

moverse

struct body bodies[n];

Después

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

Descansar todo se ve bien.

vrk001
fuente
6

Otra forma de inicializar una matriz de estructuras es inicializar los miembros de la matriz explícitamente. Este enfoque es útil y simple si no hay demasiados miembros de estructura y matriz.

Utilice el typedefespecificador para evitar volver a utilizar la structdeclaración cada vez que declare una variable de estructura:

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

Luego declare su matriz de estructuras. La inicialización de cada elemento va junto con la declaración:

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

Para repetir, esta es una solución bastante simple y directa si no tiene demasiados elementos de matriz y miembros de estructura grandes y si, como dijo, no está interesado en un enfoque más dinámico. Este enfoque también puede ser útil si los miembros de la estructura se inicializan con variables enum nombradas (y no solo números como el ejemplo anterior) por lo que le da al lector de código una mejor descripción general del propósito y función de una estructura y sus miembros en ciertos aplicaciones.

Abdel Aleem
fuente
1
¡Me gusta esto! Respuesta agradable y simple 👍
Ethan
1

Ese error significa que el compilador no puede encontrar la definición del tipo de su estructura antes de la declaración de la matriz de estructuras, ya que está diciendo que tiene la definición de la estructura en un archivo de encabezado y el error está en nbody.cese momento. debe verificar si está incluyendo correctamente el archivo de encabezado. Verifique sus #includey asegúrese de que la definición de la estructura esté hecha antes de declarar cualquier variable de ese tipo.

David
fuente
Dudo que OP signifique encabezado como archivo de encabezado, como él escribió, "la línea de abajo está encima de las cosas de arriba" antes de la declaración de matriz de estructura que está en su archivo nbody.c. Esperemos a que se despierte y aclare la duda.
nims
@nims es correcto, por encabezado me refiero al área sobre la maindeclaración.
Amndeep
1

Solución usando punteros:

#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;
}
Ayudando a Bean
fuente