Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Wierd Val() Behavior

Status
Not open for further replies.

stanlyn

Programmer
Sep 3, 2003
945
US
Hi,

If lcTempWord equals "6" (char 6) when hitting the code block below, what could cause "Val(lcTempWord)" to return as numeric 0 instead of numeric 6?

After the debugger runs through the code block below the debugger states the following:
lcTempWord has a value of "6", type=C
Val(lcTempWord) has a value of 0, type=N
Val(lcTempWord) > 2 has a value of .F., type=L

code block...
If Val(lcTempWord) > 0
llMatchFound = .T.​
Endif

VFP9sp2 on win7-32

Thanks,
Stanley
 
I can't see any obvious explanation for this. The only thing I can think of is that lcTempWord contains a non-visible character before the "6". For example, if lcTempWord contains CHR(0) + "6", then VAL (lcTempWord) would indeed contain 0. But it's a long shot.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
I would test for LEN(lcTempWord) and check out Mike's theory

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are not good for you.
 
Hi,

Mike seems to be is right. Test the code below

Code:
lcX = "	6" && put a tab before 6
?LEN(lcX) && = 2
?VAL(lcX) && = 0.00
?VAL(ALLTRIM(lcX)) && = 0.00

hth

MarK
 
I guess along the same line of Mike & Mark.

Something very improbable would be a redefinition of the VAL function, eg as in

Code:
#Define Val MyVal
? Val("6")
Function MyVal(tcVal)
  Return 0

Bye, Olaf.
 
Maybe your string is a double-byte or unicode, not ASCII?


My respects,
Vilhelm-Ion Praisach
Resita, Romania
 
I played a bit with what the debugger shows, when setting a variable to chr(x)+"6". With x=0 the Locals windows shows "" as Value - the debugger may actually have a bug here with chr(0). With chr(1) it shows " 6" with a clearly visible extra space before 6 and with a space (x=32) the extra space is narrower (as the debugger shows all things with a proportional font), but VAL(" 6") is 6. I'm sure you'll find something.

You could easily inspect the binary values of all string bytes by adding CREATEBINARY(lcTempWord) into the Watch window of the debugger. If that's 0h36 you only have a "6", if its more than that you know what's in front, causing VAL() to convert to 0.0 as it does with any string not starting with a "+","-","." or digit.

Bye, Olaf.
 
Ok, you guys hit it right on...

Per your suggestions of testing the length, I am getting a length of 3 for lcTempWord, which is clearly not what I was expecting when it clearly shows the value as "6". Anyway, the length is 3. Issuing CREATEBINARY(lcTempWord) returns "0h6F6633"

How would be the best way to find/parse out the invisible characters that I could apply to the whole string first. I'm thinking of iterating through the entire string removing all invisible characters...

Thanks,
Stanley
 
Code:
Function StripNonNumeric
  parameters m.inString  
  private m.string,i,m.outString
  m.outString = ""
  for i = 1 to Len(m.inString)
    if substr(m.inString,i,1)$"0123456789."
      m.outString = m.outString + substr(m.inStringi,1)
    endif
  next
  return(m.outString)

or

Function StripNonNumeric
  parameters m.inString  
  private m.string,i,m.outString,m.myChar
  m.outString = ""
  for i = 1 to Len(m.inString)
    m.myChar = substr(m.inString,i,1)
    if m.myChar$"0123456789."
      m.outString = m.outString + m.myChar
    endif
  next
  return(m.outString)

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are not good for you.
 
? ''+0h6F6633

displays as "of3". Are you sure that's displaying as "6" for you?
o and f surely are not invisible chars.

Before I'd use some string filter function, I'd step back several levels from your detail problem and ask: What's you real world problem?

Bye, Olaf.
 
If you still see "6" in the Locals window of the debugger, the display might be outdated. Click there to refresh, perhaps. The debugger for example can't always refresh when you "Run to Cursor". Best run in single steps, (F8), and the variable display would update. In the Watch window, changed values will even be highlighted red.

Bye, Olaf.

 
There may be a faster way:

