Search code examples
clinuxglibcscanf

parse decimal string with sscanf


I want to parse string to integer. The string can contain any data, including invalid or float integers. This is my code which shows how I'm using sscanf():

errno = 0;
uint32_t temp;
int res = sscanf(string, "%"SCNu32, &temp);
if (0 != errno || 1 != res)
{
    return HEX_ECONVERSION;
}

where string passed as argument.

I've expected that this code would fail on "3.5" data. But unfortunately, sscanf() truncate "3.5" to 3 and write it to temp integer. What's wrong?

Am I improperly using sscanf()? And how to achieve this task by using sscanf, without writing hand-written parser (by directly calling strtoul() or similar).


Solution

  • Using the "%n" records where the scan is in the buffer.
    We can use it to determine what stopped the scan.

    int n;
    int res = sscanf(string, "%"SCNu32 " %n", &temp, &n);
    if (0 != errno || 1 != res || string[n] != '\0')
      return HEX_ECONVERSION;
    

    Appending " %n" says to ignore following white-space, then note the buffer position. If there is not additional junk like ".5", the string[n] will point to the null terminator.


    Be sure to test n after insuring temp was set. This was done above with 1 != res.

    "%n" does not affect the value returned by sscanf().