Logo

Hacker’s Guide to Visual FoxPro
An irreverent look at how Visual FoxPro really works. Tells you the inside scoop on every command, function, property, event and method of Visual FoxPro.

STR(), VAL()

STR() and VAL() are reciprocal functions for converting numeric values to strings and vice versa. Both process null values correctly, returning nulls.

Usage

cReturn = STR( nNumeric [, nLength [, nDecimals ] ] )
nReturn = VAL( cString )

Parameter

Value

Meaning

nNumeric

Numeric

The numeric value to be converted.

nLength

Numeric

The overall length of the resulting field, including preceding minus signs and any decimal places. Defaults to 10 if not specified. Limited to a maximum of 237.

nDecimals

Numeric

Number of decimal places to be returned. If nDecimals is greater than (nLength minus 2), the length takes priority and no more than (nLength minus 2) decimal places are returned. Defaults to zero if not specified. Limited to a maximum of 18.

cString

Character

A numeric value expressed in a string. Preceding plus or minus signs recognized. 16-character limit.

STR() takes a numeric value and returns a character value. Optionally, the length and number of decimal places of the field may be specified. If the length is less than the number of digits to the left of the decimal place, one of two things happens. If the number is less than 10 billion or the specified size is less than seven characters, asterisks are returned. But wait. If the numeric value has 10 digits to the left of the decimal place and the resulting string length is specified as at least seven, one of two things happens. In all cases, a string is returned in scientific notation. However, the string disagrees slightly between VFP 3 and later versions. Both versions are mathematically correct, but the string returned by the later versions more closely resembles what we learned was “scientific notation” in school:

? STR(1234567890123,7)  && Returns ".1E+13" in VFP 3
? STR(1234567890123,7)  && Returns "1.E+12" in VFP 5 and later
? STR(1234567890123,12)  && Returns ".123456E+13" in VFP 3
? STR(1234567890123,12)  && Returns "1.23456E+12" in VFP 5 and later

This can be as useless as asterisks, because the exact value of the number has been lost for display purposes. If you’re performing bulk conversions of numeric data to strings, make sure that you check for a return of asterisks or one containing the letter “E”.

In versions prior to VFP 7, Help claims that the function truncates values. In actuality, STR() rounds fractional values ending in .50 up and .49 down. In all versions, STR(12345.6789,5) returns "12346", not 12345, and STR(12345.6789,7,2) returns "12345.7". The documentation finally matches the behavior in VFP 7.

STR() first fits the whole number portion into the string, and what is left over is used for the decimal portion. You cannot assume that an expression STR(x,8,3) will always have the decimal point four spaces from the right end of the string—STR(1234.567,8,3) returns "1234.567", but STR(123456.7,8,3) returns "123456.7". We think this should result in a "Numeric Overflow" error, not in a string that looks different from the others.

VAL() returns a number based on its evaluation of the numeric portion of a string. VAL() ignores alphabetic characters after the number, converting VAL(“234abc”) to 234. VAL() recognizes and correctly parses leading spaces, and plus and minus signs. VAL() also understands scientific notation, properly converting character expressions in the form “xE±z”.

VAL() converts nearly all character strings to numbers—the only problem is that some of these numbers may be beyond the range FoxPro can actually work with. VAL("1E+307") creates a numeric without an error message, but this value cannot be stored in a numeric, double, float or integer field, nor can you do much useful processing on it. If you are converting character data to numeric in your applications, you need to range-check the result to ensure that you are working with legitimate numbers.

Like other functions that depend on settings and symbols that vary by country, VAL() correctly respects the settings of SET(“POINT”) to display and parse decimal points. If your application is likely to be used with data that may have been saved with another decimal mark, make sure you have a way of detecting this. Similarly, if your users can customize your application to their native settings, you need to bracket code where you assume the setting of POINT.

This bug was introduced in VFP 5 and was fixed in VFP 7 Service Pack 1: Under some circumstances, passing VAL() a valid number in scientific notation or passing a character value would crash VFP.

Example

nHardDriveSize = VAL(SYS(2020))
cPageNum = "Page "+LTRIM(STR(_PAGENO))
lnWrongVal = VAL("123,456")  && What's this value?

lcPointSet = SET("POINT")  && Preserve the setting
SET POINT TO "."           && Set to known value
lnMyVal = VAL("12345.67")  && Use it
SET POINT TO lcPointSet    && Restore the setting

The first example shows how VAL() can return a numeric value from one of the SYS() Functions, which typically return their values as character strings. The second example shows one of the most common uses of the STR() function—converting the system memory variable _PAGENO, representing the current page being printed, to a string to use as part of your report header or footer. The third example, lnWrongVal, shows a killer mistake. In the U.S., this number is parsed up to the alphabetic comma and is evaluated as exactly 123. In most of Europe, where the POINT is typically a comma and the thousands separator a period, this value has a potentially significant decimal portion. Miscalculations at this level can be disastrous, and a bear to track down. The last example shows an example of the right way to capture the POINT setting, change it, perform your function, and restore it.

See Also

Asc(), Chr(), Round(), Transform(), Set Point