Yet another way to go about it (a tad more robust, perhaps), You can also easily modify it so that you could `setf' a character in the string once the callback is called, but I didn't do it that way because it seemed like you don't need this sort of ability. Also, in that later case, I'd rather use a macro.
(defun mapc-words (function vector
&aux (whites '(#\Space #\Tab #\Newline #\Rubout)))
"Iterates over string `vector' and calls the `function'
with the non-white characters collected so far.
The white characters are, by default: #\Space, #\Tab
#\Newline and #\Rubout.
`mapc-words' will short-circuit when `function' returns false."
(do ((i 0 (1+ i))
(start 0)
(len 0))
((= i (1+ (length vector))))
(if (or (= i (length vector)) (find (aref vector i) whites))
(if (> len 0)
(if (not (funcall function (subseq vector start i)))
(return-from map-words)
(setf len 0 start (1+ i)))
(incf start))
(incf len))) vector)
(mapc-words
#'(lambda (word)
(not
(format t "word collected: ~s~&" word)))
"a1 b1 c1 d1 e1
a2 b2 c2 d2 e2")
;; word collected: "a1"
;; word collected: "b1"
;; word collected: "c1"
;; word collected: "d1"
;; word collected: "e1"
;; word collected: "a2"
;; word collected: "b2"
;; word collected: "c2"
;; word collected: "d2"
;; word collected: "e2"
Here's an example macro you could use, if you wanted to modify the string as you read it, but I'm not entirely happy with it, so maybe someone will come up with a better variant.
(defmacro with-words-in-string
((word start end
&aux (whites '(#\Space #\Tab #\Newline #\Rubout)))
s
&body body)
`(do ((,end 0 (1+ ,end))
(,start 0)
(,word)
(len 0))
((= ,end (1+ (length ,s))))
(if (or (= ,end (length ,s)) (find (aref ,s ,end) ',whites))
(if (> len 0)
(progn
(setf ,word (subseq ,s ,start ,end))
,@body
(setf len 0 ,start (1+ ,end)))
(incf ,start))
(incf len))))
(with-words-in-string (word start end)
"a1 b1 c1 d1 e1
a2 b2 c2 d2 e2"
(format t "word: ~s, start: ~s, end: ~s~&" word start end))