方案中(等于?)比较的类型不正确



我正在scheme中编写一个程序,该程序将允许我管理与学生有关的信息列表。该列表的每个元素都是另一个列表,包含关于学生的3个项目:ID(数字字符串)、学生姓名(字符字符串)和成绩(整数)。我目前正在尝试编写一个函数,按ID升序对我的学生列表进行排序。除了这个函数,我还试图编写两个辅助函数,"最小"one_answers"删除">

我测试了我的最小函数,它正确地返回了最小的ID。现在我正在测试我的remove函数,看看它是否会返回一个列表,其中包含删除了最小ID的student元素:

当我调用(display(remove花名册(最小花名册(car(car花名册))))时,我得到一个错误,说‘;作为参数传递给字符串->数字的对象("4"lini"94")不是字符串。'进行此调用时的当前列表为:((5 me 95)(4 lini 94)(3 rudy 93)(2 mark 92)(1 silas 91))。我使用了字符串->number函数进行>比较,所以我认为它在这里也能工作,但我也没有得到我想要比较的列表中的正确元素。这导致我将(car(car花名册)添加到(equal?)的第二个参数中,这给了我错误';作为第一个参数传递给car的对象"5"不是正确的类型

有人知道我在这里做错了什么吗?我也被限制使用set!函数、do循环和任何内置的排序函数。

(define smallest
(lambda (roster record)
(if (null? roster)
(begin (display record) record)
(if (> (string->number record) (string->number (car (car roster))))
(smallest (cdr roster) (car(car roster)))
(smallest (cdr roster) record)))
))
(define remove
(lambda (roster record)
(if (equal? (string->number record) (string->number (car(car(car roster)))))   
(cdr roster)
(remove (list (cdr roster) (car roster)) record) 
)))
(define performtask
(lambda (n roster)
(cond ((= n 0) (begin
(display "ntOption 0.")
(display "nReset Roster")
(menu '())
))
((= n 1) (begin
(display "ntOption 1.")
(display "nLoad Roster From File")
(menu roster)
))
((= n 2) (begin                                   
(display "ntOption 2.")
(display "nStore Roster To File")
(display (list (remove roster (smallest roster (car(car roster))))))
(menu roster)
))
((= n 3) (begin                                   
(display "ntOption 3.")
(display "nDisplay Roster by ID")
(display "nsmallest record is: ")
(smallest roster (car (car roster)))
(menu roster)
))
((= n 4) (begin                                   
(display "ntOption 4.")
(display "nDisplay Student Info")
(menu roster)
))
((= n 5) (begin                                   
(display "ntOption 5.n")
(display roster)
(newline)
(menu (cons (ano-read-3-items 0 '()) roster))
))
((= n 6) (begin                                   
(display "ntOption 6.")
(display "nRemove a student from Roster")
(menu roster)
))
((= n 7) (begin(display "ntOption 7. Exitn")
#t
))
(else (begin
(display "ntTask No. ")
(display n)
(display " does not exit.nn")
(menu roster)
)
)
)
)
)
(define menu
(lambda (roster)
(begin
(display "t============================n")
(display "t    MENUn")
(display "t============================n")
(display "t0. Reset rostern")
(display "t1. Load roster from filen")
(display "t2. Store roster to filen")
(display "t3. Display roster sorted by IDn")
(display "t4. Display student informationn")
(display "t5. Add a student to rostern")
(display "t6. Remove a student from rostern")
(display "t7. Exitn")
(display "tEnter your choice: ")
(performtask (read) roster)
)
)
)

因此您在以下方面存在问题:

(define roster '(("5" "me" 95) ("4" "lini" 94) ("3" "rudy" 93) ("2" "mark" 92) ("1" "silas" 91)))
(remove roster "1") ; some error

你的错误是这部分:

(remove (list (cdr roster) (car roster)) record) 

假设您正在发送(student1 student2),而student1不是要删除的。然后,它以列表((student2) student1)作为参数重复出现。第二次出现错误,因为您要查找的数据所在的层比您预期的低。此外,列表不会变短,所以如果你的测试成功了,你就会得到无限递归。

解决办法是否定答案。当找到被删除的对象时,它与计算为列表尾部的基本情况相匹配,因此之前的任何元素都必须在此之前被保留,否则您将删除所有内容,直到您试图删除的id为止。它应该看起来像(cons non-match1 (cons non-match2 (cdr roster)),因此递归发生在cons:的cdr

(cons non-match (remove rest-of-list record))

您可能试图通过在访问id时添加另一个car来解决此问题?我看到了,不同于smallest使用caar来获取id,您在remove中使用caaar。这是我看到的第一件事,我想知道为什么。

最新更新