Mombu the Programming Forum sponsored links

Go Back   Mombu the Programming Forum > Programming > problem with quotes and "&" operator
User Name
Password
REGISTER NOW! Mark Forums Read

sponsored links


Reply
 
1 16th April 11:52
jules alberts
External User
 
Posts: 1
Default problem with quotes and "&" operator



(my Clipper is rusty, so please bear with me :-)

Somewhere in a app I use a condition that is made at runtime, its use is
to search in a table for a record that meets one or more conditions. I
make the condition (a character string) and evaluate it with the "&"
operator. All is well unless a part of the condition contains a quote
character. I brought the problem back to this small example:

cValue := "DArtagnan"
cCondition := "cValue == '" + cValue + "'"

cls
? 'test for ' + cCondition
? ''

if &cCondition
? 'true'
else
? 'false'
endif

This prints "true". Now change cValue to "D'Artagnan" and a runtime error
will occur BASE/1449 Syntax error (the text string is not a valid Clipper
expression). In the debugger I see that the compiler has translated the
double quotes "" to single ones ''.

How can I solve this? TIA!
  Reply With Quote


  sponsored links


2 16th April 11:52
dave pearson
External User
 
Posts: 1
Default problem with quotes and "&" operator



* Jules Alberts <joolz@xs4all.nl.invalid>:


Valid string delimiters in Clipper are '', "" and []. While it won't be a
perfect solution you could probably change your code so that the macro wraps
the string with [] (not that I can remember if the macro compiler handles
them, I think it does). Of course, that's still a problem if someone happens
to include [ or ] in the text you want to test.

Perhaps it would help if you give a better indication of what it is you're
trying to do because your example is a little "pointless" (comparing a
variable against itself doesn't really indicate what you're really trying to
do).

For example, depending on what you're really trying to do you could possibly
employ code blocks, either supplied at compile time or built at run-time.

--
Dave Pearson | OSLib - Timeslice release functions.
http://www.davep.org/ | eg - Norton Guide reader for Linux.
http://www.davep.org/clipper/ | weg - Norton Guide reader for Windows.
http://www.davep.org/norton-guides/ | dgscan - DGROUP scanner for Clipper.
  Reply With Quote
3 16th April 11:52
gabor salai
External User
 
Posts: 1
Default problem with quotes and "&" operator


as i remember everybody, even his hollyness (or whatever) cardinal himself
allways had problems with nasty d'artagnan

try:
cValue:="D'Artagnan"
cCondition:="cValue=="+chr(34)+cValue+chr(34)
?&cCondition

before making & execution, it is allways useful to print macro string,
to visualy check does text contain correct clipper syntax.
so before
?&cCondition
do
?cCondition
  Reply With Quote
4 16th April 11:52
douglas woodrow
External User
 
Posts: 1
Default problem with quotes and "&" operator


On Thu, 17 Jul 2003 14:11:21 Jules Alberts <joolz@xs4all.nl.invalid>

