我在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()时,该函数将打印正确的结果。但是,在打印队列之后,前后指针的值发生变化,并且打印尝试对队列执行任何其他操作当然会导致段错误,因为它试图访问不同的内存区域而不是它应该。如何改变指针的值?我在更改指针值之前已将队列复制到临时队列,那么为什么实际队列的指针会发生变化?
修改 作为数组如何输入队列的一个例子 -
int array[3] = {4,3,2};
runQueue(array,3);
然后在runQueue()中,for循环通过数组递减并为数组中的每个元素调用enQueue()。在这种情况下,调用enQueue(q,2),然后调用enQueue(q,3),然后调用enQueue(q,4)。
编辑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);
}
进行此更改后,指针是正确的,但在退出函数之前我仍然遇到段错误。
编辑3: 我试着免费评论(tmp),但我仍然遇到了段错误。但是我发现了问题!不知怎的,我在循环外面有一个printf(),我没有注意到:
printf("Queue node %d: data val %d ptr %p front ptr %p\n", iterator+1, tmp->data, tmp, tmp->next);
现在删除它会停止段错误并且所有指针都是正确的。非常感谢!
答案 0 :(得分:0)
你的" printQueue"有一些问题。 :
首先,为什么要为malloc分配tmp
,然后给它q
的值?
你的malloc分配内存并返回这个内存的地址,但是使用q
更改它,你就丢失了这个内存。
然后tmp
包含q
的地址,所以当你这样做时:
tmp->front = tmp->front->next;
您更改了队列的前节点。
您应该执行node *tmp = q->front;
之类的操作,并使用它来迭代链接列表,就像您已经使用tmp->front
一样。区别在于您不会更改队列中前端节点的地址,而是更改指向其前节点的tmp变量。
最后,通过使用tmp != NULL
作为条件,在循环之后,您不必为最后一个节点做特殊情况。
修改强>
我忘记了一些事情,做了free(tmp)
,在你的帖子中,它的值与q相同,你释放队列结构,这样你就不能再在你的代码中使用它了。
答案 1 :(得分:0)
解决问题......
我将tmp变量从队列结构的引用更改为 队列的头节点的引用并通过迭代迭代 queue(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。