我们可以在一个语句中拆分,操作和重新加入c ++中的字符串吗?

时间:2010-09-20 17:08:10

标签: c++ boost stl

这是一个愚蠢的问题,但出于好奇,可能会在逗号上拆分一个字符串,对字符串执行一个函数,然后在一个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"

我意识到这是OTT,但我只想扩展我的助力魔法。

4 个答案:

答案 0 :(得分:1)

首先,请注意你的程序写“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_iterator两次。我猜boost.range胜出。

答案 1 :(得分:1)

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。也许我稍后会想到什么。

答案 2 :(得分:1)

我实际上正在开发一个库,允许以比单独的迭代器更可读的方式编写代码...不知道我是否会完成项目,但似乎死的项目往往会积累在我的计算机上...

无论如何,我在这里的主要责任显然是使用迭代器。我倾向于将迭代器视为低级实现细节,在编码时你很少想要使用它们。

所以,我们假设我们有一个合适的库:

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()
    ),
    ","
  );
}

视图的想法是围绕另一个容器的光包装:

  • 从用户的角度来看,它的行为就像一个容器(减去实际修改容器结构的操作)
  • 从实现的角度来看,它是一个轻量级对象,包含尽可能少的数据 - &gt;这里的价值是短暂的,只有迭代者活着才会存在。

我已经让transform部分工作,我想知道split如何工作(一般),但我想我会进入它;)

答案 3 :(得分:0)

好的,我想这是可能的,但请不要在生产代码中真正做到这一点。

更好的是像

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;
}

它不仅会表现得更好,下一个人阅读和理解也会容易得多。