ing 发表于 2020-1-29 11:25

C 传递指针引起程序异常退出

本帖最后由 ing 于 2020-1-29 21:20 编辑



如图断点处,为什么这样 enQueue(&q,t) 传递指针会使程序异常?



如果改成 &t(或者 t) 就不会异常,但得到的结果不是我想要的,这个结果说明 enQueue() 方法没有生效






修改方法 enQueue 的参数 Tree *t 为 Tree t 后
enQueue(Queueq,Tree *** t**) ⇒ enQueue(Queueq,**Tree t**)
再将传递给 enQueue 方法的参数 &t 改为 (*t) 程序才正确运行,但这是为什么?我不理解

ing 发表于 2020-1-29 15:50

我的爱是你 发表于 2020-1-29 12:47
我很奇怪你们都是用的什么编译器?

我vs直接爆出了16个错误无法进行编译。


...我的问题是
如果入队方法是这样 enqueue(Queue ** q,Tree * t)
那么传递给他的参数(Tree)那里必须是 enQueue(..,(*t));
否则程序异常或得不到结果。
但我不理解为什么不能传入 t 而是 *t。

我的爱是你 发表于 2020-1-29 19:42

本帖最后由 我的爱是你 于 2020-1-29 19:43 编辑

抱歉抱歉{:301_995:}
脑子有坑了,修改结构体是最愚蠢最愚蠢的做法。。。。



既然给了指针而结构体不需要指针只需要指针内的参数,那么直接取指针值也是一样。。。。修改结构体工作量要上天了!
以下运行结果:↓

改完函数后把这两处改完即可顺利运行。

ing 发表于 2020-1-29 11:31

