C 使用单链表更新队列adt中的尾部指针时出现问题

C 使用单链表更新队列adt中的尾部指针时出现问题,c,linked-list,queue,C,Linked List,Queue,我正在尝试创建一个基于我已经创建的链表库的队列库。具体来说,在向链表添加新节点后,更新队列结构中的尾部指针时遇到问题 链表结构: struct listNode { int nodeLength; int nodeValue; struct listNode *next; }; typedef struct listNode node; struct QueueRecord { node *list; node *front; node *ba

我正在尝试创建一个基于我已经创建的链表库的队列库。具体来说,在向链表添加新节点后,更新队列结构中的尾部指针时遇到问题

链表结构:

struct listNode {
    int nodeLength;
    int nodeValue;
    struct listNode *next;
};

typedef struct listNode node;
struct QueueRecord {
    node *list;
    node *front;
    node *back;
    int maxLen;
};
typedef struct QueueRecord queue;
队列结构:

struct listNode {
    int nodeLength;
    int nodeValue;
    struct listNode *next;
};

typedef struct listNode node;
struct QueueRecord {
    node *list;
    node *front;
    node *back;
    int maxLen;
};
typedef struct QueueRecord queue;
这是我在队列库中的add函数

void add(queue currentQueue, int data){
    addTail(currentQueue.list, data, data+5);
    currentQueue.back = currentQueue.back->next;

}
以及链接列表库中的addTail函数

void addTail (node *head, int value, int length) {
    node *current = head;
    node *newNode = (struct listNode *)malloc(sizeof(node));
    newNode = initNode(value, length);

    while (current->next != NULL)   
        current = current->next;

    newNode->next = NULL;
    current->next = newNode;
}
所以我的问题是尾部指针没有设置到列表中的最后一个节点。它与头指针保持在同一位置。我已经研究了好几个小时,试图看看我是否遗漏了一些小东西,但我找不到。如果需要更多的代码或解释来理解我的问题,我可以提供它

如何创建队列:

queue createQueue(int maxLen){
    queue newQueue;
    newQueue.list = createList();
    newQueue.front = newQueue.list;
    newQueue.back = newQueue.list;
    newQueue.maxLen = maxLen;
    return newQueue;
}    

node *createList (){
    node *head = NULL;
    head = (struct listNode *)malloc(sizeof(node));
    head->next = NULL;
    return head;
}

node *initNode (int value, int length){
    node *newNode = NULL;
    newNode = (struct listNode *)malloc(sizeof(node));
    newNode->nodeValue = value;
    newNode->nodeLength = length;
    newNode->next = NULL;
    return newNode;
}
您正在将
队列
结构的副本传递给
添加
,因此仅更改副本的成员。您需要将
队列*
传递给函数才能更改
队列
本身的成员

void add(queue *currentQueue, int data){
    if (currentQueue == NULL) {
        exit(EXIT_FAILURE);
    }
    addTail(currentQueue->list, data, data+5);
    currentQueue->back = currentQueue->back->next;
}
并将其称为
add(&your_queue)

addTail
函数中,您应该检查
head
是否也是
NULL

node *newNode = (struct listNode *)malloc(sizeof(node));
newNode = initNode(value, length);
addTail
中,您遇到了一个严重的问题。使用赋值
newNode=initNode(值,长度)
,您正在丢失对刚刚
malloc
ed内存的引用

如果
initNode
malloc
是一个新的内存块,它“只是”一个内存泄漏,那么您应该删除
addTail
中的
malloc

否则,我担心
initNode
会返回局部变量的地址,即la

node * initNode(int val, int len) {
    node new;
    new.nodeValue = val;
    new.nodeLength = len;
    new.next = NULL;
    return &new;
}
如果
initNode
看起来与此类似,则会导致问题,因为一旦函数返回,地址就会变为无效。但是如果
initNode
看起来像这样,编译器应该警告您

无论如何,如果没有看到
initNode
的代码,我就无法诊断原因

但是如果您将
addTail
更改为

void addTail (node *head, int value, int length) {
    if (head == NULL) { // violation of contract, die loud
        exit(EXIT_FAILURE);
    }
    node *current = head;
    node *newNode = malloc(sizeof(node));
    if (newNode == NULL) {
        exit(EXIT_FAILURE); // or handle gracefully if possible
    }
    newNode->nodeValue = value;
    newNode->nodeLength = length;
    newNode->next = NULL;

    while (current->next != NULL)   
        current = current->next;

    current->next = newNode;
}
它应该会起作用

但是,由于您有指向列表中第一个和最后一个节点的指针,因此使用
back
指针附加一个新节点会更有效

void add(queue *currentQueue, int data){
    node *newNode = malloc(sizeof *newNode);
    if (newNode == NULL) {
        exit(EXIT_FAILURE); // or handle gracefully if possible
    }
    newNode->nodeValue = data;
    newNode->nodeLength = data+5;
    newNode->next = NULL;
    currentQueue->back->next = newNode;
    currentQueue->back = newNode;
}
因为你不需要遍历整个列表来找到结尾


一个简单的示例程序

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

struct listNode {
    int nodeLength;
    int nodeValue;
    struct listNode *next;
};

typedef struct listNode node;

struct QueueRecord {
    node *list;
    node *front;
    node *back;
    int maxLen;
};
typedef struct QueueRecord queue;

node *createList (){
    node *head = NULL;
    head = (struct listNode *)malloc(sizeof(node));
    head->next = NULL;
    return head;
}

void addTail (node *head, int value, int length) {
    if (head == NULL) { // violation of contract, die loud
        exit(EXIT_FAILURE);
    }
    node *current = head;
    node *newNode = malloc(sizeof(node));
    if (newNode == NULL) {
        exit(EXIT_FAILURE); // or handle gracefully if possible
    }
    newNode->nodeValue = value;
    newNode->nodeLength = length;
    newNode->next = NULL;

    while (current->next != NULL)   
        current = current->next;

    current->next = newNode;
}

queue createQueue(int maxLen){
    queue newQueue;
    newQueue.list = createList();
    newQueue.front = newQueue.list;
    newQueue.back = newQueue.list;
    newQueue.maxLen = maxLen;
    return newQueue;
}

void add(queue *currentQueue, int data){
    if (currentQueue == NULL) {
        exit(EXIT_FAILURE);
    }
    addTail(currentQueue->list, data, data+5);
    currentQueue->back = currentQueue->back->next;
}

int main(void) {
    queue myQ = createQueue(10);
    for(int i = 1; i < 6; ++i) {
        add(&myQ, i);
        printf("list:  %p\nfront: %p\nback:  %p\n",
                (void*)myQ.list, (void*)myQ.front, (void*)myQ.back);
    }
    node *curr = myQ.front->next;
    while(curr) {
        printf("Node %d %d, Back %d %d\n", curr->nodeValue,
                 curr->nodeLength, myQ.back->nodeValue, myQ.back->nodeLength);
        curr = curr->next;
    }
    while(myQ.list) {
        myQ.front = myQ.front->next;
        free(myQ.list);
        myQ.list = myQ.front;
    }
    return 0;
}
#包括
#包括
结构列表节点{
节点长度;
int节点值;
结构listNode*next;
};
typedef结构listNode节点;
结构队列记录{
节点*列表;
节点*前端;
节点*返回;
int-maxLen;
};
typedef结构队列记录队列;
节点*createList(){
node*head=NULL;
head=(struct listNode*)malloc(sizeof(node));
head->next=NULL;
回流头;
}
void addTail(节点*头,int值,int长度){
如果(head==NULL){//违反合同,大声地死去
退出(退出失败);
}
节点*电流=头部;
node*newNode=malloc(sizeof(node));
if(newNode==NULL){
退出(退出失败);//如果可能,请优雅地处理
}
新建节点->节点值=值;
新建节点->节点长度=长度;
newNode->next=NULL;
while(当前->下一步!=NULL)
当前=当前->下一步;
当前->下一步=新节点;
}
队列创建队列(int-maxLen){
队列新建队列;
newQueue.list=createList();
newQueue.front=newQueue.list;
newQueue.back=newQueue.list;
newQueue.maxLen=maxLen;
返回新队列;
}
无效添加(队列*当前队列,整数数据){
if(currentQueue==NULL){
退出(退出失败);
}
addTail(currentQueue->list,data,data+5);
currentQueue->back=currentQueue->back->next;
}
内部主(空){
队列myQ=createQueue(10);
对于(int i=1;i<6;++i){
添加(&myQ,i);
printf(“列表:%p\n前面:%p\n后面:%p\n”,
(void*)myQ.list,(void*)myQ.front,(void*)myQ.back);
}
节点*curr=myQ.front->next;
while(curr){
printf(“节点%d%d,返回%d%d\n”),curr->nodeValue,
当前->节点长度,myQ.back->节点值,myQ.back->节点长度);
当前=当前->下一步;
}
while(myQ.list){
myQ.front=myQ.front->next;
免费(myQ.list);
myQ.list=myQ.front;
}
返回0;
}

正如预期的那样,也可以使用可选的
add
实现。

我认为您从未初始化过back,所以back->next是一些随机指针?

在标准的普通c中,所有结构都是通过引用传递的,不是吗?不,所有内容都是通过值传递的,但是对于数组,会传递指向第一个元素的指针。确定吗?所以当我的sizeof(queue):=5000并且我调用fun(queue)时,5000字节被复制到堆栈上(当您写入时)?我们在C语言中,不是在一个面向对象的环境中,在这个环境中,一个“副本”被放在堆栈上是的,就是这样。因为这个原因,你应该通过指针传递大的东西。好的,我以前确实这样设置过,它给我带来了问题,但是解释帮助了我,谢谢。现在我不确定我的尾巴指向什么,因为当我从那里打印列表时,当它应该只打印最后一个节点时,它不会打印任何内容。