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

时间:2015-04-18 20:26:26

标签: list sorting comparison scheme

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

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

当我打电话给(显示(删除名册(最小的名单(汽车(汽车名册)))))时,我得到一个错误,说'&#39 ;;对象(" 4" " lini"" 94"),作为参数传递给string->数字,不是字符串。'进行此调用时的当前列表是:((5 me 95)(4 lini 94)(3 rudy 93)(2标记92)(1 silas 91))。我使用string->数字函数作为>比较所以我认为它也可以在这里工作,但我也没有得到我希望与之比较的列表中的正确元素。这导致我将(汽车(汽车名单)添加到(等于?)的第二个参数中它给了我错误&#39 ;;对象" 5",作为第一个参数传递给汽车,不是正确的类型。'

有谁知道我在做错了什么? 我也限制使用套装!函数,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 "\n\tOption 0.")
                        (display "\nReset Roster")
                        (menu '())
                        ))
              ((= n 1) (begin
                        (display "\n\tOption 1.")
                        (display "\nLoad Roster From File")
                        (menu roster)
                        ))
              ((= n 2) (begin                                   
                        (display "\n\tOption 2.")
                        (display "\nStore Roster To File")
                        (display (list (remove roster (smallest roster (car(car roster))))))
                        (menu roster)
                        ))
              ((= n 3) (begin                                   
                        (display "\n\tOption 3.")
                        (display "\nDisplay Roster by ID")
                        (display "\nsmallest record is: ")
                        (smallest roster (car (car roster)))
                        (menu roster)
                        ))
              ((= n 4) (begin                                   
                        (display "\n\tOption 4.")
                        (display "\nDisplay Student Info")
                        (menu roster)
                        ))
              ((= n 5) (begin                                   
                        (display "\n\tOption 5.\n")
                        (display roster)
                        (newline)
                        (menu (cons (ano-read-3-items 0 '()) roster))
                        ))
              ((= n 6) (begin                                   
                        (display "\n\tOption 6.")
                        (display "\nRemove a student from Roster")
                        (menu roster)
                        ))
              ((= n 7) (begin(display "\n\tOption 7. Exit\n")
                        #t
                        ))
              (else (begin
                        (display "\n\tTask No. ")
                        (display n)
                        (display " does not exit.\n\n")
                        (menu roster)
                    )
              )
        )
  )
)

(define menu
  (lambda (roster)
        (begin
           (display "\t============================\n")
           (display "\t    MENU\n")
           (display "\t============================\n")
           (display "\t0. Reset roster\n")
           (display "\t1. Load roster from file\n")
           (display "\t2. Store roster to file\n")
           (display "\t3. Display roster sorted by ID\n")
           (display "\t4. Display student information\n")
           (display "\t5. Add a student to roster\n")
           (display "\t6. Remove a student from roster\n")
           (display "\t7. Exit\n")
           (display "\tEnter your choice: ")
           (performtask (read) roster)
        )
  )
)

1 个答案:

答案 0 :(得分:0)

所以您遇到以下问题:

(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))因此递归发生在cdr的{​​{1}}中:

cons

您可能尝试通过在访问ID时添加另一个(cons non-match (remove rest-of-list record)) 来解决此问题吗?我明白了,与使用car获取ID的smallest不同,您在caar中使用了caaar。这是我看到的第一件事,我想知道为什么。