sto_util- Length-Limited String-to-Number Conversion Functions
The STO_UTIL package provides functions for converting length-limited substrings to numbers.
There is a standard set of NUL-terminated string to number conversion
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, &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
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.
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
idea I like except for the problems with
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
#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
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) ;
strnto...() functions, of course, have the extra length
argument at the end.
Shortly afterwards, I added the
anto...() functions, which are
strnto...() functions without the endpoint and base
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 long
for the complete source, including support routines and build files.)