Como você faz uma matriz de estruturas em C?

100

Estou tentando fazer uma série de estruturas onde cada estrutura representa um corpo celeste.

Não tenho muita experiência com structs, por isso decidi tentar usá-los em vez de um monte de arrays. No entanto, continuo encontrando vários erros diferentes. Tentei implementar as técnicas que vi em vários threads e no StackOverflow (como Array de structs em C e C - inicializar array de structs ), mas nem todos eram aplicáveis.

Mais informações para quem leu até aqui: Não preciso que nada disso seja dinâmico, sei / defino o tamanho de tudo de antemão. Eu também preciso que isso seja uma matriz global, pois estou acessando isso em vários métodos diferentes que têm argumentos definidos (ou seja, métodos GLUT).

É assim que estou definindo a estrutura em meu cabeçalho:

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

Eu tenho uma lista de outras variáveis ​​globais que estou definindo antes de definir o interior da estrutura, e uma delas é a matriz dessa estrutura (basicamente, se estou sendo muito confuso em minha fala nebulosa, a linha abaixo está acima do material acima):

struct body bodies[n];

Só para você saber, né algo que eu defini legitimamente (isto é #define n 1).

Eu uso esse array em vários métodos diferentes, mas o mais fácil e que menos ocupa espaço é uma forma simplificada do meu principal. Aqui eu inicializo todas as variáveis ​​em cada uma das estruturas, apenas para definir as variáveis ​​com certeza antes de modificá-las de alguma forma:

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

O erro atual que estou enfrentando é nbody.c:32:13: error: array type has incomplete element typeonde a linha 32 é onde estou criando a matriz das estruturas.

Um último esclarecimento, por cabeçalho quero dizer o espaço acima, int main(void)mas no mesmo *.carquivo.

Amndeep7
fonte
Bem, funciona bem para mim. Você não está declarando struct body bodies[n];antes da struct body {}declaração?
Jack
Observe que o uso de matrizes de comprimento variável pode frequentemente causar erros misteriosos ou travamentos quando o tamanho da matriz excede o tamanho da pilha do programa em seu sistema (o que está completamente fora de seu controle como programador). É melhor usar malloc () para esse tipo de coisa.
Adrian

Respostas:

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

isso funciona bem. a propósito, sua pergunta não foi muito clara, portanto, combine o layout de seu código-fonte com o acima.

nims
fonte
Além disso, eu tenho uma pergunta sobre o posicionamento entre a declaração do tipo de estrutura e, em seguida, realmente fazer uma instância dela - eu tenho uma estrutura diferente, que defini o conteúdo abaixo, onde primeiro faço uma instância dela (apenas uma desta vez, não uma matriz), então por que isso não cometeu a enorme série de erros? Funcionou muito bem, o que me levou a pensar que minha tentativa de fazer um array também deveria ter funcionado, mas dessa vez não funcionou. Além disso, obrigado pela sua resposta, funcionou.
Amndeep7
1
Olá, .... 59 gostos? Não vi arrays de struct, só vejo arrays de variável de struck ...
12

Acho que você também poderia escrever assim. Eu também sou um estudante, então entendo sua luta. Resposta um pouco atrasada, mas 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
fonte
11

Então, para juntar tudo 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
fonte
8
A linha malloc deve ter numStudents * sizeof (STUDENT)?
Todd
@Todd É melhor não fazer isso. sizeof *studentsé a mesma coisa e não será errado se ALUNO algum dia mudar.
trentcl de
@trentcl Ele alocou memória para {numStudents} quantidade de ponteiros. Não estruturas, mas ponteiros. O tamanho do ponteiro é geralmente de 4 bytes, enquanto o tamanho da estrutura é de 20 bytes. 20 bytes é o número divisível por 4, portanto, nenhum preenchimento é necessário e a estrutura é armazenada a cada 20 bytes a partir do endereço inicial. Só funciona porque você aloca memória para apenas um caso específico. Caso contrário, outros mallocs podem sobrescrever a memória de suas estruturas, porque não está alocado e você sobrecarregou a memória de seu aluno.
John Smith
3
@JohnSmith Você está enganado; Leia isso novamente. sizeof *studentsé o tamanho do que está apontado , ou seja sizeof(STUDENT), não sizeof(STUDENT*). Você está cometendo exatamente o erro contra o qual o ptr = malloc(num * sizeof *ptr)idioma deve se proteger. Verifique aqui (observe que o servidor, como a maioria dos PCs modernos, tem ponteiros de 8 bytes, então os tamanhos são 8 e 32 em vez de 4 e 20).
trentcl
@trentcl Obrigado pela explicação. Fiquei confuso com a sintaxe do ponteiro de desreferenciamento em sua própria inicialização. Eu diria que é um pouco confuso, mas definitivamente uma solução mais compacta.
John Smith
8

mover

struct body bodies[n];

para depois

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

Descansar tudo parece bem.

vrk001
fonte
6

Outra maneira de inicializar uma matriz de estruturas é inicializar os membros da matriz explicitamente. Essa abordagem é útil e simples se não houver muitos membros de estrutura e matriz.

Use o typedefespecificador para evitar reutilizar a structinstrução sempre que declarar uma variável de estrutura:

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

Em seguida, declare sua matriz de estruturas. A inicialização de cada elemento acompanha a declaração:

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 é uma solução bastante simples e direta se você não tiver muitos elementos de matriz e grandes membros de estrutura e se, como você afirmou, não estiver interessado em uma abordagem mais dinâmica. Essa abordagem também pode ser útil se os membros de struct forem inicializados com variáveis ​​enum nomeadas (e não apenas números como o exemplo acima), por meio do qual dá ao leitor de código uma visão geral melhor do propósito e função de uma estrutura e seus membros em certos formulários.

Abdel Aleem
fonte
1
Amo isso! Resposta agradável e simples 👍
Ethan
1

Esse erro significa que o compilador não é capaz de encontrar a definição do tipo de sua estrutura antes da declaração da matriz de estruturas, já que você está dizendo que tem a definição da estrutura em um arquivo de cabeçalho e o erro está em nbody.centão você deve verificar se está incluindo corretamente o arquivo de cabeçalho. Verifique o seu #includee certifique-se de que a definição da estrutura foi feita antes de declarar qualquer variável desse tipo.

David
fonte
duvido que OP signifique cabeçalho como arquivo de cabeçalho, como ele escreveu, "a linha abaixo está acima das coisas acima" antes da declaração da matriz de estrutura que está em seu arquivo nbody.c. Vamos esperar que ele acorde e tire as dúvidas.
nims
@nims está correto, por cabeçalho eu quis dizer a área acima da maindeclaração.
Amndeep7
1

Solução usando ponteiros:

#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;
}
Ajudando Bean
fonte