user-0 提问: 【问题多多】…链表的第一个节点就没连上去…求指导…

回复:
user: user-1
content: 楼主你好，我不同意以上的回复，我觉得calloc没有问题，虽然函数原型是（size_num，size_size），意思就是分配多少个字节给你的链表的每一个元素，试想sizeof(int) 会是4或者8，如果你想分配int的话，直接就是calloc（4,1），或者是calloc（8,1），这和电脑的不同和编译器的不同有关，但是sizeof(node)已经指明了要分配多少个1字节，所以calloc的问题不是问题，只是严谨不严谨的问题，还有current=current->next的问题，上面说的只是打印的头结点我觉得是不对的，  while(current->next) {       print_node(current);       current=current->next; }  这个语句先是判断current->next是不是空，不空就打印 如果你的链表有三个，Head指向a指向b指向c指向NULL 这样的话打印的就是a,b但是不打印c  while(current) {      print_node(current);      current=current->next; }  这个语句打印的是头结点，a,b,c多打印了一个头结点，严格说也是不对的 应该先让current=head->next再运行上面的代码，就可以打印出楼主想打印的内容。

user: user-0
content: 谢谢各位的耐心指导，我现在觉得写单向链表已经顺利多了，昨天又试了一下，只是不熟悉罢了，但是都还能运行，我很开心！

user: user-1
content: 刚刚看见，不知道楼主还在吗？上面我说的有错误，因为昨天时间紧急，你的calloc是可以为头结点分配内存的，刚刚我用vs试了一下你的代码,就是你发帖的代码，你的代码可以编译成功，但是运行的时候输入确有问题，出现在  scanf("%s", &node->name);  链表里面的东西是不能这样赋值的，即使是int float可以用scanf，给链表的内容赋值你可以先建立一个数组a[255]，然后scanf("%s",a);strcpy(node->name,a);这样才可以。 其他地方我试了没有出问题，至于你的头结点地址的问题我没有遇见，或许是我们俩的编译器不同，我修改了赋值语句之后所有的代码都可以成功运行，并且分配数据。 以上的代码是我成功运行在vs上面的，希望楼主试一下。

user: user-2
content: 引用 18楼我是你的主体 的回复:[quote=引用 13 楼 qq_36100960 的回复:] 遍历打印的逻辑错了。。。 你的逻辑是：current指向头，current的下一个结点不是空，所以打印current，然后将current移到下一个结点， 此时current指向第二个结点，判断current的下一个结点是否为NULL，发现为NULL，退出。 所以你打印的一直是头  这么看的话我应该 while(current){     print_node(current);     current = current->next;l }[/quote]你把打印和后移换一下就好了

user: user-0
content: 引用 17 楼 gaozeng851998821 的回复:还是试着尽量用calloc()函数吧，可以初始化。  好的，感谢指导！

user: user-0
content: 引用 13 楼 qq_36100960 的回复:遍历打印的逻辑错了。。。 你的逻辑是：current指向头，current的下一个结点不是空，所以打印current，然后将current移到下一个结点， 此时current指向第二个结点，判断current的下一个结点是否为NULL，发现为NULL，退出。 所以你打印的一直是头  这么看的话我应该 while(current){     print_node(current);     current = current->next;l }

user: user-3
content: 还是试着尽量用calloc()函数吧，可以初始化。

user: user-0
content: 引用 14 楼 gaozeng851998821 的回复:temp = (NODE *)calloc(sizeof(NODE), 1);   这一句 对calloc()函数的运用有误，应该是calloc(1，sizeof(NODE)) 吧  呃…谢谢！的确函数原型是void* calloc (size_t num, size_t size);…实在不行……我还是老老实实的malloc(sizeof(NODE))吧……

user: user-0
content: 引用 12 楼 qize9956 的回复:...... 其他地方我试了没有出问题，至于你的头结点地址的问题我没有遇见，或许是我们俩的编译器不同，我修改了赋值语句之后所有的代码都可以成功运行，并且分配数据。 以上的代码是我成功运行在vs上面的，希望楼主试一下。   非常感谢，我明白了。 话说是不是和字符有关的这种赋值都要用strcpy这种方式？ 额……原理是？……

