Jak tworzysz tablicę struktur w C?

101

Próbuję stworzyć tablicę struktur, w których każda struktura reprezentuje ciało niebieskie.

Nie mam zbyt dużego doświadczenia ze strukturami, dlatego zdecydowałem się spróbować ich użyć zamiast całej masy tablic. Jednak ciągle napotykam na wiele różnych błędów. Próbowałem zaimplementować techniki, które widziałem w różnych wątkach i na StackOverflow (takie jak Array of structs w C i C - zainicjuj tablicę struktur ), jednak nie wszystkie z nich miały zastosowanie.

Dalsze informacje dla tych, którzy przeczytali do tej pory: nie potrzebuję tego, aby być dynamicznym, wiem / określam rozmiar wszystkiego wcześniej. Potrzebuję również, aby była to tablica globalna, ponieważ uzyskuję do niej dostęp w kilku różnych metodach, które mają zdefiniowane argumenty (tj. Metody GLUT).

Oto jak definiuję strukturę w moim nagłówku:

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

Mam listę innych zmiennych globalnych, które definiuję przed zdefiniowaniem wnętrza struktury, a jedną z nich jest tablica tej struktury (w zasadzie, jeśli jestem zbyt niejasny w moim zamglonym mowie, wiersz poniżej jest nad rzeczami powyżej):

struct body bodies[n];