Use square brackets instead of the single quote (and make sure cValue
doesn't include square brackets):-

cCondition := "cValue == [" + cValue + "]"

--
Doug Woodrow
  Reply With Quote
5 16th April 11:52
jules alberts
External User
 
Posts: 1
Default problem with quotes and "&" operator


* Dave Pearson <davep.news@davep.org> 17 Jul 2003 12:40:30 GMT:

(I'm O.P. from another machine)

Something like let the end-user enter one or more of these values: a
name, a birth date, a company code etc. I have a function evaluate the
input, create a string that contains the criteria to which the record
must meet and then search the record.

Yes, maybe... Me and codeblock have never been intimate friends :-)
(apart from the obvious error handling stuff)
  Reply With Quote
6 16th April 11:52
jules alberts
External User
 
Posts: 1
Default problem with quotes and "&" operator


* Dave Pearson <davep.news@davep.org> 17 Jul 2003 12:40:30 GMT:


Your idea works, thanks. I tried something similar earlier: putting
the whole string between square brackets and leave the single quotes
around the embedded cValue. This didn't work, when looking in the
debugger, the brackets were translated to single quotes.

Not a very elegant solution, like you said, when somebody type [ or ]
a runtime will occur. Too bad Clipper doesn't do escaping like C etc.
  Reply With Quote
7 21st April 23:32
dave pearson
External User
 
Posts: 1
Default problem with quotes and "&" operator


* Jules Alberts <root@localhost.localdomain_invalid>:


Is it just the thing you're testing for that's configurable or is the
"source" configurable too? If it's just the thing to test for then,
presumably, you don't actually need to macro compile anything at all:

,----
| ...get cValue from user...
|
| If SwordsMen->Name == cValue
| ...do stuff...
| EndIf
`----

If you need to decide the "source" at runtime you could use a macro compile
to create a code block that lets you do the test without worrying about
quotes:

,----
| cSource = "SwordsMen->Name" // Got from somewhere else?
| ...get cValue from user...
|
| bTest := &( "{|cTarget| " + cSource + " == cTarget }" )
|
| If eval( bTest, cValue )
| ...do stuff..
| EndIf
`----

Of course, at this point you can use bTest anywhere you like and you don't
have to worry about quotes and the like.

Like I say, without knowing exactly what it is you're trying to do it's hard
to know if these suggestions make much sense.

--
Dave Pearson | OSLib - Timeslice release functions.
http://www.davep.org/ | eg - Norton Guide reader for Linux.
http://www.davep.org/clipper/ | weg - Norton Guide reader for Windows.
http://www.davep.org/norton-guides/ | dgscan - DGROUP scanner for Clipper.
  Reply With Quote
8 21st April 23:32
jules alberts
External User
 
Posts: 1
Default problem with quotes and "&" operator


Thanks for the suggestion, but I think the codeblock solution Dave
suggests is better, it doesn't need the assumption that a user will never
enter ', " and [ or ] at once.
  Reply With Quote
9 21st April 23:32
jules alberts
External User
 
Posts: 1
Default problem with quotes and "&" operator


The problem is that I don't know at compiletime if user wil want to search
for either a name, a birthdate or both.


Yes, I think this is the correct solution.


Here's the code, sorry for the long post. Comments are in dutch and Pan
wrapped some lines. The idea is to present a screen to the user
(that's a seperate part of code) allowing him to enter one or more
values to search for in several tables (about 800).

/***
*
* naam : li_zm
* doel : zoek een medewerker op verschillende criteria
* parameters : met defaultwaarden:
* 1 "klantcode"
* 2 space(4)
* 3 "beeindigde klanten meenemen"
* 4 "N"
* 5 "medewerkercode"
* 6 space(LEN_MWCODE)
* 7 "sofinummer"
* 8 " . . "
* 9 "achternaam"
* 10 space(30)
* 11 "exact op achternaam zoeken"
* 12 "J"
* 13 "geboortedatum"
* 14 ctod("")
* 15 "alleen eerste treffer tonen"
* 16 "N"
* retour : naam van bestand waarin de uitvoer staat
* maker : Jules Alberts 2000
*
*/
#include "ara_io.ch"
#include "ara_dbf.ch"
#include "ara_loc.ch"

function li_zm(aParams)
local cUitvoer := '', ;
aSet := setall(), ;
cOldpath := ''

// de parameters
local cKlant := aParams[2], ;
lBeeindigd := if(aParams[4] == "J", .t., .f.), ;
cMwCode := aParams[6], ;
cSofi := aParams[8], ;
cNaam := aParams[10], ;
lExact := if(aParams[12] == "J", .t., .f.), ;
dGeboren := aParams[14], ;
lAlleenEerste := if(aParams[16] == "J", .t., .f.), ;
aKl := {}, ;
i := 0

local cConditie := ""

memvar cDataPad

private cNewpath := "", ;
lEerste := .t.

waarschuw('de lijst wordt voorbereid...')

// stel de conditie samen if !empty(cMwCode)
cConditie := "upper(medewerk->code) == '" + cMwCode + "'"
endif

if !empty(charrem("0", charrem(".", cSofi)))
cConditie := if(empty(cConditie), cConditie, cConditie + " .and. ")
cConditie += "crypt(medewerk->sofinummer, memvar->cPw) == '" + cSofi + "'"
endif

if !empty(cNaam)
cConditie := if(empty(cConditie), cConditie, cConditie + " .and. ") if lExact
cConditie += "alltrim(upper(medewerk->naam)) == ["
cConditie += alltrim(upper(cNaam)) + "]" else
cConditie += "soundex(alltrim(upper(medewerk->naam))) == ["
cConditie += soundex(alltrim(upper(cNaam))) + "]"
endif
endif

if !empty(dGeboren)
cConditie := if(empty(cConditie), cConditie, cConditie + " .and. ")
cConditie += "dtos(medewerk->geboren) == '" + dtos(dGeboren) + "'"
endif

if empty(cConditie)
melding("Er is geen conditie ingevuld")
return (NIL)
endif

dbcloseall()
cUitvoer := tempfile(delslash(TEMPDIR), 'tmp')
set alternat to (cUitvoer)

begin sequence
do case
case empty(cKlant)
if dbfopen(,,"klant") == DBF_ERROR
melding()
break
else
if !lBeeindigd
// zet index op alleen actuele klanten
klant->(dbsetfilter({||!beeindigd()}, '!beeindigd()')) endif endif
klant->(dbgotop())
do while !klant->(eof())
waarschuw("klant " + klant->code + " wordt verwerkt")
set path to (sl(cDataPad) + klant->code)
if verwerk(klant->code, cConditie, lAlleenEerste)
break
endif
set path to dbfclose("medewerk")
klant->(toonskip())
enddo
case alltrim(upper(cKlant)) == "BA"
aKl := asort(BA_KLANTEN)
for i := 1 to len(aKl)
waarschuw(aKl[i] + " wordt verwerkt")
set path to (sl(cDataPad) + aKl[i])
if verwerk(aKl[i], cConditie, lAlleenEerste)
break
endif
set path to
dbfclose("medewerk")
next
case alltrim(upper(cKlant)) == "ZVBM"
aKl := asort(ZVBM_KLANTEN)
for i := 1 to len(aKl)
waarschuw(aKl[i] + " wordt verwerkt")
set path to (sl(cDataPad) + aKl[i])
if verwerk(aKl[i], cConditie, lAlleenEerste)
break
endif
set path to
dbfclose("medewerk")
next
otherwise // cKlant is ingevuld
set path to (sl(cDataPad) + cKlant)
if verwerk(cKlant, cConditie, lAlleenEerste)
break
endif
dbfclose("medewerk")
set path to
endcase
end sequence

set alternat to
dbcloseall()
setall(aSet)
waarschuw()
return (cUitvoer)

static function verwerk(cKlant, cConditie, lAlleenEerste)
if dbfopen(,,"medewerk") == DBF_ERROR
LOG_AAN
? "fout bij openen medewerkertabel van klant " + cKlant
LOG_UIT
return (.f.) endif
medewerk->(dbgotop())
do while !medewerk->(eof())
if &cConditie
schrijf(cKlant)
if lAlleenEerste
return (.t.) endif endif
medewerk->(dbskip())
enddo
return (.f.)

static function schrijf(cKlant)
memvar lEerste

LOG_AAN
if lEerste
lEerste := .f.
?? "klant medewerker" + space(30) + "geboren sofinummer"
? ""
endif

? cKlant + " "
?? medewerk->code + " "
?? padr(substr(alltrim(medewerk->naam) + ", " +
alltrim(medewerk->initialen), 1, 25), 25, ".") + "..."
?? dtoc(medewerk->geboren)
?? " " + crypt(medewerk->sofinummer, memvar->cPw)
LOG_UIT

return (NIL)
  Reply With Quote
10 21st April 23:33
dave pearson
External User
 
Posts: 1
Default problem with quotes and "&" operator


* Jules Alberts <joolz@xs4all.nl.invalid>:

Right, if I'm reading the code correctly then I think the code block
solution should work for you. Moreover it should actually result in faster
code because you won't be doing the macro compile for every single iteration
of the loop.

I can see that, given how this code works, it might be a bit of a headache
building up one long string that can be compiled into a code block. One
approach to this that I used many years ago was to, instead, build up an
array of code blocks that need to be satisfied for each record. In that case
your `verwerk' function's main body, rather than doing the macro compile,
would look a little like:

,----
| Function IncludeRecord( aTests )
| Local lInclude := .T.
| Local nMax := len( aTests )
| Local n
|
| For n := 1 To nMax
| If !( lInclude := eval( aTests[ n ] ) )
| Exit
| EndIf
| Next
|
| Return( lInclude )
`----

This might not exactly fit what you're doing but I think you should be able
to adapt this approach to your code.

--
Dave Pearson | OSLib - Timeslice release functions.
http://www.davep.org/ | eg - Norton Guide reader for Linux.
http://www.davep.org/clipper/ | weg - Norton Guide reader for Windows.
http://www.davep.org/norton-guides/ | dgscan - DGROUP scanner for Clipper.
  Reply With Quote
Reply


Thread Tools
Display Modes




Copyright © 2006 SmartyDevil.com - Dies Mies Jeschet Boenedoesef Douvema Enitemaus -
666