Reputation: 5203
In Common Lisp, I need to capture user input in the form of a list of reals. This list is terminated by two zeros in a row. For example, 5.0 0 6.0 3 2.0 5 1.0 7 13.0 8 0 0
should return the list (5.0 0 6.0 3 2.0 5 1.0 7 13.0 8)
.
I've come across the function read-delimited-list
, which takes a single character as an ending point. I can stop at a single zero, but I'm not sure how to expand this function, and I don't know of another function that takes a delimited string instead of a char.
EDIT Thanks to the accepted answer, I've developed the following:
(butlast (loop for y = -1 then x for x = (read stream) until (and (= 0 x) (= 0 y))
collect x)))
It seems a bit more readable to me (and at this point I'm openly admiting that my Lisp eyes are only 3 days old), and I'm not sure about performance implications (does collect
append or reverse the list after the loop exits scope? is there an easier way to chop off the last element, or simply not append it?).
Upvotes: 2
Views: 927
Reputation: 51551
The best way to parse numbers in Common Lisp is to use the library parse-number
. If your user input can be read line by line, you can simply split the lines on whitespace and use parse-number
on the results.
Upvotes: 0
Reputation: 9451
For such simple case you can just use read
in a loop, collect the results read so far and stop, when the last two are zeros.
(defun read-double-zero-terminated-list (stream)
(do* ((prev -1 val)
(val (read stream) (read stream))
list)
((and (zerop prev) (zerop val)) (reverse (cdr list)))
(push val list)))
read-delimited-list
is intended for the cases of creating specialized syntax, so it's probably overkill here.
Upvotes: 4