简体   繁体   English

(字符串)基于迭代器到 int 的转换

[英](String)Iterator based conversion to int

There are the atox , strtox and stox families that I know of, but I can't seem to find any iterator based string to int conversions in the Standard Library or Boost.我知道atoxstrtoxstox系列,但我似乎无法在标准库或 Boost 中找到任何基于迭代器的字符串到 int 转换。

The reason I need them is because I am having a parser whose match result is a range referencing the input string.我需要它们的原因是因为我有一个解析器,它的匹配结果是一个引用输入字符串的范围。 I might very well have an input string like我很可能有一个输入字符串

...8973893488349798923475...
     ^begin   ^end

so I need 738934883 as an integer.所以我需要738934883作为整数。

Of couse, I could first take begin and end to construct an std::string to use with any of above families, but I would very much like to avoid that overhead.当然,我可以先使用beginend来构造一个std::string以用于上述任何系列,但我非常想避免这种开销。

So my question: Is there anything in the Standard Library or Boost accepting iterators as input, or do I have to write my own.所以我的问题是:标准库或 Boost 中是否有任何东西接受迭代器作为输入,还是我必须自己编写。

Boost does actually support this, using the Lexical Cast library. Boost 确实支持这一点,使用Lexical Cast库。 The following code uses a substring range to parse the number without performing any dynamic allocation:以下代码使用子字符串范围来解析数字而不执行任何动态分配:

#include <boost/lexical_cast.hpp>
#include <string>
#include <iostream>

int convert_strings_part(const std::string& s, std::size_t pos, std::size_t n)
{
    return boost::lexical_cast<int>(s.data() + pos, n);
}

int main(int argc, char* argv[])
{
    std::string s = "8973893488349798923475";

    // Expect: 738934883

    std::cout << convert_strings_part(s, 2, 9) << std::endl;

    return 0;
}

The output (tested on OS X with Boost 1.60):输出(在带有 Boost 1.60 的 OS X 上测试):

738934883

The lexical cast library has some great features for conversion to and from strings, though it isn't as well known as some of the others for some reason.词法转换库有一些很好的转换字符串和从字符串转换的特性,尽管由于某些原因它不像其他一些那样广为人知。

Until gavinb's answer, I was not aware of any such library function.在 gavinb 回答之前,我不知道有任何这样的库函数。 My try would have been this, using any of atox and strtox as follows (you could avoid a dependency on boost library then, if wanted):我的尝试是这样的,使用 atox 和 strtox 中的任何一个,如下所示(如果需要,您可以避免对 boost 库的依赖):

::std::string::iterator b; // begin of section
::std::string::iterator e; // end of section, pointing at first char NOT to be evaluated
char tmp = *e;
*e = 0;
int n = atoi(&*b);
*e = tmp;

If you only had const_iterators available, you would have to apply a const_cast to *e before modifying.如果您只有 const_iterators 可用,则必须在修改之前将 const_cast 应用于 *e。

Be aware that this solution is not thread safe, though.但是请注意,此解决方案不是线程安全的。

You could do it with strstream but it was depracated.你可以用 strstream 做到这一点,但它已被弃用。 Below two examples, with strstream and boost arrays:下面是两个带有 strstream 和 boost 数组的示例:

http://coliru.stacked-crooked.com/a/04d4bde6973a1972 http://coliru.stacked-crooked.com/a/04d4bde6973a1972

#include <iostream>
#include <strstream>

 #include <boost/iostreams/device/array.hpp>
 #include <boost/iostreams/stream.hpp>
 #include <boost/iostreams/copy.hpp>

int main()
{
    std::string in = "8973893488349798923475";
    //                  ^^^^^

    auto beg = in.begin()+2;
    auto end = in.begin()+6; 

    // strstream example - DEPRECATED
    std::istrstream os(&*beg, end-beg);
    int n;
    std::string ss;
    os >> n;
    std::cout << n << "\n";


    // Boost example
    namespace io = boost::iostreams;
    int n2;
    io::array_source src(&*beg, end-beg);
    io::stream<io::array_source> os2(src);

    os2 >> n2;
    std::cout << n2 << "\n";

    return 0;
}

使用现代 STL 实现std::string(begin,end)并没有那么糟糕 - SSO 消除了对小于 ~15 个字符(64 位为 22 个)的字符串的任何分配。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM