【问题标题】:How to access a double pointer structure in another structure如何访问另一个结构中的双指针结构
【发布时间】:2020-09-10 19:54:42
【问题描述】:

我在访问我的结构中的双指针结构时遇到问题。

typedef struct monster
{
    char *name;
    char *element;
    int population;
} monster;

typedef struct region
{
    char *name;
    int nmonsters;
    int total_population;
    monster **monsters;
} region;


region **
readRegion (FILE * infile, int *regionCount)
{
    
    region **temp;
    char garbage[50];
    char garbage2[50];
    
    char rName[50];
    int monsterNum;
    
    fscanf (infile, "%d %s", regionCount, garbage);
    temp = malloc (*regionCount * sizeof (region *));
    
    for (int i = 0; i < *regionCount; i++)
    {
        fscanf (infile, "%s%d%s", rName, &monsterNum, garbage2);
        temp[i] = createRegion (inFile, rName, monsterNum);
    }
    return temp;
}

region *
createRegion (FILE * inFile, char *rName, int nMonsters)
{
    region *r = malloc (sizeof (region));
    char rMonster[50];
    int rLength;
    r->name = malloc ((strlen (rName) + 1) * sizeof (char));
    strcpy (r->name, rName);
    r->nmonsters = nMonsters;
    
    for (int i = 0; i < nMonsters; i++)
    {
        r->monsters.name = (nMonsters * sizeof (r->monsters.name));
        fscanf (in, "%s", rMonster);
        
        r->monsters.name = malloc ((strlen (rMonster) + 1) * sizeof (char));
        strcpy (r->monsters.name, rMonster);
    }
    return r;
}

希望我的代码是可读的,您可以从中了解我试图对我的区域结构中的 monster** monsters 指针做什么。任何关于如何在结构中访问和使用双结构指针的解释都会有所帮助。

【问题讨论】:

  • ⟼通过采用indentation style 并一致地应用它,这段代码可以受益匪浅。缩进传达了结构和意图,使我们更容易理解您的代码,而无需花费大量时间来破译它,而且它还可以使错误更加明显,因为它们在视觉上很突出。
  • 这段代码提出了很多问题,但首先:为什么monster **monsters?你需要一个二维数组吗?为什么region** temp?你在这里使用双指针的方式对我来说没有任何意义。事实上,这里的指针太多了。为什么int *regionCount 是一个指针?我的建议:停止使用这么多无意义的指针
  • 这些结构被分配给我们使用,所以你不能以任何方式编辑它们的形状或形式。我们需要读入指定给某个区域的怪物名称并将它们保存到该区域名称。
  • 哦,如果这是由一位老师教授的学术代码,他对 C 的含义有自己的奇怪解释,那说明了很多。这些结构不是 C 通常是如何完成的,也不是它*应该*如何完成的。希望你能在这门课程中幸免于难。
  • 是的,注册晚了,得到了 5 分教授。祝我好运

标签: c struct


【解决方案1】:

我已尝试清理并重新解释您的 createRegion 以使其更像传统 C:

region* createRegion(FILE * inFile, char *rName, int nMonsters) {
  region *r = malloc(sizeof(region));
  char buffer[1024];

  r->name = strdup(rName);

  r->nmonsters = nMonsters;

  r->monsters = calloc(nMonsters, sizeof(monster*));

  for (int i=0; i < nMonsters; i++) {
    // Allocate a monster
    monster *m = malloc(sizeof(monster));

    fscanf(in,"%s", buffer);

    m->name = strdup(buffer);
    m->element = NULL; // TBD?
    m->population = 1; // TBD?

    // Put this monster in the monsters pointer array
    r->monsters[i] = m;
  }
  return r;
}

这里的关键是你必须分配怪物。这里是单独完成的,但你也可以分配为一个slab:

