【问题标题】:How can I have an array of structure inside a structure?如何在结构中拥有结构数组?
【发布时间】:2016-06-24 18:59:37
【问题描述】:

假设我有一个名为“Film”的结构和一个名为“Actor”的结构

typedef struct actor{
    char *Name;
    char *Surname;
    int year_birth;
    Title_Film * Film_recited;
}Actor;


typedef struct film{
    Title_Film * Title; //pointer to structure 
    int year;
    type genre; //enum
    director * director_Film; //pointer to structure
    //array of "Actor" structure
}Film;

我想在结构“电影”中插入结构“演员”的数组,因为在电影中有很多演员。我能做到吗?怎么做?

【问题讨论】:

  • 只需交换定义,并在struct film 中定义一个数组成员。
  • 您知道数组通常具有固定大小,对吧?那么是什么阻止了你?
  • 我对这两个结构中的 Title_Film * 成员有点担心。在struct film 的情况下,我可以看到它可能应该是电影标题,但在struct actor 的情况下,它可能是一个电影数组,其中演员出现。然而声明是相同的,没有发布。
  • 是的,你是对的,'演员'中的'电影标题'也应该是一个数组。我的错。这是我第一次遇到结构数组,所以我有点困惑,但现在我明白了。
  • 声明中没有数组。指针不是数组!

标签: c arrays structure


【解决方案1】:

首先,你需要在定义电影之前定义一个演员,否则编译器将不知道如何处理它。

在电影结构中,只需声明指针,如下所示。

typedef struct actor{
    char *Name;
    char *Surname;
    int year_birth;
    Title_Film * Film_recited;
}Actor;


typedef struct film{
    Title_Film * Title; //pointer to structure 
    int year;
    type genre; //enum
    director * director_Film; //pointer to structure
    //array of "Actor" structure
    Actor* cast;
}Film;

一旦你有了你的指针,你就需要弄清楚你将拥有多少个演员。如果您有特定的实例,您可以提示输入或将其硬编码到您的程序中。无论你的船漂浮什么。

