2

I need strtol to convert some numbers from a range of [0 to 255] how can I check the conversion of 0 if 0 is also a number that i need to convert?

long conv = strtol(argv, &p, 10);
if (conv == 0)
{
    perror("Conversion error");
    exit(EXIT_FAILURE);
}
if ((conv >= LONG_MAX || conv <= LONG_MIN) && errno == 34);
{
    perror("Invalid Range!");
    exit(EXIT_FAILURE);
}
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
Unknown
  • 71
  • 8

1 Answers1

4

Prior to calling strtol, set errno to 0.

Then after the call, check the value of errno. If it's 0, you know the call was successful. Addtionally, you'll want to check if *p is 0. If so, that means the entire string was parsed successfully with no extra characters.

errno = 0;
long conv = strtol(argv, &p, 10);  
if (errno)
{
    perror("Conversion error");
    exit(EXIT_FAILURE);
}
else if (*p)
{
    perror("Not all characters converted");
    exit(EXIT_FAILURE);
}

The man page also mentions this in the "Notes" section:

Since strtol() can legitimately return 0, LONG_MAX, or LONG_MIN (LLONG_MAX or LLONG_MIN for strtoll()) on both success and failure, the calling program should set errno to 0 before the call, and then determine if an error occurred by checking whether errno has a nonzero value after the call.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • 1
    I'm not sure it is required that `errno` is set when no conversion is done. The man page says: "The implementation **may** also set errno to EINVAL in case no conversion was performed (no digits seen, and 0 returned)." and the standard only mentions ERANGE as errno in case of over/underflow. This example doesn't set `errno` https://ideone.com/T3ddyH . I think you need to compare `argv` and `p` to catch the case with no conversion – Support Ukraine Jan 02 '19 at 16:36
  • The C standard has no requirements about `errno` when conversion fails (only range issues). The Linux man page is inconsistent with the C spec on this point. Code should check `if (argv == p)` for the no conversion condition. – chux - Reinstate Monica Jan 02 '19 at 19:25
  • @chux The code I've posted should account for all error cases, whether or not `errno is set to `EINVAL`. It both checks `errno` and check that `p` points to the end of the string to test for a complete conversion. – dbush Jan 02 '19 at 19:30
  • If `errno` was not set by `strtol()` on a non-conversion (which is compliant with the C standard), this code would errantly not complain about `strtol("", &p, 10);` – chux - Reinstate Monica Jan 02 '19 at 22:02