s c h e m a t i c s : c o o k b o o k

/ StringRecipes / Cookbook.ProcessingChars

This Web


WebHome 
WebChanges 
TOC (with recipes)
NewRecipe 
WebTopicList 
WebStatistics 

Other Webs


Chicken
Cookbook
Erlang
Know
Main
Plugins
Sandbox
Scm
TWiki  

Schematics


Schematics Home
Sourceforge Page
SchemeWiki.org
Original Cookbook
RSS

Scheme Links


Schemers.org
Scheme FAQ
R5RS
SRFIs
Scheme Cross Reference
PLT Scheme SISC
Scheme48 SCM
MIT Scheme scsh
JScheme Kawa
Chicken Guile
Bigloo Tiny
Gambit LispMe
GaucheChez

Lambda the Ultimate
TWiki.org

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: StringRecipes
Other Parents:
Next Topic: StringReverse

 
 
Copyright © 2004 by the contributing authors. All material on the Schematics Cookbook web site is the property of the contributing authors.
The copyright for certain compilations of material taken from this website is held by the SchematicsEditorsGroup - see ContributorAgreement & LGPL.
Other than such compilations, this material can be redistributed and/or modified under the terms of the GNU Lesser General Public License (LGPL), version 2.1, as published by the Free Software Foundation.
Ideas, requests, problems regarding Schematics Cookbook? Send feedback.
/ You are Main.guest