既然您知道您的演员表有多大(假设您将其作为整数保存在变量 castSize 中,请分配内存:

movie.cast = (Actor*)malloc(sizeof(Actor)*castSize);

您现在可以像访问数组一样访问演员列表,这将使您能够访问他们的属性。例如:

movie.cast[0]->Name = "Scarlet";
movie.cast[0]->Surname = "Johansson";
movie.cast[0].year_birth = 1984;

【讨论】:

    【解决方案2】:

    假设您事先不知道需要多少个数组元素,您可以这样做:

    typedef struct film{
        Title_Film * Title; //pointer to structure 
        int year;
        type genre; //enum
        director * director_Film; //pointer to structure
        Actor *actor_list;
    }Film;
    

    这里,actor_list 是一个指针,它可以指向动态分配的Actor 对象数组。您可以按如下方式按时间分配空间:

    Film myfilm;
    ...
    myfilm.actor_list = malloc(num_of_actors * sizeof(Actor));
    

    另一方面,如果您确实知道在编译时需要多少,则只需直接声明数组成员:

    #define ACTOR_LEN 20
    
    typedef struct film{
        Title_Film * Title; //pointer to structure 
        int year;
        type genre; //enum
        director * director_Film; //pointer to structure
        Actor actor_list[ACTOR_LEN];
    }Film;
    

    【讨论】:

    • 你声称actor_list 是一个数组?
    • Assuming you know know how many you need ahead of time...问。为什么我需要知道?答:数组。问:不然呢? A:指针和动态分配。 (请添加此
    【解决方案3】:

    您可以将演员数组插入到影片结构中

    #define ACTORS_MAX_N 10
    struct film {
        /* ... */
        struct actor arr[ACTORS_MAX_N];
    };
    

    或者您可以在该结构中保留一个指向包含演员的内存的指针:

    struct film {
        /* ... */
        struct actor *arr;
    };
    

    如您所见,在第一种情况下(内置数组),您必须提前知道该数组的大小。在第二种情况下(指针),您可以获得动态数组分配/释放/重新分配的灵活性,因此同一个 film 对象可以引用不同大小的数组。


    在 C-99 标准中也有可能存储灵活数组,即动态分配的数组,因此它可以有不同的大小:

    struct film {
        /* ... */
        size_t actors_n;
        struct actor arr[]; /* flexible array MUST be last member in struct */
    };
    

    sizeof 操作符会返回灵活数组的偏移量,所以可以这样分配:

    struct film *allocate_film(size_t actors_n) {
        struct film *film = malloc(sizeof *film + actors_n * sizeof(film->arr[0]));
        if (film == NULL) {
            return NULL;
        }
        film->actors_n = actors_n;
        for (size_t i = 0; i < actors_n; ++i) {
            film->arr[i].Name = /* ...  */
            /* ... allocate actor */
        }
        return film;
    }
    

    【讨论】:

      【解决方案4】:

      对于任何类型的T,您可以通过以下两种方式之一获得T 数组:

      • 作为数组对象:T arr[N];
      • 作为指向T 的指针,您可以为其动态分配内存:T *arr = malloc( sizeof *arr * N );

      因此,在您的 Film 类型中,您可以执行以下任一操作:

      typedef struct film{
          Title_Film * Title; //pointer to structure 
          int year;
          type genre; //enum
          director * director_Film; //pointer to structure
          Actor cast[N]; // where N is known at compile time
      }Film;
      

      typedef struct film{
          Title_Film * Title; //pointer to structure 
          int year;
          type genre; //enum
          director * director_Film; //pointer to structure
          Actor *cast;
      }Film;
      

      在第一种情况下,您只需要创建Film 实例即可同时创建cast 数组:

      Film jaws;
      jaws.cast[0].name = strdup( "Roy" );         // assumes strdup is available
      jaws.cast[0].surname = strdup( "Scheider" ); // otherwise you'll have to use
      jaws.cast[1].name = strdup( "Richard" );     // a combination of malloc and
      jaws.cast[1].surname = strdup( "Dreyfuss" ); // strcpy
      

      等等

      在第二种情况下,需要额外的步骤来为cast 数组分配内存:

      Film jaws2;
      jaws2.cast = malloc( sizeof *jaws2.cast * cast_size );
      
      jaws2.cast[0].name = strdup( "Roy" );
      jaws2.cast[0].surname = strdup( "Scheider" );
      

      等等。

      在这两种情况下,完成后,您都需要 free 每个 cast[i].namecast[i].surname。在第二种情况下,您还需要free cast 成员本身(每个malloc/calloc 应该在某处有一个对应的free)。

      由于薄膜之间的流延尺寸不同,第二种方法更可取,因为它可以根据每个薄膜的需要调整尺寸。此外,如果您以后需要扩展它,它还允许您使用realloc resize 数组。一个更好的解决方案是使用可以根据需要增长和缩小的链接列表或类似容器,但这是一个bit 更多的工作。

      不清楚为什么需要Title_Film 类型中的Actors 成员;由于演员与电影相关联,因此标题已经存在。

      说实话,建模多对多关系(电影有多个演员,演员出现在多部电影中)的正确方法是Film包含@数组987654345@ 或反之亦然;相反,您应该有单独的 FilmActor 数组(或列表,或树,等等),并创建一个关联类型的 附加 数组(或列表,或树,等等)个人Actor 条目到Film 条目:

      struct assoc {
         Actor *actor;
         Film *film;
      } ActorFilmAssoc;
      
      Actor *findActor( Actor *list, const char *surname, const char *name ) { ... }
      Film *findFilm( Film *list, const char *title ) { ... }
      
      Actor *actors = calloc( num_actors, sizeof *actors );
      Film  *films  = calloc( num_films, sizeof *films );
      
      /**
       * Add entries to actors and films
       */
      
      ActorFilmAssoc *map = calloc( someSize, sizeof *map );
      size_t entry = 0;
      ...
      map[++entry].actor = findActor( actors, "Scheider", "Roy" );
      map[entry].film = findFilm( films, "Jaws" );
      map[++entry].actor = findActor( actors, "Scheider", "Roy" );
      map[entry].film = findFilm( films, "All That Jazz" );
      

      我们不是在每部电影中为 Roy Scheider 存储多个 Actor 条目,而是将单个条目存储在 actors 数组中,并且在 map 中只有多个指向它的指针。

      这是一个非常简单的例子;您想要为您的地图使用比线性数组更复杂的东西。但它应该说明这个概念。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-06-08
        • 2017-01-28
        • 1970-01-01
        • 1970-01-01
        • 2015-03-29
        • 1970-01-01
        • 2012-05-02
        相关资源
        最近更新 更多