Common Lisp学习笔记(九)

9 Input/Output

9.2 string

string在lisp中用双引号括起来,它的值也是自己本身,和数字一样,string不是symbols

stringp判断是否是一个string

> "hello"
"hello"

> (stringp "hello")
t

9.3 format

format用来输出到显示器或者文件中,函数总是返回nil.输出到显示器的时候,第一个参数是t,第二个参数是string

> (format t "hello")
hello
nil

string中以下几个符号有特殊含义:

  • ~% : 输出换行
  • ~& : 输出换行,除非刚好在新的一行开始的位置。意思就是及时有几个~&符号也只会输出一个换行
  • ~S : 用后面的字符替换,如(format t "from ~S to ~S" 'guangzhou 'zhuhai) -> from guangzhou to zhuhai
  • ~A: 与~S类似,但是不使用escape characters,eg
    (defun test (x)
      (format t "~&with escape chars: ~S" x)
      (format t "~&without escape chars: ~A" x))
    
    > (test "hello")
    with escape chars: "hello"
    without escape chars: hello
    nil
    

ex 9.2

(defun draw-line (n)
  (cond ((equal n 1) (format t "*~&"))
        (t (format t "*") (draw-line (- n 1)))))

ex 9.3

(defun draw-box (x y)
  (cond ((equal y 1) (draw-line x))
        (t (draw-line x) (draw-box x (- y 1)))))

ex 9.5

(defun print-board (b)
  (labels ((print-line (line) (format t " ~A | ~A | ~A ~%" (first line) (second line) (third line))))
  (let ((b1 (sublis '((x . "X")
                     (o . "O")
                     (nil . " ")) b)))
  (format t "~&")
  (print-line b1)
  (format t "-----------~%")
  (print-line (nthcdr 3 b1))
  (format t "-----------~%")
  (print-line (nthcdr 6 b1)))))

9.4 read

read函数从键盘读取一个对象然后返回对象的值,对象前面不需要加',因为它不会被evaluated

(defun my-square ()
  (format t "enter a number:")
  (let ((x (read)))
    (format t "the number ~S squared is ~S.~%" x (* x x))))

ex 9.7

(defun cookie-monster ()
  (format t "give me cookie!!!~%cookie?")
  (let ((response (read)))
    (cond ((equal response 'cookie) 
           (format t "~&thank you!...munch munch munch ...burp~%"))
          (t (format t "~&no want ~S....~%" response)
             (cookie-monster)))))

9.5 yes-or-no-p

(defun riddle ()
  (if (yes-or-no-p "do you seek zen enlightenment?")
      (format t "then do not ask for it!")
      (format t "you have found it.")))

> (riddle)
do you ...?yes
then do not ask for it!

yes-or-no-p函数输出后面的string内容,然后要求用户输入yes或者no,代表函数返回t或者nil

9.6 with-open-file

(with-open-file (var pathname)
    body)

打开路径下文件名的文件,并创建变量名var的stream object用来操作

eg,

(defun get-tree-data ()
  (with-open-file (stream "~/hello.dat")
    (let* ((tree-loc (read stream))
           (tree-table (read stream))
           (num-trees (read stream)))
     (format t "~&there are ~S trees on ~S." num-trees tree-loc)
     (format t "~&they are:   ~S." tree-table))))

> (get-tree-data)
there are 100 trees on "the north slope"
they are : ((45 redwood) (12 oak) (43 maple))
nil

read stream每次从文件中读取一个lisp对象

9.7 writing files with with-open-file

format函数的第二个参数是t代表输出到显示器,改成文件的stream object则输出到文件中

我们可以输入任意内容到文件中,内容可以不是lisp的对象,比如不成对的小括号等,但是后面就不能使用read stream的形式来进行读取

ex 9.10

(defun test (n)
  (format t "~%>>>")
  (space-over n)
  (format t "<<<"))

(defun space-over (n) 
  (cond ((< n 0) (format t "error"))
        ((zerop n) nil)
        (t (format t " ") (space-over (- n 1)))))

(defun plot-one-point (plotting-string y-val)
  (space-over y-val)
  (format t "~A~&" plotting-string))

(defun plot-points (plotting-string y-vals)
  (mapcar #'(lambda (b) (plot-one-point plotting-string b)) y-vals)) 

(defun generate (m n) 
  (cond ((= m n) (list m))
        ((< m n) (cons m (generate (+ 1 m) n)))))

9.8 parameters to format directives

~S输出替换字符,~10S则可以设置输出宽度为10个字符 ~D输出十进制整数 ~F输出浮点数,可以设定总的位数和小数位数,如~7,5F输出5位小数,总共占7个字符

9.9 file EOF

当程序读到文件的结尾时,会产生end-of-file error。给read增加两个参数可以不产生报错,第一个是nil,表示不产生错误,第二个是eof indicator,表示读到这个对象就代表结尾

(defun read-my-file ()
  (with-open-file (stream "~/hello.dat")
    (let ((contents (read-all-objects stream (list '$eof$))))
     (format t "~&read ~S objects from the file." (length contents))
     contents)))

(defun read-all-objects (stream eof-indicator)
  (let ((result (read stream nil eof-indicator)))
    (if (eq result eof-indicator) nil (cons result (read-all-objects stream eof-indicator)))))

例子中使用(list '\(eof\))作为结尾标识,这是一个新建的cons,后面进行比较的时候用eq而不是equal是为了对地址进行比较,确认就是结尾标识。

ex 9.11

(defun dot-prinl (x)
  (cond ((null x) (format t "nil"))
        ((atom x) (format t "~S" x))
        (t (format t "(") 
           (dot-prinl (car x)) 
           (format t " . ")
           (dot-prinl (cdr x))
           (format t ")"))))
posted @ 2015-05-12 21:39  Jolin123  阅读(392)  评论(0编辑  收藏  举报