从字符串指针解析int

c++ parse int from string pointer

本文关键字:int 指针 字符串      更新时间:2023-10-16

是否有一种方便的方法从c++中的string::iterator解析整数?对于这个特殊的问题,我只关心以10为底的非负整数,但是所有这些解都可以很容易地推广到任意整数。注意,与类似的问题不同,我没有对原始字符串的引用,只有一个迭代器,例如

int parse_next_int(std::string::iterator begin, std::string::iterator end) {
    // ...
}

我能想到很多方法,但没有一个是好的。另一个注意事项,我没有声明stl头,并且我假设一切都在std名称空间中完成。希望这不会使示例难以解析。

  1. 分配一个新字符串,然后调用stoi:

    int parse_next_int(string::iterator begin, string::iterator end) {
          string::iterator num_end = find_if(
              begin, end, [](char c)->bool{return !isdigit(c);});
          string to_parse(begin, num_end);
          return stoi(to_parse);
    }
    
  2. 这样做的缺点是,我最终会为可能被动态解析的东西分配一个新的缓冲区。
  3. 将unsafely视为c字符串。

    int parse_next_int(std::string::iterator begin, std::string::iterator end) {
        return atoi(&(*begin));
    }
    

    这在某种程度上可以工作,但是如果它到达字符串的末尾并且不是null终止(这在c++字符串中不能保证),它将出现段错误,所以虽然很简洁,但这可能是最糟糕的。

  4. 我自己写:

    int parse_next_int(std::string::iterator begin, std::string::iterator end) {
          int result = 0;
          while (begin != end && isdigit(*begin)) {
              result = result * 10 + (*begin++ - '0');
          }
          return result;
    }
    

    这是工作和简单,但它也严重依赖于问题,不是很容错

是否有一些明显不同的方法,主要依赖于更宽容的stl调用,同时仍然是简单的,避免复制不必要的缓冲区?

如果您可以访问boost,则可以使用:

int parse_next_int(std::string::iterator begin, std::string::iterator end) {
    return boost::lexical_cast<int>(&(*begin), std::distance(begin, end));
}
  1. 从迭代器中创建一个std::string
  2. string创建std::istringstream
  3. istringstream中提取整数

int parse_next_int(std::string::iterator begin, std::string::iterator end) {
   std::string s(begin, end);
   std::istringstream str(s);
   int i;
   str >> i;
   return i;
}

PS添加错误处理代码,使其适合生产。

不要使用atoi,如果超过INT_MAX,会导致未定义的行为。选项3也有同样的问题。

我的建议是:
  1. 查找数字的末尾,使用find_ifstrchr或任何其他方法;如果你愿意,允许-+的前导。
  2. null -终止子字符串
  3. 使用strtol转换,用代码处理所有溢出情况

关于null终止,您可以选择以下选项之一:

    复制到一个自动数组(最简单的选项)。
  • 如果end实际上不是字符串的结尾,在那里写一个临时空终止符,然后恢复旧的字符。

请注意,自c++ 11以来,std::string s 保证以null结束,因此您的解引用和处理作为C字符串的解决方案根本不安全;并且,在评论中解释了发生了什么,我将为这个问题的最佳解决方案投票。