Làm thế nào để bạn tạo một mảng cấu trúc trong C?


100

Tôi đang cố gắng tạo một mảng cấu trúc trong đó mỗi cấu trúc đại diện cho một thiên thể.

Tôi không có nhiều kinh nghiệm về cấu trúc, đó là lý do tại sao tôi quyết định thử sử dụng chúng thay vì toàn bộ mảng. Tuy nhiên, tôi vẫn tiếp tục gặp phải vô số lỗi khác nhau. Tôi đã cố gắng triển khai các kỹ thuật mà tôi đã thấy trên các luồng khác nhau và trên StackOverflow (chẳng hạn như Mảng cấu trúc trong CC - khởi tạo mảng cấu trúc ), tuy nhiên không phải tất cả chúng đều áp dụng được.

Thông tin thêm cho những người đã đọc đến đây: Tôi không cần bất kỳ thứ gì trong số này để trở nên năng động, tôi biết / xác định trước kích thước của mọi thứ. Tôi cũng cần đây là một mảng toàn cục vì tôi đang truy cập nó trong một số phương thức khác nhau có các đối số được xác định (tức là các phương thức GLUT).

Đây là cách tôi xác định cấu trúc trong tiêu đề của mình:

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

Tôi có một danh sách các biến toàn cục khác mà tôi đang xác định trước khi xác định phần bên trong của cấu trúc và một trong số đó là mảng của cấu trúc này (về cơ bản, nếu tôi quá không rõ ràng trong bài nói của mình, thì dòng dưới đây ở trên những thứ ở trên):

struct body bodies[n];

Mong bạn biết đấy, nlà thứ mà tôi đã xác định một cách hợp pháp (tức là #define n 1).

Tôi sử dụng mảng này trong một số phương pháp khác nhau, nhưng phương pháp dễ nhất và ít tốn dung lượng nhất là một dạng đơn giản của chính của tôi. Ở đây tôi khởi tạo tất cả các biến trong mỗi cấu trúc, chỉ để đặt các biến cho một số biến trước khi tôi sửa đổi chúng theo một cách nào đó:

  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ỗi hiện tại mà tôi đang gặp phải là nbody.c:32:13: error: array type has incomplete element typedòng 32 là nơi tôi đang tạo mảng cấu trúc.

Một lời giải thích cuối cùng, theo tiêu đề, tôi có nghĩa là khoảng trống ở trên int main(void)nhưng trong cùng một *.ctệp.


Vâng, nó hoạt động tốt cho tôi. Không phải bạn khai báo struct body bodies[n];trước khi struct body {}khai báo?
Jack

Lưu ý rằng việc sử dụng mảng có độ dài thay đổi thường có thể gây ra lỗi hoặc sự cố bí ẩn khi kích thước của mảng vượt quá kích thước ngăn xếp của chương trình trên hệ thống của bạn (điều này hoàn toàn nằm ngoài tầm kiểm soát của bạn với tư cách là một lập trình viên). Tốt hơn là sử dụng malloc () cho loại điều này.
adrian

Câu trả lời:


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

điều này hoạt động tốt. Nhân tiện, câu hỏi của bạn không rõ ràng lắm, vì vậy hãy khớp bố cục mã nguồn của bạn với phần trên.


Ngoài ra, tôi có một câu hỏi về vị trí giữa việc khai báo kiểu struct và sau đó thực sự tạo một phiên bản của nó - tôi có một cấu trúc khác, một cấu trúc mà tôi đã xác định nội dung bên dưới nơi tôi tạo phiên bản đầu tiên (chỉ một lần này, không phải là một mảng), vậy tại sao điều này không tạo ra một loạt lỗi lớn? Nó hoạt động tốt, khiến tôi nghĩ rằng nỗ lực của tôi trong việc tạo ra một mảng lẽ ra cũng có hiệu quả, nhưng lần này nó không thành công. Ngoài ra, cảm ơn bạn đã trả lời, nó đã hoạt động.
Amndeep7

1
Xin chào, .... 59 lượt thích? Tôi không thấy mảng cấu trúc, tôi chỉ thấy mảng biến từ bị đánh ...

12

Tôi nghĩ bạn cũng có thể viết nó theo cách đó. Tôi cũng đang là sinh viên nên tôi hiểu sự vất vả của các bạn. Một chút phản hồi muộn nhưng 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

Vì vậy, để kết hợp tất cả lại với nhau bằng cách sử dụng 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
Dòng malloc của bạn có nên có numStudents * sizeof (STUDENT) không?
Todd

@Todd Tốt hơn là không nên. sizeof *studentslà điều tương tự và sẽ không sai nếu STUDENT thay đổi.
trentcl

@trentcl Anh ấy đã cấp phát bộ nhớ cho số lượng con trỏ {numStudents}. Không phải cấu trúc, mà là con trỏ. Kích thước con trỏ thường là 4 byte, trong khi kích thước của cấu trúc là 20 byte. 20 byte là số chia hết cho 4, vì vậy không cần đệm và cấu trúc được lưu trữ trên mỗi byte thứ 20 từ địa chỉ bắt đầu. Nó chỉ hoạt động vì bạn chỉ cấp phát bộ nhớ cho một trường hợp cụ thể. Nếu không, các mallocs khác có thể ghi đè bộ nhớ cấu trúc của bạn vì nó không được cấp phát và bạn đã làm tràn bộ nhớ học sinh của mình.
John Smith

3
@JohnSmith Bạn nhầm rồi; đọc lại lần nữa. sizeof *studentslà kích thước của những gì được chỉ vào , tức là sizeof(STUDENT), không phải sizeof(STUDENT*). Bạn đang mắc sai lầm chính xác mà ptr = malloc(num * sizeof *ptr)thành ngữ được cho là phải đề phòng. Kiểm tra nó ở đây (lưu ý rằng máy chủ, giống như hầu hết các PC hiện đại, có con trỏ 8 byte nên kích thước là 8 và 32 thay vì 4 và 20).
trentcl

@trentcl Cảm ơn bạn đã giải thích. Tôi đã bối rối bởi cú pháp của con trỏ hội nghị trong phần khởi tạo của chính nó. Tôi muốn nói rằng nó hơi khó hiểu, nhưng chắc chắn là giải pháp nhỏ gọn hơn.
John Smith

8

di chuyển

struct body bodies[n];

sau này

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

Còn lại tất cả đều ổn.


6

Một cách khác để khởi tạo mảng cấu trúc là khởi tạo các thành viên mảng một cách rõ ràng. Cách tiếp cận này hữu ích và đơn giản nếu không có quá nhiều cấu trúc và thành viên mảng.

Sử dụng trình typedefxác định để tránh sử dụng lại structcâu lệnh mỗi khi bạn khai báo một biến cấu trúc:

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

Sau đó khai báo mảng cấu trúc của bạn. Việc khởi tạo mỗi phần tử đi cùng với khai bá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}};

