【问题标题】:Cant pass a correct Dynamic array of structs in c无法在 c 中传递正确的动态结构数组
【发布时间】:2016-06-28 07:08:46
【问题描述】:

我正在为学校做一个项目,但我无法将结构的动态数组传递给 c 中的另一个函数。该函数只是应该检查结构的一个元素,如果该数组的元素等于当前元素,则返回已经添加的元素。我也无法声明接受 calloc 数组的函数。任何帮助,将不胜感激!我整晚都在寻找解决方案。

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>
struct EDGETAG;
typedef struct
     {
      char c;
      bool isVisited;
      struct EDGETAG* p;
     } VERTEX;

typedef struct EDGE
    {
    VERTEX* v;
    struct EDGETAG* q;
    } EDGE;

int main(int argc, char* argv[])
   {
    int a;
    struct VERTEX *vert = (VERTEX*)calloc(100, sizeof (VERTEX*));
    char s;
    int count = 0;
    FILE* input = fopen(argv[1],"r");
    while((a = fgetc(input)) != EOF)
       {
        if(isspace(a)==0)
         {
         s = a;
         printf("%c ",s);
         determiner(s,vert,count);
         count++;            
         }
      }
return 0;
}

以及被调用的函数

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>


typedef struct VERTEX
    {
    char c;
    bool isVisited;
    struct EDGETAG* p;
    } VERTEX;


typedef struct EDGETAG
    {
   VERTEX* v;
    struct EDGETAG* q;
    } EDGE;


void determiner (char a, struct VERTEX *vert, int count)
    {
    int i;
    for(i=0;i < count; i++)
       {
       if(vert[i].c == a)
         {
         printf("%c allready added ",vert[i].c);
         return ;
         }
     else
       {
       VERTEX* new1 = (VERTEX*)malloc(sizeof(VERTEX));
       new1->c = a;
       vert[i] = *new1;
      }
    }
return ;

输入是: 甲乙 乙丙 前任 光盘 交流电 输出:A B B B allready added C E X C D A C

【问题讨论】:

  • I can't pass a dynamic array 有什么问题?
  • 你应该从determiner返回一个布尔值来指示元素是否被找到或新分配,只有在后一种情况下count才应该增加,否则你会访问未初始化的内存
  • 你想创建一个顶点链表吗?你确定它们应该在一个数组中吗?
  • 为什么标题中没有类型定义?他们应该是。干燥——不要重复自己。并且请学会以正统的方式缩进你的代码。它极大地提高了人们发现您的问题的机会。

标签: c arrays dynamic struct calloc


【解决方案1】:

你从不实际分配任何顶点。

struct VERTEX *vert = (VERTEX*)calloc(100, sizeof (VERTEX*));

注意到sizeof(VERTEX*)了吗?您已经为 100 个指向顶点的指针分配了足够的空间!

【讨论】:

  • 这不是为 100 个 vertices 分配空间(不是指向顶点的指针)吗?此外,它是 OP 代码中的 sizeof(VERTEX)
  • 不,它没有。注意sizeof (VERTEX*)?
  • 我以为这是一个错字,因为它在函数内部是sizeof(VERTEX)。此外,我希望指向指针数组的指针是struct VERTEX **?这样*vert 只需要几个int 指针并将它们转换为VERTEX
  • 这很可能是一个错字,但这并没有减少它的灾难性。
  • @Groo 我认为大卫在谈论main() 中的电话,这是有问题的。
【解决方案2】:

除了 David Schwartz 指出的问题,determiner 的缩进版本更清楚地显示了另一个问题:

void determiner(char a, struct VERTEX *vert, int count)
{
    int i;
    for (i = 0; i < count; i++)
    {
        if (vert[i].c == a)
        {
            printf("%c allready added ", vert[i].c);
            return;
        }
        else{
            VERTEX* new1 = (VERTEX*)malloc(sizeof(VERTEX));
            new1->c = a;
            vert[i] = *new1;
        }
    }
    return;
}

您当前的代码查看数组的第一个元素,看它是否与 a 匹配

  • 如果匹配,则返回(良好)
  • 如果不匹配,它将用新数据覆盖第一个元素(错误)

然后它循环并对第二个元素等做同样的事情。

要解决此问题,请将添加新元素的代码移到检查循环之外。如果检查循环结束,那么它还没有找到,所以可以添加。

现在,您有第二个问题 - 无论determiner 是否找到匹配项,您总是增加count。您应该更改determiner 以返回一个指示是否添加了项目的值,然后在main 中使用它来增加计数。

编辑:另请注意 - 如果您只是要将其内容复制到 vert[i],则不需要(或不想)使用 malloc 分配新节点。目前您正在泄漏内存 - 直接更新 vert[i].c 更容易。

【讨论】:

    【解决方案3】:

    你在第一个文件中调用

    typedef struct
    {
      char c;
      bool isVisited;
      struct EDGETAG* p;
    } VERTEX;
    

    后来,你有

    struct VERTEX *vert = ...
    

    struct VERTEX 不是第一个文件中的类型。 VERTEX 被定义为一种类型。您应该将结构类型更改为

    typedef struct VERTEX // note the VERTEX here
    {
      char c;
      bool isVisited;
      struct EDGETAG* p;
    } VERTEX;    
    

    这已经在第二个文件中完成了。

    作为一般样式指南,您应该将 VERTEXEDGE 的结构声明包含在单独的头文件中,并将其包含在您的 .c 文件中。

    【讨论】:

      【解决方案4】:

      你的代码有很多问题,但我会在上面的答案中加上我的 2 美分,因为我相信它可能会有所帮助:

      1. 正如@David 已经注意到的,您正在实例化一个指针数组:

        // this should be a struct VERTEX**, if you want to
        // have a "pointer to the first pointer to VERTEX"
        struct VERTEX *vert = (VERTEX*)calloc(100, sizeof (VERTEX*));
        

        但你(很可能)想要实例化一个 VERTEX 数组:

        // you probably want space for 100 x sizeof(VERTEX),
        // so that vert is simply a "pointer to the first VERTEX".
        // ALSO: don't cast the result of calloc/malloc 
        struct VERTEX *vert = calloc(100, sizeof(VERTEX));
        

        vert 不是指向分配数组的第一个 VERTEX 元素的指针。您不需要分配单独的 VERTEX 元素,并且 vert 在迭代时永远不会是 null,因此您需要自己跟踪 count

      2. count 不应在 main 正文内递增,因为您不知道是否实际添加了元素。

      3. 您的determiner 函数不正确;您似乎在 each 循环迭代中添加了一个新实例。当它实际添加元素时,我也会从函数返回计数值:

        void determiner (char a, struct VERTEX *vert, int *count)
        {
            for(int i = 0; i < count; i++)
            {
                if (vert[i].c == a)
                {
                    printf("%c already added ",vert[i].c);
        
                    // no need to increase count
                    return;
                }
            }
        
            // if we are here, we didn't find the element,
            // so this is where you actually initialize it
            // and increase count
        
            vert[count]->c = a;
            count++;
        }
        

        调用函数时,将指针传递给count,让函数增加:

        determiner(s, vert, &count);
        
      4. 在处理图形时,通常使用链表,即让节点指向其他节点。在这种情况下,您无需分配数组,而是分别为每个节点使用malloc,然后向前跳转,直到到达null。尝试在谷歌上搜索有关如何在 C 中实现图形的示例,以更好地了解正确的方法。

      【讨论】:

        猜你喜欢
        • 2017-09-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-14
        • 1970-01-01
        • 1970-01-01
        • 2011-05-06
        相关资源
        最近更新 更多