完整代码
```
#include<stdarg.h>
#include<malloc.h>
#include<stdio.h>

#define MAX_VERTEX_NUM 50
#define VType int
#define InfoType char
typedef enum {false,true} bool;
bool visited;

typedef struct
{
    int weight;
    InfoType info;
}Matrix;

typedef struct
{
    VType vertex;
    Matrix arcs;
    int arcNum,vertexNum;
}MGraph;

typedef struct Node
{
    VType data;
    struct Node * l_child;
    struct Node * nextSibling;
}*Tree,Node;

typedef struct Queue
{
    //队列中存放的为树结点
    Tree node;
    struct Queue * next;
}Queue;

int locateVertex(MGraph *g, VType vertex)
{
    for (int i = 0; i < g->vertexNum; ++i) {
      if (g->vertex == vertex)
      {
            return i;
      }
    }
    return -1;
}

void createDN(MGraph * g)
{
    g->arcNum = 13;
    g->vertexNum = 13;
//    printf("请输入顶点数据 \n");
//    for (int i = 0; i < g->vertexNum; ++i) {
//      //strtol
//      scanf("%d",&(g->vertex));
//    }
    for (int i = 0; i < g->vertexNum; ++i) {
      //strtol
      g->vertex = i+1;
    }

    for (int k = 0; k < g->vertexNum; ++k) {
      for (int i = 0; i < g->vertexNum; ++i) {
            g->arcs.weight = 00;
            g->arcs.info = NULL;
      }
    }
//    printf("请输入弧头和弧尾 \n");
//    for (int j = 0; j < g->vertexNum; ++j) {
//      VType v1,v2;
//      scanf("%d,%d",&v1,&v2);
//      int n = locateVertex(g,v1);
//      int m = locateVertex(g,v2);
//      g->arcs.weight = 1;
//      g->arcs.weight = 1;
//    }

    int n = 0, m = 1;
    g->arcs.weight = 1;
    g->arcs.weight = 1;
    m = 2;
    g->arcs.weight = 1;
    g->arcs.weight = 1;
    m = 5;
    g->arcs.weight = 1;
    g->arcs.weight = 1;
    n = 0, m = 11;
    g->arcs.weight = 1;
    g->arcs.weight = 1;
    n = 1, m = 12;
    g->arcs.weight = 1;
    g->arcs.weight = 1;
    n = 4, m = 2;
    g->arcs.weight = 1;
    g->arcs.weight = 1;
    m = 7, n = 6;
    g->arcs.weight = 1;
    g->arcs.weight = 1;
    m = 9;
    g->arcs.weight = 1;
    g->arcs.weight = 1;
    m = 8;
    g->arcs.weight = 1;
    g->arcs.weight = 1;
    n = 7, m = 9;
    g->arcs.weight = 1;
    g->arcs.weight = 1;
    n = 11,m=10;
    g->arcs.weight = 1;
    g->arcs.weight = 1;
    n=12;
    g->arcs.weight = 1;
    g->arcs.weight = 1;
    m=11;
    g->arcs.weight = 1;
    g->arcs.weight = 1;

}

void initQueue(Queue ** q)
{
    (*q) = (Queue*)malloc(sizeof(Queue));
    (*q)->next = NULL;
}

void deQueue(Queue ** q,Tree * t)
{
    (*t) = (*q)->next->node;
    (*q)->next = (*q)->next->next;
}

bool isEmpty(Queue * q)
{
    if (q->next)
      return false;
    else
      return true;
}

int firstAdjVex(MGraph * g,int v)
{
    for (int i = 0; i < g->vertexNum; ++i) {
      if (g->arcs.weight == 1)
      {
            return i;
      }
    }
    return -1;
}

int nextAdjVex(MGraph * g,int v,int w)
{
    for (int i = w+1; i < g->vertexNum; ++i) {
      if (g->arcs.weight == 1)
      {
            return i;
      }
    }
    return -1;
}

void enQueue(Queue ** q,Tree t)
{
    Queue * e = malloc(sizeof(Queue));
    e->node = t;
    e->next = NULL;
    Queue * temp = (*q);
    while (temp->next)
    {
      temp = temp->next;
    }
    temp->next = e;
}

//Tree t
void bfsTree(MGraph * g,Tree * t)
{
    Queue * q = NULL;
    initQueue(&q);
    //根结点入队
    enQueue(&q, (*t)); // t
    //存储出队列的结点
    Tree p = NULL;
    //while (q)
    while (!isEmpty(q))
    {
      bool first = true;
      deQueue(&q,&p);
      //判断出队结点中的数据在数组中的具体位置
      int v = locateVertex(g,p->data);
      visited = true;
      for (int i = firstAdjVex(g,v); i > -1; i = nextAdjVex(g,v,i)) {
            if (!visited)
            {
                Tree temp = malloc(sizeof(Node));
                temp->data = g->vertex;
                temp->l_child = NULL;
                temp->nextSibling = NULL;
                enQueue(&q,temp);
                if (first)
                {
                  p->l_child = temp;
                  first = false;
                }
                else
                {
                  p->nextSibling = temp;
                }
                visited = true;
                p = temp;
            }
      }
    }
}

//Tree t
void bfsForest(MGraph * g, Tree * t)
{
    (*t) = NULL;
    Tree q = NULL;
    for (int i = 0; i < g->vertexNum; ++i) {
      visited = false;
    }
    for (int j = 0; j < g->vertexNum; ++j) {
      if (!visited)
      {
            Tree p = malloc(sizeof(Node));
            p->data = g->vertex;
            p->nextSibling = NULL;
            p->l_child = NULL;
            //如果树为空,则该顶点作为树的树根
            if (!(*t))
            {
                (*t) = p;
            }
            else
            {
                q->nextSibling = p;
            }
            q = p;
            bfsTree(g,t);
      }
    }
}

void preOrderTraverse(Tree t)
{
    if (t)
    {
      printf("%d ",t->data);
      preOrderTraverse(t->l_child);
      preOrderTraverse(t->nextSibling);
    }
}

int main(int argc, char* argv[])
{
    MGraph g;
    createDN(&g);
    Tree t;
    bfsForest(&g,&t);
    preOrderTraverse(t);

    return 0;
}


```

stardxxx 发表于 2020-1-29 11:42

广搜?
没看懂你问的问题,,

我的爱是你 发表于 2020-1-29 12:47

本帖最后由 我的爱是你 于 2020-1-29 12:49 编辑

我很奇怪你们都是用的什么编译器?

我vs直接爆出了16个错误无法进行编译。

以下是我修改的。



#include<stdarg.h>
#include<malloc.h>
#include<stdio.h>

#define MAX_VERTEX_NUM 50
#define VType int
#define InfoType char
typedef enum { False, TRUE } boo;
boo visited;

typedef struct
{
      int weight;
      InfoType info;
}Matrix;

typedef struct
{
      VType vertex;
      Matrix arcs;
      int arcNum, vertexNum;
}MGraph;

typedef struct Node
{
      VType data;
      struct Node* l_child;
      struct Node* nextSibling;
}*Tree, Node;

typedef struct Queue
{
      //队列中存放的为树结点
      Tree node;
      struct Queue* next;
}Queue;

int locateVertex(MGraph* g, VType vertex)
{
      for (int i = 0; i < g->vertexNum; ++i) {
                if (g->vertex == vertex)
                {
                        return i;
                }
      }
      return -1;
}

