尝试按字母顺序将学生插入链接列表。学生有名字和年龄。它们按名称排序,如果名称相同,则按年龄排序。
我可以正确命名名称,但是年龄有点棘手。分解的部分是第一个if语句。当一个新学生与列表中的第一个人同名时,则必须按年龄对他们进行排序,但是当我尝试使用该代码时,这给我带来了细分错误。其余代码有效。
这里是code
:
Student* insert(Student* student, Student* list)
{
Student* current;
if (list == NULL || (precedes(student->name, list->name) > 0) || strcmp(student->name, list->name) == 0){
if (strcmp(list->name, student->name) == 0) { // goes wrong here i think
if (student->age < list->age) {
student->next = list;
list = student;
} else {
student->next = list->next;
list->next = student;
}
} else {
student->next = list;
list = student;
}
} else {
current = list;
while(current->next != NULL && (precedes(current->next->name, student->name) > 0)) {
current= current->next;
}
if (current->next != NULL && strcmp(current->next->name, student->name) == 0) {
if (current->next->age > student->age){
student->next = current->next;
current->next = student;
} else {
student->next = current->next->next;
current->next->next = student;
}
} else {
student->next = current->next;
current->next = student;
}
}
return list;
}
答案 0 :(得分:2)
您正在做的事情比需要做的要困难得多。
您有一个明确的案例,其中肯定要取消引用空指针,这样就可以确保未定义的行为。在您的代码中:
if (list == NULL || (precedes(student->name, list->name) > 0) || strcmp(student->name, list->name) == 0){
if (strcmp(list->name, student->name) == 0) { // goes wrong here i think
如果由于list == NULL
为真而输入了if块,则将立即取消引用该空指针以访问其name
和age
成员。随之而来的是未定义的行为,实际上您是不幸的您的程序崩溃了(这可能更糟;它可能成功了,并让您相信自己没有错误)。
实用程序比较功能
只有两个Student
对象的比较可能潜在地是两阶段而不是一阶段的事实,才使此任务变得复杂。所以做两件事:
Student
结构的任何地方使用该功能。这样的比较功能如下:
int cmp_Student(const Student *lhs, const Student *rhs)
{
int cmp = strcmp(lhs->name, rhs->name);
if (cmp == 0)
cmp = (lhs->age < rhs->age) ? -1 : rhs->age < lhs->age;
return cmp;
}
当< 0
引用的lhs
小于Student
时,返回rhs
,当lhs
等于{{1}时返回零。 },以及rhs
比> 0
“大”的lhs
。
使用它,您可以编写一个简单的指针到指针漫游算法,该算法在列表中漫游指针以寻找合适的插入点,然后使用指针到指针来实现这一点。由于您确实不在乎,因此在rhs
为NULL时,这也消除了使用特殊大小写的需要。
list
即使您不执行此Student *insert(Student *student, Student *list)
{
Student **pp = &list;
while (*pp && cmp_Student(student, *pp) < 0)
pp = &(*pp)->next;
student->next = *pp;
*pp = student;
return list;
}
方法,仍可以将insert
用于自己的算法。无论如何,值得仔细阅读以上内容以了解其工作方式,而调试器是实现此目的的绝佳方法。
如果您坚持使用现有的实现,显然您需要修复该空指针取消引用代码路径,因为这显然是错误的。