Вы хотите сделать join . Существует много учебников об этом и различных способах делать это.
Используйте delimiter.c_str()
как разделитель :
copy(x.begin(),x.end(), ostream_iterator<int>(s,delimiter.c_str()));
Таким образом, вы получаете const char*
, указывающие на строку, что ostream_operator
ожидает от ваш std::string
.
int array[ 6 ] = { 1, 2, 3, 4, 5, 6 };
std::vector< int > a( array, array + 6 );
stringstream dataString;
ostream_iterator<int> output_iterator(dataString, ";"); // here ";" is delimiter
std::copy(a.begin(), a.end(), output_iterator);
cout<<dataString.str()<<endl;
output = 1; 2; 3; 4; 5; 6;
string join(const vector<string> & v, const string & delimiter = ",") {
string out;
if (auto i = v.begin(), e = v.end(); i != e) {
out += *i++;
for (; i != e; ++i) out.append(delimiter).append(*i);
}
return out;
}
Несколько моментов:
Это расширение для двух ответов, уже представленных выше, поскольку производительность во время исполнения показалась темой комментариев. Я добавил бы его в качестве комментариев, но у меня еще нет этой привилегии.
Я тестировал 2 реализации для производительности во время исполнения с использованием Visual Studio 2015:
Использование stringstream:
std::stringstream result;
auto it = vec.begin();
result << (unsigned short)*it++;
for (; it != vec.end(); it++) {
result << delimiter;
result << (unsigned short)*it;
}
return result.str();
Использование accumulate:
std::string result = std::accumulate(std::next(vec.begin()), vec.end(),
std::to_string(vec[0]),
[&delimiter](std::string& a, uint8_t b) {
return a + delimiter+ std::to_string(b);
});
return result;
Производительность выполнения сборки сборки была близка к парам тонкостей.
Реализация накопления была немного быстрее (20-50 мс, ~ 10-30% от общей продолжительности (~ 180 мс) на 1000 итераций по 256-элементному вектору). Однако реализация accumulate
была только быстрее, когда параметр a
для функции лямбда был передан по ссылке. Передача параметра a
по значению привела к аналогичной разнице во времени во время реализации stringstream
. Реализация accumulate
также улучшилась, когда возвратная строка была возвращена напрямую, а не назначена локальной переменной, которая была немедленно возвращена. YMMV с другими компиляторами C ++.
Сборка Debug была в 5-10 раз медленнее с использованием accumulate
, поэтому я думаю, что добавление дополнительной строки, отмеченное в нескольких комментариях выше, разрешено оптимизатором.
Я искал конкретную реализацию, используя vector
значений uint8_t
. Полный тестовый код:
#include <vector>
#include <iostream>
#include <sstream>
#include <numeric>
#include <chrono>
using namespace std;
typedef vector<uint8_t> uint8_vec_t;
string concat_stream(const uint8_vec_t& vec, string& delim = string(" "));
string concat_accumulate(const uint8_vec_t& vec, string& delim = string(" "));
string concat_stream(const uint8_vec_t& vec, string& delimiter)
{
stringstream result;
auto it = vec.begin();
result << (unsigned short)*it++;
for (; it != vec.end(); it++) {
result << delimiter;
result << (unsigned short)*it;
}
return result.str();
}
string concat_accumulate(const uint8_vec_t& vec, string& delimiter)
{
return accumulate(next(vec.begin()), vec.end(),
to_string(vec[0]),
[&delimiter](string& a, uint8_t b) {
return a + delimiter + to_string(b);
});
}
int main()
{
const int elements(256);
const int iterations(1000);
uint8_vec_t test(elements);
iota(test.begin(), test.end(), 0);
int i;
auto stream_start = chrono::steady_clock::now();
string join_with_stream;
for (i = 0; i < iterations; ++i) {
join_with_stream = concat_stream(test);
}
auto stream_end = chrono::steady_clock::now();
auto acc_start = chrono::steady_clock::now();
string join_with_acc;
for (i = 0; i < iterations; ++i) {
join_with_acc = concat_accumulate(test);
}
auto acc_end = chrono::steady_clock::now();
cout << "Stream Results:" << endl;
cout << " elements: " << elements << endl;
cout << " iterations: " << iterations << endl;
cout << " runtime: " << chrono::duration<double, milli>(stream_end - stream_start).count() << " ms" << endl;
cout << " result: " << join_with_stream << endl;
cout << "Accumulate Results:" << endl;
cout << " elements: " << elements << endl;
cout << " iterations: " << iterations << endl;
cout << " runtime: " << chrono::duration<double, milli>(acc_end - acc_start).count() << " ms" << endl;
cout << " result:" << join_with_acc << endl;
return 0;
}
std::string Gesture::getLabeledPointsString(const std::string delimiter) {
return boost::join(getLabeledPoints(), delimiter);
}
Я не убежден в том, что в этот момент getLabeledPointsString
убедится;)
более быстрый вариант:
vector<string> x = {"1", "2", "3"};
string res;
res.reserve(16);
std::accumulate(std::begin(x), std::end(x), 0,
[&res](int &, string &s)
{
if (!res.empty())
{
res.append(",");
}
res.append(s);
return 0;
});
он не создает промежуточные строки, а просто выделяет память один раз для всего результата строки и добавляет каждый элемент в конец & res
code
; result.reserve (128); для (auto & amp; it: x) {if (! result.emty ()) {result.append (& quot;, "); } result.append (it); } code
– max.kondr
1 April 2016 в 21:28
accumulate()
, но полностью игнорируете этот результат. Вместо этого вы должны использовать std::for_each()
.
– Alexis Wilke
12 July 2016 в 23:07
accumulate
ожидает, что его функция не будет иметь побочных эффектов? Этот код лучше выражать как for_each
.
– xtofl
13 September 2016 в 11:52
begin(x)+1
, а *begin(x)
- как начальный элемент.
– xtofl
13 September 2016 в 11:57
Еще один способ сделать это:
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
template <typename T>
string join(const T& v, const string& delim) {
ostringstream s;
for (const auto& i : v) {
if (&i != &v[0]) {
s << delim;
}
s << i;
}
return s.str();
}
int main() {
cout << join(vector<int>({1, 2, 3, 4, 5}), ",") << endl;
}
(c ++ 11 для цикла и «авто»)
delimiter
на выходе. – David Rodríguez - dribeas 14 February 2012 в 15:49stringstream
управляет собственным буфером, поэтому он должен динамически расти. Здесь вы знаете, прежде чем генерировать строку, какой длины она будет, поэтому вы должны зарезервировать буфер перед конкатенацией. – wilhelmtell 14 February 2012 в 15:56