我正在编写一个简单链接列表,它具有由 {name,price} 组成的元素结构,并且在我正在实现的一些函数中呈现出奇怪的行为。这些功能是:
PopFront
(删除列表的最后一个元素)PopByIndex
(给定条目索引,它将删除该位置上的元素)
到底发生了什么?好吧,这些函数确实删除了它们应该删除的元素,但它们以某种方式改变了列表中另一个元素的价格值😕。
示例:
使用前删除功能
Name: A Price: 1.00
Name: B Price: 2.00
Name: C Price: 3.00
Name: D Price: 4.00
--------
|Menu|
--------
(1) Add Element in Front
(2) Add Element in Back
(3) Add Element in Position
(4) Remove Element from Front
(5) Remove Element from Back
(6) Remove Element by Position
(7) Print List
(8) Calculate Itens Sum
(0) Exit Program
删除 D 元素后,A 的价格为 0
Name: A Price: 0.00
Name: B Price: 2.00
Name: C Price: 3.00
--------
|Menu|
--------
(1) Add Element in Front
(2) Add Element in Back
(3) Add Element in Position
(4) Remove Element from Front
(5) Remove Element from Back
(6) Remove Element by Position
(7) Print List
(8) Calculate Itens Sum
(0) Exit Program
我用gdb查看了元素被修改的具体时刻,发现是当我调用free()
来释放被删除元素地址的内存时
最小可重现示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node Node;
typedef struct List List;
struct Node {
char name[100];
float price;
int code;
struct Node *prox;
};
struct List{
struct Node *head;
int size;
};
Node* InstantiateNode() {
Node *new_node = malloc(sizeof new_node);
new_node->prox = NULL;
return new_node;
}
void InitNode(Node *node, char *name, float price) {
strcpy(node->name, name);
node->price = price;
}
void PrintNode(Node node){
printf("Name: %8s Price: %.2f\n", node.name, node.price);
}
int EmptyList(List list) {
return list.size == 0 ? 1 : 0;
}
List *InstantiateList(void) {
List *new_list = malloc(sizeof new_list);
new_list->head = NULL;
new_list->size = 0;
return new_list;
}
void InitList(List *list, Node *new_node) {
new_node->prox = list->head;
list->head = new_node;
list->size++;
}
void PushFront(List *list, Node *new_node) {
if (EmptyList(*list)) {
InitList(list, new_node);
return;
}
Node *tracker = list->head;
while (tracker->prox != NULL)
tracker = tracker->prox;
tracker->prox = new_node;
list->size++;
}
void PushBack(List *list, Node *new_node) {
InitList(list, new_node);
}
Node *TrackListbyIndex(List lista, int index) {
if (index > lista.size) {
printf("Unreachable List index \n"); // Warning
return NULL;
}
int cont = 0;
Node *aux = lista.head;
while (cont != index) {
aux = aux->prox;
cont++;
}
return aux;
}
void PushByIndex(List *list, Node *new_node, int index) {
if (index == 0) {
PushBack(list, new_node);
return;
}
Node *aux = TrackListbyIndex(*list, index - 1);
Node *aux2 = aux->prox;
if (aux) {
new_node->prox = aux->prox;
aux->prox = new_node;
list->size++;
}
}
void PopFront(List *list) {
if (EmptyList(*list))
return;
Node* aux = list->head;
Node* tracker, *tracker_next;
tracker = list->head;
if (tracker->prox != NULL) {
tracker_next = tracker->prox;
while (tracker_next->prox != NULL) {
tracker = tracker_next;
tracker_next = tracker_next->prox;
}
tracker->prox = NULL;
aux = tracker_next;
}
if (aux == list->head) {
list->head = NULL;
}
free(aux);
list->size--;
}
void PopBack(List* list){
if(EmptyList(*list))
return;
Node* aux = list->head;
list->head = list->head->prox;
free(aux);
list->size--;
}
void PopByIndex (List *list, int index) {
if (index == 0) {
PopBack(list);
return;
}
//if (index + 1 == list->size) {
// PopFront(list);
// return;
//}
Node *aux, *aux_next;
aux = TrackListbyIndex(*list, index - 1);
if (aux) {
aux_next = aux->prox;
aux->prox = aux_next->prox;
free(aux_next);
list->size--;
}
}
void PrintList(List list) {
Node *tracker = list.head;
while (tracker != NULL) {
PrintNode(*tracker);
tracker = tracker->prox;
}
}
void Menu(void);
void HandleMenu(int);
int main(void) {
int option;
for (;;) {
Menu();
printf("Type your choosen:");
scanf("%d", &option);
system("clear");
HandleMenu(option);
}
return 0;
}
void Menu(void) {
printf("\t--------\n");
printf("\t |Menu|\n");
printf("\t--------\n");
printf("(1) Add Element in Front\n");
printf("(2) Add Element in Back\n");
printf("(3) Add Element in Position\n");
printf("(4) Remove Element from Front\n");
printf("(5) Remove Element from Back\n");
printf("(6) Remove Element by Position\n");
printf("(7) Print List\n");
printf("(8) Calculate Itens Sum\n");
printf("(0) Exit Program\n");
}
void HandleMenu(int option) {
static List *market_list = NULL;
Node* new_node = NULL;
char node_name[100];
float node_price;
int index;
if (market_list == NULL)
market_list = InstantiateList();
switch (option) {
case 0:
exit(1);
break;
case 1:
new_node = InstantiateNode();
printf("Type the product's name: ");
scanf(" %[^\n]", node_name);
printf("Type the product's price: ");
scanf("%f", &node_price);
InitNode(new_node, node_name, node_price);
PushFront(market_list, new_node);
printf("Item Added\n");
break;
case 2:
new_node = InstantiateNode();
printf("Type the product's name: ");
scanf(" %[^\n]", node_name);
printf("Type the product's price: ");
scanf("%f", &node_price);
InitNode(new_node, node_name, node_price);
PushBack(market_list, new_node);
printf("Item Added\n");
break;
case 3:
new_node = InstantiateNode();
printf("Type the product's name: ");
scanf(" %[^\n]", node_name);
printf("Type the product's price: ");
scanf("%f", &node_price);
InitNode(new_node, node_name, node_price);
printf("Type Index: ");
scanf("%d", &index);
PushByIndex(market_list, new_node, index-1);
printf("Item Added\n");
break;
case 4:
PopFront(market_list);
break;
case 5:
PopBack(market_list);
break;
case 6:
printf("Type Index: ");
scanf("%d", &index);
PopByIndex(market_list, index-1);
break;
case 7:
PrintList(*market_list);
break;
}
}
最佳答案
InstantiateNode()
为Node *
分配空间,但您想要为Node
分配空间:
Node *new_node = malloc(sizeof *new_node);
InstantiateList()
为List *
分配空间,但您想要为List
分配空间:
List *new_list = malloc(sizeof *new_list);
经过这两项更改后,这是删除后的输出:
Name: A Price: 1.00
Name: B Price: 2.00
Name: C Price: 3.00
关于c - 简单链表实现 C 中的奇怪内存问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75710158/