首页 文章

c队列链表 - 打印队列改变指针值?

提问于
浏览
0

我在C中创建了一个链表列表 . 我的结构是这样的:

typedef struct Node{
    int *data;
    struct Node *next;
} node;

typedef struct Queue{
    node *front, *rear;
} queue;

在我的main()函数中,我得到一个用户输入,确定队列的长度,创建一个这个长度的数组,并为数组的每个元素获取用户输入 . 然后我调用一个名为runQueue()的函数 .

void runQueue(int array[], int len){
    queue *q = (queue *)malloc(sizeof(queue));
    q->front = q->rear = NULL;
    for(int i = len - 1; i >= 0; i--){ //len-1, user doesn't input 0-based index
        enQueue(q, array[i]);
    }
    printQueue(q);
    enQueue(q,4);
    printQueue(q);
    queueMenu(q);
}

在这个函数中,我在一个循环中调用一个函数enQueue(),将所有节点从数组中排入队列 . 然后我调用printQueue() .

void enQueue(queue *q, int data){
    node *tmp = (node *) malloc(sizeof(node));
    tmp->data = data;
    tmp->next = NULL;

    if (q->rear == NULL){
        q->front = q->rear = tmp;
        return;
    }

    q->rear->next = tmp;
    q->rear = tmp;
}

void printQueue(queue *q){
    int iterator = 0;
    queue *tmp = (queue *)malloc(sizeof(queue));
    tmp = q;
    while(tmp->front->next != tmp->rear->next && tmp->front != NULL){
        iterator += 1;
        //printf("in loop, i = %d\n",iterator);
        printf("Queue node %d: data val %d ptr %p front ptr %p\n", iterator, tmp->front->data, tmp->front, tmp->front->next);
        tmp->front = tmp->front->next;
    }
    printf("Queue node %d: data val %d ptr %p front ptr %p\n", iterator+1, tmp->front->data, tmp->front, tmp->front->next);
    free(tmp);
}

问题是这样的:我可以运行它,并且enqueue函数似乎工作正常 . 我第一次调用printQueue()时,该函数将打印正确的结果 . 但是,在打印队列之后,前后指针的值发生变化,并且打印尝试对队列执行任何其他操作当然会导致段错误,因为它试图访问不同的内存区域而不是它应该访问的区域 . 如何改变指针的值?我在更改指针值之前已将队列复制到临时队列,那么为什么实际队列的指针会发生变化?

EDIT: 作为数组如何输入队列的示例 -

int array[3] = {4,3,2};
runQueue(array,3);

然后在runQueue()内,for循环通过数组递减并为数组中的每个元素调用enQueue() . 在这种情况下,调用enQueue(q,2),然后调用enQueue(q,3),然后调用enQueue(q,4) .

EDIT 2: 我通过将功能更改为此来尝试了Thomas Blanquet的建议:

void printQueue(queue *q){
    int iterator = 0;
    node *tmp = (node *)malloc(sizeof(node));
    tmp = q->front;
    while(tmp != NULL){
        iterator += 1;
        printf("Queue node %d: data val %d ptr %p front ptr %p\n", iterator, tmp->data, tmp, tmp->next);
        tmp = tmp->next;
    }
    printf("Queue node %d: data val %d ptr %p front ptr %p\n", iterator+1, tmp->data, tmp, tmp->next);
    free(tmp);
}

进行此更改后,指针是正确的,但我仍然在退出函数之前得到段错误 .

EDIT 3: 我尝试评论免费(tmp),但我仍然得到一个段错误 . 但是我发现了问题!不知怎的,我在循环外面有一个printf(),我没有注意到:

printf("Queue node %d: data val %d ptr %p front ptr %p\n", iterator+1, tmp->data, tmp, tmp->next);

现在删除它会停止段错误并且所有指针都是正确的 . 非常感谢!

2 回答

  • 0

    您的“printQueue”存在一些问题:

    首先,为什么要用malloc分配 tmp ,然后给它 q 的值?您的malloc分配内存并返回此内存的地址,但使用 q 更改它,您丢失了此内存 .

    然后 tmp 包含 q 的地址,所以当你这样做时:

    tmp->front = tmp->front->next;
    

    您更改队列的前节点 .

    您应该执行 node *tmp = q->front; 之类的操作并使用它来迭代链接列表,就像您已经使用 tmp->front 一样 . 区别在于您不会更改队列中前端节点的地址,而是更改指向其前节点的tmp变量 .

    最后,通过使用 tmp != NULL 作为条件,在循环之后,您不必为最后一个节点做特殊情况 .

    Edit

    我忘了一些东西,通过做 free(tmp) ,在你的帖子中,你的值与q相同,你释放了队列结构,所以你不能再在你的代码中使用它了 .

  • 0

    解决问题...

    • 我将我的tmp变量从队列结构的引用更改为队列头节点的引用,并在队列中迭代(tmp = tmp-> next)

    • 我删除了自由行(tmp),因为它释放了实际队列的位置,因此删除了部分队列!

    • 我删除了在我不小心放在那里的循环之外的额外printf()!

    代码现在看起来像这样:

    void printQueue(queue *q){
        int iterator = 0;
        node *tmp = q->front;
        while(tmp != NULL){
            iterator += 1;
            printf("Queue node %d: data val %d ptr %p front ptr %p\n", iterator, tmp->data, tmp, tmp->next);
            tmp = tmp->next;
        }
    }
    

    非常感谢Thomas Blanquet .

相关问题