私があなたのコードについて何か理解しているなら、
問題1(もっともらしい):
goList = userInventory;
do {
...
goList = goList->next;
} while (goList != userInventory);
これは循環リストですか?そうでない場合、の条件はwhile ()
真になりません。
問題2:
goList = userInventory;
do {
if (strcmp(userInventory->username, args[1]) == 0) {
...
}
goList = goList->next;
} while (goList != userInventory);
ここでは、現在のノードの文字列を比較する代わりに、リストの先頭(または末尾)の文字列を比較し続けますgoList
。一致を見つけることは、一致が最初にuserInventory
指す最初のノード(ヘッド/テール)にある場合にのみ、上記のコードで成功することができます。
問題3:
temp2 = userInventory->next;
if (userInventory->next != NULL) {
userInventory->next = temp2->next;
userInventory->next->prev = userInventory;
}
free(temp2);
userInventory
すでに次のように修正されていると仮定しましょうgoList
:
temp2 = goList->next;
if (goList->next != NULL) {
goList->next = temp2->next;
goList->next->prev = goList;
}
free(temp2);
まず第一に、それfree()
は一致するノードではなく、その次のノード(またはおそらくNULL
)に行きますが、これは間違っています。
第二に、このコードはノードの適切なリンク解除と再リンクを行っていません。それがどうあるべきか(リストが循環していないと仮定して):
temp2 = goList;
if (goList->next != NULL) {
goList->next->prev = goList->prev; // now goList->next node points to goList->prev node
}
if (goList->prev != NULL) {
goList->prev->next = goList->next; // now goList->prev node points to goList->next node
}
free(temp2);
問題4:
do {
if (strcmp(goList->username, args[1]) == 0) {
temp2 = goList;
if (goList->next != NULL) {
goList->next->prev = goList->prev; // now goList->next node points to goList->prev node
}
if (goList->prev != NULL) {
goList->prev->next = goList->next; // now goList->prev node points to goList->next node
}
free(temp2);
}
goList = goList->next;
} while (...);
削除が成功すると、この行は解放されたばかりのノードにアクセスし、プログラムをクラッシュさせる可能性があります。
goList = goList->next;
したがって、コードを次のように変更する必要があります。
do {
if (strcmp(goList->username, args[1]) == 0) {
temp2 = goList;
if (goList->next != NULL) {
goList->next->prev = goList->prev; // now goList->next node points to goList->prev node
}
if (goList->prev != NULL) {
goList->prev->next = goList->next; // now goList->prev node points to goList->next node
}
goList = goList->next;
free(temp2);
}
else
{
goList = goList->next;
}
} while (...);
問題5:
goList = userInventory;
リストヘッド(またはテール?)ノードを削除した場合はuserInventory
、その次のノードを指すように更新する必要があります。そうしuserInventory
ないと、残りのノードが存在する場合ではなく、解放されたメモリを指すため、リストへのすべてのアクセスが失われます。
問題6(もっともらしい):
free(temp2);
上記の行はfree()
、背後のメモリではありませんtemp2->username
。それが編集されfree()
た場合、あなたはそれをしたいです。malloc()
実際には、一度に1ステップずつ問題に取り組む必要があります(たとえば、最初にリストを反復処理し、次にノードのリンク解除/再リンクを行い、次にノードを削除します)。
物事がはっきりしない、または機能していない場合は、紙と鉛筆(または製図板とペンまたはチョーク)を使用して、問題を自分で視覚化します。オブジェクト、ポインターまたはそれらの間のその他の接続を示す矢印などを描画し、オブジェクトの横に変数名を書き留めて、図からコードに進む方法を明確に確認できるようにします。