Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;将子字符串解析为整数_C++_Performance_String Parsing - Fatal编程技术网

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';
}