void createDN(MGraph* g)
{
      g->arcNum = 13;
      g->vertexNum = 13;
      //    printf("请输入顶点数据 \n");
      //    for (int i = 0; i < g->vertexNum; ++i) {
      //      //strtol
      //      scanf("%d",&(g->vertex));
      //    }
      for (int i = 0; i < g->vertexNum; ++i) {
                //strtol
                g->vertex = i + 1;
      }

      for (int k = 0; k < g->vertexNum; ++k) {
                for (int i = 0; i < g->vertexNum; ++i) {
                        g->arcs.weight = 00;
                        g->arcs.info = NULL;
                }
      }
      //    printf("请输入弧头和弧尾 \n");
      //    for (int j = 0; j < g->vertexNum; ++j) {
      //      VType v1,v2;
      //      scanf("%d,%d",&v1,&v2);
      //      int n = locateVertex(g,v1);
      //      int m = locateVertex(g,v2);
      //      g->arcs.weight = 1;
      //      g->arcs.weight = 1;
      //    }

      int n = 0, m = 1;
      g->arcs.weight = 1;
      g->arcs.weight = 1;
      m = 2;
      g->arcs.weight = 1;
      g->arcs.weight = 1;
      m = 5;
      g->arcs.weight = 1;
      g->arcs.weight = 1;
      n = 0, m = 11;
      g->arcs.weight = 1;
      g->arcs.weight = 1;
      n = 1, m = 12;
      g->arcs.weight = 1;
      g->arcs.weight = 1;
      n = 4, m = 2;
      g->arcs.weight = 1;
      g->arcs.weight = 1;
      m = 7, n = 6;
      g->arcs.weight = 1;
      g->arcs.weight = 1;
      m = 9;
      g->arcs.weight = 1;
      g->arcs.weight = 1;
      m = 8;
      g->arcs.weight = 1;
      g->arcs.weight = 1;
      n = 7, m = 9;
      g->arcs.weight = 1;
      g->arcs.weight = 1;
      n = 11, m = 10;
      g->arcs.weight = 1;
      g->arcs.weight = 1;
      n = 12;
      g->arcs.weight = 1;
      g->arcs.weight = 1;
      m = 11;
      g->arcs.weight = 1;
      g->arcs.weight = 1;

}

void initQueue(Queue** q)
{
      (*q) = (Queue*)malloc(sizeof(Queue));
      (*q)->next = NULL;
}

void deQueue(Queue** q, Tree* t)
{
      (*t) = (*q)->next->node;
      (*q)->next = (*q)->next->next;
}

boo isEmpty(Queue* q)
{
      if (q->next)
                return False;
      else
                return TRUE;
}

int firstAdjVex(MGraph* g, int v)
{
      for (int i = 0; i < g->vertexNum; ++i) {
                if (g->arcs.weight == 1)
                {
                        return i;
                }
      }
      return -1;
}

int nextAdjVex(MGraph* g, int v, int w)
{
      for (int i = w + 1; i < g->vertexNum; ++i) {
                if (g->arcs.weight == 1)
                {
                        return i;
                }
      }
      return -1;
}

void enQueue(Queue** q, Tree t)
{
      Queue* e = (struct Queue*)malloc(sizeof(Queue));
      e->node = t;
      e->next = NULL;
      Queue* temp = (*q);
      while (temp->next)
      {
                temp = temp->next;
      }
      temp->next = e;
}

//Tree t
void bfsTree(MGraph* g, Tree* t)
{
      Queue* q = NULL;
      initQueue(&q);
      //根结点入队
      enQueue(&q, (*t)); // t
      //存储出队列的结点
      Tree p = NULL;
      //while (q)
      while (!isEmpty(q))
      {
                boo first = TRUE;
                deQueue(&q, &p);
                //判断出队结点中的数据在数组中的具体位置
                int v = locateVertex(g, p->data);
                visited = TRUE;
                for (int i = firstAdjVex(g, v); i > -1; i = nextAdjVex(g, v, i)) {
                        if (!visited)
                        {
                              Tree temp = (struct Node*)malloc(sizeof(Node));
                              temp->data = g->vertex;
                              temp->l_child = NULL;
                              temp->nextSibling = NULL;
                              enQueue(&q, temp);
                              if (first)
                              {
                                        p->l_child = temp;
                                        first = False;
                              }
                              else
                              {
                                        p->nextSibling = temp;
                              }
                              visited = TRUE;
                              p = temp;
                        }
                }
      }
}

