Data Conversion
Technical Notes
Overview
Naming Conventions
Numeric-to-String Conversion-Integer
String-to-Numeric Conversion-Integer
Fixed-Point Integers
Numeric-to-String Conversion-Fixed-Point
String-to-Numeric Conversion-Fixed-Point
BCD-to-String and String-to-BCD Conversion
Converting Between Integers and BCD Numbers
Numeric-to-String Conversion-Floating-Point
String-to-Numeric Conversion-Floating-Point
Initializing the Data Conversion Formatting Functions
Formatting and Unformatting Numeric Strings
Sample Program
This unit consists of functions which perform numeric-to-string and string-to-numeric data conversion on integer, floating-point, fixed-point integer, and BCD numeric types. Functions are also included which format ASCII numeric strings, convert formatted ASCII numeric strings to standard format ASCII numeric strings, and convert BCD numbers to and from integers.
The integer conversion functions read or write ASCII strings representing numbers in base 10 (decimal), base 16 (hexadecimal), or in a specified base from 2 to 36. The floating-point, fixed-point, BCD conversion, and formatting functions read or write ASCII strings in base 10 (decimal). Supported integer numeric types include char, int, long, and quad in both signed and unsigned representations. Supported fixed-point numeric types include int, long, and quad in both signed and unsigned representations. Supported floating-point types include float (32 bit), double (64 bit), and long double (80 bit) reals. The supported bcd numeric type is a packed ten byte (80 bit) signed BCD format.
The numeric-to-string and string-to-numeric formatting functions in this unit support the following formatting options:
Formatting Option Examples
Currency symbol string (arbitrary or country-specific) "$1.23", "Cr$1,23", ...
Currency symbol position (arbitrary or country-specific) "1.23 ", "1,23", ...
Thousands delimiter (arbitrary or country-specific) "1,234.56", "1.234,56", ...
Decimal delimiter (arbitrary or country-specific) "1.23", "1,23", ...
Precision (arbitrary or country-specific) "1.23", "1.23456" (0 to 30 digits)
Maximum field width (0 to 126 characters)
Positive number representation "123", "CR 123", "+123", "123+", ...
Negative number representation "-123", "(123)", "< 123 >", "123-", ...
Truncated or rounded result 1.226 to "1.22" or "1.23"
Fixed, floating, padded digits to right of decimal point 1.200 to "1.2", "1.200", or "1.2 "
Use a leading zero for numbers between -1 and 1 "0.123" or ".123"
Exponent indicator string "1.2E34", "1.2x10^34", ...
Minimum number of digits in the exponent "1.2e3", "1.2e03", "1.2e003", "1.2e0003"
Optional "+" for positive exponents "1.2e+34" or "1.2e34"
Output format: integer, exponential, non-exponential, or flex-exponential
Numeric-to-string conversion functions follow a naming convention of numeric_TO_string, where numeric is a descriptive name for the numeric type and string is a descriptive name for the string type. String-to-numeric conversion functions follow a naming convention of string_TO_numeric.
The descriptive names used for numeric and string types are as follows:
Descriptive Name Description Range or Radix
uc unsigned char 0 to 255
c char -128 to 127
ui unsigned int 0 to 65,535
i int -32,768 to 32,767
ul unsigned long 0 to 4,294,967,295
l long -231 to 231-1
uq uquad 0 to 264-1
q quad -263 to 263-1
ufixpi fixed-point unsigned int 0.00 to 655.35*
fixpi fixed-point int -327.68 to 327.67*
ufixpl fixed-point unsigned long 0.00 to 42,949,672.95*
fixpl fixed-point long -21,474,836.48 to 21,474,836.47*
ufixpq fixed-point uquad 0.00 to 184,467,440,737,095,516.15*
fixpq fixed-point quad -92,233,720,368,547,758.08 to 92,233,720,368,547,758.07*
bcd binary coded decimal (packed) -1018+1 to 1018-1
f float (32-bit real) 1.17x10-38 to 3.40x1038
d double (64-bit real) 2.22x10-308 to 1.79x10308
ld long double (80-bit real) 3.36x10-4932 to 1.19x104932
asc ASCII string of alphanumeric digits2 radix 36
dec ASCII string of decimal digitsradix = 10
hex ASCII string of hexadecimal digitsradix = 16
*The position of the decimal point in a fixed-point number must be specified. This representation assumes a fixed-point precision of two.
Because C does not supply defined types for 64-bit integers or BCD values, the following typedefs are provided to simplify the use of 64-bit integer and BCD types in C applications: uquad for unsigned 64-bit integers, quad for signed 64-bit integers and bcd for binary coded decimal values. The bcd, quad and uquad types are defined using typedef, as follows:
typedef signed char quad[8];
typedef unsigned char uquad[8];
typedef unsigned char bcd[10];
- _uc_to_hex
- Converts an unsigned char to a hexadecimal ASCIIZ string.
- _uc_to_hexe
- Converts an unsigned char to a hexadecimal ASCII string, returning a pointer to the end of the resulting string.
- _ui_to_hex
- Converts an unsigned int to a hexadecimal ASCIIZ string.
- _ui_to_hexe
- Converts an unsigned int to a hexadecimal ASCII string, returning a pointer to the end of the resulting string.
- _uc_to_dec
- Converts an unsigned char to a decimal ASCIIZ string.
- _uc_to_dece
- Converts an unsigned char to a decimal ASCII string, returning a pointer to the end of the resulting string.
- _c_to_dec
- Converts a char to a decimal ASCIIZ string.
- _c_to_dece
- Converts a char to a decimal ASCII string, returning a pointer to the end of the resulting string.
- _ui_to_dec
- Converts an unsigned int to a decimal ASCIIZ string.
- _ui_to_dece
- Converts an unsigned int to a decimal ASCII string, returning a pointer to the end of the resulting string.
- _i_to_dec
- Converts a int to a decimal ASCIIZ string.
- _i_to_dece
- Converts a int to a decimal ASCII string, returning a pointer to the end of the resulting string.
- _ul_to_dec
- Converts an unsigned long to a decimal ASCIIZ string.
- _ul_to_dece
- Converts an unsigned long to a decimal ASCII string, returning a pointer to the end of the resulting string.
- _l_to_dec
- Converts a long to a decimal ASCIIZ string.
- _l_to_dece
- Converts a long to a decimal ASCII string, returning a pointer to the end of the resulting string.
- _uq_to_dec
- Converts a uquad to a decimal ASCIIZ string.
- _uq_to_dece
- Converts a uquad to a decimal ASCII string, returning a pointer to the end of the resulting string.
- _q_to_dec
- Converts a quad to a decimal ASCIIZ string.
- _q_to_dece
- Converts a quad to a decimal ASCII string, returning a pointer to the end of the resulting string.
- _uc_to_asc
- Converts an unsigned char to an ASCIIZ string in a given radix.
- _uc_to_asce
- Converts an unsigned char to an ASCII string in a given radix, returning a pointer to the end of the resulting string.
- _c_to_asc
- Converts a char to an ASCIIZ string in a given radix.
- _c_to_asce
- Converts a char to an ASCII string in a given radix, returning a pointer to the end of the resulting string.
- _ui_to_asc
- Converts an unsigned int to an ASCIIZ string in a given radix.
- _ui_to_asce
- Converts an unsigned int to an ASCII string in a given radix, returning a pointer to the end of the resulting string.
- _i_to_asc
- Converts a int to an ASCIIZ string in a given radix.
- _i_to_asce
- Converts a int to an ASCII string in a given radix, returning a pointer to the end of the resulting string.
- _ul_to_asc
- Converts an unsigned long to an ASCIIZ string in a given radix.
- _ul_to_asce
- Converts an unsigned long to an ASCII string in a given radix, returning a pointer to the end of the resulting string.
- _l_to_asc
- Converts a long to an ASCIIZ string in a given radix.
- _l_to_asce
- Converts a long to an ASCII string in a given radix, returning a pointer to the end of the resulting string.
- _uq_to_asc
- Converts a uquad to an ASCIIZ string in a given radix.
- _uq_to_asce
- Converts a uquad to an ASCII string in a given radix, returning a pointer to the end of the resulting string.
- _q_to_asc
- Converts a quad to an ASCIIZ string in a given radix.
- _q_to_asce
- Converts a quad to an ASCII string in a given radix, returning a pointer to the end of the resulting string.
These functions convert a numeric value to a string of alphanumeric ASCII digits. The ..._to_asc and ..._to_asce functions accept a radix as an input and convert the numeric value to a string of alphanumeric ASCII digits in the given radix. The ..._to_hex, ..._to_hexe, ..._to_dec and ..._to_dece functions convert the numeric value directly to a hexadecimal or decimal ASCII string. All numeric-to-string functions output uppercase ASCII letters for digits above decimal nine. For example, in base 11 and above, 1010 is represented as "A" rather than "a".
The ..._to_dec functions produce output strings in decimal ASCII integer format, which is a special case of the standard non-exponential format. Strings in this format may be used with the formatting functions described later in this chapter. Decimal ASCII integer format is defined as follows:
- [-][d...]d
- (where d denotes any decimal digit)
Function names which end with an "e" denote functions which return a pointer to the character after the end of the resulting string. These functions do NOT terminate the resulting string with a NULL. Functions which accept signed input values always place a minus sign at the beginning of the resulting string if the input value is negative.
The following example takes advantage of the fact that _ui_to_dece returns a pointer to the end of the resulting string:
#include
#include
#include
char xy_msg[] = "X,Y coordinates: (";
char xy_coord[11];
char *ptr;
void main(void)
{
ptr = _i_to_dece(23,xy_coord);
*ptr++ = ',';
ptr = _i_to_dece(45,ptr+1);
*ptr++ = ')';
*ptr = 0;
_put_str(_str_cat(xy_msg, xy_coord));
}
In the example above, the displayed string would be "X,Y coordinates: (23,45)".
- _asc_to_uc
- Converts an ASCII string to an unsigned char in a given radix.
- _asc_to_c
- Converts an ASCII string to a char in a given radix.
- _asc_to_ui
- Converts an ASCII string to an unsigned int in a given radix.
- _asc_to_i
- Converts an ASCII string to a int in a given radix.
- _asc_to_ul
- Converts an ASCII string to an unsigned long in a given radix.
- _asc_to_l
- Converts an ASCII string to a long in a given radix.
- _asc_to_uq
- Converts an ASCII string to a uquad in a given radix.
- _asc_to_q
- Converts an ASCII string to a quad in a given radix.
- _dec_to_uc
- Converts a decimal ASCII string to an unsigned char.
- _dec_to_c
- Converts a decimal ASCII string to a char.
- _dec_to_ui
- Converts a decimal ASCII string to an unsigned int.
- _dec_to_i
- Converts a decimal ASCII string to a int.
- _dec_to_ul
- Converts a decimal ASCII string to an unsigned long.
- _dec_to_l
- Converts a decimal ASCII string to a long.
- _dec_to_uq
- Converts a decimal ASCII string to a uquad.
- _dec_to_q
- Converts a decimal ASCII string to a quad.
- _hex_to_uc
- Converts a hexadecimal ASCII string to an unsigned char.
- _hex_to_ui
- Converts a hexadecimal ASCII string to an unsigned int.
These functions convert digits from an ASCII string to a binary value. The _hex_to_... and _dec_to_... functions interpret the characters from the string as hexadecimal or decimal digits, respectively. The _asc_to_... functions interpret the characters as digits in a specified radix from 2 to 36. The unsigned functions treat leading plus or minus signs as invalid characters; the signed functions accept a single leading plus or minus sign.
Both upper and lowercase ASCII letters are recognized as digits in the range 1010 to 3510 . For example, in base 11 and above, either "A" or "a" is equivalent to 1010 , and in base 36, both "Z" and "z" are accepted as 3510 .
All of the string-to-numeric conversion functions return a pointer to the first string character which is not a valid digit. Leading white space characters are not automatically skipped since this is not always desirable. If white space characters should be skipped, call _str_skipw or _str_skips before calling the string-to-numeric function.
The integer string-to-numeric conversion functions are subject to overflow. The char and int functions provide simple overflow checking. In the event of overflow, 1 is returned in the global c_code condition variable, an index pointer is advanced past the entire number, and the return value is undefined. This provides some overflow checking without hindering execution speed; it also allows overflow to be ignored without writing additional code. The long and quad functions do notcheck for overflow because it cannot be done without seriously hindering execution speed. If overflow occurs, the return value is undefined. Note that the _hex_to_... functions do not provide an overflow return. Instead, they provide a return which indicates that more hexadecimal digits remain to be processed.
Fixed-point integers are true integer values with an implied number of decimal digits to the right of an implied decimal point. The precision of a fixed-point number specifies the fixed number of digits to the right of the decimal point. (Restated, fixed-point integers have implied exponents of precision or a value of fixed-point10precision.)
For example, a fixed-point integer value of 54,321 with a precision of 3 represents 54321e-3 or 54.321. A fixed-point integer value of 10,025 in U.S. monetary units (precision of 2), represents 10,025 cents or $100.25.
The precision of a fixed-point value is only specified when the _dec_to_fixp or _fixp_to_dec data conversion functions are called. In all other respects, fixed-point integers are treated as integer values. Because fixed-point integers are manipulated using standard integer math routines, they provide a fast, tight alternative to floating-point values.
WARNING! It is the responsibility of the programmer to keep track of the precision of each fixed-point value. When fixed-point values are multiplied, their precisions must be added to determine the precision of the result. When fixed-point values are divided, the precision of the divisor must be subtracted from the precision of the dividend. Negative precisions are not supported. Standard integer values have a precision of 0.
- _ufixpi_to_dec
- Converts a fixed-point unsigned int to a decimal ASCIIZ string.
- _fixpi_to_dec
- Converts a fixed-point int to a decimal ASCIIZ string.
- _ufixpi_to_dece
- Converts a fixed-point unsigned int to a decimal ASCII string, returning a pointer to the end of the resulting string.
- _fixpi_to_dece
- Converts a fixed-point int to a decimal ASCII string, returning a pointer to the end of the resulting string.
- _ufixpl_to_dec
- Converts a fixed-point unsigned long to a decimal ASCIIZ string.
- _fixpl_to_dec
- Converts a fixed-point long to a decimal ASCIIZ string.
- _ufixpl_to_dece
- Converts a fixed-point unsigned long to a decimal ASCII string, returning a pointer to the end of the resulting string.
- _fixpl_to_dece
- Converts a fixed-point long to a decimal ASCII string, returning a pointer to the end of the resulting string.
- _ufixpq_to_dec
- Converts a fixed-point uquad to a decimal ASCIIZ string.
- _fixpq_to_dec
- Converts a fixed-point quad to a decimal ASCIIZ string.
- _ufixpq_to_dece
- Converts a fixed-point uquad to a decimal ascii string, returning a pointer to the end of the resulting string.
- _fixpq_to_dece
- Converts a fixed-point quad to a decimal ASCII string, returning a pointer to the end of the resulting string.
The fixp_to_dec functions convert fixed-point numeric values to strings of ASCII digits. These functions allow fixed-point numeric values to be maintained as integers and output with an embedded decimal point. (See Fixed-Point Integers, above, for a discussion of fixed-point integers.)
Functions which write out an ASCIIZ string return a pointer to the beginning of the resulting string. Function with names which end with an "e" write out non-NULL terminated ASCII strings and return a pointer to the first character past the end of the string. This makes it possible to append additional characters very rapidly. Functions which accept signed input values always place a minus sign at the beginning of the resulting string if the input value is negative.
The fixp_to_dec functions create output strings in decimal ASCII fixed-point format, which is a special case of standard non-exponential format. Strings in this format may be used with theformatting functions described later in this chapter. Decimal ASCII fixed-point format is defined as follows:
- [-][d...][.][d...]
- (where d denotes any decimal digit)
- _dec_to_ufixpi
- Converts a decimal ASCII string to a fixed-point unsigned int.
- _dec_to_fixpi
- Converts a decimal ASCII string to a fixed-point int.
- _dec_to_ufixpl
- Converts a decimal ASCII string to a fixed-point unsigned long.
- _dec_to_fixpl
- Converts a decimal ASCII string to a fixed-point long.
- _dec_to_ufixpq
- Converts a decimal ASCII string to a fixed-point uquad.
- _dec_to_fixpq
- Converts a decimal ASCII string to a fixed-point quad.
These functions convert decimal ASCII strings to fixed-point integer values. The unsigned functions treat leading plus or minus signs as invalid characters; the signed functions accept a single leading plus or minus sign. All functions recognize a decimal character (".") as a valid character. (See Fixed-Point Integers, above, for a discussion of fixed-point integers.)
All of the fixed-point-to-numeric functions return a pointer to the first string character which is not a valid digit. Leading white space characters are not automatically skipped since this is not always desirable. To skip leading white space characters, call _str_skipw or _str_skips before calling the fixed-point-to-numeric function.
The integer fixed-point-to-numeric conversion functions are subject to overflow. The int functions provide simple overflow checking. In the event of overflow, 1 is returned in the global c_code condition variable, an index pointer is advanced past the entire number, and the return value is undefined. This provides some overflow checking without hindering execution speed; it also allows overflow to be ignored without writing additional code. The long and quad functions do not check for overflow because checking cannot be done without seriously hindering execution speed. If overflow occurs, the return value is undefined.
- _bcd_to_dec
- Converts a bcd number to a decimal ASCIIZ string.
- _bcd_to_dece
- Converts a bcd number to a decimal ASCII string, returning a pointer to the end of the resulting string.
- _dec_to_bcd
- Converts an ASCII string to a bcd number.
The _bcd_to_dec... functions convert numeric bcd values to strings of decimal ASCII digits. These functions support the same packed bcd format which is supported by the 8087 numeric coprocessor. However, these functions do NOT require a numeric coprocessor.
The _bcd_to_dec... functions accept signed input values and always place a minus sign at the beginning of the resulting string if the input value is negative. _bcd_to_dec writes out an ASCIIZ string and returns a pointer to the beginning of the resulting string. _bcd_to_dece writes out a non-NULL terminated ASCII string and returns a pointer to the first character past the end of the string. This makes it possible to append additional characters more rapidly than is possible with _bcd_to_dec.
_dec_to_bcd converts digits from an ASCII string to a bcd value. This function accepts an optional leading plus or minus sign followed by the ASCII digits to convert. The returned pointer points to the first string character which is not a valid digit. _dec_to_bcd does not check for overflow. Leading white space characters are not automatically skipped since this is not always desirable. To skip leading white space characters, call _str_skipw or _str_skips before calling the string-to-numeric function.
The _bcd_to_dec functions create output strings in decimal ASCII integer format, which is a special case of standard non-exponential format. Strings in this format may be used with the numeric formatting functions described later in this chapter. Decimal ASCII integer format is defined as follows:
- [-][d...]d
- (where d denotes any decimal digit)
- _q_to_bcd
- Converts a quad to a BCD number.
- _bcd_to_q
- Converts a BCD number to a quad.
These functions provide conversion facilities between quad integers and packed bcd numbers. The format of the packed bcd number is the same format supported by the 8087 numeric coprocessor. These functions do NOT require a numeric coprocessor and are provided to allow integer math facilities to be used for bcd numbers.
- _f_to_dec
- Converts a float to a decimal ASCIIZ string in standard exponential format.
- _f_to_dece
- Converts a float to a decimal ASCII string in standard exponential format, returning a pointer to the end of the resulting string.
- _f_to_decn
- Converts a float to a decimal ASCIIZ string in standard non-exponential format.
- _f_to_decne
- Converts a float to a decimal ASCII string in standard non-exponential format, returning a pointer to the end of the resulting string.
- _d_to_dec
- Converts a double to a decimal ASCIIZ string in standard exponential format.
- _d_to_dece
- Converts a double to a decimal ASCII string in standard exponential format, returning a pointer to the end of the resulting string.
- _d_to_decn
- Converts a double to a decimal ASCIIZ string in standard non-exponential format.
- _d_to_decne
- Converts a double to a decimal ASCII string in standard non-exponential format, returning a pointer to the end of the resulting string.
- _ld_to_dec
- Converts a long double to a decimal ASCIIZ string in standard exponential format.
- _ld_to_dece
- Converts a long double to a decimal ASCII string in standard exponential format, returning a pointer to the end of the resulting string.
- _ld_to_decn
- Converts a long double to a decimal ASCIIZ string in standard non-exponential format.
- _ld_to_decne
- Converts a long double to a decimal ASCII string in standard non-exponential format, returning a pointer to the end of the resulting string.
These functions convert a floating-point numeric value to a decimal ASCII string in standard exponential or non-exponential format. A numeric coprocessor or 8087 compatible emulator is required for these functions. When these functions are used, the appropriate floating-point conversion library (_FPC??.LIB) must also be linked in.
The ..._to_dec and ..._to_dece functions convert the floating-point value directly to an ASCII string in standard exponential format. The ..._to_decn and ..._to_decne functions convert the floating-point value directly to an ASCII string in standard non-exponential format. These standard formats are defined as follows:
Standard Exponential Format:
[-]d[.][d...]e[-]d[d...](where d denotes any decimal digit)
Standard Non-Exponential Format:
[-][d...]d[.][d...] (where d denotes any decimal digit)
Functions which write out an ASCIIZ string return a pointer to the beginning of the resulting string. Functions with names which end with an "e" write out non-NULL terminated ASCII strings andreturn a pointer to the end of the resulting string. This makes it possible to append additional characters very rapidly.
A minus sign is always written at the beginning of the resulting string if the input value is negative. No decimal point is written if there are no digits after the decimal point (e.g., "12345" and "1e2"). Floating-point numbers in the range -1 < n < 1 which are converted to non-exponential format are written with a leading zero (e.g., 1.234e-2 is converted to "0.01234" in non-exponential format).
- _dec_to_f
- Converts an ASCII string to a float.
- _dec_to_d
- Converts an ASCII string to a double.
- _dec_to_ld
- Converts an ASCII string to a long double.
These functions convert digits from a standard exponential or non-exponential format ASCII string to a floating-point value. A numeric coprocessor or 8087 compatible emulator is required for these functions. When these functions are used, the appropriate floating-point conversion library (_FPC??.LIB) must also be linked in.
These functions accept an optional leading plus or minus sign followed by the ASCII digits to convert. The following characters are also allowed in the string: a leading minus sign ("-"), a decimal point ("."), the default exponent indicator ("e"), and a minus sign in the exponent (as in "-1.23e-4"). A pointer is returned to the first string character which is not a valid character. Leading white space characters are not automatically skipped. To skip leading white space characters, call _str_skipw or _str_skips before calling these string-to-numeric functions.
The numeric result of these functions uses IEEE floating-point format (interpretable by the 8087 numeric coprocessor).
- dc_addr
- (Variable) Contains the address of the current data conversion options structure.
- _dc_init
- Initializes the current data conversion options structure with DOS country information.
dc_addr is a near/far pointer that contains the address of the current data conversion options structure (dcopts). In small data models (TINY, SMALL, MEDIUM), this variable is a near pointer which contains the offset of the structure within DGROUP (global or static non-far data). In large data models (COMPACT, LARGE, HUGE), this variable is a far pointer which contains the segment and offset of the structure.
The current dcopts structure specifies global data conversion formatting options and is used by _form_to_dec, _dec_to_form, and the scripted I/O functions. The behavior of these functions may be changed by modifying this structure or by modifying dc_addr to point to a different dcopts structure.
dc_addr is initialized with the address of the default dcopts structure. The default dcopts structure is defined in DATACONV.H as follows:
typedef struct {
char * dc_leadplus; /* leading plus string pointer ("+") */
char * dc_trailplus; /* trailing plus string pointer (NULL) */
char * dc_leadneg; /* leading neg string pointer ("-") */
char * dc_trailneg; /* trailing neg string pointer (NULL) */
char * dc_expstr; /* exponent string pointer ("e") */
char dc_curstr[6]; /* ASCIIZ currency string ("$") */
char dc_thdelim; /* thousands delimiter (",") */
char dc_decdelim; /* decimal delimiter (".") */
char dc_curdigits; /* currency digits after decimal point (2) */
unsigned char dc_flags; /* currency location, use "+" in exp, suppress
leading zero, min number of exponent digits */
} dcopts;
The DC_DEFAULT symbolic constant (defined in DATACONV.H) may be specified for any field which accepts a pointer. This causes the data conversion functions to use the default string, shown in the comments above, for each field in which it is specified.
Each field in the dcopts structure specifies a data conversion option. The dcopts structure fields are defined as follows:
- dc_leadplus
- Address of the leading positive sign indicator string. If DC_DEFAULT is specified, the default "+" string is assumed. If a string address is specified, that string is used in place of the default "+" string. This string precedes positive decimal strings if the DC_PLUS formatting flag is specified (see _dec_to_form).
- dc_trailplus
- Address of the trailing positive sign indicator string. If DC_DEFAULT is specified, a NULL string is assumed. If a string address is specified, that string is used instead. This string follows positive ASCII decimal strings if the DC_PLUS formatting flag is specified (see _dec_to_form).
- dc_leadneg
- Address of the leading minus sign indicator string. If DC_DEFAULT is specified, the default "-" string is assumed. If a string address is specified, that string is used in place of the default "-" string. This string precedes negative ASCII decimal strings.
- dc_trailneg
- Address of the trailing negative sign indicator string. If DC_DEFAULT is specified, a NULL string is assumed. If a string address is specified, that string is used instead. This string follows negative ASCII decimal strings.
- dc_expstr
- Address of the exponent indicator string. If DC_DEFAULT is specified, the default "e" exponent indicator is assumed. If a string address is specified, it is used in place of the default "e" exponent indicator.
- dc_curstr
- Currency symbol string (ASCIIZ). If a currency format is selected, this immediate string either precedes or follows the decimal ASCII string depending on the state of the DC_CPRECEDE bit in the dc_flags field. The default string is "$". This field is updated by _dc_init. (This field is defined as a string instead of a string pointer for compatibility with DOS country information.)
- dc_thdelim
- Thousands delimiter character. This character appears after every third significant digit from right to left, starting at the decimal point in the decimal ASCII string. The default character is the comma. This character only appears if the DC_THOUS formatting flag is specified (see _dec_to_form). This field is updated by _dc_init.
- dc_decdelim
- Decimal delimiter character. This character separates the integer and fractional portions of the decimal ASCII string. The default character is a period. This field is updated by _dc_init.
- dc_curdigits
- Number of digits to the right of the decimal point in country-specific currency strings. The default is 2 digits. This field is updated by _dc_init.
- dc_flags
- Miscellaneous formatting information (see the dc_flag equates below). All bits are clear by default. Portions of this field are updated by _dc_init.
The following symbolic constants (defined in DATACONV.H) may be used to check or modify the information in the dc_flags field:
- DC_CPRECEDE
- (0x00) Currency symbol precedes the number (default)
- DC_CFOLLOW
- (0x01) Currency symbol follows the number
- DC_NOEXPPLUS
- (0x00) No "+" on positive exponent strings (default)
- DC_EXPPLUS
- (0x04) Use "+" on positive exponent strings
- DC_LEADZERO
- (0x00) Use leading zero if number would start with "." (default)
- DC_NOLEADZERO
- (0x08) No leading zero if number would start with "."
- DC_MINEXP1
- (0x00) Use minimum of 1 digit in exponent (default)
- DC_MINEXP2
- (0x40) Use minimum of 2 digits in exponent
- DC_MINEXP3
- (0x80) Use minimum of 3 digits in exponent
- DC_MINEXP4
- (0xC0) Use minimum of 4 digits in exponent
Defines with a value of zero are the defaults and are provided for completeness only.
- _dc_init
- updates the current data conversion options structure (referenced by dc_addr) with the DOS country information for the current or specified country. Updated information includes the currency string, thousands delimiter, decimal delimiter, currency digits, and currency symbol position. (The currency position is stored by setting DC_CURR_PN or DC_CURR_FN in dc_flags and prefixing or appending the appropriate number of space characters to the currency symbol string specified in dc_curstr.) This function does not need to be called if the dcopts structure already contains the correct information.
- _dec_to_form
- Converts a decimal ASCII numeric string to a formatted decimal ASCIIZ numeric string.
- _dec_to_forme
- Converts a decimal ASCII numeric string to a formatted decimal ASCII numeric string, returning a pointer to the end of the resulting string.
- _fdec_to_form
- Converts a standard decimal ASCII string to a formatted decimal ASCIIZ string using far pointers.
- _fdec_to_forme
- Converts a standard decimal ASCII string to a formatted decimal ASCII string using far pointers, returning a pointer to the end of the resulting string.
- _form_to_dec
- Converts a formatted decimal ASCII string to a standard decimal ASCIIZ string.
- _form_to_dece
- Converts a formatted decimal ASCII string to a standard decimal ASCII string, returning a pointer to the end of the resulting string.
- _fform_to_dec
- Converts a formatted decimal ASCII string to a standard decimal ASCIIZ string using far pointers.
- _fform_to_dece
- Converts a formatted decimal ASCII string to a standard decimal ASCII string using far pointers, returning a pointer to the end of the resulting string.
The _dec_to_form... and _fdec_to_form... functions convert decimal ASCII strings to formatted decimal ASCII strings. Strings are formatted by fixing the precision to the right of the decimal point (if applicable), inserting thousands separators, currency symbols, etc. Input strings must be in standard exponential or standard non-exponential format with an optional leading plus sign character for positive values.
The _form_to_dec... and _fform_to_dec... functions strip formatting characters from formatted decimal ASCII strings to create exponential or non-exponential decimal ASCII strings.
_dec_to_form, _fdec_to_form, _form_to_dec, and _fform_to_dec return a pointer to the resulting ASCIIZ string. _dec_to_forme, _fdec_to_forme, _fform_to_dece, and _form_to_dece return a pointer to the end of the resulting non-NULL terminated string. This makes it possible to append additional characters very rapidly. Leading white space characters are not automatically skipped. To skip leading white space characters, call _str_skipw or _str_skips before calling these formatting functions.
A numeric coprocessor is NOT required for these formatting functions.
When formatting is performed, the precision of the result is specified and the result is never allowed to exceed a specified number of characters (width). The format of the result is specified in three places: 1) the current data conversion options structure; 2) numeric formatting flags which specify plus sign, currency, thousands, and exponential format options, and 3) precision flags which specify rounding, truncation, and significant digit formatting options. For the _dec_to_form functions, these options designate the final appearance of the formatted output string. For the _form_to_dec functions, these options indicate the expected format of the formatted input string.
The current data conversion options structure specifies global formatting options such as sign indicator strings, thousands delimiter, decimal delimiter, currency symbol location, currency precision, exponent string, exponent sign suppression, minimum number of exponent digits, and zero suppression before the decimal point. These options may be accessed or modified through the dc_addr variable. (See dc_addr, above, for further information.)
Numeric formatting options are specified using the following symbolic constants (defined in DATACONV.H):
- DC_NOPLUS
- (0x00) No plus sign is written if the value is positive. On input, no plus sign is allowed.
- DC_PLUS
- (0x10) A plus sign is written if the value is positive. On input, a plus sign is allowed and is specifically checked for. The plus sign is read or written using the leading/trailing plus sign strings which are specified in the current dcopts structure.
- DC_NOCURRENCY
- (0x00) No currency symbol is inserted into the result. On input, no currency symbols are allowed.
- DC_CURRENCY
- (0x08) A currency symbol is inserted into the result in the position specified in the current dcopts structure. On input, currency symbols are checked for and removed if present. The currency symbol and insertion position are specified in the current dcopts structure.
- DC_NOTHOUS
- (0x00) Thousands separators are not used in the result. On input, thousands separators are not allowed.
- DC_THOUS
- (0x04) Thousands separators are used in the result. On input, thousands separators are allowed. Separators appear only to the left of the decimal point.
- DC_NOEXP
- (0x00) The result is written in non-exponential form; NULL is returned if the result exceeds width. On input, exponential format is specifically disallowed; if an exponential number is read, then only the mantissa is converted (the exponent is ignored).
- DC_EXP
- (0x01) The result is written in exponential form; NULL is returned if the result exceeds width. On input, exponential format is allowed.
- DC_FLEX
- (0x02) The result is written in non-exponential form if possible; precision indicates the maximum or required number of digits to the right of the decimal point. On input, exponential format is allowed. This format supports all possible output values in a more consistent and visually pleasing form than the "G" or "g" formats supported by printf. The result is written in exponential form if the non-exponential result would exceed width. If exponential form must be used, the maximum possible number of digits are written to the right of the decimal point; NULL is returned if the exponential result would exceed width.
Precision flags are specified by bitwise ORing together the constants from the following list (defined in DATACONV.H) into the specified precision value:
- DC_ROUND
- (0x00) The result is rounded if required. "Round to nearest" is the rounding method employed. If both destinations are equidistant, then "rounding away from zero" is performed.
- DC_TRUNC
- (0x20) The result is not rounded. Less significant digits are truncated.
- DC_FIX
- (0x00) Forces precision digits to the right of the decimal point by appending trailing zeros if necessary. This option is ignored on input.
- DC_FILL
- (0x40) Forces precision characters to the right of the decimal point by replacing trailing zeros with the space character. If the decimal point is suppressed, it is also replaced with the space character. (Note that this inserts space characters between the mantissa and exponent in exponential format.) This option causes trailing space characters to be skipped after the mantissa on input.
- DC_FLOAT
- (0x80) Allows at most precision digits to right of the decimal point. Trailing zeros are not written. The decimal point is suppressed if there are no digits to the right of the decimal point. This option is ignored on input.
In addition, the following constant allows the precision of currency strings to be specified in a country-independent manner whether or not a currency symbol is written. This constant is used in place of the precision value specified in the precision parameter:
- DC_CDIGITS
- (0x1F) Use the country-specific precision specified for currency in the dc_curdigits field of the current data conversion options structure.
width must be in the range 0 to 126. A width of 0 denotes "no limit" (which translates into the maximum internally supported width of at least 126 characters).
The following table of flags, input strings, and output strings shows the results of some simple combinations of numeric and precision flags. These examples all assume a precision of 2:
Input strings: "155.0023" "3.1209e1" "12045" "3.006e12"
Numeric flags: DC_NOEXP DC_NOEXP DC_EXP DC_EXP
Precision flags output strings:
DC_ROUND+DC_FIX "155.00" "31.21" "1.20e4" "3.01e12"
DC_ROUND+DC_FILL "155 " "31.21" "1.2 e4" "3.01e12"
DC_ROUND+DC_FLOAT "155" "31.21" "1.2e4" "3.01e12"
DC_TRUNC+DC_FIX "155.00" "31.20" "1.20e4" "3.00e12"
DC_TRUNC+DC_FILL "155 " "31.2 " "1.2 e4" "3 e12"
DC_TRUNC+DC_FLOAT "155" "31.2" "1.2e4" "3e12"
Requirements for Using Floating-Point Conversion Functions
Most of the ASCII-to-floating-point and floating-point-to-ASCII conversion functions make use of the 80x87 floating-point instruction set. Therefore, the appliction must be linked with floating-point emulation enabled if these functions are used in an application which may be run on a system without a coprocessor. This requirement is documented in the reference section for each function to which it applies.
Spontaneous Assembly functions which use 8087 floating-point instructions are NOT present in the standard libraries (_SA?.LIB). Instead, these functions are found in separate floating-point libraries (_FPC??.LIB) which have been pre-assembled to support specific compilers or a numeric coprocessor (no floating-point emulation). These libraries are as follows:
Library Description
- FPCBm.LIB
- Spontaneous Assembly functions which have been assembled specifically for use with Borland/Turbo C/C++
- FPCMm.LIB
- Spontaneous Assembly functions which have been assembled specifically for use with Microsoft C/C++
- FPCTm.LIB
- Spontaneous Assembly functions which have been assembled specifically for use with TopSpeed C
- FPCZm.LIB
- Spontaneous Assembly functions which have been assembled specifically for use with Zortech C++
- FPCNm.LIB
- Spontaneous Assembly functions which have been assembled for use in systems which have a numeric coprocessor
In each library name shown above, m denotes a single letter (T, S, M, C, or L) which indicates one of the five standard memory models (TINY, SMALL, MEDIUM, COMPACT, or LARGE).
FPCNm.LIB should be used if floating-point facilities are not required by the application.
At present, only the floating-point data conversion functions (_DF*.ASM) are included in these special floating-point coprocessor libraries.
The CALC sample program described in the Integer Math technical notes uses several data conversion functions and demonstrates conversions from asc-to-quad and quad-to-asc in various radices.