StringTools - Maple Programming Help

Home : Support : Online Help : Programming : Names and Strings : StringTools Package : Miscellaneous Utilities : StringTools/StringBuffer

StringTools

 StringBuffer
 string buffer constructor

 Calling Sequence b := StringBuffer() b:-clear() b:-append( s ) b:-appendf( fmt, ... ) b:-newline(n) b:-space(n) b:-value() b:-value( opt )

Parameters

 b - string buffer object s - Maple string fmt - Maple string; format string as for sprintf n - (optional) non-negative integer; number of characters inserted, default is 1 opt - (optional) option of the form clear = true (or just clear) or clear = false

Description

 • The StringBuffer constructor returns a string buffer object. String buffers are useful for incrementally building long strings from shorter substrings. The naive approach, which repeatedly concatenates each new substring to the end of an ever-growing string, is extremely inefficient. StringBuffer provides an efficient mechanism for building strings.
 • The StringBuffer object returned by the constructor is a module with six methods: clear, append, appendf, newline, space, and value.
 • The clear method empties the buffer; an empty string buffer represents the empty string $""$. This method is executed only for effect; no useful value is returned, and no arguments are required.
 • The append method appends its argument, which must be a Maple string, to the string that the buffer represents. The buffer itself is returned. This allows you to chain multiple calls to the append method of a given buffer in a single expression. The appendf (append formatted'') method allows you to append formatted strings. It accepts arguments identical to those accepted by sprintf.
 • The newline method appends newlines n to the buffer. If the argument n is supplied, it inserts that many newlines, otherwise it defaults to one.
 • The space method appends spaces n to the buffer. If the argument n is supplied, it inserts that many spaces, otherwise defaults to one.
 • The value method returns the string represented by the buffer. No arguments are required, but it accepts a clear option (of type truefalse) which, if set, causes the buffer to be cleared upon returning the string value.
 • The intention is that you can build a long string in a string buffer by repeatedly calling the append method of the buffer, and then retrieve the value of the represented string, as a string, by calling the value method. The clear method simply allows you to re-use an existing string buffer to create a new long string, once you are done with its current contents.
 • StringBuffer objects operate efficiently in algorithms for which the number of calls to the append method greatly exceeds the number of calls to the value or clear methods.
 • All of the StringTools package commands treat strings as (null-terminated) sequences of $8$-bit (ASCII) characters.  Thus, there is no support for multibyte character encodings, such as unicode encodings.

Examples

 > $\mathrm{with}\left(\mathrm{StringTools}\right):$
 > $b≔\mathrm{StringBuffer}\left(\right):$
 > $b:-\mathrm{append}\left("The"\right)$
 ${"The"}$ (1)
 > $b:-\mathrm{append}\left("quick"\right):-\mathrm{append}\left("brown"\right):-\mathrm{append}\left("fox."\right)$
 ${"The quick ...ick brown"}$ (2)
 > $b:-\mathrm{value}\left(\right)$
 ${"The quick brown fox.quick brown"}$ (3)
 > $b:-\mathrm{clear}\left(\right):$$b:-\mathrm{appendf}\left("%a",2+3\mathrm{sin}\left(\frac{x}{y}\right)\right):$$b:-\mathrm{value}\left(\right)$
 ${"2+3*sin\left(x/y\right)"}$ (4)

