Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

'In-situ' String Replacement functions

114 views
Skip to first unread message

Mel Smith

unread,
May 19, 2012, 3:24:04 PM5/19/12
to
Hi:

// I know and use often the strtran() function --- BUT,

// I now have a 20kbyte string (its actually a web page template) where
I have to replace all the 'field codes' with actual user data in 200+ input
fields.

// I've been doing this before with statements like:

cMyPage := strtran(cMyPage,"#fs78#","Some Info") // actual data
pulled from my 'keyed' database

// and repeating the above *many* times. Therefore re-creating this
long string many times also.

// But now, I have more than 200 (nearly 300) field codes to replace
with consequently that many string re-creation operations

// Is there a string replacement function that would do all the field
replacements 'in situ', that is do *all* the replacements in one static
string perhaps as follows

aFields := array(200,2)

// then fill the array with 200 field codes, and 200 user data values
from my databases

// then

cTemplate := memoread("template.htm") // where this template is the
template page with all necessary field codes embedded

// Now pass the aFields array, and the cTemplate to this new 'in situ'
string replacement function
// and replace all the field codes with actual user data *without*
creating a new string each time.

cMyPage := new_string_replacement_function(aFields,cTemplate)

// Now my page will be able to display the actual user data !

Can anyone point me to a function such as this or tell me how I should
create it for in situ replacement ??

Thanks,
--
Mel Smith


dlzc

unread,
May 19, 2012, 3:55:15 PM5/19/12
to
Dear Mel Smith:

On Saturday, May 19, 2012 12:24:04 PM UTC-7, Mel Smith wrote:
> Hi:
>
> // I know and use often the strtran()
> function --- BUT,
>
> // I now have a 20kbyte string (its actually
> a web page template) where I have to replace
> all the 'field codes' with actual user data
> in 200+ input fields.
>
> // I've been doing this before with statements
> like:
>
> Can anyone point me to a function such as this
> or tell me how I should create it for in situ
> replacement ??

We aren't really strong on stomping on assigned memory, and in situ replacement simply won't work if the length of the string changes.

How about a single hand-crafted loop,
sourcing from the original string (pointer and substr),
constructing the final string maybe in a file (that way you don't burn memory quite so much / often),
reading to the next "#" (move the source pointer to the final delimiter),
using ascan to return the replacement for "#fs78#" as you go?

David A. Smith

ella....@xharbour.com

unread,
May 19, 2012, 5:12:49 PM5/19/12
to
Hello,

Below is a simplified code sequnce for "in situ" workup.
Of course you can preallocate the result string with a maximum value (bigger, then the expected size)...

Ella


local X, Res
local a:="aaa", b:="bbbbb", c:="cccccccc" // simplified
local nRes, nX, nY, nPos, i, j
X:= {a, b, c} // simplified
nRes := 0
nX := len( X )
for i:=1 to nX
nRes += len( X[i] )
next
Res := replicate( chr(0), nRes ) // preallocating
nPos := 0
for i:= 1 to nX
nY := len( X[i] )
for j:=1 to nY
Res[nPos+j] := X[i][j]
next
nPos += nY
next
alert( Res )


Mel Smith

unread,
May 19, 2012, 6:52:56 PM5/19/12
to
Ella & David:

Thanks for your suggestions. Will puzzle on then (and learn) over the
weekend.

-Mel Smith


Patrice

unread,
May 22, 2012, 6:36:48 PM5/22/12
to
Hi,

Some time ago I deviced a technic for a similar problem, the goal was
to avoid endless string copiing while replacing some data fields.

The problem was to inset custom data in a binary output in PCL for an
HP printer.

In first, I have inserted once for all my fields with tags diferent
tags in front and after each fields <#MYFIELD#> in original printer
code.

How I do my stuff:

1) I loop into the string searching for each beginning tag starting at
second char of string.
when I find one, I append what is before the tag to a list
and last piece of string goes at the end of list.