Code:
FUNCTION JustDigits
	PARAMETERS m.inString
	PRIVATE m.inString, m.DigitsOnly, m.outString
	
	m.DigitsOnly = "0123456789"

	m.outString = CHRTRAN(m.inString, CHRTRAN(m.inString, m.DigitsOnly, ""), "")

	RETURN (m.outString)

Makes no allowance for decimals, works by stripping out digits, then repeating but stripping out only what isn't a digit.
Inner CHRTRAN presents string with no digits, outer CHRTRAN strips original string of whats left - leaving only digits.

Compliments to Frank Perez for his 2010 post in stackoverflow for the idea.

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are not good for you.
 
Hi,

You might want to check the code that "feeds" your variable - anything else remains error prone.

ht

MarK
 
How would be the best way to find/parse out the invisible characters that I could apply to the whole string first.

That's the wrong way to go about it. What you should do is find out how the bad characters got into the string in the first place.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Now you already got 3 warning about sinmple filtering. A simple Digits filter can transform "7 of 9" into "79", "1.23" into "123" and cause other unwanted side effects, even more so, if lcTempWord would suddenly contain KBytes of text, you could get very large numbers of all the digits inside the text being extracted into one number.

Your code up to today expected numbers only, so find out why there are more than numbers in the input, to address the problem where it comes from.

Bye, Olaf.
 
For example: If the input comes from user input, eg a textbox. Init the Textbox.Value to 0 and a user can't type in "of6" or anything non numeric anymore. Also, you wouldn't need VAL to transform the input to a number. Sanitizing (user) input is the general topic, here.

Bye, Olaf.
 
In the following example, lctmp2 is a string with len()=3, who seems to be "6" and val()=0

Code:
lctmp=STRCONV("06",5) && convert to Unicode
?lctmp,VAL(lctmp),LEN(lctmp)
lctmp2=SUBSTR(lctmp,2)
?lctmp2,VAL(lctmp2),LEN(lctmp2)

My respects,
Vilhelm-Ion Praisach
Resita, Romania
 
Hi Mike,

>> That's the wrong way to go about it. What you should do is find out how the bad characters got into the string in the first place.

I cannot control that as it is output from ocr functions from less than ideal scans and contains a lot of gibberish characters. I'm pretty sure it is extended ascii as that is claimed by the ocr folks.

I'm dealing with them, by making several passes through the string.

1. The 1st pass I'm stripping all the low chr() characters and chr(127). Looks like I will need to add the high chr()s as well.
2. Next I'm replacing chars like ~, &, #, and several others with spaces as they would not be important to our full text searches.
3. Next I'm iterating thru the string looking for an uppercase letter that has a lower case immediately to its right which indicates it is the start of a word, then build that word by concatenating the next letters until a space of another uppercase letter is found.
4. Then do a similar run thru that preserves the numerics,
5. then run it thru foxtool's reduce().
6. There is actually more to that routine than what I mentioned.

And yes, I know its a lot of work, but it is actually correcting words that would fail our dictionary lookups, thus improving full text hits.

Hope I explained it, and I too wish the text was perfect,
Stanley
 

Hi Olaf,

>> Your code up to today expected numbers only

No, I'm expecting both numbers and characters that I actually spell check against a dictionary table. I don't ever remembering mentioning that I was only seeking numbers.

>> If Val(lcTempWord) > 0
>> llMatchFound = .T

Actually lcTempWord is a result of foxtool's word() function. The word() function returns any character or group of characters separated by spaces which is considered a word. The val(lcTempWord) is tested to see if it is really a number by returning a number, while characters do not. Looks like unicode changes that...

Currently, I've resorted to iterating through the entire string and passing each character to the isalpha() and isdigit() functions. I looked for a builtin function that would return true if a string was actually a legal number. Did I miss it?

Thanks,
Stanley

 
Hi Vilhelm-Ion Praisach,

Yes, looks like you nailed it... I tried your code and it produced the same results I was seeing.

Thanks,
Stanley
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top