下午好。我从StephenG.Kochan的一本名为《用C编程第三版》的书中学习C语言。我写了一些代码,应该从列表中插入和删除某些条目,但它确实做到了,问题是,它没有删除正确的条目,也没有完全将条目插入正确的位置。代码如下。如有任何帮助,我们将不胜感激!
//Insert and Remove entry functions using doubly linked lists
#include <stdio.h>
struct Entry
{
int Value;
struct Entry *Previous;
struct Entry *Next;
};
int main()
{
void InsertEntry (struct Entry *InsertPosition, struct Entry EntryToInsert);
void RemoveEntry (struct Entry *EntryToRemove);
struct Entry N1, N2, N3, N4, N5, Insert, *Start = &N1;
//set initial values
N1.Value = 10;
N2.Value = 20;
N3.Value = 20;
N4.Value = 30;
N5.Value = 40;
Insert.Value = 35;
//link the list
N1.Next = &N2;
N2.Next = &N3;
N3.Next = &N4;
N4.Next = &N5;
N5.Next = (struct Entry *) 0;
//Link again
N1.Previous = &N1;
N2.Previous = &N1;
N3.Previous = &N2;
N4.Previous = &N3;
N5.Previous = &N4;
InsertEntry(&N4, Insert);
RemoveEntry(&N2);
//Display the Lists
while (Start->Next != (struct Entry *) 0)
{
printf("Previous: %i, Current: %i, Next: %in", Start->Previous->Value, Start->Value, Start->Next->Value);
Start = Start->Next;
}
return 0;
}
void InsertEntry (struct Entry *InsertPosition, struct Entry EntryToInsert)
{
EntryToInsert.Previous = InsertPosition->Previous;
EntryToInsert.Next = InsertPosition;
InsertPosition->Previous->Next = &EntryToInsert;
}
void RemoveEntry (struct Entry *EntryToRemove)
{
EntryToRemove->Previous->Next = EntryToRemove->Next;
}
代码中有几个问题。
将InsertEntry和RemoveEntry的声明移到main()之前。
初始化Previous字段时,列表头需要Previous=NULL。
当打印出列表时,需要避免分别打印出列表头和尾部的"上一个->值"one_answers"下一个->值"。
在InsertEntry()函数中,代码通过将副本插入列表的值传递EntryToInsert结构。我猜您打算通过指针将原始结构插入列表。
在InsertEntry()函数中,还需要设置InsertPosition->Next->Previous。
在InsertEntry()函数中,在设置InsertPosition->Previous->Next和InsertPosition->Next->Previous之前,需要检查您是否分别位于列表的开头和末尾。
在RemoveEntry()函数中,还需要设置EntryToRemove->Next->Previous。
在RemoveEntry()函数中,在设置EntryToRemove->Previous->Next和EntryToRemove->Next->Previous之前,需要分别检查您是否位于列表的开头和末尾。
在RemoveEntry()函数中,还需要设置EntryToRemove->Previous=NULL和EntryToRemove->Next=NULL。
我建议你尝试自己解决上述每一个问题。如果你在修复给定问题时遇到问题,我已经将完整的代码与我建议的修复程序一起提供给你看。
struct Entry
{
int Value;
struct Entry *Previous;
struct Entry *Next;
};
void InsertEntry(struct Entry *InsertPosition, struct Entry *EntryToInsert);
void RemoveEntry(struct Entry *EntryToRemove);
int main()
{
struct Entry N1, N2, N3, N4, N5, Insert, *Start = &N1;
//set initial values
N1.Value = 10;
N2.Value = 20;
N3.Value = 20;
N4.Value = 30;
N5.Value = 40;
Insert.Value = 35;
//link the list
N1.Next = &N2;
N2.Next = &N3;
N3.Next = &N4;
N4.Next = &N5;
N5.Next = NULL;
//Link again
N1.Previous = NULL;
N2.Previous = &N1;
N3.Previous = &N2;
N4.Previous = &N3;
N5.Previous = &N4;
InsertEntry(&N4, &Insert);
RemoveEntry(&N2);
//Display the Lists
while (Start != (struct Entry *) 0)
{
printf("Previous: ");
if (Start->Previous != NULL)
{
printf("%i", Start->Previous->Value);
}
else
{
printf("NULL");
}
printf(", Current: %i, Next: ", Start->Value);
if (Start->Next != NULL)
{
printf("%i", Start->Next->Value);
}
else
{
printf("NULL");
}
printf("n");
Start = Start->Next;
}
return 0;
}
void InsertEntry(struct Entry *InsertPosition, struct Entry *EntryToInsert)
{
EntryToInsert->Previous = InsertPosition->Previous;
EntryToInsert->Next = InsertPosition;
if (InsertPosition->Previous != NULL)
{
InsertPosition->Previous->Next = EntryToInsert;
}
InsertPosition->Previous = EntryToInsert;
}
void RemoveEntry(struct Entry *EntryToRemove)
{
if (EntryToRemove->Previous != NULL)
{
EntryToRemove->Previous->Next = EntryToRemove->Next;
}
if (EntryToRemove->Next != NULL)
{
EntryToRemove->Next->Previous = EntryToRemove->Previous;
}
EntryToRemove->Previous = NULL;
EntryToRemove->Next = NULL;
}
InsertEntry
函数有几个问题。
首先,您需要将指针传递给InsertPosition
和EntryToInsert
。这是因为在C中,所有东西都是通过值传递的。这意味着,当您将值传递给函数时,该函数将看到该值的副本,而不是原始值。一旦该功能完成,副本将永远消失。因此,如果你想修改函数内部的某些内容,并在函数完成后使其可见,那么你必须传递一个指向该内容的指针。C中的指针指向内存中的某个位置,因此即使函数获得了该指针的副本,它指向的位置也是相同的。
这意味着第一步是将函数定义为:
void InsertEntry (struct Entry *InsertPosition*, struct Entry *EntryToInsert)
其次,插入EntryToInsert
的顺序与您想要完成的任务不符-您希望在InsertPosition
之后而不是之前插入此值
void InsertEntry (struct Entry *InsertPosition, struct Entry *EntryToInsert)
{
//Goal is to insert EntryToInsert *before* InsertPosition
// so that it will look like:
// ??? --> EntryToInsert --> InsertPosition
//Step 1: ??? <-- EntryToInsert
EntryToInsert->Prev = InsertPosition->Prev;
//Step 2: EntryToInsert --> InsertPosition
EntryToInsert->Next = InsertPosition;
//Step 3: ??? --> EntryToInsert
EntryToInsert->Prev->Next = EntryToInsert;
//Step 4: EntryToInsert <-- InsertPosition
InsertPosition->Prev = EntryToInsert;
}
最后,您当前在main
函数内部的函数声明通常在函数外部(之前)。
解决这个问题应该可以解决RemoveEntry
函数的任何问题——再说一遍,我认为这没有问题。