//Tree t
void bfsForest(MGraph* g, Tree* t)
{
      (*t) = NULL;
      Tree q = NULL;
      for (int i = 0; i < g->vertexNum; ++i) {
                visited = False;
      }
      for (int j = 0; j < g->vertexNum; ++j) {
                if (!visited)
                {
                        Tree p = (struct Node*)malloc(sizeof(Node));
                        p->data = g->vertex;
                        p->nextSibling = NULL;
                        p->l_child = NULL;
                        //如果树为空,则该顶点作为树的树根
                        if (!(*t))
                        {
                              (*t) = p;
                        }
                        else
                        {
                              q->nextSibling = p;
                        }
                        q = p;
                        bfsTree(g, t);
                }
      }
}

void preOrderTraverse(Tree t)
{
      if (t)
      {
                printf("%d ", t->data);
                preOrderTraverse(t->l_child);
                preOrderTraverse(t->nextSibling);
      }
}

int main(int argc, char* argv[])
{
      MGraph g;
      createDN(&g);
      Tree t;
      bfsForest(&g, &t);
      preOrderTraverse(t);

      return 0;
}



这个是楼主想要的结果?


你这个malloc怎么可以不定义返回的结构指针!


还有你这个宏为啥直接能用bool命名。。

我进行了以上修改就没有任何问题了。lz的错误在于语法问题。{:301_971:}


ing 发表于 2020-1-29 15:58

本帖最后由 ing 于 2020-1-29 16:09 编辑

我的爱是你 发表于 2020-1-29 12:47
我很奇怪你们都是用的什么编译器?

我vs直接爆出了16个错误无法进行编译。

我用Clion,VS跑程序会出错我都不知道是什么原因。。
我在Clion定义返回的结构指针是这样的形式 (Queue*) ,没有struct
后来发现不写也不影响,就懒得写了我不知道这是必须的{:1_907:}
你这是C++吧?因为后缀不是 .c;
然后 bool 功能是要自己实现的。。

最后,能加我吗?我不知道怎么玩 VS,在Clion可运行的代码放VS就异常

我的爱是你 发表于 2020-1-29 17:19

ing 发表于 2020-1-29 15:58
我用Clion,VS跑程序会出错我都不知道是什么原因。。
我在Clion定义返回的结构指针是这样的形式 (Queue* ...

我这是c ,cpp只不过是新建文件懒得改了。
void返回理论可以是任何返回,但规范来说malloc为你申请了一篇内存域 ,你理应按照语法返回指针为该申请的结构类型。
另外我知道bool被你重定义为枚举类型,但我没记错的话bool变量在编译器内已经使用typedef进行过宏定义,你这不亚于用int重定义char类型 命名是不规范的。

我的爱是你 发表于 2020-1-29 17:50

本帖最后由 我的爱是你 于 2020-1-29 18:19 编辑

ing 发表于 2020-1-29 15:50
...我的问题是
如果入队方法是这样 enqueue(Queue ** q,Tree * t)
那么传递给他的参数(Tree)那里必须 ...
void bfsTree(MGraph* g, Tree* t)

你这里函数不是定义t为指针了吗,你直接enQueue(&q,t) 是传给了它一个指针
而你这个函数void enQueue(Queue** q, Tree t)第二参数只接受实参 ,
而 * 这个符号名字叫做取值符,你怕是忘了加了这个在t上意思为将t指针所指向的值取出。
也就是将取出的值给予了第二参数 ,并不是将指针给予了第二参数。这个问题太明显了!

你想要enQueue(&q,t)它接受t指针也就是必须void enQueue(Queue** q, Tree* t)这样。否自就必须加上取值符。

ing 发表于 2020-1-29 18:40

我的爱是你 发表于 2020-1-29 17:50
你这里函数不是定义t为指针了 ...

可如果方法这样 void enQueue(Queue** q, Tree* t)
再这样调用 enQueue(&q,t)
就出现了第一张图片的运行结果,异常退出了。

然后,在 bfsForest 方法的最后一行代码是 bfsTree(g, t);
然而这个方法这样的声明 `void bfsTree(MGraph * g,Tree * t)` 却是可行的。
在定义函数 enQueue 这里却翻车了

我的爱是你 发表于 2020-1-29 19:18



改完函数确实可以接受指针,但你结构也应当做相应改变

否则node本来接受一个实参,现在你给它了一个指针并不匹配接受到的指针当然会出错。



同时第二个enQueue既然第二个参数接受指针 ,那么原来的temp也需要改动。
这里enQueue(&q, &temp);可以直接将temp地址给予参数二。
如都不进行改动 自然报错{:301_1008:}
页: [1] 2
查看完整版本: C 传递指针引起程序异常退出