我正在尝试通过编写一个程序来学习 C 基础知识,该程序提示用户输入整数,然后将值存储在链接列表中。如果输入为 -128
或更低,则 current
节点将设置为 NULL
并且提示结束。然后程序遍历列表并计算输入值的平均值。然而,列表的计数器总是比预期多一个元素,从而导致不正确的平均值,尽管我在添加每个值和递增计数器之前明确指定了 NULL
检查。
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main()
{
struct record {
int temperature;
struct record *next;
};
// Keep hold of the first record for iterating --v
struct record *first = NULL;
first = (struct record *)malloc(sizeof(struct record));
// Keep hold of the current record used in the while loop --v
struct record *current = first;
while (true) {
// Get user input --v
int temp;
printf("Enter measurement: ");
scanf("%d", &temp);
// If input is less than -128, end the loop --v
if (temp <= -128) {
current = NULL;
break;
}
// Record the temperature --v
current->temperature = temp;
// Allocate memory for the next record --v
current->next = (struct record *)malloc(sizeof(struct record));
// The next now becomes the current because we are done with the current --v
current = current->next;
printf("Next record created!\n");
}
// Calculate average --v
current = first;
double sum = 0.;
int count = 0;
// As long as the record is not NULL --v
while (current != NULL) {
sum += current->temperature;
count++;
printf("%d %d\n", count, current->temperature);
// Move to the next record --v
current = current->next;
}
printf("\nAverage of the list values: %.1f", sum / count);
}
这是正确的行为吗? C 语言中是否有一些我不知道的机制?
我添加了一些调试行,以便可以跟踪计数器以及相应的记录,并发现尽管我显式设置了 current
属性,但它似乎并不为 NULL它为NULL。这是代码的输出:
Enter measurement: 22
Next record created!
Enter measurement: 22
Next record created!
Enter measurement: 22
Next record created!
Enter measurement: -128
1 22
2 22
3 22
4 0
Average of the list values: 16.5
我确实尝试使用free(current)
释放current
指针的内存,但结果并没有更好,因为温度
然后只保存一个随机数。
最佳答案
问题是指针current
和current->next
是两个不同的指针,占用不同的内存范围。 current
是局部变量,而 current->next
是动态分配节点的数据成员。
在此声明中
current = current->next;
您将指针current->next
的值设置为指针current
。所以两个指针具有相同的值。
但在这个 if 语句中
if (temp <= -128) {
current = NULL;
break;
}
仅改变了指针当前
。指针“前一个”当前->下一个
保持不变。也就是说,局部变量current
已更改,但动态分配节点的数据成员next
未更改,并且指向具有未初始化数据成员的动态分配节点。
分配内存时的做法是这样的
// Allocate memory for the next record --v
current->next = (struct record*) malloc(sizeof(struct record));
// The next now becomes the current because we are done with the current --v
current = current->next;
并且它的地址被分配给指针current->next
,然后尝试在循环内将指针设置为NULL
,无论如何都会导致内存泄露。您应该重新设计代码的逻辑。
最简单的方法是使用指向指针的指针,例如
struct record *first = NULL;
struct record **current = &first;
while (true) {
// Get user input --v
int temp;
printf("Enter measurement: ");
scanf("%d", &temp);
// If input is less than -128, end the loop --v
if (temp <= -128) {
break;
}
*current = malloc( sizeof( struct record ) );
( *current )->temperature = temp;
( *current )->next = NULL;
current = &( *current )->next;
puts("Next record created!");
}
在 while 循环之外,您需要使用另一个名称作为辅助指针。例如
// Calculate average --v
struct record *tmp = first;
// and so on...
请注意——当不再需要该列表时,您将需要释放所有分配的内存。
关于c - 在 C 中迭代链表时空检查行为不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75476068/