royvandewater
royvandewater

Reputation: 1428

Convert a lisp string to stream

I have a file that looks like this:

A B C D E
0 8 6 12 5
8 0 10 8 9
6 10 0 7 11
12 8 7 0 6
5 9 11 6 0

I don't know ahead of time how many rows and columns there will be. I would like to read the top line, which will let me know the number of rows to expect . I found lisp's (read <stream>) function which, in a loop, can parse each of the characters as symbols. I have not found a way, however, to limit the loop to only reading the first line and stopping there. The solution I'm trying to make work would be something like

(with-open-file (stream "/home/doppler/tmp/testcase1.txt")
  (setf line (read-line stream))
  (when line
    (loop for symbol = (read line nil)
         while symbol do (print symbol))))

The problem with this is that (read-line stream) returns a string which cannot be parsed by (read line nil) to extract the symbols (s-expressions).

How can I either convert the string line to a stream, or, if possible, extract the symbols directly from the string?

Upvotes: 8

Views: 3545

Answers (3)

kd4ttc
kd4ttc

Reputation: 1185

Lisp has a number of libraries that can handle various tasks. The str library would help in this case.

* (str:words "A B C D E")
("A" "B" "C" "D" "E")

Documentation for str can be found through the Common Lisp Cookbook in the Strings section: https://lispcookbook.github.io/cl-cookbook/strings.html

If you find you get an error that str is not available, use (ql:quickload "str") to get the library.

Upvotes: 0

jsparkes
jsparkes

Reputation: 321

I had to use sb-ext:string-to-octects which allow me to specify the external format as utf-8. I was surprised since the default format should be utf-8 according to https://www.sbcl.org/manual/#The-Default-External-Format. I guess the internal format is iso-8859-1.

I ended up with

(test base64-3
      (is (string= "YWJjZMKj" (cl-base64:usb8-array-to-base64-string
                               (sb-ext:string-to-octets "abcd£" :external-format :utf-8)))))

Upvotes: 0

Matthias Benkard
Matthias Benkard

Reputation: 15759

You can either use the string as a stream by using the with-input-from-string macro, or use read-from-string in a loop. You may also be interested in the read-delimited-list function, although you would have to add some kind of delimiter character to the end of the string before using it.

Upvotes: 7

Related Questions