在C.Segfault中将元素添加到队列时设计队列

在C.Segfault中将元素添加到队列时设计队列,c,pointers,segmentation-fault,queue,C,Pointers,Segmentation Fault,Queue,我用C编写的队列程序有问题。这是一个循环队列,因此最后一项也必须指向第一项。addQueue函数中存在此问题。首先检查head指针是否设置为NULL,如果设置为NULL,则将第一项添加到队列中。但是,head不等于NULL,然后我将该项添加到队列的末尾。我创建了一个迭代指针来迭代,直到在以下情况下找到结束: 迭代->下一步==*头部; 我遇到的问题是,当我创建iterate并将其设置为*head时,它并没有正常运行。这是我的代码和我收到的输出,我在代码中添加了一些打印,以显示我遇到的问题 #i

我用C编写的队列程序有问题。这是一个循环队列,因此最后一项也必须指向第一项。addQueue函数中存在此问题。首先检查head指针是否设置为NULL,如果设置为NULL,则将第一项添加到队列中。但是,head不等于NULL,然后我将该项添加到队列的末尾。我创建了一个迭代指针来迭代,直到在以下情况下找到结束: 迭代->下一步==*头部; 我遇到的问题是,当我创建iterate并将其设置为*head时,它并没有正常运行。这是我的代码和我收到的输出,我在代码中添加了一些打印,以显示我遇到的问题

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


 //define the Q element struct
 typedef struct _item{
        struct _item* next;
         struct _item* prev;
         int data;
} item;

 item * newItem(){

         item * node = malloc(sizeof(item));
         return node;
 }

 void initQueue(item ** head){
         *head = NULL; //Empty queue means head points to NULL
 }

 void addQueue(item ** head, item item_p){
         //create new item
         item * newIt = newItem();
         newIt = &item_p;
         printf("NewItem: %d\n\n", newIt->data);

         //if *head is NULL, make it point to item
         if(*head == NULL)
         {       
                 *head = newIt; //set head to address of item
                 newIt->next = *head;
                 printf("Again: %p\n\n",  *head);
         }
         //else the list is not empty, add item to end of list
         else    
         {       
                 item * iterate = NULL; 
                 iterate = *head;
                 printf("it: %p head: %p\n\n", iterate, *head);
                 /*while (iterate->next != *head)
                 {
                         iterate = iterate->next;
                 }
                 iterate->next = newIt;
                 newIt->next = *head;*/
         }
 }
我创建了三个要插入队列的项。第一个是放置在没有问题。但是,当我插入第二项时,我遇到了问题。headTemp->数据应该保持不变,无论我将什么放入队列,但是它从1到2到3,这是我创建的所有项目的数据。我不确定问题出在哪里,答案可能就在我面前。但我真的很感激你能帮我

干杯

您的
addQueue()
函数不合适

void addQueue(item ** head, item item_p){
28         //create new item
29         item * newIt = newItem();
30         newIt = &item_p;
31         printf("NewItem: %d\n\n", newIt->data);
32         
33         //if *head is NULL, make it point to item
34         if(*head == NULL)
35         {       
36                 *head = newIt; //set head to address of item
37                 newIt->next = *head;
38                 printf("Again: %p\n\n",  *head);
39         }
在这种情况下,您可以使用
newItem()
来获取新分配的节点,但您可以再次将其重新分配给第30行的
&itemp\p
。这不好,因为您没有使用分配的内存,而是使用
main()
中声明的项变量
i1、i2、i3

另外,在
newItem()
中,将
next
prev
设置为
NULL

17 item * newItem(){
18 
19         item * node = malloc(sizeof(item));
           if(node) { //You can use calloc too.
              node->next = NULL;
              node->prev = NULL;
           }
20         return node;
21 }

感谢您发布可粘贴代码。走出大门,这是错误的:

 item * newIt = newItem();
 newIt = &item_p;
这是一个即时内存泄漏。更糟糕的是,替换它的地址是一个按值自动变量。因此,一旦该函数完成,地址将无效,甚至无法进行计算,更不用说取消引用了

接下来,您需要为节点设置所有成员变量的有效状态。如何做到这一点取决于您,但最简单的方法是在节点创建代码中。要真正做到这一点,您的节点创建代码应该是一个“工厂”函数。即,它应将初始化节点所需的内容作为参数。因此,首先要这样做:

item* newItem( int data )
{
    item * node = malloc(sizeof(item));
    if (item == NULL)
    {
        perror("failed to allocate node.");
        exit(EXIT_FAILURE);
    }

    node->data = data;
    node->next = node->prev = NULL;
    return node;
}
一旦获得该实体,您可以修改
addQueue
以执行此操作:

void addQueue(item** head, int data)
{
    item *prev = NULL;
    while (*head)
    {
        prev = *head;
        head = &prev->next;
    }

    *head = newItem(data);
    (*head)->prev = prev;
}
这段代码离deque还有很长的路要走。要做到这一点,您需要两个指针,保存它们的最佳位置是在一个单独的结构中,以及进行大小查询的计数O(1)。正确地做,插入是O(1)在一个完整的deque中,但您最终会到达那里

无论如何,下面会出现一个更新的main,用于测试它所做的一切。最终你会想要一个流行的function,等等

int main()
{
    item *q = NULL;

    for (int i=1; i<=20; ++i)
        addQueue(&q, i);

    item *p = q;
    while (p)
    {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
    return 0;
}

不要将结构作为参数传递。使用指针。请不要给你的行编号。剪切用于测试的粘贴代码是毫无价值的。如果您必须提醒注意某一行的特定错误,请添加一条注释,说明“这是行”。也就是说,这对学术界来说是一个悲哀的见证,当我真的很想在海报上投一个问题的时候,仅仅是因为海报的代表人数不足1K,并且没有正确地投下
malloc()
(干得好,顺便说一句)。查看您的代码,看看您是否可以找到新节点在哪里有
next
prev
指针,如果没有设置为以前的有效地址,指针将初始化为NULL。另外,在前两行中,您会立即泄漏
addQueue
方法中的内存。这不是java。您的代码将自动变量推送到队列中,一旦函数返回,该变量将无效。您没有将元素添加到列表末尾。@WhozCraig感谢您提供有关行号的提示。这是我第一篇关于stackoverflow的帖子,所以我还在努力适应。非常感谢。这帮了大忙。
void addQueue(item** head, int data)
{
    item *prev = NULL;
    while (*head)
    {
        prev = *head;
        head = &prev->next;
    }

    *head = newItem(data);
    (*head)->prev = prev;
}
int main()
{
    item *q = NULL;

    for (int i=1; i<=20; ++i)
        addQueue(&q, i);

    item *p = q;
    while (p)
    {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
    return 0;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20