region* createRegion(FILE * inFile, char *rName, int nMonsters) {
  region *r = malloc(sizeof(region));
  char buffer[1024];

  r->name = strdup(rName);

  r->nmonsters = nMonsters;

  // Make a single allocation, which is usually what's returned from
  // C functions that allocate N of something
  monsters* m = calloc(nMonsters, sizeof(monster));

  // Normally you'd see a definition like m in the region struct, but
  // that's not the case here because reasons.

  r->monsters = calloc(nMonsters, sizeof(monster*));

  for (int i=0; i < nMonsters; i++) {
    fscanf(in,"%s", buffer);

    m[i].name = strdup(buffer);
    m[i].element = NULL; // TBD?
    m[i].population = 1; // TBD?

    // Put this monster in the monsters pointer array
    r->monsters[i] = &m[i];
  }

  return r;
}

请注意,我已经通过简单的 strdup 调用切换了基于 strlen 的非常古怪的代码。看到sizeof(char) 被使用也很奇怪,因为在您可能与之交互的任何计算机上,无论是嵌入式微控制器还是花哨的大型机,为 1。

【讨论】:

  • 我认为在第二版中应该是r-&gt;monsters[i] = &amp;m[i];
  • @Bodo 很好,谢谢。没有去编译这个。
【解决方案2】:

既然你问的是访问结构内的双指针,我认为你的问题主要是关于这个函数:

region *
createRegion (FILE * inFile, char *rName, int nMonsters)
{
    region *r = malloc (sizeof (region));
    char rMonster[50];
    int rLength;
    r->name = malloc ((strlen (rName) + 1) * sizeof (char));
    strcpy (r->name, rName);
    r->nmonsters = nMonsters;

[A点]

到目前为止,一切都很好,但在这里你开始偏离轨道。

    for (int i = 0; i < nMonsters; i++)
    {
        r->monsters.name = (nMonsters * sizeof (r->monsters.name));

等一下。 r-&gt;monsters 的类型为 monster **,但您正试图访问它,就像它是 monster 一样。此外,r-&gt;monsters 从未分配过任何值,因此您可以安全地使用它确实很少。

我认为这个想法一定是让r-&gt;monsters指向一个动态分配的monster *数组,并且循环分配和初始化怪物,并将指向它们的指针写入数组。

然后,您需要为数组分配空间,但您只需要或只想分配一次数组。在循环之前,在上面的 A 点执行此操作,如下所示:

      r->monsters = malloc(nMonsters * sizeof(*r->monsters));  // a monster **

然后,在循环内部,您需要为一个怪物分配空间,并将指向该怪物的指针分配给您的数组:*

    r->monsters[i] = malloc(sizeof(*r->monsters[i]));  // a monster *

然后,要访问实际的 monster 对象,您需要取消引用并使用直接成员选择运算符 (.) ...

    (*r->monsters[i]).name = /* ... */;

...或使用间接成员选择运算符 (-&gt;) ...

    r->monsters[i]->name = /* ... */;

。两者是等价的,但大多数 C 程序员似乎更喜欢后一种风格。

然而,在这一点上,我注意到在循环体中,您似乎试图对怪物的name 成员进行两个单独的分配。这没有意义,第一次尝试肯定没有意义,因为您似乎试图为指针分配一个数字。

        fscanf (in, "%s", rMonster);
        
        r->monsters.name = malloc ((strlen (rMonster) + 1) * sizeof (char));
        strcpy (r->monsters.name, rMonster);

然后,使用上述方法,并利用 sizeof(char) 根据定义为 1 的事实,您想要的似乎是

        // ...

        r->monsters[i]->name = malloc(strlen(rMonster) + 1);
        strcpy (r->monsters[i]->name, rMonster);

最后,

    }
    return r;
}

请注意,对应于类型monster ** 中的两个间接级别,通过r-&gt;members 对单个怪物属性的每次访问都需要两个级别的引用。在上面的表达式中,一个由索引运算符[] 提供,另一个由间接成员访问运算符-&gt; 提供。


* 或者您可以一次性为所有怪物分配空间,在循环之前和循环内部只需初始化它们和指向它们的指针数组。使用monster ** 建议使用单独的分配方法,但选择哪种方法在一定程度上取决于如何使用这些方法。这两个选项基本上可以互换,但并不完全等同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-16
    • 1970-01-01
    • 2014-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-01
    相关资源
    最近更新 更多