↑ Software ↑

GEONius.com
28-Aug-2022
 E-mail 

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 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.

Public Procedures

String-to functions:
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.
Abbreviated ASCII-to functions:
antof() - ASCII to double.
antoi() - ASCII to integer.
antol() - ASCII to long.
antoll() - ASCII to long long

Source Files

sto_util.c
sto_util_template.h
sto_util.h

(See libgpl for the complete source, including support routines and build files.)


Alex Measday  /  E-mail