2016-09-15 135 views
1

有没有一种方便的方法来解析c + +中的string::iterator的整数?对于这个特定的问题,我只关心非负整数,但所有这些解决方案都可以很容易地扩展为任意整数。请注意,与similar questions不同,我没有对原始字符串的引用,只有一个迭代器,例如C++从字符串指针解析int

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. 不安全地视为c字符串。

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

    这将一定程度上工作,但如果它击中了字符串的结尾,它不是没有空值终止的(这是不符合C++字符串的保证),它会段错误,所以虽然漂亮,简洁,这可能是最不好。

  3. 写自己:

    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电话,同时仍然简单,避免不必要的复制缓冲区显著不同的方法?

+2

只是间接通过迭代器,你得到的字符串。然后你可以使用任何你会使用的方法,如果你有字符串。 – Barmar

+0

'strtol'比'atoi'更可取。 (但都有问题,你不能限制他们'结束')。你的选项3会导致一些输入的未定义行为(与atoi相同的问题) –

回答

3

如果你有机会来提高你可以使用:

int parse_next_int(std::string::iterator begin, std::string::iterator end) { 
    return boost::lexical_cast<int>(&(*begin), std::distance(begin, end)); 
} 
+0

我不是很倾向于单独使用boost,但是从我可以收集的信息看来,这个调用似乎避免了为整型类型分配stringstream,所以这看起来像是一个有效的答案。我仍然在更多地考虑实施。 – Erik

1
  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添加错误处理代码,使其生产价值。

+0

是的,我想到了这一点,但这与“stoi”选项没有什么不同,你也可以一直复制到最后,很贵。你提到一个更好的方法来做字符串复制,但我会更新问题来反映。 – Erik

+0

@Erik,'stoi'也应该有效。我对这两种方法之间的低水平差异没有感觉。 –

0

注意,由于C++ 11,std::string小号保证是空值终止,所以您提领和治疗,如-aC-string解决方案根本不是不安全的;并且在解释发生了什么的评论时,我会投票选出解决这个问题的最佳解决方案。

+0

[null只是另一个字符](http://stackoverflow.com/questions/11752705/does-string-contain-null-terminator) – wally

1

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

我的建议是:

  1. 查找数结束时,使用find_ifstrchr或任何其他方法;如果您愿意,可以领先-+
  2. 空终止子字符串
  3. 使用strtol转换,用代码来处理所有的溢出情况。

关于空终止,您可以选择下列之一:

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