C++ C++;将子字符串解析为整数
我需要一个C++ C++;将子字符串解析为整数,c++,performance,string-parsing,C++,Performance,String Parsing,我需要一个strtol函数,它允许我指定解析字符串的边界。比如说 char * number = "123456789"; std::cout << my_strtol(number, 1, 3); 但是,如果字符串大于LONG_MAX(无论所述部分的值如何),则此操作失败。例如,输入“12345678901213456789”调用str_to_l(数字,1,3)将失败并返回0。此外,它使用了不必要的pow——性能至关重要 编辑:我希望避免构造新的字符串或字符串流,因为我将从同一缓
strtol
函数,它允许我指定解析字符串的边界。比如说
char * number = "123456789";
std::cout << my_strtol(number, 1, 3);
但是,如果字符串大于LONG_MAX
(无论所述部分的值如何),则此操作失败。例如,输入“12345678901213456789”调用str_to_l(数字,1,3)
将失败并返回0。此外,它使用了不必要的pow
——性能至关重要
编辑:我希望避免构造新的字符串或字符串流,因为我将从同一缓冲区提取多个整数,更重要的是,我将执行成千上万个这样的调用
对于那些对建议解决方案的(偶然)分析结果感兴趣的人:
//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;
}
因此,如果您不需要超级便携性(例如,支持泰国、中国和阿拉伯数字):
int32我的字符串(const char*str,int from_char,int to_char,int base=10)
{
int32_t res=0;
for(int i=从字符i<到字符i++)
{
char ch=str[i];
如果(通道>9'和底部>10)
{
ch&=~32;/*使用大写字母*/
ch-=“A”+10;
}
其他的
{
ch-='0';
}
如果(ch>base | | ch<0)…请执行一些错误处理。。。
res*=基准;
res+=ch;
}
返回res;
}
如果您有Boost,它可以作为一个单行程序使用,它有一个重载,以char
指针和长度作为参数。据我所知,这是经过优化(专门化)的,可以直接对输入字符串进行操作,不需要执行拷贝或内存分配,也不需要涉及流
#include <iostream>
#include <boost/lexical_cast.hpp>
int
main()
{
const auto text = "123456789";
const auto number = boost::lexical_cast<int>(text + 1, 3);
std::cout << number << '\n';
}
我知道我以前从一个非常类似的问题的另一个答案中学到了这一点,但我又找不到它,所以我将在这里复制它。
std::stol
是C的strtol
的C++11版本。你试过调试它吗?你采取了什么措施?你希望打电话给strtol做什么?提示:它将尝试从from_字符转换,直到看到空终止符。请尝试在上使用而不是char*
。实际上,它是否以null结尾很重要。将进行转换,直到达到非数字字符或空终止符。这就是为什么您会遇到值大于LONG\u MAX
的问题;返回std::stol(number.substr(from_char,to_char-from_char))@wondra我已经写了三种方法:这些方法中有适合的吗?很抱歉误导了示例,没有提及它-我只希望使用10进制的ASCII字符串输入。我只编写了更通用的测试示例,因为它没有使代码复杂化。@wondra适应Mats的解决方案很容易。只需乘以10而不是base
,并删除对非数字字符的处理。当然,您仍然应该对字符串索引进行一些范围检查。唯一可以添加的是res
分析的数据类型。分析结果表明此解决方案优雅、安全且速度相当快,我之所以选择此解决方案,是因为其简单性和全面的结果。
int32_t my_strtol(const char* str, int from_char, int to_char, int base = 10)
{
int32_t res = 0;
for(int i = from_char; i < to_char; i++)
{
char ch = str[i];
if (ch > '9' && base > 10)
{
ch &= ~32; /* Make it upper case */
ch -= 'A' + 10;
}
else
{
ch -= '0';
}
if (ch > base || ch < 0) ... do some error handling ...
res *= base;
res += ch;
}
return res;
}
#include <iostream>
#include <boost/lexical_cast.hpp>
int
main()
{
const auto text = "123456789";
const auto number = boost::lexical_cast<int>(text + 1, 3);
std::cout << number << '\n';
}