代码之家  ›  专栏  ›  技术社区  ›  Salgar

在一个语句中,我们可以将C++中的字符串拆分、操作和重新连接吗?

  •  2
  • Salgar  · 技术社区  · 15 年前

    这是一个令人毛骨悚然的问题,但是出于好奇,是否可能在逗号上拆分字符串,在字符串上执行函数,然后用C++在一个语句中重新加入逗号?

    这就是我目前为止所拥有的:

    string dostuff(const string& a) {
      return string("Foo");
    }
    
    int main() {
      string s("a,b,c,d,e,f");
    
      vector<string> foobar(100);
      transform(boost::make_token_iterator<string>(s.begin(), s.end(), boost::char_separator<char>(",")),
                boost::make_token_iterator<string>(s.end(), s.end(), boost::char_separator<char>(",")),
                foobar.begin(),
                boost::bind(&dostuff, _1));
      string result = boost::algorithm::join(foobar, ",");
    }
    

    所以这会导致转向 "a,b,c,d,e,f" 进入之内 "Foo,Foo,Foo,Foo,Foo,Foo"

    我知道这是奥特,但只是想扩大我的助推魔法。

    4 回复  |  直到 15 年前
        1
  •  1
  •   Cubbi    15 年前

    首先,请注意程序将“foo、foo、foo、foo、foo、foo、foo、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、”写入结果字符串--正如注释中所述,您希望在该字符串中使用back inserter。

    至于答案,只要有一个范围的值,我就会看到 std::accumulate (从那以后 折叠/缩小的C++版本

    #include <string>
    #include <iostream>
    #include <numeric>
    #include <boost/tokenizer.hpp>
    #include <boost/algorithm/string.hpp>
    #include <boost/bind.hpp>
    std::string dostuff(const std::string& a) {
      return std::string("Foo");
    }
    int main() {
      std::string s("a,b,c,d,e,f");
      std::string result =
        accumulate(
         ++boost::make_token_iterator<std::string>(s.begin(), s.end(), boost::char_separator<char>(",")),
           boost::make_token_iterator<std::string>(s.end(), s.end(), boost::char_separator<char>(",")),
           dostuff(*boost::make_token_iterator<std::string>(s.begin(), s.end(), boost::char_separator<char>(","))),
           boost::bind(std::plus<std::string>(), _1,
             bind(std::plus<std::string>(), ",",
                bind(dostuff, _2)))); // or lambda, for slightly better readability
      std::cout << result << '\n';
    }
    

    除了现在 方式 在顶部,重复make_token_迭代器两次。我想是助推。射程赢了。

        2
  •  1
  •   Matthieu M.    15 年前
    void dostuff(string& a) {
        a = "Foo";
    }
    
    int main()
    {
        string s("a,b,c,d,e,f");
        vector<string> tmp;
        s = boost::join(
              (
                boost::for_each(
                  boost::split(tmp, s, boost::is_any_of(",")),
                  dostuff
                ),
                tmp
              ),
              ","
            );
    
        return 0;
    }
    

    不幸的是,我不能不提 tmp 两次。也许我以后会想些什么。

        3
  •  1
  •   Matthieu M.    15 年前

    实际上,我正在开发一个库,允许以比单用迭代器更可读的方式编写代码…不知道我是否能完成这个项目,虽然,似乎死的项目往往积累在我的电脑上…

    不管怎样,我在这里遇到的主要问题显然是迭代器的使用。我倾向于认为迭代器是低级的实现细节,在编码时,您几乎不想使用它们。

    那么,假设我们有一个合适的库:

    struct DoStuff { std::string operator()(std::string const&); };
    
    int main(int argc, char* argv[])
    {
      std::string const reference = "a,b,c,d,e,f";
    
      std::string const result = boost::join(
        view::transform(
          view::split(reference, ","),
          DoStuff()
        ),
        ","
      );
    }
    

    视图的概念是在另一个容器周围做一个光包装:

    • 从用户的角度来看,它的行为就像一个容器(减去实际修改容器结构的操作)。
    • 从实现的角度来看,它是一个轻量级对象,包含尽可能少的数据-->这里的值是短暂的,并且仅与迭代器的寿命相同。

    我已经有了 transform 部分工作,我想知道 split 可以工作(一般情况下),但我想我会参与的;)

        4
  •  0
  •   Billy ONeal    15 年前

    好吧,我想这是可能的,但是请不要在生产代码中这样做。

    最好是这样的

    std::string MakeCommaEdFoo(std::string input)
    {
        std::size_t commas = std::count_if(input.begin(), input.end(),
            std::bind2nd(std::equal_to<char>(), ','));
        std::string output("foo");
        output.reserve((commas+1)*4-1);
        for(std::size_t idx = 1; idx < commas; ++idx)
            output.append(",foo");
        return output;
    }
    

    它不仅性能更好,而且更容易让下一个人阅读和理解。