我正在构建一个函数,该函数应该删除链表中的一个项。我的问题是,我可以删除任何元素,但不能删除第一个,为什么?
我的目标文件:
typedef struct list {
char *key;
char *value;
struct list *next;
} List;
void db_init(List *list) {
list = malloc(sizeof(db_sizeOfStruct()));
list->next = NULL;
list->key = NULL;
list->value = NULL;
}
void db_delete(char *key, List *list) {
List *prev;
db_init(prev);
int first = 1;
while(list != NULL) {
if(strcmp(key, list->key) == 0) {
if(first == 1) {
list = list->next; // This is supposed to delete the first item in the list but it does not work...
} else {
prev->next = list->next;
}
return;
} else {
prev = list;
list = list->next;
first = 0;
}
}
}
在程序的主文件中:
void delete(List *list) {
printf("key: ");
char *key;
key = malloc(sizeof(key)+1);
readline(key, 128, stdin);
if(key != NULL) {
db_delete(key, list);
}
}
int main(void) {
delete(list);
return 0;
}
这里有几个问题
首先,调用db_init,即使您想删除一个元素,它也会分配一个元素。
其次,您需要考虑的是,如果第一个元素被删除,您需要返回新的第一个元素的地址,但对于您当前的函数,您不需要这样做。
原型应该是这样的,而不是
void db_delete(char *key, List **list)
或者可能更整洁一点,通过返回第一个元素:
List* db_delete(char *key)
所以这个功能可能看起来像这个
List* db_delete(const char *key, List *list)
{
// normally it is not a good idea to use an argument
// to a function as a loop variable in a function
// also check arguments to avoid segfaults and
// other headaches
if ( key != NULL && list != NULL )
{
List* cur = list;
List* prev = NULL;
for ( ; cur != NULL; cur=cur->next )
{
// identify if it is the one to delete
if ( !strcmp(key, cur->key) )
{
if ( prev != NULL ) // if not first
{
List* tmp = cur;
prev->next = cur->next;
free(tmp);
return list;
}
else // if first
{
List* tmp = cur;
List* next = cur->next;
free( tmp );
return next;
}
}
}
prev = cur;
}
return list;
}
另一个技巧是使用calloc而不是malloc,然后就不用了需要初始化next、prev,因为它们将已经是0。
这是因为删除函数无法与调用方通信,所以列表现在有了一个新的第一个元素。
最好的解决方案是让它返回列表的新标题:
List * db_delete(List *list, const char *key);
您必须更改main中的列表Variable。如果您将一个指针传递给一个指向删除函数(如"delete(List**List)"