I need a strtol function that would allow me specify bounds in which the string will be parsed. For example
char * number = "123456789";
std::cout << my_strtol(number, 1, 3);
Should print "234".
Using some pointer arithmetic I could get pretty close:
int32_t my_strtol(const char* str, int from_char, int to_char, int base = 10)
{
char *end;
auto res = strtol(str + from_char, &end, base);
auto extra_digits = end - str - (to_char + 1);
if(extra_digits > 0) res /= pow(10, extra_digits);
return res;
}
this however it fails if the string is greater than LONG_MAX (regardless the value of said part). For example input for "1234567890123456789" the call str_to_l(number, 1, 3) would fail and return 0. Moreover it uses unnecessary pow – the performance is crucial.
Edit: I would like to avoid constructing new strings or string streams, because I will be extracting multiple integers from same buffer and even more importantly I will be literally performing tens thousands of these calls.
For those who are interested in (casual)profiling results of suggested solutions:
//put temp null character at end
int32_t my_strtol1(char* str, int from_char, int to_char, int base = 10)
{
char tmp = str[to_char];
str[to_char] = '\0';
auto res = strtol(str + from_char, nullptr, base);
str[to_char] = tmp;
return res;
}
//use substr()
int32_t my_strtol2(const std::string& str,
const std::string::size_type from_char,
const std::string::size_type to_char,
int base = 10) {
return std::stol(str.substr(from_char, to_char - from_char + 1));
}
//using boost
int32_t my_strtol3(char* str, int from_char, int to_char) {
return boost::lexical_cast<int>(str + from_char, to_char - from_char + 1);
}
//parse characters one by one
int32_t my_strtol4(const char* str, int from_char, int to_char)
{
int32_t res = 0;
for (int i = from_char; i < to_char; i++)
{
char ch = str[i];
ch -= '0';
if (ch > 10 || ch < 0) return 0;
res *= 10;
res += ch;
}
return res;
}
The output (measured by clock_t) on my machine was:
Manipulating null character with 100000 iterations took 0.114s
Using substr() with 100000 iterations took 0.62s
Using boost::lexical_cast<T>() with 100000 iterations took 0.231s
Parsing character one by one with 100000 iterations took 0.083s
std::stolis the C++11 version of C'sstrtol.std::stringinstead ofchar *, and usestd::stolon a.substr().strtolwill convert until it reaches a non-digit character or a null terminator. This is why you're getting issues with values greater thanLONG_MAX.std::string numstr = number; return std::stol(number.substr(from_char, to_char-from_char));