Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C-链表-插入元素未更新-仅添加最后一个输入元素_C_Linked List - Fatal编程技术网

C-链表-插入元素未更新-仅添加最后一个输入元素

C-链表-插入元素未更新-仅添加最后一个输入元素,c,linked-list,C,Linked List,前言:目标是提示用户输入,将每个元素(输入行)添加到链接列表中 char command[120]; int counter = 0; while(counter < 3) { printf("Enter element: "); fgets((void *)command, sizeof(command), stdin); push(test_list, command); //Insert counter++; } 我一直在使用中的一些示例代码,其

前言:目标是提示用户输入,将每个元素(输入行)添加到链接列表中

char command[120];
int counter = 0;
while(counter < 3) {
    printf("Enter element: ");
    fgets((void *)command, sizeof(command), stdin);
    push(test_list, command);   //Insert
    counter++;
}
我一直在使用中的一些示例代码,其中显示了一个链表示例。 我修改了代码,使其采用“字符串”而不是整数

我的插入功能如下所示:

void push(node_t * head, char *data) {
    node_t * current = head;

    if(head == NULL) {
      printf("First element ever!\n");
    }
    else if(current->data == NULL) {
      current->data = data;
      current->next = NULL;

    }
    else {
      while (current->next != NULL) {
        current = current->next;
        }
      current->next = malloc(sizeof(node_t));
      current->next->data = data;
      current->next->next = NULL;
   }
}
node_t * test_list = malloc(sizeof(node_t));
void print_list(node_t * head) {
    node_t * current = head;

    printf("**** Printing list ****\n");
    while (current != NULL) {
        printf("%s\n", current->data);
        current = current->next;
    }
}
现在,我主要提出以下清单:

void push(node_t * head, char *data) {
    node_t * current = head;

    if(head == NULL) {
      printf("First element ever!\n");
    }
    else if(current->data == NULL) {
      current->data = data;
      current->next = NULL;

    }
    else {
      while (current->next != NULL) {
        current = current->next;
        }
      current->next = malloc(sizeof(node_t));
      current->next->data = data;
      current->next->next = NULL;
   }
}
node_t * test_list = malloc(sizeof(node_t));
void print_list(node_t * head) {
    node_t * current = head;

    printf("**** Printing list ****\n");
    while (current != NULL) {
        printf("%s\n", current->data);
        current = current->next;
    }
}
通过以下方式添加元素:

  push(test_list, "FOO");
  push(test_list, "FEE");
  push(test_list, "FAA");
打印列表时,使用打印列表(测试列表),我得到以下输出:

FOO
FEE
FAA
问题

然而,我随后加入了一个while循环,提示用户输入,并将其添加到链表中

char command[120];
int counter = 0;
while(counter < 3) {
    printf("Enter element: ");
    fgets((void *)command, sizeof(command), stdin);
    push(test_list, command);   //Insert
    counter++;
}
该列表打印为:

FOO
FEE
FAA
Sweden
Sweden
Sweden
编辑(添加打印功能)

我的打印功能如下所示:

void push(node_t * head, char *data) {
    node_t * current = head;

    if(head == NULL) {
      printf("First element ever!\n");
    }
    else if(current->data == NULL) {
      current->data = data;
      current->next = NULL;

    }
    else {
      while (current->next != NULL) {
        current = current->next;
        }
      current->next = malloc(sizeof(node_t));
      current->next->data = data;
      current->next->next = NULL;
   }
}
node_t * test_list = malloc(sizeof(node_t));
void print_list(node_t * head) {
    node_t * current = head;

    printf("**** Printing list ****\n");
    while (current != NULL) {
        printf("%s\n", current->data);
        current = current->next;
    }
}

我遗漏了什么,或者:我如何修复这个问题?非常感谢您的帮助

您有一个容量为120的数组
命令
。您可以使用它来读取值。这没关系

然后发送指向要存储的数组的指针。它被储存起来了,一切都很好

下次读取输入时,将其读取到同一数组,并为该数组指定要存储的指针。因此,您正在更改指针指向的内存内容。这不好

您需要为每个字符串分配单独的内存区域,并处理它们的释放
strdup
是获取包含用户输入内容的新内存块的最简单方法


但请记住,当您不再需要内存时,您确实必须释放内存。在这种情况下,您可能永远不会删除任何字符串,但删除时,您不能只删除元素,还必须释放字符串使用的内存。

current->data=data此处仅复制指针地址而不是数据,在该地址(“命令”地址)上,最后一个数据(“瑞典”)将可用。

您应该使用
strcpy(当前->数据,数据)
来复制数据。

使用
strdup
来返回堆上分配的字符串的副本

函数的作用是:返回一个指向新字符串的指针,该字符串是字符串s的副本。新字符串的内存由malloc(3)获得,可用free(3)释放

node_t*test_list=malloc(sizeof(node_t));
测试列表->下一步=空;
测试列表->数据=NULL;
while(计数器<3){
printf(“输入元素:”);
fgets((void*)命令、sizeof(命令)、stdin);
push(test_list,strdup(command));//插入
计数器++;
}

我认为您应该使用strcpy复制城市名称,在这种情况下,使用指针指向城市名称可能不起作用。
node_t*test_list=malloc(sizeof(node_t));测试列表->数据=NULL推送(测试列表,标准(“FAA”);push(测试列表、strdup(命令))如果您在将“命令”字符串推送到列表之前打印它,那么您将看到您实际推送的内容,并确保得到您想要的内容,因为它在循环外部工作。调试器、记录器………@northerner您可以发布您的打印方法吗?我想这就是问题所在,谢谢你。有没有关于如何做到这一点的建议?发现内存分配很混乱。@Northern它看起来像是一个很难的主题。您应该阅读这方面的最佳实践,但一种开始的方法是思考谁“拥有”数据。在这种情况下,您可以假设列表“拥有”字符串,因此当从列表中删除元素时,列表节点和字符串都将是自由的。但请注意,之后不能有任何指向该节点或字符串的指针。这很公平。但是,为什么代码可以处理单独的push调用,比如push(test_list,“Hello”)和push(test_list,“Bye”)?为什么这些像HELLO-BYE而不是BYE-BYE一样存储@北方人,因为它们是由不同指针指向的独立内存区域。如果您要执行strcpy(命令“Hello”);推送(测试列表、命令);strcpy(命令,“再见”);推送(测试列表、命令)您将得到两次再见,因为您正在重用相同的内存区域。