Common Lisp中从文件逐字符读取内容填充到数组的问题求助
问题排查与修正
原代码存在的问题
- 不该在函数内部使用
defvar定义全局变量*count*:defvar定义的变量是全局特殊变量,不仅会污染全局命名空间,每次调用函数都会重置它的值,完全不符合局部计数的需求,应该用局部变量替代。 my-array未声明就直接赋值:直接用setf给未声明的变量赋值,大部分Common Lisp实现会抛出未定义变量的错误,即使不报错也会默认创建全局变量,应该用let声明为局部变量。- 变量赋值误用
set:修改已经声明的变量值应该用setf,set是操作符号的符号值的特殊函数,用法和场景完全不同。 - 固定长度数组有越界风险:你创建的数组长度固定为10,只要文件字符数超过10就会触发索引越界错误,完全不通用。
- 未填充的数组位置会残留默认值:如果文件字符数不足10,数组剩余位置会是默认的
NIL,不符合你存储文件字符的需求。
修正后代码
固定长度数组版本(适合已知编码的普通文本文件)
(defun gppinterpreter (filename) (with-open-file (stream filename) ;; 先获取文件总字符数,创建对应长度的数组 (let* ((file-length (file-length stream)) (my-array (make-array file-length :element-type 'character))) ;; 逐字符读取填充数组 (dotimes (i file-length my-array) (setf (aref my-array i) (read-char stream))) ;; 输出数组 (print my-array))))
可调长数组版本(兼容性更强,适合多字节编码/动态内容的文件)
(defun gppinterpreter (filename) (let ((my-array (make-array 0 :element-type 'character :adjustable t :fill-pointer 0))) (with-open-file (stream filename) (do ((char (read-char stream nil) (read-char stream nil))) ((null char)) (vector-push-extend char my-array))) (print my-array)))
两种实现都移除了不必要的全局变量,解决了索引越界问题,完全匹配逐字符读取填充数组的需求。
内容的提问来源于stack exchange,提问作者Burcu Sultan Orhan
相关产品推荐
相关产品推荐