Nhắc lại, đây là một giải pháp khá đơn giản và dễ hiểu nếu bạn không có quá nhiều phần tử mảng và các thành viên cấu trúc lớn và nếu bạn, như bạn đã nêu, không quan tâm đến cách tiếp cận năng động hơn. Cách tiếp cận này cũng có thể hữu ích nếu các thành viên cấu trúc được khởi tạo bằng các biến enum được đặt tên (và không chỉ là số như ví dụ trên), nhờ đó nó cung cấp cho người đọc mã cái nhìn tổng quan hơn về mục đích và chức năng của cấu trúc và các thành viên của nó trong một số các ứng dụng.


1
Thích cái này! Câu trả lời hay và đơn giản 👍
Ethan

1

Lỗi đó có nghĩa là trình biên dịch không thể tìm thấy định nghĩa về kiểu cấu trúc của bạn trước khi khai báo mảng cấu trúc, vì bạn đang nói rằng bạn có định nghĩa về cấu trúc trong tệp tiêu đề và lỗi nằm ở nbody.csau đó. bạn nên kiểm tra xem bạn có đang bao gồm đúng tệp tiêu đề hay không. Kiểm tra của bạn #includevà đảm bảo rằng định nghĩa của cấu trúc được thực hiện trước khi khai báo bất kỳ biến nào thuộc loại đó.


tôi nghi ngờ OP có nghĩa là tiêu đề dưới dạng tệp tiêu đề, như anh ấy đã viết, "dòng bên dưới nằm trên dòng bên trên" trước khai báo mảng struct nằm trong tệp nbody.c của anh ấy. Hãy đợi anh ta thức dậy và xóa bỏ nghi ngờ.
nims

@nims là đúng, theo tiêu đề, tôi có nghĩa là khu vực phía trên maincâu lệnh.
Amndeep 7

1

Giải pháp sử dụng con trỏ:

#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;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.