Use of a StringBuffer is much more efficient that the naive approach shown here.

 > $N≔1000:$
 > $s≔"":$
 > $\mathrm{txt}≔\mathrm{Random}\left(10,'\mathrm{lower}'\right)$
 ${\mathrm{txt}}{≔}{"yhcmxxkyzm"}$ (5)
 > $\mathrm{st}≔\mathrm{time}\left(\right):$$\mathbf{for}\phantom{\rule[-0.0ex]{0.3em}{0.0ex}}i\phantom{\rule[-0.0ex]{0.3em}{0.0ex}}\mathbf{to}\phantom{\rule[-0.0ex]{0.3em}{0.0ex}}N\phantom{\rule[-0.0ex]{0.3em}{0.0ex}}\mathbf{do}\phantom{\rule[-0.0ex]{0.0em}{0.0ex}}\phantom{\rule[-0.0ex]{2.0em}{0.0ex}}s≔\mathrm{cat}\left(s,\mathrm{txt}\right)\phantom{\rule[-0.0ex]{0.0em}{0.0ex}}\mathbf{end}\phantom{\rule[-0.0ex]{0.3em}{0.0ex}}\mathbf{do}:$$\mathrm{time}\left(\right)-\mathrm{st}$
 ${0.006}$ (6)
 > $b:-\mathrm{clear}\left(\right):$$\mathrm{st}≔\mathrm{time}\left(\right):$$\mathbf{for}\phantom{\rule[-0.0ex]{0.3em}{0.0ex}}i\phantom{\rule[-0.0ex]{0.3em}{0.0ex}}\mathbf{to}\phantom{\rule[-0.0ex]{0.3em}{0.0ex}}N\phantom{\rule[-0.0ex]{0.3em}{0.0ex}}\mathbf{do}\phantom{\rule[-0.0ex]{0.0em}{0.0ex}}\phantom{\rule[-0.0ex]{2.0em}{0.0ex}}b:-\mathrm{append}\left(\mathrm{txt}\right)\phantom{\rule[-0.0ex]{0.0em}{0.0ex}}\mathbf{end}\phantom{\rule[-0.0ex]{0.3em}{0.0ex}}\mathbf{do}:$$\mathrm{time}\left(\right)-\mathrm{st}$
 ${0.004}$ (7)
 > $\mathrm{evalb}\left(b:-\mathrm{value}\left(\right)=s\right)$
 ${\mathrm{true}}$ (8)

Here is another, more subtle example.

 > G := proc()    description "extremely inefficient string concatenator";    local   r;    r := proc()        if nargs = 0 then            ""        elif nargs = 1 then            args[ 1 ]        else            cat( args[ 1 ], procname( args[ 2 .. -1 ] ) )        end if    end proc;    r( args ) end proc:

This can be transformed into an O(1) algorithm by passing a string buffer to the recursive calls.

 > F := proc()    description "efficient version of G";    local    b, r;    b := StringTools:-StringBuffer();    r := proc()        if nargs = 1 then            b:-append( args[ 1 ] )        else            b:-append( args[ 1 ] );            procname( args[ 2 .. -1 ] )        end if    end proc;    r( args ):-value() end proc:
 > $s≔\mathrm{seq}\left(\mathrm{Random}\left(10,'\mathrm{lower}'\right),i=1..1000\right):$
 > $\mathrm{time}\left(G\left(s\right)\right)$
 ${0.123}$ (9)
 > $\mathrm{time}\left(F\left(s\right)\right)$
 ${0.009}$ (10)

Here is a procedure to read the contents of a file, one line at a time, applying a given filtering operation to each line.

 > FilterFile := proc( fname::string, filter )    local   b, line;    b := StringTools:-StringBuffer();    do        line := readline( fname );        if line = 0 then break end if;        b:-append( filter( line ) )    end do;    b:-value() end proc:
 > $\mathrm{filename}≔\mathrm{FileTools}:-\mathrm{JoinPath}\left(\left["help","StringTools","cbc03.txt"\right],\mathrm{base}=\mathrm{datadir}\right)$
 ${\mathrm{filename}}{≔}{"/maple/cbat/active/147321/data/help/StringTools/cbc03.txt"}$ (11)
 > $\mathrm{FilterFile}\left(\mathrm{filename},s↦s\right)$
 ${"Francesco Totti scored the game-winning goal on a penalty shot in injury time to lift Italy to a dramatic 1-0 win over Australia Monday at the World Cup in Kaiserslautern, Germany."}$ (12)
 > $\mathrm{FilterFile}\left(\mathrm{filename},\mathrm{Trim}\right)$
 ${"Francesco Totti scored the game-winning goal on a penalty shot in injury timeto lift Italy to a dramatic 1-0 win over Australia Monday at the World Cup inKaiserslautern, Germany."}$ (13)
 > $\mathrm{FilterFile}\left(\mathrm{filename},s↦\mathrm{if}\left(\mathrm{IsSpace}\left(s\right),"",s\right)\right)$
 ${"Francesco Totti scored the game-winning goal on a penalty shot in injury time to lift Italy to a dramatic 1-0 win over Australia Monday at the World Cup in Kaiserslautern, Germany."}$ (14)