Мне нужна функция strtol
, которая позволила бы мне определить границы, в которых будет разбираться строка. Например,C++ parse sub-string to integer
char * number = "123456789";
std::cout << my_strtol(number, 1, 3);
Следует напечатать «234».
Используя некоторые арифметические операции над указателями я мог бы получить довольно близко:
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;
}
это, однако он терпит неудачу, если строка больше LONG_MAX
(независимо от стоимости указанной части). Например, для ввода "123456789"
вызов str_to_l(number, 1, 3)
завершился с ошибкой и вернул 0. Более того, он использует ненужные pow
- производительность имеет решающее значение.
Edit: Я хотел бы избежать строительств новых строк или строковые потоков, потому что я буду извлекать несколько чисел из одной буфера и что еще более важно, я буду буквально исполнительскими десятки тысяч этих вызовов.
Для тех, кто заинтересован в (случайных) профилирующих результатов предложенных решений:
//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;
}
Выход (измеряется clock_t
) на моей машине было:
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 :: stol' - это версия C++ 11 C-strtol. –
Вы пробовали отладить его? Какие шаги вы предприняли? Что вы ожидаете от вызова strtol? Подсказка: он попытается преобразовать from_char, пока не увидит нулевой терминатор. Попробуйте ['std :: string'] (http://en.cppreference.com/w/cpp/string/basic_string) вместо' char * 'и используйте [' std :: stol'] (http: // ru.cppreference.com/w/cpp/string/basic_string/stol) на ['.substr()'] (http://en.cppreference.com/w/cpp/string/basic_string/substr). – Andrew
@MatsPetersson благодарит за комментарий, но неважно, является ли ввод строкой с нулевым завершением в стиле c или std :: string (я могу выбрать, какой тип буфера символов использовать). – wondra