我一直很难弄明白这段代码:
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 firstrenew被分配给该结构,指向first指针,该指针最初为空,first被分配相同的地址给renew,然后该地址指向renew的地址。在第二次循环之后,相同的renew显然被克隆,并且还指向first的地址,然后first的地址被分配到与克隆的renew相同的地址。
所有这些都不合理。
发布于 2017-03-10 09:11:05
没有发生renew的克隆。每次迭代都会分配一个新的内存块(这就是malloc调用正在做的事情),并更改renew指针以引用这个新内存。
发布于 2017-03-10 09:19:52
这是一个将新元素添加到链表开头的循环。
第一个scanf读取类名,仅此而已。然后,还有另一个scanf,它将名字、姓氏和成绩存储到3个变量中,然后while循环开始:
每次代码使用malloc为新元素分配空间,然后填充它的3个字段(您没有显示struct student_grade的定义,但我们可以推断出它具有字段first_name、last_name和grade),方法是将用户使用scanf插入的数据复制到其中,然后再有2行处理链表:我们在开头插入,这意味着新元素将成为第一个元素。因此,renew->next = first;确保我们正在创建的元素之后的元素(它还不在列表中!)是当前的第一个(它将成为下一行的第二个),然后使用first = renew;,程序确保从现在开始列表将从我们添加的元素开始。
在循环结束时,新的scanf请求另一个学生的数据,这些数据存储在与之前相同的变量中,以便在循环的下一次迭代中可以将它们复制到结构中,并继续执行,直到用户插入0。
这里没有克隆。每次调用malloc时,您都会得到一个新的内存块,它的地址临时存储在renew中。因为renew每次都会被覆盖,并且您不想丢失它,所以必须确保它存储在某个地方:第一个元素的地址总是存储在first中,每个元素都存储一个指向下一个元素的指针(next),这样就不会丢失地址。renew并不是每次都被克隆;相反,变量总是相同的,但它的值(地址)每次都会改变。
发布于 2017-03-10 09:20:27
在第二次循环之后,同样的“
”显然被克隆了……
首先,renew没有被克隆。一个全新的内存空间被分配给它。
您希望将renew添加到列表的开头。另一个指针(first)指向列表的开头。
renew->next = first; -使用这一行,你基本上可以说‘好的,从现在开始,renew将是我列表中的第一项,它的下一项将是实际的first。基本上,renew是我列表中的第0项。’
first = renew; -你有一个指向列表开头的renew指针。您还希望first指针指向列表的开头。因此,解决此问题的方法是将first指针设置为指向与first指针相同的内存位置。现在,您和您的指针将正确地指向列表中的第一项。
renew基本上被用作辅助指针。它有助于向列表中添加新项目。另一方面,first指针是列表中的一个重要组成部分。它的作用是指向列表中的第一个元素。
https://stackoverflow.com/questions/42708163
复制相似问题