获取标准输入并将其作为字符串存储在lisp中

时间:2011-03-29 05:22:09

标签: string lisp common-lisp stdin

我意识到这可能是一个非常愚蠢的问题,但我不知道为什么这不起作用,我几乎放弃了。基本上我试过了:

(setq answer (string (read)))

(setq answer 0)
(format answer "~s" (read))

(setq answer (read))

当我尝试评估时

(if (stringp answer) 
    (princ "works")
    (princ "failed"))

在任何上述尝试中总是失败。

我做错了什么?

2 个答案:

答案 0 :(得分:20)

或者你可以这样做:

(setq answer (read-line))

那就给你一个字符串。

[1]> (setq answer (read))
3
3
[2]> (type-of answer)
(INTEGER 0 16777215)
[3]> (setq answer (read-line))
3
"3"
[4]> (type-of answer)
(SIMPLE-BASE-STRING 1)
[5]>

答案 1 :(得分:5)

启动一个新的REPL,然后尝试检查每个步骤的返回值:

T1> (read)
foo
FOO
T1> (read)
1
1
T1> (type-of (read))
foo
SYMBOL
T1> (type-of (read))
1
BIT

现在请注意,STRING不适用于所有输入类型:

T1> (string 'foo)
"FOO"
T1> (string 1)

另请注意,与setq不同,(format foo ...)不会设置 foo,而是写入,如果它是stream或一个string fill-pointer。看看它的Documentation,你会看到:

  

格式化目标控制字符串   & rest args =>结果

     

[...]

     

目的地--- nil,t,流或a   带填充指针的字符串。

     

[...]

     

格式对于很好地生成很有用   格式化文本,产生好看   消息,等等。格式可以   生成并返回一个字符串或输出   到目的地。

     

如果destination是一个字符串,一个流,   或者t,结果是零。   否则,结果是一个字符串   包含`output。'

试试这样:

T1> (setq *answer*
          (with-output-to-string (s)
            (format s "~s" (read))))
1
"1"
T1> *answer*
"1"

或者像这样:

T1> (setq *answer* (make-array 20 :element-type 'character :fill-pointer 0))
""
T1> (format *answer* "~s" (read))
1
NIL
T1> *answer*
"1" 

这些是我在代码中找到的唯一相关错误。这肯定会在每个符合要求的CL中返回"works"(您也可以使用prin1-to-string):

T1> (defvar *answer*)
*ANSWER*
T1> (setq *answer* (format nil "~s" (read)))
1
"1"
T1> (if (stringp *answer*)
        (princ "works")
        (princ "failed"))
works
"works"

除非您处于混乱的程序包中(在评估代码之前尝试(in-package cl-user))或重新定义基本功能,否则这将起作用。如果仍然没有,请提供更准确的错误描述。

ED:

读过Bill的回答,他正确指出read-line是一个较短的解决方案,我应该提一下,我并没有试图在我的回答中展示最好,最简洁或最惯用的方法,而且这取决于你真正想做的事情。 (最短的解决方案可能是"works" :)它们只是帮助解释代码失败原因的示例。

我忘了说的另一件事是你应该记住,在setqdefvar未定义的变量上defparameter通常应该避免在任何事情上进行调整在REPL,因为后果不明确。此外,按照惯例,这些变量包含在星号(也称为 earmuffs )中,以防止因使用词法范围变量混淆特殊错误而导致的错误。