2) I loop the list and search each substring for an ending tag and
split the string when found, the end of string is inserted at next
position in kist.

at this point, every custom field is alone in a string of the list.

3) I loop the list searching if the string begin with my tag, if
found, I search if my string match a field name in my field list and
replace that field name with the value. since the whole string is the
field name, I just replace it with the value.

Since the result is just printed, I don't merge the pieces, I send
each of them to the printer.

you can also merge the pieces by first computing the whole lentgh and
using the technic of ella.

Patrice

Mel Smith

unread,
May 22, 2012, 9:59:34 PM5/22/12
to
Patrice:

I'll read this over carefully.

Thank you !

(btw, my field codes in my page templates are always of the style:
"#fsomename#". Where the ID of the element is "isomename", and the
name="somename")

-Mel Smith


aardvark

unread,
May 29, 2012, 10:49:49 PM5/29/12
to
On 19/05/2012 20:24, Mel Smith wrote:

> // But now, I have more than 200 (nearly 300) field codes to replace
> with consequently that many string re-creation operations
>

Hi

Another possible suggestion (assuming you basically want to do a "mail
merge" with the template for multiple database records)

1) Mark your fieldnames with distinct characters (pipe, tab character,
whatever)
2) Split the template string into an array using the hbatokens() function.
3) macro compile the field references into the codeblocks.
4) aeval(aSplitTemplate, {|x|qqout(iif(valtype(x)=='B',eval(x),x))})

Regards
"aardvark"

druzus

unread,
May 31, 2012, 10:57:46 AM5/31/12
to
XTRANS() function with small test code below. It uses hash array
for better performance and supports dynamic (fields 'date', 'time')
and
static (fields 'fs01', 'fs02') translations.
I want a beer ;-)

best regards,
Przemek



proc main()
local cData, hTrans

cData := "#normal #text#, some data [#fs01#]=>(#fs02#), #date#
#time##"
hTrans := { "fs01" => "VAL-01", "fs02" => "VAL-02", ;
"date" => {||dtoc(date())}, "time"=> {||time()} }
? cData
? xtrans( cData, hTrans )
return

function xtrans( cData, hTrans )
local cText, cResult, cDelim, xValue, lNext
cResult := ""
cDelim := "#"
lNext := .f.
for each cText in hb_aTokens( cData, cDelim )
if lNext
if cText $ hTrans
xValue := hTrans[ cText ]
if valtype( xValue ) $ "BS"
xValue := eval( xValue )
endif
else
xValue := NIL
endif
if valtype( xValue ) $ "CM"
cResult += xValue
lNext := .f.
else
cResult += cDelim
cResult += cText
endif
else
cResult += cText
lNext := .t.
endif
next
return cResult

Mel Smith

unread,
May 31, 2012, 7:04:53 PM5/31/12
to
Przemek:

Thank you, I'll test it on the weekend.

Right now, I'vre got to go buy some 'wings' for my wife and myself, and
some good strong Canadian beer (i.e., Gold Strong -- 6.3% alcohol) :))

(I've been golfing all day with two of my sons, and I'm thirsty and
starved !)

Thanks again !

-Mel Smith


Douglas Woodrow

unread,
Jun 1, 2012, 10:44:23 AM6/1/12
to
On Thu, 31 May 2012 07:57:46, druzus <przemysla...@gmail.com>
wrote
Very neat!
--
Doug Woodrow

Mel Smith

unread,
Jun 1, 2012, 1:09:34 PM6/1/12
to

"Douglas Woodrow" <newsg...@nospam.demon.co.uk> wrote in message
news:aPUDM4IH...@woodrowhorsfall.plus.com...
> On Thu, 31 May 2012 07:57:46, druzus <przemysla...@gmail.com> wrote
>
> Very neat!

Douglas:

I agree !

(Now, I've got to puzzle over how to use it in *my* system)

Thanks to Przemek again.

-Mel Smith


0 new messages