11

Is there a standard C function similar to strtol which will take a char* and a length for a non-null-terminated string?

I know that I could copy out the string into a null-terminated region, but for efficiency reasons that is undesirable.

Zoe
  • 27,060
  • 21
  • 118
  • 148
kdt
  • 27,905
  • 33
  • 92
  • 139
  • 3
    hi, I come from the future. Would you believe that 10 years later there still is no standard solution that does not require one to copy the string to a temporary buffer? And remember that Simpsons episode aired in 2000 where Trump was the United States president? You won't believe it if I told you... – user1593842 Apr 30 '19 at 13:26
  • @user1593842 If you are willing to use the C++ standard library, https://en.cppreference.com/w/cpp/utility/from_chars is a decent solution. –  Feb 03 '20 at 23:23

4 Answers4

4

No such function in the standard library. You will either have to use the temporary buffer method, or write your own function from scratch.

4

To answer your question: no, there is no standard function, but it is simple enough to write your own:

#include <stdio.h>
#include <ctype.h>

int natoi(char *s, int n)
{
    int x = 0;
    while(isdigit(s[0]) && n--)
    {
        x = x * 10 + (s[0] - '0');      
        s++;
    }
    return x;
}

int main(int argc, char*argv[])
{
    int i;
    for(i = 1; i < argc; i++)
        printf("%d: %d\n", i, natoi(argv[i], 5));
}
Wernsey
  • 5,411
  • 22
  • 38
2

strntol is probably what you're after... it's not standard C, though.

Stobor
  • 44,246
  • 6
  • 66
  • 69
1

If you're that pressed for efficiency, you can probably motivate the time to write and debug your own.

But: just do it with a copy; you probably have an upper bound for how long the string can be (a decimal numeral that fits in a long has a strict upper bound on its maximum length), so you can have a static buffer. Then profile your entire application, and see if the copying/conversion really is a bottleneck. If it really is, then you know you need to write your own.

Here's a rough (untested, browser-written) starting point:

long limited_strtol(const char *string, size_t len)
{
  long sign = 1;
  long value = 0;

  for(; len > 0 && *string == '-'; string++, len--)
    sign *= -1;

  for(; len > 0 && isdigit(*string); string++, len--)
  {
   value *= 10;
   value += *string - '0';
   len--;
   string++;
  }
  return sign * value;
}
unwind
  • 391,730
  • 64
  • 469
  • 606