2
aaa bbb ccc

Fot the above line, I just want to get the sring "aaa", just like scanf("%s",str) in C.

sds
  • 58,617
  • 29
  • 161
  • 278
chaosink
  • 1,329
  • 13
  • 27
  • possible duplicate of [How to convert a string to list using clisp?](http://stackoverflow.com/questions/7459501/how-to-convert-a-string-to-list-using-clisp) – sds Dec 01 '14 at 19:10

2 Answers2

1

In C, scanf does tokenization, i.e., it splits on whitespace. This corresponds to read in Common Lisp:

(with-input-from-string (s "aaa bbb ccc")
  (list (read s) (read s) (read s)))
==> (AAA BBB CCC)

Note that read returns symbols for unquoted strings; if you want strings, you are looking for something like:

(defparameter *my-string* "aaa bbb ccc")
(subseq *my-string* 0 (position #\Space *my-string*))
==> "aaa"
sds
  • 58,617
  • 29
  • 161
  • 278
  • Then what about "bbb"? Is there a function like scanf("%s",str)? Or I hava to write it by myself? – chaosink Dec 01 '14 at 04:06
  • Thanks! But I want original string "aaa" instead of the symbol AAA. – chaosink Dec 01 '14 at 08:13
  • If the original string is "aAa", function read will make all characters capital. – chaosink Dec 01 '14 at 08:16
  • Take a look at [`symbol-name`](http://www.lispworks.com/documentation/HyperSpec/Body/f_symb_2.htm) and [`readtable-case`](http://www.lispworks.com/documentation/HyperSpec/Body/f_rdtabl.htm). However, the symbols will still be interned, so you will need to unintern them to have them garbage-collected. – sds Dec 01 '14 at 11:09
  • While it is possible that someone already wrote a scanf for CL (vsedach/Vacietis seems to have one), I would still write it myself, maybe using flexi-streams library. – sid_cypher Dec 01 '14 at 19:07
1

To solve your problem gracefully you need a function to extract words. This may work, or you can find some good library:

CL-USER> (defun split (str token &aux result (len (length str)))
           (labels ((rec (i)
                      (if (< i len)
                          (let ((p (or (position token str :start i)
                                       len)))
                            (when (/= p i)
                              (push (subseq str i p) result))
                            (rec (1+ p)))
                          (reverse result))))
             (rec 0)))
SPLIT

This function traverses given string and copies its parts that don't contain given token. Note how we don't copy entire string on every recursive call, but move 'pointer' i to know where to start next search.

Now you can use nth to access any word:

CL-USER> (nth 0 (split "aaa bbb ccc" #\space))
"aaa"
CL-USER> (nth 1 (split "aaa bbb ccc" #\space))
"bbb"
CL-USER> (nth 2 (split "aaa bbb ccc" #\space))
"ccc"
Mark Karpov
  • 7,499
  • 2
  • 27
  • 62