Dla twojej wiadomości njest to coś, co zgodnie z prawem zdefiniowałem (tj #define n 1.).

Używam tej tablicy w kilku różnych metodach, ale najłatwiejszą i najmniej zajmującą miejsce jest uproszczona forma mojego main. Tutaj inicjalizuję wszystkie zmienne w każdej ze struktur, aby ustawić zmienne na pewne, zanim je zmodyfikuję:

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

Bieżący błąd, z którym się spotykam, to miejsce, w nbody.c:32:13: error: array type has incomplete element typektórym linia 32 jest miejscem, w którym tworzę tablicę struktur.

Ostatnie wyjaśnienie, przez nagłówek mam na myśli spację powyżej, int main(void)ale w tym samym *.cpliku.

Amndeep7
źródło
Cóż, dla mnie działa dobrze. Czy nie deklarujesz struct body bodies[n];przed struct body {}deklaracją?
Jack
Zauważ, że używanie tablic o zmiennej długości może często powodować tajemnicze błędy lub awarie, gdy rozmiar tablicy przekracza rozmiar stosu programu w twoim systemie (co jest całkowicie poza twoją kontrolą jako programista). Do tego typu rzeczy lepiej jest używać funkcji malloc ().
adrian

Odpowiedzi:

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

to działa dobrze. Twoje pytanie nie było zbyt jasne, więc dopasuj układ swojego kodu źródłowego do powyższego.

nims
źródło
Mam też pytanie o umiejscowienie między deklaracją typu struct, a następnie wykonaniem jej instancji - mam inną strukturę, taką, którą zdefiniowałem poniżej, gdzie najpierw tworzę jej instancję (tylko jedną tym razem nie tablica), więc dlaczego nie spowodowało to ogromnej serii błędów? Zadziałało dobrze, co doprowadziło mnie do wniosku, że moja próba stworzenia tablicy również powinna zadziałać, ale tym razem nie zadziałała. Dziękuję również za odpowiedź, zadziałało.
Amndeep7
1
Cześć ... 59 polubień? Nie widziałem tablic struct, widzę tylko tablice zmiennych z uderzenia ...
12

Myślę, że mógłbyś to też napisać w ten sposób. Jestem też studentem, więc rozumiem twoją walkę. Trochę późna odpowiedź, ale 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
źródło
11

Aby to wszystko połączyć, używając 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
źródło
8
Czy twoja linia malloc powinna mieć numStudents * sizeof (STUDENT)?
Todd
@Todd Lepiej tego nie robić. sizeof *studentsjest tym samym i nie będzie źle, jeśli UCZNIOWIEC kiedykolwiek się zmieni.
trentcl
@trentcl Przydzielił pamięć na {numStudents} liczbę wskaźników. Nie struktury, ale wskazówki. Rozmiar wskaźnika to najczęściej 4 bajty, podczas gdy rozmiar struktury to 20 bajtów. 20 bajtów to liczba podzielna przez 4, więc nie jest potrzebne wypełnianie, a struktura jest przechowywana co 20 bajtów od adresu początkowego. Działa tylko dlatego, że przydzielasz pamięć tylko dla jednego konkretnego przypadku. W przeciwnym razie inne malloki mogą nadpisać pamięć twoich struktur, ponieważ nie jest ona przydzielona i przepełniłeś pamięć uczniów.
John Smith
3
@JohnSmith Jesteś w błędzie; Przeczytaj to ponownie. sizeof *studentsjest rozmiarem tego, na co wskazuje , tj . sizeof(STUDENT)nie sizeof(STUDENT*). Popełniasz dokładnie taki błąd, przed którym ptr = malloc(num * sizeof *ptr)ma strzec idiom. Sprawdź tutaj (zwróć uwagę, że serwer, podobnie jak większość współczesnych komputerów, ma wskaźniki 8-bajtowe, więc rozmiary to 8 i 32 zamiast 4 i 20).
trentcl
@trentcl Dziękuję za wyjaśnienie. Byłem zdezorientowany przez składnię wskaźnika wyłuskiwania w jego własnej inicjalizacji. Powiedziałbym, że to trochę zagmatwane, ale zdecydowanie bardziej kompaktowe rozwiązanie.
John Smith
8

ruszaj się

struct body bodies[n];

po

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

Reszta wygląda dobrze.

vrk001
źródło
6

Innym sposobem inicjalizacji tablicy struktur jest jawna inicjalizacja elementów tablicy. To podejście jest przydatne i proste, jeśli nie ma zbyt wielu elementów strukturalnych i tablicy.

Użyj typedefspecyfikatora, aby uniknąć ponownego użycia structinstrukcji za każdym razem, gdy deklarujesz zmienną struct:

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

Następnie zadeklaruj swoją tablicę struktur. Inicjalizacja każdego elementu idzie w parze z deklaracją:

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

Powtarzam, jest to raczej proste i nieskomplikowane rozwiązanie, jeśli nie masz zbyt wielu elementów tablicy i dużych elementów strukturalnych oraz jeśli, jak powiedziałeś, nie jesteś zainteresowany bardziej dynamicznym podejściem. Takie podejście może być również przydatne, jeśli elementy składowe struktury są inicjowane za pomocą nazwanych zmiennych wyliczeniowych (a nie tylko liczb, jak w powyższym przykładzie), dzięki czemu zapewnia czytelnikowi kodu lepszy przegląd celu i funkcji struktury i jej elementów członkowskich w określonych Aplikacje.

Abdel Aleem
źródło
1
Kocham to! Miła i prosta odpowiedź 👍
Ethan
1

Ten błąd oznacza, że ​​kompilator nie jest w stanie znaleźć definicji typu twojej struktury przed deklaracją tablicy struktur, ponieważ mówisz, że masz definicję struktury w pliku nagłówkowym, a błąd jest nbody.cwtedy powinieneś sprawdzić, czy poprawnie dołączasz plik nagłówkowy. Sprawdź swoje #includei upewnij się, że definicja struktury została wykonana przed zadeklarowaniem jakiejkolwiek zmiennej tego typu.

David
źródło
wątpię, że OP oznacza nagłówek jako plik nagłówkowy, jak napisał, „linia poniżej jest nad tym, co powyżej” przed deklaracją tablicy struct, która znajduje się w jego pliku nbody.c. Poczekajmy, aż się obudzi i rozwiąże wątpliwości.
nims
@nims jest poprawne, przez nagłówek miałem na myśli obszar nad maininstrukcją.
Amndeep7
1

Rozwiązanie wykorzystujące wskaźniki:

#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;
}
Helping Bean
źródło