The Verify function locates the position where a character within a string does not correspond with those defined in the 2nd argument. Two types of searches are supported.
When performing a Match search the Verify function locates the first character that matches those defined in the 2nd argument.
When performing a NoMatch search the Verify function locates the first character that does not match those defined in the 2nd argument.
Note: the character case is significant during the matching process.
| result = Verify( string, charSet [, [ option ] [, start ] ] ) |
NoMatch -- locates where the string does not match a reference character (Default)
Match -- locates where the string matches a reference character
|
Examples:
say Verify( 'Shazam', 'abcsh' ) -- shows: 1, the character case of the 'S' does not match say Verify( 'Shazam', 'abcSh' ) -- shows: 4 say Verify( 'Shazam', 'abcsh', 'N' ) -- shows: 1, the character case of the 'S' does not match say Verify( 'Shazam', 'abcSh', 'N' ) -- shows: 4 say Verify( 'Shazam', 'abc', 'M' ) -- shows: 3, locates the first 'a' say Verify( 'Shazam', 'abc', 'M', 4 ) -- shows: 5 say Verify( 'Shazam', 'def', 'M' ) -- shows: 0, none of the reference characters were located say Verify( '123.45', '0123456789' ) -- shows: 4, the decimal point is not a digit say Verify( '123.45', '0123456789.' ) -- shows: 0, the decimal point is matched now say Verify( '123.45.678', '0123456789.' ) -- shows: 0, both decimal points are matched now |
Please observe !!!
Occasionally, you will use the Verify function to advance through a string, and pick out segments that either match or lack the referenced characters. A programming pitfall can occur if the end of the string is reached instead of a target character. Consider the following program that extracts numeric values from a string.
/* get numeric expense values */
/* trace '?I' */ /* <<<--- turn on the trace to study the defect ! */
expenses = 'Air fare 456.78 Car rental 78.90 Hotel 123.45 Meals 89.01'
values = ''
do exp_ix=1 while expenses <> ''
pos = verify( expenses, '0123456789', 'M' ) /* find first numeric value */
expenses = substr( expenses, pos )
endpos = verify( expenses, '0123456789', 'N' ) /* find end of numeric value */
parse var expenses leading =(endpos) expenses 1 . =(endpos) dotCh +1 rest
if dotCh = '.' then do
endpos = verify( rest, '0123456789', 'N' ) /* find end of trailing digits */
parse var rest trailing =(endpos) expenses
values = values leading'.'trailing
end
else
values = values leading
end exp_ix
say 'Expense values:' values
|
At first glance the above logic seems to be correct. You would expect the program to produce:
Expense values: 456.78 78.90 123.45 89.01However the program loops until memory is exhausted! You can activate tracing (trace '?I') to analyze the program's progress. The defect occurs when the 89.01 value is encountered, rest is set to 01 by the first parse instruction. Then, the following verify request does not operate as expected:
endpos = verify( rest, '0123456789', 'N' ) /* find end of trailing digits */
endpos is set to 0 because the remaining values are all digits !!! A similar defect can occur with the first verify request when no more numeric values remain in the string. These defects can be corrected by using match_pos and mismatch_pos procedures. The improved program follows
/* get numeric expense values -- IMPROVED */
expenses = 'Air fare 456.78 Car rental 78.90 Hotel 123.45 Meals 89.01'
values = ''
do exp_ix=1 while expenses <> ''
pos = match_pos( expenses, '0123456789' ) /* find first numeric value */
expenses = substr( expenses, pos )
endpos = mismatch_pos( expenses, '0123456789' ) /* find end of numeric value */
parse var expenses leading =(endpos) expenses 1 . =(endpos) dotCh +1 rest
if dotCh = '.' then do
endpos = mismatch_pos( rest, '0123456789' ) /* find end of trailing digits */
parse var rest trailing =(endpos) expenses
values = values leading'.'trailing
end
else
values = values leading
end exp_ix
say 'Expense values:' values
return
match_pos : procedure
if arg(1) == '' then return 0
pos = verify( arg(1), arg(2), 'M' )
if pos = 0 then
return length( arg(1) ) + 1 /* see "note" below */
return pos
mismatch_pos : procedure
if arg(1) == '' then return 0
pos = verify( arg(1), arg(2), 'N' )
if pos = 0 then
return length( arg(1) ) + 1 /* see "note" below */
return pos
|
Note: "length( arg(1) ) + 1" is returned instead of "length( arg(1) )". This is due to the behavior of the "=(endpos)" term in the parse template.
Performance insight !!!
If you know that the data to process only contains text and numbers then the extraction of the numbers can be performed in a single line !
expenses = 'Air fare 456.78 Car rental 78.90 Hotel 123.45 Meals 89.01'
say 'Expense values:' ,
space( translate( expenses, '0123456789.', '0123456789.'xrange() ), 1 )
|