user: user-3
content: temp = (NODE *)calloc(sizeof(NODE), 1);   这一句 对calloc()函数的运用有误，应该是calloc(1，sizeof(NODE)) 吧

user: user-2
content: 遍历打印的逻辑错了。。。 你的逻辑是：current指向头，current的下一个结点不是空，所以打印current，然后将current移到下一个结点， 此时current指向第二个结点，判断current的下一个结点是否为NULL，发现为NULL，退出。 所以你打印的一直是头

user: user-0
content: 引用 10 楼 qq_36100960 的回复:首先不认同楼上的观点，calloc是在堆上分配，楼主这样返回地址是可以的  我直接拿你云盘里的代码进行验证，编译有个fprintf的警告，运行结果没问题   这是我原先的代码 http://pan.baidu.com/s/1pL8pH2N  您下载的是我之后按照@cfjtaishan的代码吧自己的代码重写的，重写之后我的确可以正常添加节点了，但是我最开始的代码却不能正确运行。我看这两个版本的代码最主要的区别似乎只是“if(HEAD == NULL) return NULL;”和"if(!HEAD)return NULL;"。  我想知道到底我先前写的旧代码是哪里出的问题。

user: user-2
content: 首先不认同楼上的观点，calloc是在堆上分配，楼主这样返回地址是可以的  我直接拿你云盘里的代码进行验证，编译有个fprintf的警告，运行结果没问题

user: user-0
content: 引用 6 楼 cfjtaishan 的回复:#include <stdio.h> #include <stdlib.h> #include <string.h>  ... 改了一些地方，试一下  我又仔细的看了一遍你的代码，我发现改动不大，主要是在这里的分歧：  你的是： [code] ...     if (!HEAD) {         fprintf(stderr, "malloc error!\n");         exit(-1);     }       HEAD->next = NULL;     return HEAD; }   [code] ...     if(HEAD == NULL)return HEAD;       HEAD->next = NULL;     return HEAD; }   难道主要区别就在这里么？具体时什么区别？  我按照你之前代码的提示，写了自己的版本。的确用你的判断方式就OK了……好神奇…… 我的版本：http://pan.baidu.com/s/1slLIODR

user: user-0
content: 引用 5 楼 qize9956 的回复:..... 这就是C语言的机制，你用主函数定义了一个空指针。然后想用函数的方式给这个空指针，让这个指针指向你用函数分配的空间，这个空间只在函数里面有效，当运行完函数后，这个空间就被C语言释放了。   麻烦您帮我看看我这个应该怎么改？

user: user-0
content: 引用 6 楼 cfjtaishan 的回复:#include <stdio.h> #include <stdlib.h> #include <string.h>  typedef struct node{     int id; ... 改了一些地方，试一下  厄……谢谢你帮我补完了很多我还没有开始着手写的功能。但是我更想知道我关注的那些问题。  比如我的代码中append_node或者create_head哪里出的问题，修改成什么样才可以，为什么要这样改——这种。  毕竟我还是新手，想真正能玩转指针+结构体+链表。  麻烦兄弟多费心大概解释解释。谢谢！

