首页 > 解决方案 > Lisp 基本打印功能获取用户输入

问题描述

我应该编写一个程序,将简单的用户输入作为字符串获取,并且代码应该写回响应(姓名,你是一个人等)。该程序假设在输入单词“再见”时终止。代码如下:

(defun x()
    (setq words "empty")
    (loop while (string/= words "BYE")
        (setq words (read-delimited-list #\~)   
        (write-line words)
        (format t "ROBBIE%: Hello, who are you?")
        (case (string-include "I'm" words)
            (format t "ROBBIE%: Nice to see you, how are you?")
            ((string-include "Hi" words)
            (format t "ROBBIE%: How are you?")
            (or (string-include "fine" words) (string-include "person" words))
            (format t "ROBBIE%: No I'm a computer")))
            (format t "BYE"))

(X)

但是,当我在程序 2 上编译它时会弹出错误:

Line2:3 警告:未定义变量:COMMON-LISP-USER:: WORDS

Line3:3 错误:在 (LOOP WHILE (STRING/= WORDS "BYE") ...) 的宏展开期间。使用BREAK-ON-SIGNALS拦截。

我已经在 python 中完成了编程,但这对我来说是非常复杂的语言,我需要一些帮助来理解为什么这不起作用?任何意见是极大的赞赏!

标签: lispcommon-lisp

解决方案


让我专注于其他解决方案尚未涵盖的代码方面。

环形

这是您的循环结构:

(let ((words "empty"))
  (loop
    while (string/= words "BYE")
    do
    (progn
      (setq words (read-line)))))

首先,在do你不需要(progn ...). 你可以同样写:

(let ((words "empty"))
  (loop
    while (string/= words "BYE")
    do (setq words (read-line))))

必须初始化words为某个任意值(有时称为哨兵值)是一种代码异味(并不总是坏事,但可能有更好的选择)。在这里,您可以使用for子句来简化循环。

(loop
  for words = (read-line)
  while (string/= words "BYE")
  do ...)

此外,您可能希望untilstring=测试一起使用,这可能更具可读性:

(loop
  for words = (read-line)
  until (string= words "BYE")
  do ...)

搜索

您可以使用SEARCH. 下面是一段带注释的代码片段,用于展示字符串操作函数的工作原理:

(defun test-I-am (input)
  (let ((start (search "I'am" input)))
    (when start
      ;; we found an occurrence at position start
      ;; let's find the next space character
      (let ((space (position #\space input :start start)))
        (when space
          ;; we found a space character, the name starts just after
          (format nil "Hello ~a!" (subseq input (1+ space))))))))

使用这个简单的算法,这是一个测试(例如在您的 REPL 中):

> (test-i-am "I'am tired")
"Hello tired!"

推荐阅读