问题
My next project is writing a hangman game. I figured it would help me brush up on strings and file I/O.
Currently, i'm stuck on reading in a file of strings into a list. I'm trying to avoid global variables, so could someone point me in the right direction to make this (probably broken) code into a function that returns a list?
(defun read-word-list ()
"Returns a list of words read in from a file."
(let ((word-list (make-array 0
:adjustable t
:fill-pointer 0)))
(with-open-file (stream #p"wordlist.txt")
(loop for line = (read-line stream)
while line
(push line word-list)))
(select-target-word word-list)))))
回答1:
You can read-in the words as Lisp symbols, with just a few lines of code:
(defun read-words (file-name)
(with-open-file (stream file-name)
(loop while (peek-char nil stream nil nil)
collect (read stream))))
Example input file - words.txt:
attack attempt attention attraction authority automatic awake
bright broken brother brown brush bucket building
comfort committee common company comparison competition
Reading the file:
> (read-words "words.txt")
=> (ATTACK ATTEMPT ATTENTION ATTRACTION AUTHORITY AUTOMATIC AWAKE BRIGHT BROKEN BROTHER BROWN BRUSH BUCKET BUILDING COMFORT COMMITTEE COMMON COMPANY COMPARISON COMPETITION)
The case could be preserved by enclosing the symbols in pipes (|) or declaring them as strings:
|attack| "attempt" ...
Reading without losing case:
> (read-words "words.txt")
=> (|attack| "attempt" ...)
回答2:
If the words are one per line, you could do something like this:
(defun file-words (file)
(with-open-file (stream file)
(loop for word = (read-line stream nil)
while word collect word)))
You could then use it like this;
(file-words "/usr/share/dict/words")
来源:https://stackoverflow.com/questions/4120973/returning-a-list-of-words-from-a-file