2017-03-10 93 views
1

我一直有一个很难搞清楚这段代码:链表开头插入

typedef struct student_grade sg; 

sg *first = NULL; 
sg *renew = NULL; 
sg *temp = NULL; 

int num; 
float g; 
char classname[12], fn[STR_LENS], ln[STR_LENS]; 

printf("Enter the classname (without spaces): "); 
scanf("%11s", classname); 

printf ("Enter the student's name and their grade. Enter 0 0 0 to quit. \n(FirstLast ##.#): "); 



num = scanf("%11s %11s %f", fn, ln, &g); 

while (fn[0] != '0') 
{ 
    if (num == 3) 
    { 
     renew = (sg*) malloc(sizeof(sg)); 

     strncpy(renew->first_name, fn, STR_LENS-1); 
     strncpy(renew->last_name, ln, STR_LENS-1); 
     renew->grade = g; 
     renew->next = first; //next pointer to first 
     first = renew; //assign address of renew to first 
    } 
    else 
    { 
     return 1; 
    } 

    printf("Enter the student's name and their grade.Enter 0 0 0 to quit\n(First Last ##.#): "); 

    num = scanf("%11s %11s %f", fn, ln, &g); 

} 

特别是这部分:

 renew = (sg*) malloc(sizeof(sg)); 

     strncpy(renew->first_name, fn, STR_LENS-1); 
     strncpy(renew->last_name, ln, STR_LENS-1); 
     renew->grade = g; 
     renew->next = first; //next pointer to first 
     first = renew; //assign address of renew to first 

renew被分配结构,指向first指针,它最初是NULL,并且first被指定了与renew相同的地址,然后指向地址renew。在第二次循环之后,同样的renew显然被克隆,并且也指向first的地址,然后first的地址被分配与克隆的renew相同的地址。

没有一个加起来。

回答

0

没有发生renew的克隆。每次迭代都会分配一块新的内存(这就是malloc调用的目的),并将指针更改为引用此新内存。

0

这是一个向链表添加新元素的循环。

第一个scanf读取类名,就是这样。然后,还有另一种scanf存储姓,名和等级分为3个变量,然后while循环开始:

每次代码malloc新元素的空间分配,然后填充它的3个字段(您没有显示struct student_grade的定义,但我们可以推断出它具有first_name,last_namegrade)字段,方法是将用户使用scanf插入的数据复制到这些数据中,然后再处理链表两行:我们在开始时插入,这意味着新元素将成为第一个元素。因此,renew->next = first;确保在我们正在创建的元素之后的元素(它不在列表中!)是当前的第一个(它将成为下一行的第二个元素),然后与first = renew;程序确保从现在开始,名单将从我们添加的元素开始。

在循环结束时,新的scanf要求提供另一名学生的数据,这些数据与以前一样存储在相同的变量中,以便在循环的下一次迭代中将它们复制到结构中,并且它一直持续到用户插入一个0.

这里没有克隆。每次拨打电话malloc时,都会获得一块与上一块不同的新内存块,其地址暂存在renew中。由于每次都会覆盖renew,并且您不想丢失它,所以您必须确保它存储在某处:第一个元素的地址始终存储在first中,并且每个元素都将指针(next)存储到下一个元素,这样就不会丢失地址。每次都不克隆renew;相反,变量总是相同的,但其值(地址)每次都会改变。

0

第二次循环后,同样的'更新'显然被克隆...

首先renew未被克隆。一个全新的内存空间被分配给它。

您想将renew添加到列表的开头。一个不同的指针(first)指向列表的开始。

renew->next = first; - 这条线,你基本上说,“好吧,从这点renew将是第一个项目在我的名单和它的下一个项目将是实际first。基本上renew是我的清单中的第0项。“

first = renew; - 您有指针指向您的列表开头。您还希望first点指向列表的开始。所以解决方法是将first指针设置为指向first指针所指向的内存位置。现在,您的指针都会正确指向列表中的第一个项目。

renew基本上用作辅助指针。它有助于将新项目添加到列表中。另一方面,first指针是你列表的重要组成部分。它的工作是指向列表中的第一个元素。