具有空指针的图形的奇怪输出

Strange output of a Graph with void pointers

我正在尝试构建一个可以处理具有邻接列表或矩阵的图的程序,为此老师教我们将邻接声明为 void *,以便将其转换为列表或矩阵。

使用下面的代码我得到了这个输出:

如您所见,B 节点中存在一些奇怪的东西。

如果我尝试使用 CodeBlocks 进行调试,调试器会在 appendNodeList at if (L->target != target) {..

中给出 Segmentation Fault

我认为 initGraphList 中的动态分配有问题,但我不知道如何解决它。

您认为这里的问题是什么?是分配吗?如果是,我该如何解决? 在此先感谢您的帮助!

代码:

main.c

#include <stdio.h>
#include <stdlib.h>
#include "Graph.h"

int main(int argc, const char * argv[]) {
    Graph G = NULL;
    G = initGraphList(3);
    addEdgeList(G, 0, 1, 1);
    addEdgeList(G, 0, 2, 2);
    addEdgeList(G, 1, 0, 3);
    addEdgeList(G, 1, 2, 4);
    addEdgeList(G, 2, 0, 5);
    addEdgeList(G, 2, 1, 6);
    printGraphList(G);
    return 0;
}

Graph.h

#include "List.h"

struct TGraph {
    void **adj;
    int nodes_count;
};

typedef struct TGraph *Graph;

typedef struct AdjList{
    List *nodes;
}AdjList;

Graph initGraphList(int);
void printGraphList(Graph G);
void addEdgeList(Graph G, int source, int target, float peso);

Graph.c

#include <stdio.h>
#include <stdlib.h>
#include "Graph.h"

Graph initGraphList(int nodes_count){
    Graph G = (Graph)malloc(sizeof(struct TGraph));
    G->adj = malloc(sizeof(AdjList));
    G->nodes_count = nodes_count;
    ((AdjList *)(G->adj))->nodes = malloc(nodes_count * sizeof(List));
    return G;
}

void printGraphList(Graph G) {
    if (G != NULL) {
        int i;
        for(i = 0; i < G->nodes_count; i++) {
            printf("%c -> ", i + 'A');  //I use this in order to print out the nodes as A,B,C,.. instead of 0,1,2,...
            printList(((AdjList *)(G->adj))->nodes[i]);
            puts("\n");
        }
    }
}

void addEdgeList(Graph G, int source, int target, float peso){
    if(G != NULL){
        if(source != target){
            if(source < G->nodes_count){
                if(target < G->nodes_count)
                    ((AdjList*)(G->adj))->nodes[source]= appendNodeList(((AdjList*)(G->adj))->nodes[source], target, peso);
                else
                    fprintf(stderr, "Il nodo %d non e' compreso nel grafo\n", target);
            }else
                fprintf(stderr, "Il nodo %d non e' compreso nel grafo\n", source);
        }else
            fprintf(stderr, "Non e' possibile inserire un arco che punta allo stesso nodo\n");
    }else
        fprintf(stderr, "Grafo invalido\n");
}

List.h

struct TList {
    char target;
    float peso;
    struct TList* next;
};

List initNodeList(int info, float peso);
List appendNodeList(List L, int target, float peso);
void printList(List L);

List.c

#include <stdio.h>
#include <stdlib.h>
#include "List.h"

List initNodeList(int info, float peso) {
    List L = malloc(sizeof(struct TList));
    L->target = info;
    L->peso = peso;
    L->next = NULL;
    return L;
}

List appendNodeList(List L, int target, float peso) {
    if (L != NULL) {
        if (L->target != target) {
            L->next = appendNodeList(L->next, target, peso);
        }
    } else {
        L = initNodeList(target, peso);
    }
    return L;
}

void printList(List L) {
    if (L != NULL) {
        printf(" %c(%f), ", L->target + 'A', L->peso);
        printList(L->next);
    }
}

首先你忘了用 NULL 初始化你的指针数组。这是我在您的代码中发现的主要错误。

如果你使任何指针 typedef 避免误导名称(例如添加后缀 'Ptr' 到 typename)

typedef struct TList {
    char target;
    float peso;
    struct TList* next;
} *TListPtr;

typedef struct TAdjList{
    TListPtr *nodes;
} *TAdjListPtr;

不需要void **adjTAdjListPtr *adj为所欲为

typedef struct TGraph {
    TAdjListPtr adj;
    int nodes_count;
} *TGraphPtr;

TListPtr initNodeList(int info, float peso) {
    TListPtr L = malloc(sizeof(struct TList));
    L->target = info;
    L->peso = peso;
    L->next = NULL;
    return L;
}

TListPtr appendNodeList(TListPtr L, int target, float peso) {
    if (L != NULL) {
        if (L->target != target) {
            L->next = appendNodeList(L->next, target, peso);
        }
    } else {
        L = initNodeList(target, peso);
    }
    return L;
}

void printList(TListPtr L) {
    if (L != NULL) {
        printf(" %c(%f), ", L->target + 'A', L->peso);
        printList(L->next);
    }
}

你必须用 NULL 初始化你的指针数组。为此使用 memset

TGraphPtr initGraphList(int nodes_count){
    TGraphPtr G = malloc(sizeof(struct TGraph));
    G->adj = malloc(sizeof(TAdjList));
    G->nodes_count = nodes_count;
    G->adj->nodes = (TListPtr*)malloc(nodes_count * sizeof(TListPtr));
    memset( G->adj->nodes, 0, nodes_count * sizeof( TListPtr ) );
    return G;
}

void printGraphList(TGraphPtr G) {
    if (G != NULL) {
        int i;
        for(i = 0; i < G->nodes_count; i++) {
            printf("%c -> ", i + 'A');  //I use this in order to print out the nodes as A,B,C,.. instead of 0,1,2,...
            printList(G->adj->nodes[i] );
            puts("\n");
        }
    }
}

void addEdgeList(TGraphPtr G, int source, int target, float peso){
    if(G != NULL){
        if(source != target){
            if(source < G->nodes_count){
                if(target < G->nodes_count)
                    G->adj->nodes[source] = appendNodeList(G->adj->nodes[source], target, peso);
                else
                    fprintf(stderr, "Il nodo %d non e' compreso nel grafo\n", target);
            }else
                fprintf(stderr, "Il nodo %d non e' compreso nel grafo\n", source);
        }else
            fprintf(stderr, "Non e' possibile inserire un arco che punta allo stesso nodo\n");
    }else
        fprintf(stderr, "Grafo invalido\n");
}

消除编译器errors.and 警告后

但没有添加错误检查,这是结果。

注意::我没有检查此代码是否有任何未定义的行为

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


struct TList
{
    size_t target;
    float peso;
    struct TList* next;
};
//typedef struct TList * List;

struct TList * initNodeList(size_t info, float peso);
struct TList * appendNodeList(struct TList * L, size_t target, float peso);
void printList(struct TList * L);

struct TGraph
{
    struct TList **nodes;
    size_t nodes_count;
};

//typedef struct TGraph * Graph;



struct TGraph * initGraphList(size_t);
void printGraphList(struct TGraph *);
void addEdgeList(struct TGraph *, size_t, size_t, float);



int main( void )
{
    struct TGraph * G = NULL;
    G = initGraphList(3);
    addEdgeList(G, 0, 1, 1);
    addEdgeList(G, 0, 2, 2);
    addEdgeList(G, 1, 0, 3);
    addEdgeList(G, 1, 2, 4);
    addEdgeList(G, 2, 0, 5);
    addEdgeList(G, 2, 1, 6);
    printGraphList(G);
    return 0;
} // end function: main


struct TList * initNodeList(size_t info, float peso)
{
    struct TList * L = malloc(sizeof(struct TList));
    L->target = info;
    L->peso = peso;
    L->next = NULL;
    return L;
} // end function: initNodeList


struct TList * appendNodeList(struct TList * L, size_t target, float peso)
{
    if (L != NULL)
    {
        if (L->target != target)
        {
            L->next = appendNodeList(L->next, target, peso);
        }
    }

    else
    {
        L = initNodeList(target, peso);
    }
    return L;
} // end function: appendNodeList


void printList(struct TList * L)
{
    if (L != NULL)
    {
        printf(" %c(%f), ", (char)L->target + 'A', L->peso);
        printList(L->next);
    }
} // end function: printList


struct TGraph * initGraphList(size_t nodes_count)
{
    struct TGraph * G = malloc(sizeof(struct TGraph));
    G->nodes_count = nodes_count;
    G->nodes = malloc(nodes_count * sizeof(struct TList *));
    return G;
} // end function: initGraphList


void printGraphList(struct TGraph * G)
{
    if (G != NULL)
    {
        for(size_t i = 0; i < G->nodes_count; i++)
        {
            printf("%c -> ", (char)i + 'A');  //I use this in order to print out the nodes as A,B,C,.. instead of 0,1,2,...
            printList(G->nodes[i]);
            puts("\n");
        }
    }
}

void addEdgeList(struct TGraph * G, size_t source, size_t target, float peso)
{
    if(G != NULL)
    {
        if(source != target)
        {
            if(source < G->nodes_count)
            {
                if(target < G->nodes_count)
                    G->nodes[source]= appendNodeList(G->nodes[source], target, peso);
                else
                    fprintf(stderr, "Il nodo %c non e' compreso nel grafo\n", (char)target);
            }

            else
                fprintf(stderr, "Il nodo %c non e' compreso nel grafo\n", (char)source);
        }

        else
            fprintf(stderr, "Non e' possibile inserire un arco che punta allo stesso nodo\n");
    }

    else
        fprintf(stderr, "Grafo invalido\n");
}

输出为:

A ->  B(1.000000),  C(2.000000), 

B ->  A(3.000000),  C(4.000000), 

C ->  A(5.000000),  B(6.000000),