user: user-4
content: #include <stdio.h> #include <stdlib.h> #include <string.h>  typedef struct node{     int id;     char name[255];     double value;     struct node *next; }NODE;   int init_node(NODE *node) {     short int stat = -1;      printf("\nNODE ADDR 0x%p...\n", node);      printf("\n\nPLEASE FILL THIS FORM:\nID >>> ");     scanf("%d",&node->id);     printf("NAME >>> ");     scanf("%s",node->name);     printf("VALUE >>> $");     scanf("%lf",&node->value);      printf("NODE INFORMATION INITLIZED.\n\n");     stat = 0;      return stat; }  NODE *create_head() {     NODE *HEAD = (NODE *)calloc(sizeof(NODE), 1);     if (!HEAD) {         fprintf(stderr, "malloc error!\n");         exit(-1);     }      HEAD->next = NULL;     return HEAD; }  int append_node(NODE *HEAD) {     NODE *temp, *current = HEAD;      while (current->next)         current = current->next;      temp = (NODE *)calloc(sizeof(NODE), 1);     if(!temp)         return -1;      printf("\nNODE ADDR 0x%p...\n", temp);      temp->next = NULL;     init_node(temp);      printf("\ncurrent: 0x%p...\n",current);     printf("\ncurrent->next: 0x%p...\n",current->next);     current->next = temp;     printf("\ncurrent: 0x%p...\n",current);     printf("\ncurrent->next: 0x%p...\n",current->next);     current = current->next;     printf("\ncurrent: 0x%p...\n",current);     printf("\ncurrent->next: 0x%p...\n",current->next);      return 0; }   int count(NODE *HEAD) {     NODE *current = HEAD;     int count = 0;      while(current){         count++;         current = current->next;     }      return count; }  static void print_node (NODE *pcur) {     printf("id = %d\t name = %s\t value = %lf\n",            pcur->id, pcur->name, pcur->value); }  void destroy_nodes(NODE *phead) {     NODE *p = phead->next, *q;      while (p) {         q = p->next;         free(p);         p = q;     } }  void delete_head(NODE *phead) {     free(phead); }  void list(NODE *HEAD) {     NODE *current = HEAD->next;     if (count(HEAD) <= 1) {         printf("YOU DO NOT HAVE ANY NODE IN TABLE.");         return;     }      while (current) {         print_node(current);         current = current->next;     } }  int main() {     NODE *head = create_head();      list(head);     if(append_node(head)){         printf("APPEND FAILED!");         return 1;     }     list(head);     destroy_nodes(head);     delete_head(head);      return 0; } 改了一些地方，试一下

user: user-1
content: 引用 2 楼 克里喵子的回复:[quote=引用 1 楼 qize9956 的回复:] 你的头节点，用的是函数分配的内存，那么问题来了，你用函数分配的head内存能返回回来吗？也就是说，在运行完函数之后，你的头节点仍然是空的。 NODE *create_head(){     NODE *HEAD = (NODE *)calloc(sizeof(NODE),1);     if(HEAD == NULL)return HEAD;       HEAD->next = NULL;     return HEAD; }  额……这里不是return的HEAD么？ 然后main里面这样调用难道取不到返回的HEAD么？  NODE *head = create_head();[/quote] 这就是C语言的机制，你用主函数定义了一个空指针。然后想用函数的方式给这个空指针，让这个指针指向你用函数分配的空间，这个空间只在函数里面有效，当运行完函数后，这个空间就被C语言释放了。

user: user-1
content: 引用 2 楼 克里喵子的回复:[quote=引用 1 楼 qize9956 的回复:] 你的头节点，用的是函数分配的内存，那么问题来了，你用函数分配的head内存能返回回来吗？也就是说，在运行完函数之后，你的头节点仍然是空的。 NODE *create_head(){     NODE *HEAD = (NODE *)calloc(sizeof(NODE),1);     if(HEAD == NULL)return HEAD;       HEAD->next = NULL;     return HEAD; }  额……这里不是return的HEAD么？ 然后main里面这样调用难道取不到返回的HEAD么？  NODE *head = create_head();[/quote] 这就是C语言的机制，你用主函数定义了一个空指针。然后想用函数的方式给这个空指针，让这个指针指向你用函数分配的空间，这个空间只在函数里面有效，当运行完函数后，这个空间就被C语言释放了。

user: user-1
content: 引用 2 楼 克里喵子的回复:[quote=引用 1 楼 qize9956 的回复:] 你的头节点，用的是函数分配的内存，那么问题来了，你用函数分配的head内存能返回回来吗？也就是说，在运行完函数之后，你的头节点仍然是空的。 NODE *create_head(){     NODE *HEAD = (NODE *)calloc(sizeof(NODE),1);     if(HEAD == NULL)return HEAD;       HEAD->next = NULL;     return HEAD; }  额……这里不是return的HEAD么？ 然后main里面这样调用难道取不到返回的HEAD么？  NODE *head = create_head();[/quote] 这就是C语言的机制，你用主函数定义了一个空指针。然后想用函数的方式给这个空指针，让这个指针指向你用函数分配的空间，这个空间只在函数里面有效，当运行完函数后，这个空间就被C语言释放了。