问题描述
我是 lisp 编程的新手,我正在尝试创建一个接受六个数字并检查每个数字是奇数还是偶数的程序。
(princ"Input six number: ")
(setq a(read))
(setq b(read))
(setq c(read))
(setq d(read))
(setq e(read))
(setq f(read))
(format t "~% ~d" a)
(format t "~% ~d" b)
(format t "~% ~d" c)
(format t "~% ~d" d)
(format t "~% ~d" e)
(format t "~% ~d" f)
(if(= 0(mod a 2))
(print"even")
(print"odd"))
(if(= 0(mod b 2))
(print"even")
(print"odd"))
(if(= 0(mod c 2))
(print"even")
(print"odd"))
(if(= 0(mod d 2))
(print"even")
(print"odd"))
(if(= 0(mod e 2))
(print"even")
(print"odd"))
(if(= 0(mod f 2))
(print"even")
(print"odd"))
(terpri)
解决方法
你有很多看起来像这样的代码:
(if(= 0(mod ... 2))
(print"even")
(print"odd"))
(这可能是复制/粘贴问题,但在您的问题中,它们越来越向右缩进。然而,它们不是嵌套的,它们都处于相同的深度(它们是顶级表达式)所以通过约定它们不应缩进)。
第一步是使用这样的函数来分解它们:
(defun check-even-odd (number)
(if (= 0 (mod number 2))
(print "even")
(print "odd")))
上面定义了一个名为 check-even-odd
的函数,它有一个参数 number
,它应用与您最初对任意数字相同的逻辑。
您的其余代码可以简化为:
(check-even-odd a)
(check-even-odd b)
(check-even-odd c)
(check-even-odd d)
(check-even-odd e)
(check-even-odd f)
现在,您可以定义两个额外的全局变量:
(defparameter total-even 0)
(defparameter total-odd 0)
它们中的每一个都持有一个总和,并被初始化为 0。
您可以按如下方式重写 check-even-odd
函数以更新计数器。首先,让我们使用 cond
重写当前代码,因为我们将需要在每种情况下执行多个操作,而 if
只接受每个分支的一个表达式(组合 {{ 1}} 和 if
有点难看):
progn
上面的行为与原始代码相同。
为了将变量增加一定数量,您可以使用INCF
:
(defun check-even-odd (number)
(cond
((= 0 (mod number 2))
(print "even"))
(t
(print "odd"))))
当您执行整个脚本时,总数将被初始化为零,然后每次调用 (defun check-even-odd (number)
(cond
((= 0 (mod number 2))
(print "even")
(incf total-even number))
(t
(print "odd")
(incf total-odd number))))
都会将该数字添加到相应的计数器中。
注意事项:
- 您可能会发现其他可以使用函数抽象重复代码的地方
- 在初始化
check-even-odd
、defparameter
等时,您应该使用setq
而不是a
,否则变量不会声明并调用b
未声明的变量不是标准的 - 事实上,可以在没有任何全局状态的情况下重写整个程序,这可能是下一个很好的练习
- 您可以概括为更少或更多的数字而不是 6,您需要编写一个循环或递归函数来任意时间重复相同的代码
- 可能需要刷新输入/输出(请参阅
setq
、finish-output
),否则在缓冲底层流时您可能会遇到奇怪的行为。