56

std::stringからを構築したいと思いstd::vector<std::string>ます。

を使用できますstd::stringsteamが、もっと短い方法があると想像してください。

std::string string_from_vector(const std::vector<std::string> &pieces) {
  std::stringstream ss;

  for(std::vector<std::string>::const_iterator itr = pieces.begin();
      itr != pieces.end();
      ++itr) {
    ss << *itr;
  }

  return ss.str();
}

これを他にどのように行うことができますか?

4

8 に答える 8

109

C++03

std::string s;
for (std::vector<std::string>::const_iterator i = v.begin(); i != v.end(); ++i)
    s += *i;
return s;

C++11 (MSVC 2010 サブセット)

std::string s;
std::for_each(v.begin(), v.end(), [&](const std::string &piece){ s += piece; });
return s;

C++11

std::string s;
for (const auto &piece : v) s += piece;
return s;

std::accumulate文字列の連結には使用しないでください。これは古典的なシュレミエルのペインターのアルゴリズムであり、C で使用する通常の例よりもさらに悪いものですstrcat。C++11 の移動セマンティクスがないと、ベクトルの各要素に対してアキュムレータの不要なコピーが 2 つ発生します。移動セマンティクスを使用しても、要素ごとにアキュムレータの不要なコピーが 1 つ発生します。

上記の 3 つの例はO(n)です。

std::accumulate文字列の場合はO(n²)です。

std::accumulateカスタム ファンクターを指定することで、文字列に対して O(n) を作成できます。

std::string s = std::accumulate(v.begin(), v.end(), std::string{},
    [](std::string &s, const std::string &piece) -> decltype(auto) { return s += piece; });

sは非 const への参照である必要があり、ラムダの戻り値の型は参照である必要があり (したがってdecltype(auto))、本体では +=notを使用する必要があることに注意してください+

C++20

C++20 になる予定の現在のドラフトでは、アキュムレータに追加するときに使用するように の定義std::accumulate変更されstd::moveているため、C++20 以降でaccumulateは、文字列に対して O(n)になり、使用できます。ワンライナーとして:

std::string s = std::accumulate(v.begin(), v.end(), std::string{});
于 2013-09-09T17:30:04.863 に答える
38

ヘッダーstd::accumulate()から標準関数を使用できます( 2 つの引数の連結を返す s のオーバーロードが定義されているため、機能します)。<numeric>operator +string

#include <vector>
#include <string>
#include <numeric>
#include <iostream>

int main()
{
    std::vector<std::string> v{"Hello, ", " Cruel ", "World!"};
    std::string s;
    s = accumulate(begin(v), end(v), s);
    std::cout << s; // Will print "Hello, Cruel World!"
}

または、より効率的な小さなforサイクルを使用できます。

#include <vector>
#include <string>
#include <iostream>

int main()
{
    std::vector<std::string> v{"Hello, ", "Cruel ", "World!"};
    std::string result;
    for (auto const& s : v) { result += s; }
    std::cout << result; // Will print "Hello, Cruel World!"
}
于 2013-03-11T19:43:11.620 に答える
8

演算子 + を使用してそれらを加算しないのはなぜですか?

std::string string_from_vector(const std::vector<std::string> &pieces) {
   return std::accumulate(pieces.begin(), pieces.end(), std::string(""));
}

std::accumulate はデフォルトで内部的に std::plus を使用し、演算子 + は std::string に対してオーバーロードされているため、2 つの文字列を追加することは C++ では連結です。

于 2013-03-11T19:43:59.350 に答える
3

パーティーには少し遅れましたが、初期化子リストを使用できるという事実が気に入りました。

std::string join(std::initializer_list<std::string> i)
{
  std::vector<std::string> v(i);
  std::string res;
  for (const auto &s: v) res += s;
  return res;   
}

次に、単純に呼び出すことができます (Python スタイル):

join({"Hello", "World", "1"})
于 2015-07-23T11:18:05.340 に答える
1

c++11 では、stringstreamの方法はそれほど怖くありません。

#include <vector>
#include <string>
#include <algorithm>
#include <sstream>
#include <iostream>

int main()
{
    std::vector<std::string> v{"Hello, ", " Cruel ", "World!"};
   std::stringstream s;
   std::for_each(begin(v), end(v), [&s](const std::string &elem) { s << elem; } );
   std::cout << s.str();
}
于 2013-03-11T20:22:01.730 に答える