TWiki . Cookbook . ProcessingChars

Processing a String One Character at a Time

Problem

You want to process a string a character at a time

Solution

You can convert the string into a list and process it using map or for-each. Assuming that do-something-with-char is a function that processes characters:
(map do-something-with-char (string->list a-string))
(for-each do-something-with-char (string->list a-string))
depending on whether or not you want a list as the result or if you're relying on side effects. You can also use the iterative approach:

(do ((i 0 (+ i 1)))
    ((= i (string-length a-string)) a-string)
    (do-something-with-char (string-ref a-string i)))

SRFI-13 also defines string-map, string-for-each, string-fold, and string-for-each-index, which are all extremely useful. string-map works like map but obviates the need to convert between list and string:

(require (lib "string.ss" "srfi" "13"))
(define a-string "Hello, Scheme!")
(string-map do-something-with-char a-string)
Note that string-map creates a new string. To modify a string in place, use string-map!, but remember that you have to have a mutable string in the first place to do this, so string-map! would fail in the example just given. Also, if you're relying on side effects, string-map will get upset, in this case, you want string-for-each:
> (string-map display a-string)
string-set!: expects type <character> as 3rd argument,
given: #<void>; other arguments were: "\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 13
> (string-for-each display a-string)
Hello, Scheme!
string-for-each-index is similar to string-for-each, except that the function you pass to it expects an index to the string, instead of the character itself:
(string-for-each-index 
  (lambda (i) 
    (display (string-ref a-string i))) a-string)
Finally, string-fold and string-fold-right represent the ultimate in character processing, generalizing the effect of string-map. For example, you can produce a list of characters in a string like this:
> (string-fold-right cons '() "Hello, World!")
(#\H #\e #\l #\l #\o #\, #\space #\W #\o #\r #\l #\d #\!)
> ; in reverse order
> (string-fold cons '() "Hello, World!")
(#\! #\d #\l #\r #\o #\W #\space #\, #\o #\l #\l #\e #\H)
Of course, this doesn't demonstrate the real power of string-fold; that lies mostly in the 2nd argument, which can be any 2 argument function. The first argument will be the current character, and the 2nd will be the result of the previous application of the function (on the 1st invocation, it will be the 3rd argument to string-fold).

-- GordonWeakliem - 05 Apr 2004

CookbookForm
TopicType: Recipe
ParentTopic: StringChapter
TopicOrder: 060

----- Revision r1.6 - 09 Jun 2004 - 15:40 GMT - NoelWelsh
Copyright © 1999-2003 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback.