|
|
|
sto_util
- Length-Limited String-to-Number Conversion FunctionsThe STO_UTIL package provides functions for converting length-limited substrings to numbers.
There is a standard set of NUL-terminated string to number conversion
functions; e.g., strtol(3)
for long integers and
strtod(3)
for double floating-point numbers:
long integer = strtol (thisString, NULL, 0) ; double real = strtod (thatString, NULL) ;
Unfortunately, there aren't any standard, corresponding functions for length-limited substrings, such as:
const char *csvString = "abc,def,123,ghi,456.789" ; char *endp ; unsigned long number = strntoul (&csvString[8], &endp, 10, 5) ;
This example scans at most 5 characters beginning with the 8th character in
the string ("123,g"). In this case, strntoul()
will return a
value of 123; the end pointer will return &csvString[11]
,
the address of the comma immediately following the number.
On the internet, I found a variety of signatures for the
strnto...()
functions, some including character-set
information. My personal preference is to order arguments by type:
(i) input, (ii) input/output, and (iii) output. In
particular, the string length argument should be placed right after the
input string and the base (an input parameter) should come before the end
pointer (an output argument). If I'd had my druthers:
result = strtol (string, base, &endp) ; -- Not the real order. result = strntol (string, length, base, &endp) ;
However, I didn't have my druthers and I decided to add the string length after the existing arguments. If the functions are ever standardized, I figure that that's what will happen.
My strnto...()
functions depend on the existence of the
strto...(3)
functions. A NUL-terminated duplicate of the
substring is made with strndup(3)
and the duplicate is then
passed to the corresponding strto...()
function. With all the
strndup(3)
s, my functions are obviously not the speediest ones
in the world. One implementation I saw used alloca(3)
, an
idea I like except for the problems with alloca(3)
. Another
implementation recreated the whole kit and caboodle of the
strto...(3)
functions, modified to check if the scan has
reached the end of the substring.
After writing the strntol()
function and then modifying a copy
of it in a matter of seconds for strntoul()
, I realized that
the functions would all look the same. I created a template file,
"sto_util_template.h
", which uses C Preprocessor macros for
the function names and data types. Consequently, for each function, the
"code" in this file consists of "#define
"ing the macros and
then "#include
"ing the template.
The template handles two types of functions calls, those for integer
conversions and those for floating-point conversions, distinguished by the
number of arguments passed to their strto...(3)
functions.
For example, all the integer strto...(3)
s have 3 arguments:
result = strto...(string, &endp, base) ;
The floating-point functions drop the base and have 2 arguments:
result = strto...(string, &endp) ;
The strnto...()
functions, of course, have the extra length
argument at the end.
Shortly afterwards, I added the anto...()
functions, which are
simply the strnto...()
functions without the endpoint and base
arguments.
strntol()
- string to long.strntoul()
- string to unsigned long.strntoll()
- string to long long.strntoull()
- string to unsigned long long.strntof()
- string to float.strntod()
- string to double.strntold()
- string to long double.antof()
- ASCII to double.antoi()
- ASCII to integer.antol()
- ASCII to long.antoll()
- ASCII to long longsto_util.c
sto_util_template.h
sto_util.h
(See libgpl
for the complete source, including support routines and build files.)