【问题标题】:Create a graph with an adjacency matrix in C在 C 中创建具有邻接矩阵的图
【发布时间】:2018-11-11 03:15:16
【问题描述】:

我正在实现一个基于 C 中的邻接矩阵的图形程序。 但是我在初始化矩阵(分配零值)时遇到了分段错误。 我不确定我在访问双指针时是​​否犯了任何错误。

谁能帮我解决这个问题?

代码如下:

struct Graph {
    int V;
    int E;
    int **adj;
};


struct Graph *addelements() {
    int i,j,a,u,v;  

    struct Graph *G= (struct Graph*)malloc(sizeof(struct Graph*));
    printf("Enter the number of vertices and edges : ");
    scanf("%d %d", &G->V,&G->E);;
    printf("%d, %d\n",G->V ,G->E);
    //G->adj = (int **)malloc(sizeof(int **)*(G->V * G->E));
    G->adj = malloc(sizeof(G->V * G->E));

    //Initialization of vertices

    for(i=0;i<=G->V;i++) {
        for(j=0;i<=G->V;j++) {
            G->adj[i][j]=0;
        }
    }


    //Reading the edges;
    for(i=0;i<G->E;i++) {
        printf("Enter the source and destination : ");  
        scanf("%d %d\n", &u,&v);       
        G->adj[u][v]=1;    
        G->adj[v][u]=1;
    }

    //printing the matrix

    for(i=0;i< G->V;i++) {
        for(j=0;i< G->V;j++) {
            printf("%d", G->adj[i][j]);4
        }
    }

   return G;
}


int main() {  
    struct Graph *a= (struct Graph*)malloc(sizeof(struct Graph*)); 
    a =  addelements();  
} 

输出:

输入顶点数和边数:4 5

分段错误(核心转储)

【问题讨论】:

  • 欢迎来到 Stack Overflow!请edit你的问题告诉我们你做了什么样的调试。我希望您已经在 Valgrind 或类似的检查器中运行了您的minimal reproducible example,并使用诸如 GDB 之类的调试器进行了调查。确保您也启用了全套编译器警告。这些工具告诉了你什么,它们缺少什么信息?并阅读 Eric Lippert 的 How to debug small programs
  • 顺便说一句,你知道sizeof (G-&gt;V * G-&gt;E)sizeof (int) 是一样的吗?也许您想改为malloc(sizeof *G-&gt;adj * G-&gt;V * G-&gt;E);

标签: c struct segmentation-fault malloc


【解决方案1】:

mallocing 空间只是一个指针。改为使用:

malloc(sizeof(struct Graph));

【讨论】:

    【解决方案2】:

    正如你所说,你的错误在那里

    G->adj = malloc(sizeof(G->V * G->E));
    
    //Initialization of vertices
    
    for(i=0;i<=G->V;i++)
    {
      for(j=0;j<=G->V;j++) 
      {
        G->adj[i][j]=0;
      }
    }
    
    • 你正在写adj[V][V],在那里你分配了sizeof(G-&gt;V * G-&gt;E)的大小,这将是sizeof(int)(一个整数),即使你想要adj[V][E]

    • 1234563 @

    使用malloc( G-&gt;V * G-&gt;V * sizeof(int) ) 分配并使用adj[i*V+j] 访问/写入

    由于您期望代码的行为与它真正理解您的方式相比,您的逻辑中有很多错误。使用调试器了解故障发生的位置并检查相关变量可能很有用。

    编辑:

    也称为other answers 提及:

    您正在为 G 分配一个较小的大小,因为 malloc(sizeof(struct Graph*)) 将等同于 malloc(sizeof(void*))(分配一个指针的大小),您应该在其中 malloc(sizeof(struct Graph))

    第二次编辑:

    注意到您的j 循环中有一个错字for(j=0;i&lt;=G-&gt;V;j++) 应该是for(j=0;j&lt;=G-&gt;V;j++)

    【讨论】:

    • 还是一样...出现分段错误。
    • 如其他评论中所述,您在为指针分配空间的malloc(sizeof(struct Graph*)) 也存在问题,请改用malloc(sizeof(struct Graph))。 GDB 应该知道段错误发生在哪里
    • 键入“apropos word”以搜索与“word”相关的命令...从图形中读取符号...(未找到调试符号)...完成。 (gdb) r 启动程序:/home/datastructures/graph 输入顶点和边数:4 5 4, 5 程序接收信号 SIGSEGV,分段错误。 0x0000000000400702 in addelements () (gdb) (gdb) bt #0 0x0000000000400702 in addelements () #1 0x0000000000400867 in main () (gdb) f 0 #0 0x0000000000400702 in addelements () (gdb) 这是显示的内容>
    • 不要忘记使用-g 标志进行编译,这会神奇地使使用 gdb 进行调试更加有用
    • 糟糕,我完全忘记了……程序收到信号 SIGSEGV,分段错误。 0x0000000000400748 in addelements () at graph.c:44 44 G->adj[i][j]=0;它显示在这一行
    【解决方案3】:

    我认为你需要修改

    struct Graph *G= (struct Graph*)malloc(sizeof(struct Graph*));
    

    struct Graph *G= malloc(sizeof(struct Graph));
    

    因为您需要分配空间来存储结构变量而不是指针。

    而且您还没有为G-&gt;adj 正确分配空间。

    试试

    G->adj = malloc(sizeof(int **));
    for(int i=0; i<G->V; ++i)
    {
        G->adj[i]=malloc(sizeof(int)*G->V);
    }
    

    并将你的循环修改为

    for(i=0;i<G->V;i++)
    {
       for(j=0;j<G->V;j++) 
       {
          G->adj[i][j]=0;
       }
    }
    

    即,将&lt;= 更改为&lt; 以防止访问超出数组范围。

    在阅读边缘时,不要这样做

    scanf("%d %d\n", &u,&v);       
    

    末尾有换行符。见this

    另外,您需要检查uv 的输入值是否在限制范围内,如

    for(i=0;i<G->E;i++)  
    {
        printf("Enter the source and destination : ");  
        scanf("%d %d", &u,&v);       
        if(u<G->V && v<G->V)
        {
            G->adj[u][v]=1;    
            G->adj[v][u]=1;
        }
        else
        {
            printf("\ninvalid value. Try again.");
            i--;
        }
    }
    

    并且您不需要为main() 中的struct 指针分配空间,因为您已经为将在addelements() 函数中存储在该指针中的值分配了内存。否则会导致内存泄漏。

    所以,在main(),做

    struct Graph *a= addelements();
    

    请注意,如果分配内存失败,malloc() 将返回 NULL。您需要检查malloc() 调用是否也失败。

    而且你不需要在 C 中转换 malloc() 的返回值。阅读 this

    【讨论】:

    • 我做到了...但它仍然显示分段错误...它与//Initialization of vertices 部分的问题...
    • @Ankita 我已经编辑了我的帖子。看看它是否适合你。
    • @Ankita 还是分段错误?
    • 我使用过 gdb ...它显示在这一特定行中...程序接收到信号 SIGSEGV,分段错误。 0x0000000000400748 in addelements () at graph.c:44 44 G->adj[i][j]=0;
    • 我不确定访问它的正确方法是什么
    猜你喜欢
    • 1970-01-01
    • 2023-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多