在C++和range-v3中,如何将一串以空格分隔的数字转换成一个整数向量?

wwwo4jvm  于 2023-02-06  发布在  其他
关注(0)|答案(2)|浏览(99)

使用C++和range-v3库,将一个以空格分隔的数字字符串转换为整数向量的最佳方法是什么?
我尝试了以下代码:

#include <iostream>
#include <range/v3/all.hpp>

using namespace std::literals;

int main() {
    auto r = "1 1 2 3 5 8 13"sv
        | ranges::views::split(" "sv)
        | ranges::views::transform([](auto &&i){ return std::stoi(std::string{i}); })
        | ranges::to<std::vector<int>>();

    for (auto i: r)
        std::cout << "Value: " << i << std::endl;
}

但是它不能编译,在clang中,错误如下:

repro-range.cpp:10:60: error: no matching constructor for initialization of 'std::string' (aka 'basic_string<char>')
                | ranges::view::transform([](auto &&i){ return std::stoi(std::string{i}); })
                                                                         ^          ~~~

看起来i的类型是ranges::detail::split_outer_iterator,并且它不能转换为字符串。实际上,我不知道如何使用i,不能解引用它,不能将它转换为任何有用的东西......用字符串替换string_views也不能改善这种情况。
奇怪的是,下面的代码工作正常:

auto r = "1 1 2 3 5 8 13"sv
        | ranges::views::split(" "sv)
        | ranges::to<std::vector<std::string>>();

这表明我的问题是netiher split也不是to,而是transform本身。
如何使首件代码工作?

vtwuwzda

vtwuwzda1#

深入研究后,我发现示例中的i既不是迭代器,也不是string_view的 Package 器(如我所料),而是一个字符的 range(具有beginend迭代器的特殊类型)。
也就是说,如果我先将i转换为字符串,那么代码就可以工作了。

auto r = "1 1 2 3 5 8 13"sv
        | ranges::views::split(" "sv)
        | ranges::views::transform([](auto &&i){
            return std::stoi(i | ranges::to<std::string>());
        })
        | ranges::to<std::vector<int>>();

不过,如果有人能用更好(至少不那么冗长)的方式来做到这一点,我会很高兴。

eqqqjvef

eqqqjvef2#

如果你有一个包含空格分隔数字的字符串,你可以先在字符串上创建一个std::istringstream,然后使用ranges::istream来解析数字(这里假设int是s):

auto s = "1 1 2 3 5 8 13";
auto ss = std::istringstream{s};
auto r = ranges::istream<int>(ss)
       | ranges::to<std::vector<int>>();

这是一个demo

相关问题