您如何在C中制作结构数组?


100

我正在尝试制作一系列结构,其中每个结构都代表一个天体。

我对结构没有太多的经验,这就是为什么我决定尝试使用它们而不是一堆数组的原因。但是,我不断遇到许多不同的错误。我试图实现在各种线程和StackOverflow上看到的技术(例如CC中的结构体数组-初始化结构体数组)),但是并不是所有的人都是适用的。

对于那些到目前为止已经读过的人的更多信息:我不需要任何这些都是动态的,我事先知道/定义了所有内容的大小。我还需要将其作为一个全局数组,因为我正在使用几种定义了自变量的方法(即GLUT方法)来访问它。

这就是我在标头中定义结构的方式:

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

在定义结构的内部之前,我还有一个要定义的其他全局变量的列表,其中一个是该结构的数组(基本上,如果我不太清楚,请看下面的代码高于上述内容):

struct body bodies[n];

请注意,n这是我合理定义的内容(即#define n 1)。

我以几种不同的方法使用此数组,但是最简单,最不占用空间的是我的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;
 }

我目前面临的错误是 nbody.c:32:13: error: array type has incomplete element type在第32行中,我正在构造结构的数组。

最后一个澄清,标题是指上面的空格,int main(void)但在同一*.c文件中。


好吧,对我来说很好。您不是在声明struct body bodies[n];之前struct body {}声明吗?
2012年

请注意,当数组的大小超过系统上程序的堆栈大小时(使用程序员完全无法控制),使用可变长度数组通常会导致神秘的错误或崩溃。最好将malloc()用于此类事情。
阿德里安

Answers:


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

这很好。顺便说一句,您的问题不是很清楚,因此将源代码的布局与上述内容匹配。


另外,我对结构类型的声明与实际创建它的实例之间的位置有疑问-我有一个不同的结构,我在下面定义的内容中首先创建了它的实例(只是一个)这次,不是数组),那为什么不产生大量错误呢?它工作得很好,这使我认为我制作数组的尝试也应该起作用,但是这次没有成功。另外,感谢您的回答,它奏效了。
Amndeep7 2012年

1
嗨,.... 59喜欢?我没看到结构数组,我只看到被敲击的变量数组...

12

我想您也可以这样写。我也是学生,所以我了解您的挣扎。有点迟到但还可以。

#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

因此,使用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
您的malloc行是否应具有numStudents * sizeof(STUDENT)?
2014年

@Todd最好不要。sizeof *students是一回事,如果学生碰巧发生变化,那不会错。
trentcl

@trentcl他已为{numStudents}个指针分配了内存。不是结构,而是指针。指针的大小通常为4个字节,而结构的大小为20个字节。20个字节可被4整除,因此不需要填充,并且结构从起始地址开始每20个字节存储一次。它仅适用于您为一种特定情况分配内存的情况。否则,其他malloc可能会覆盖结构的内存,因为未分配它,并且您的学生内存已溢出。
约翰·史密斯,

3
@JohnSmith你误会了;再读一遍。sizeof *students所指对象的大小,即sizeof(STUDENT)不是sizeof(STUDENT*)。您正在犯成本该避免的确切错误ptr = malloc(num * sizeof *ptr)在此处进行检查(请注意,服务器像大多数现代PC一样,具有8个字节的指针,因此大小分别为8和32,而不是4和20)。
trentcl

@trentcl谢谢您的解释。我对在自己的初始化中取消引用指针的语法感到困惑。我会说这有点令人困惑,但绝对是更紧凑的解决方案。
约翰·史密斯,

8

移动

struct body bodies[n];

到之后

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

休息都很好。


6

初始化结构数组的另一种方法是显式初始化数组成员。如果没有太多的struct和array成员,则此方法既有用又简单。

使用说明typedef符来避免在struct每次声明结构变量时重复使用该语句:

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

然后声明您的结构数组。每个元素的初始化都伴随着声明:

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

重复一遍,如果您没有太多的数组元素和大型的struct成员,并且您如前所述对动态的方法不感兴趣,那么这是一个非常简单直接的解决方案。如果使用命名的枚举变量(而不是像上面的示例那样的数字)初始化struct成员,则此方法也很有用,从而使代码阅读器可以更好地了解结构及其成员在某些情况下的用途和功能。应用程序。


1
喜欢这个!尼斯和简单的答案👍
伊桑

1

该错误意味着,编译器无法找到你的结构类型定义结构数组的声明之前,因为你说你必须在头文件中的结构体的定义和误差在nbody.c随后您应该检查是否正确包含了头文件。#include在声明该类型的任何变量之前,请检查并确保已完成结构的定义。


我怀疑OP是将标头表示为标头文件,正如他所写的那样,“下一行在上面的内容上方”在其nbody.c文件中的struct数组声明之前。让我们等他醒来,消除疑惑。
尼姆,2012年

@nims是正确的,标题是指main语句上方的区域。
Amndeep7 2012年

1

使用指针的解决方案:

#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;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.