尝试按字母顺序将学生插入链表。学生有姓名和年龄。它们按名称排序,如果名称相同,则按年龄排序。
我可以把名字部分弄对,但年龄有点棘手。崩溃的部分是第一个 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;
}
你做得比它需要的要困难得多。
您有一个明显的情况,即取消引用空指针是确定的,因此确保未定义的行为也是如此。在您的代码中:
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
引用 a时返回Student
“小于” rhs
,当lhs
等于时返回零rhs
,> 0
当lhs
“大于”时返回rhs
。
使用它,然后您可以编写一个简单的指针到指针遍历算法,该算法遍历列表中的指针以寻找合适的插入点,然后使用指针到指针来实现这一点。当list
为 NULL 时,这也消除了特殊大小写的需要,因为您真的不在乎。
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
,你仍然可以使用cmp_Student
你自己的算法。无论如何,仔细阅读上面的内容以了解其工作原理是值得的,而调试器是一种很好的方法。
显然,如果您坚持使用现有实现,则需要修复该空指针取消引用代码路径,因为这显然是错误的。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句