Saya memiliki vector<int>
wadah yang memiliki bilangan bulat (misalnya {1,2,3,4}) dan saya ingin mengonversinya menjadi string dalam bentuk
"1,2,3,4"
Apa cara terbersih untuk melakukannya di C ++? Dengan Python, inilah cara saya melakukannya:
>>> array = [1,2,3,4]
>>> ",".join(map(str,array))
'1,2,3,4'
Jawaban:
Jelas tidak seanggun Python, tapi tidak ada yang seanggun Python di C ++.
Anda bisa menggunakan
stringstream
...#include <sstream> //... std::stringstream ss; for(size_t i = 0; i < v.size(); ++i) { if(i != 0) ss << ","; ss << v[i]; } std::string s = ss.str();
Anda juga bisa memanfaatkannya
std::for_each
.sumber
std::string s = ss.str()
. Jika Anda inginconst char*
, gunakans.c_str()
. (Perhatikan bahwa, meskipun secara sintaksis benar,ss.str().c_str()
akan memberi Andaconst char*
poin itu ke sementara yang akan tidak ada lagi pada akhir ekspresi penuh. Itu menyakitkan.)#include <sstream>
Menggunakan std :: for_each dan lambda Anda dapat melakukan sesuatu yang menarik.
#include <iostream> #include <sstream> int main() { int array[] = {1,2,3,4}; std::for_each(std::begin(array), std::end(array), [&std::cout, sep=' '](int x) mutable { out << sep << x; sep=','; }); }
Lihat pertanyaan ini untuk kelas kecil yang saya tulis. Ini tidak akan mencetak tanda koma. Juga jika kami berasumsi bahwa C ++ 14 akan terus memberi kami persamaan berbasis rentang dari algoritme seperti ini:
namespace std { // I am assuming something like this in the C++14 standard // I have no idea if this is correct but it should be trivial to write if it does not appear. template<typename C, typename I> void copy(C const& container, I outputIter) {copy(begin(container), end(container), outputIter);} } using POI = PrefexOutputIterator; int main() { int array[] = {1,2,3,4}; std::copy(array, POI(std::cout, ",")); // ",".join(map(str,array)) // closer }
sumber
Anda dapat menggunakan std :: akumulasi. Perhatikan contoh berikut
if (v.empty() return std::string(); std::string s = std::accumulate(v.begin()+1, v.end(), std::to_string(v[0]), [](const std::string& a, int b){ return a + ',' + std::to_string(b); });
sumber
','
seharusnya","
string
Kelas memiliki kelebihan beban untuk+
operator yang dapat menerima karakter juga. Jadi','
baik-baik saja.Alternatif lain adalah penggunaan
std::copy
danostream_iterator
kelas:#include <iterator> // ostream_iterator #include <sstream> // ostringstream #include <algorithm> // copy std::ostringstream stream; std::copy(array.begin(), array.end(), std::ostream_iterator<>(stream)); std::string s=stream.str(); s.erase(s.length()-1);
Juga tidak sebaik Python. Untuk tujuan ini, saya membuat sebuah
join
fungsi:template <class T, class A> T join(const A &begin, const A &end, const T &t) { T result; for (A it=begin; it!=end; it++) { if (!result.empty()) result.append(t); result.append(*it); } return result; }
Kemudian gunakan seperti ini:
std::string s=join(array.begin(), array.end(), std::string(","));
Anda mungkin bertanya mengapa saya lulus di iterator. Sebenarnya saya ingin membalikkan array, jadi saya menggunakannya seperti ini:
std::string s=join(array.rbegin(), array.rend(), std::string(","));
Idealnya, saya ingin membuat template ke titik di mana ia dapat menyimpulkan jenis karakter, dan menggunakan aliran string, tetapi saya belum bisa mengetahuinya.
sumber
join
Fungsi Anda bisa digunakan dengan vektor juga? Tolong beri contoh, saya baru mengenal C ++.Dengan Boost dan C ++ 11 ini dapat dicapai seperti ini:
auto array = {1,2,3,4}; join(array | transformed(tostr), ",");
Hampir saja. Berikut contoh lengkapnya:
#include <array> #include <iostream> #include <boost/algorithm/string/join.hpp> #include <boost/range/adaptor/transformed.hpp> int main() { using boost::algorithm::join; using boost::adaptors::transformed; auto tostr = static_cast<std::string(*)(int)>(std::to_string); auto array = {1,2,3,4}; std::cout << join(array | transformed(tostr), ",") << std::endl; return 0; }
Penghargaan untuk Praetorian .
Anda dapat menangani tipe nilai apa pun seperti ini:
template<class Container> std::string join(Container const & container, std::string delimiter) { using boost::algorithm::join; using boost::adaptors::transformed; using value_type = typename Container::value_type; auto tostr = static_cast<std::string(*)(value_type)>(std::to_string); return join(container | transformed(tostr), delimiter); };
sumber
Ini hanyalah upaya untuk memecahkan teka-teki yang diberikan oleh komentar 1800 INFORMATION tentang solusi keduanya yang kurang murah hati, bukan upaya untuk menjawab pertanyaan:
template <class Str, class It> Str join(It begin, const It end, const Str &sep) { typedef typename Str::value_type char_type; typedef typename Str::traits_type traits_type; typedef typename Str::allocator_type allocator_type; typedef std::basic_ostringstream<char_type,traits_type,allocator_type> ostringstream_type; ostringstream_type result; if(begin!=end) result << *begin++; while(begin!=end) { result << sep; result << *begin++; } return result.str(); }
Bekerja di Mesin Saya (TM).
sumber
operator<<
Kelebihan beban). Tentu saja, tipe tanpaoperator<<
dapat menyebabkan pesan kesalahan yang sangat membingungkan.join(v.begin(), v.end(), ",")
. Pemotongan argumen template tidak memberikan hasil yang benar jikasep
argumennya adalah string literal. Upaya saya mencari solusi untuk masalah ini . Juga menyediakan overload berbasis jangkauan yang lebih modern.Banyak template / ide. Milik saya tidak umum atau efisien, tetapi saya hanya memiliki masalah yang sama dan ingin memasukkan ini ke dalam campuran sebagai sesuatu yang pendek dan manis. Ia menang pada jumlah baris terpendek ... :)
std::stringstream joinedValues; for (auto value: array) { joinedValues << value << ","; } //Strip off the trailing comma std::string result = joinedValues.str().substr(0,joinedValues.str().size()-1);
sumber
substr(...)
, gunakanpop_back()
untuk menghapus karakter terakhir, menjadi lebih jelas dan bersih.Jika Anda ingin melakukannya
std::cout << join(myVector, ",") << std::endl;
, Anda dapat melakukan sesuatu seperti:template <typename C, typename T> class MyJoiner { C &c; T &s; MyJoiner(C &&container, T&& sep) : c(std::forward<C>(container)), s(std::forward<T>(sep)) {} public: template<typename C, typename T> friend std::ostream& operator<<(std::ostream &o, MyJoiner<C, T> const &mj); template<typename C, typename T> friend MyJoiner<C, T> join(C &&container, T&& sep); }; template<typename C, typename T> std::ostream& operator<<(std::ostream &o, MyJoiner<C, T> const &mj) { auto i = mj.c.begin(); if (i != mj.c.end()) { o << *i++; while (i != mj.c.end()) { o << mj.s << *i++; } } return o; } template<typename C, typename T> MyJoiner<C, T> join(C &&container, T&& sep) { return MyJoiner<C, T>(std::forward<C>(container), std::forward<T>(sep)); }
Catatan, solusi ini melakukan join langsung ke output stream daripada membuat buffer sekunder dan akan bekerja dengan semua tipe yang memiliki operator << ke sebuah ostream.
Ini juga berfungsi jika
boost::algorithm::join()
gagal, jika Anda memiliki a,vector<char*>
bukan avector<string>
.sumber
string s; for (auto i : v) s += (s.empty() ? "" : ",") + to_string(i);
sumber
std::stringstream
untuk array besar karenastringstream
akan dapat mengalokasikan memori secara optimal, yang mengarah ke performa O (n.log (n)) alih-alih O (n²) untuk ukuran arrayn
untuk jawaban ini. Jugastringstream
mungkin tidak membuat string sementara untukto_string(i)
.Saya suka jawaban tahun 1800-an. Namun saya akan memindahkan iterasi pertama keluar dari loop sebagai hasil dari pernyataan if hanya berubah satu kali setelah iterasi pertama
template <class T, class A> T join(const A &begin, const A &end, const T &t) { T result; A it = begin; if (it != end) { result.append(*it); ++it; } for( ; it!=end; ++it) { result.append(t); result.append(*it); } return result; }
Ini tentu saja dapat dikurangi menjadi lebih sedikit pernyataan jika Anda suka:
template <class T, class A> T join(const A &begin, const A &end, const T &t) { T result; A it = begin; if (it != end) result.append(*it++); for( ; it!=end; ++it) result.append(t).append(*it); return result; }
sumber
++i
kecuali di mana mereka benar-benar membutuhkannyai++
karena itulah satu-satunya cara mereka tidak akan melupakan ini ketika itu membuat perbedaan. (Itu sama dengan saya, BTW.) Mereka telah belajar Java sebelumnya, di mana semua jenis C-isme sedang populer dan butuh beberapa bulan (1 kuliah + praktikum per minggu), tetapi pada akhirnya sebagian besar mereka mempelajari kebiasaan menggunakan kenaikan awal.Ada beberapa upaya menarik untuk memberikan solusi elegan untuk masalah tersebut. Saya punya ide untuk menggunakan aliran template untuk secara efektif menjawab dilema awal OP. Meskipun ini adalah posting lama, saya berharap pengguna di masa depan yang menemukan ini akan menemukan solusi saya bermanfaat.
Pertama, beberapa jawaban (termasuk jawaban yang diterima) tidak mendukung kegunaan kembali. Karena C ++ tidak menyediakan cara yang elegan untuk menggabungkan string di pustaka standar (yang telah saya lihat), menjadi penting untuk membuat yang fleksibel dan dapat digunakan kembali. Inilah kesempatan saya:
// Replace with your namespace // namespace my { // Templated join which can be used on any combination of streams, iterators and base types // template <typename TStream, typename TIter, typename TSeperator> TStream& join(TStream& stream, TIter begin, TIter end, TSeperator seperator) { // A flag which, when true, has next iteration prepend our seperator to the stream // bool sep = false; // Begin iterating through our list // for (TIter i = begin; i != end; ++i) { // If we need to prepend a seperator, do it // if (sep) stream << seperator; // Stream the next value held by our iterator // stream << *i; // Flag that next loops needs a seperator // sep = true; } // As a convenience, we return a reference to the passed stream // return stream; } }
Sekarang untuk menggunakan ini, Anda cukup melakukan sesuatu seperti berikut:
// Load some data // std::vector<int> params; params.push_back(1); params.push_back(2); params.push_back(3); params.push_back(4); // Store and print our results to standard out // std::stringstream param_stream; std::cout << my::join(param_stream, params.begin(), params.end(), ",").str() << std::endl; // A quick and dirty way to print directly to standard out // my::join(std::cout, params.begin(), params.end(), ",") << std::endl;
Perhatikan bagaimana penggunaan aliran membuat solusi ini sangat fleksibel karena kami dapat menyimpan hasil kami dalam aliran string untuk mengklaimnya kembali nanti, atau kami dapat menulis langsung ke keluaran standar, file, atau bahkan ke koneksi jaringan yang diimplementasikan sebagai aliran. Jenis yang dicetak harus dapat diulang dan kompatibel dengan aliran sumber. STL menyediakan berbagai aliran yang kompatibel dengan berbagai jenis. Jadi Anda benar-benar bisa pergi ke kota dengan ini. Di luar kepala saya, vektor Anda bisa berupa int, float, double, string, unsigned int, SomeObject *, dan banyak lagi.
sumber
Saya telah membuat file header helper untuk menambahkan dukungan perpanjangan bergabung.
Cukup tambahkan kode di bawah ini ke file header umum Anda dan sertakan bila diperlukan.
Contoh Penggunaan:
/* An example for a mapping function. */ ostream& map_numbers(ostream& os, const void* payload, generic_primitive data) { static string names[] = {"Zero", "One", "Two", "Three", "Four"}; os << names[data.as_int]; const string* post = reinterpret_cast<const string*>(payload); if (post) { os << " " << *post; } return os; } int main() { int arr[] = {0,1,2,3,4}; vector<int> vec(arr, arr + 5); cout << vec << endl; /* Outputs: '0 1 2 3 4' */ cout << join(vec.begin(), vec.end()) << endl; /* Outputs: '0 1 2 3 4' */ cout << join(vec.begin(), vec.begin() + 2) << endl; /* Outputs: '0 1 2' */ cout << join(vec.begin(), vec.end(), ", ") << endl; /* Outputs: '0, 1, 2, 3, 4' */ cout << join(vec.begin(), vec.end(), ", ", map_numbers) << endl; /* Outputs: 'Zero, One, Two, Three, Four' */ string post = "Mississippi"; cout << join(vec.begin() + 1, vec.end(), ", ", map_numbers, &post) << endl; /* Outputs: 'One Mississippi, Two mississippi, Three mississippi, Four mississippi' */ return 0; }
Kode di balik layar:
#include <iostream> #include <vector> #include <list> #include <set> #include <unordered_set> using namespace std; #define GENERIC_PRIMITIVE_CLASS_BUILDER(T) generic_primitive(const T& v) { value.as_##T = v; } #define GENERIC_PRIMITIVE_TYPE_BUILDER(T) T as_##T; typedef void* ptr; /** A union that could contain a primitive or void*, * used for generic function pointers. * TODO: add more primitive types as needed. */ struct generic_primitive { GENERIC_PRIMITIVE_CLASS_BUILDER(int); GENERIC_PRIMITIVE_CLASS_BUILDER(ptr); union { GENERIC_PRIMITIVE_TYPE_BUILDER(int); GENERIC_PRIMITIVE_TYPE_BUILDER(ptr); }; }; typedef ostream& (*mapping_funct_t)(ostream&, const void*, generic_primitive); template<typename T> class Join { public: Join(const T& begin, const T& end, const string& separator = " ", mapping_funct_t mapping = 0, const void* payload = 0): m_begin(begin), m_end(end), m_separator(separator), m_mapping(mapping), m_payload(payload) {} ostream& apply(ostream& os) const { T begin = m_begin; T end = m_end; if (begin != end) if (m_mapping) { m_mapping(os, m_payload, *begin++); } else { os << *begin++; } while (begin != end) { os << m_separator; if (m_mapping) { m_mapping(os, m_payload, *begin++); } else { os << *begin++; } } return os; } private: const T& m_begin; const T& m_end; const string m_separator; const mapping_funct_t m_mapping; const void* m_payload; }; template <typename T> Join<T> join(const T& begin, const T& end, const string& separator = " ", ostream& (*mapping)(ostream&, const void*, generic_primitive) = 0, const void* payload = 0) { return Join<T>(begin, end, separator, mapping, payload); } template<typename T> ostream& operator<<(ostream& os, const vector<T>& vec) { return join(vec.begin(), vec.end()).apply(os); } template<typename T> ostream& operator<<(ostream& os, const list<T>& lst) { return join(lst.begin(), lst.end()).apply(os); } template<typename T> ostream& operator<<(ostream& os, const set<T>& s) { return join(s.begin(), s.end()).apply(os); } template<typename T> ostream& operator<<(ostream& os, const Join<T>& vec) { return vec.apply(os); }
sumber
Berikut solusi C ++ 11 generik yang memungkinkan Anda melakukannya
int main() { vector<int> v {1,2,3}; cout << join(v, ", ") << endl; string s = join(v, '+').str(); }
Kodenya adalah:
template<typename Iterable, typename Sep> class Joiner { const Iterable& i_; const Sep& s_; public: Joiner(const Iterable& i, const Sep& s) : i_(i), s_(s) {} std::string str() const {std::stringstream ss; ss << *this; return ss.str();} template<typename I, typename S> friend std::ostream& operator<< (std::ostream& os, const Joiner<I,S>& j); }; template<typename I, typename S> std::ostream& operator<< (std::ostream& os, const Joiner<I,S>& j) { auto elem = j.i_.begin(); if (elem != j.i_.end()) { os << *elem; ++elem; while (elem != j.i_.end()) { os << j.s_ << *elem; ++elem; } } return os; } template<typename I, typename S> inline Joiner<I,S> join(const I& i, const S& s) {return Joiner<I,S>(i, s);}
sumber
Berikut ini adalah cara sederhana dan praktis untuk mengubah elemen menjadi
vector
astring
:std::string join(const std::vector<int>& numbers, const std::string& delimiter = ",") { std::ostringstream result; for (const auto number : numbers) { if (result.tellp() > 0) { // not first round result << delimiter; } result << number; } return result.str(); }
Anda perlu
#include <sstream>
untukostringstream
.sumber
Memperluas upaya @sbi pada solusi umum yang tidak dibatasi
std::vector<int>
atau tipe string kembalian tertentu. Kode yang disajikan di bawah ini dapat digunakan seperti ini:std::vector<int> vec{ 1, 2, 3 }; // Call modern range-based overload. auto str = join( vec, "," ); auto wideStr = join( vec, L"," ); // Call old-school iterator-based overload. auto str = join( vec.begin(), vec.end(), "," ); auto wideStr = join( vec.begin(), vec.end(), L"," );
Dalam kode asli, pengurangan argumen template tidak berfungsi untuk menghasilkan tipe string pengembalian yang benar jika pemisahnya adalah string literal (seperti dalam contoh di atas). Dalam hal ini, typedefs seperti
Str::value_type
di badan fungsi salah. Kode mengasumsikan bahwaStr
selalu tipe sepertistd::basic_string
, jadi jelas gagal untuk string literal.Untuk memperbaikinya, kode berikut mencoba untuk menyimpulkan hanya tipe karakter dari argumen pemisah dan menggunakannya untuk menghasilkan tipe string kembali default. Ini dicapai dengan menggunakan
boost::range_value
, yang mengekstrak tipe elemen dari tipe rentang yang diberikan .#include <string> #include <sstream> #include <boost/range.hpp> template< class Sep, class Str = std::basic_string< typename boost::range_value< Sep >::type >, class InputIt > Str join( InputIt first, const InputIt last, const Sep& sep ) { using char_type = typename Str::value_type; using traits_type = typename Str::traits_type; using allocator_type = typename Str::allocator_type; using ostringstream_type = std::basic_ostringstream< char_type, traits_type, allocator_type >; ostringstream_type result; if( first != last ) { result << *first++; } while( first != last ) { result << sep << *first++; } return result.str(); }
Sekarang kita dapat dengan mudah menyediakan overload berbasis rentang yang hanya meneruskan ke overload berbasis iterator:
template <class Sep, class Str = std::basic_string< typename boost::range_value<Sep>::type >, class InputRange> Str join( const InputRange &input, const Sep &sep ) { // Include the standard begin() and end() in the overload set for ADL. This makes the // function work for standard types (including arrays), aswell as any custom types // that have begin() and end() member functions or overloads of the standalone functions. using std::begin; using std::end; // Call iterator-based overload. return join( begin(input), end(input), sep ); }
Demo Langsung di Coliru
sumber
seperti yang dilakukan @capone,
std::string join(const std::vector<std::string> &str_list , const std::string &delim=" ") { if(str_list.size() == 0) return "" ; return std::accumulate( str_list.cbegin() + 1, str_list.cend(), str_list.at(0) , [&delim](const std::string &a , const std::string &b) { return a + delim + b ; } ) ; } template <typename ST , typename TT> std::vector<TT> map(TT (*op)(ST) , const vector<ST> &ori_vec) { vector<TT> rst ; std::transform(ori_vec.cbegin() , ori_vec.cend() , back_inserter(rst) , [&op](const ST& val){ return op(val) ;} ) ; return rst ; }
Kemudian kita bisa memanggil seperti berikut:
int main(int argc , char *argv[]) { vector<int> int_vec = {1,2,3,4} ; vector<string> str_vec = map<int,string>(to_string, int_vec) ; cout << join(str_vec) << endl ; return 0 ; }
seperti python:
>>> " ".join( map(str, [1,2,3,4]) )
sumber
Saya menggunakan sesuatu seperti ini
namespace std { // for strings join string to_string( string value ) { return value; } } // namespace std namespace // anonymous { template< typename T > std::string join( const std::vector<T>& values, char delimiter ) { std::string result; for( typename std::vector<T>::size_type idx = 0; idx < values.size(); ++idx ) { if( idx != 0 ) result += delimiter; result += std::to_string( values[idx] ); } return result; } } // namespace anonymous
sumber
Saya mulai dengan jawaban @ sbi tetapi sebagian besar waktu berakhir dengan menyalurkan string yang dihasilkan ke aliran sehingga menciptakan solusi di bawah ini yang dapat disalurkan ke aliran tanpa overhead untuk membuat string penuh dalam memori.
Ini digunakan sebagai berikut:
#include "string_join.h" #include <iostream> #include <vector> int main() { std::vector<int> v = { 1, 2, 3, 4 }; // String version std::string str = join(v, std::string(", ")); std::cout << str << std::endl; // Directly piped to stream version std::cout << join(v, std::string(", ")) << std::endl; }
Di mana string_join.h adalah:
#pragma once #include <iterator> #include <sstream> template<typename Str, typename It> class joined_strings { private: const It begin, end; Str sep; public: typedef typename Str::value_type char_type; typedef typename Str::traits_type traits_type; typedef typename Str::allocator_type allocator_type; private: typedef std::basic_ostringstream<char_type, traits_type, allocator_type> ostringstream_type; public: joined_strings(It begin, const It end, const Str &sep) : begin(begin), end(end), sep(sep) { } operator Str() const { ostringstream_type result; result << *this; return result.str(); } template<typename ostream_type> friend ostream_type& operator<<( ostream_type &ostr, const joined_strings<Str, It> &joined) { It it = joined.begin; if(it!=joined.end) ostr << *it; for(++it; it!=joined.end; ++it) ostr << joined.sep << *it; return ostr; } }; template<typename Str, typename It> inline joined_strings<Str, It> join(It begin, const It end, const Str &sep) { return joined_strings<Str, It>(begin, end, sep); } template<typename Str, typename Container> inline joined_strings<Str, typename Container::const_iterator> join( Container container, const Str &sep) { return join(container.cbegin(), container.cend(), sep); }
sumber
Saya telah menulis kode berikut. Itu berbasis di C # string.join. Ia bekerja dengan std :: string dan std :: wstring dan banyak jenis vektor. (contoh di komentar)
Sebut saja seperti ini:
std::vector<int> vVectorOfIds = {1, 2, 3, 4, 5}; std::wstring wstrStringForSQLIn = Join(vVectorOfIds, L',');
Kode:
// Generic Join template (mimics string.Join() from C#) // Written by RandomGuy (stackoverflow) 09-01-2017 // Based on Brian R. Bondy anwser here: // http://stackoverflow.com/questions/1430757/c-vector-to-string // Works with char, wchar_t, std::string and std::wstring delimiters // Also works with a different types of vectors like ints, floats, longs template<typename T, typename D> auto Join(const std::vector<T> &vToMerge, const D &delimiter) { // We use std::conditional to get the correct type for the stringstream (char or wchar_t) // stringstream = basic_stringstream<char>, wstringstream = basic_stringstream<wchar_t> using strType = std::conditional< std::is_same<D, std::string>::value, char, std::conditional< std::is_same<D, char>::value, char, wchar_t >::type >::type; std::basic_stringstream<strType> ss; for (size_t i = 0; i < vToMerge.size(); ++i) { if (i != 0) ss << delimiter; ss << vToMerge[i]; } return ss.str(); }
sumber
Berikut adalah cara mudah untuk mengubah vektor bilangan bulat menjadi string.
#include <bits/stdc++.h> using namespace std; int main() { vector<int> A = {1, 2, 3, 4}; string s = ""; for (int i = 0; i < A.size(); i++) { s = s + to_string(A[i]) + ","; } s = s.substr(0, s.length() - 1); //Remove last character cout << s; }
sumber
bergabunglah menggunakan fungsi template
Saya menggunakan a
template
function
untuk menggabungkanvector
item, dan menghapusif
pernyataan yang tidak perlu dengan mengulang hanya item pertama ke item kedua dari belakang divector
, lalu bergabung dengan item terakhir setelahfor
loop. Ini juga meniadakan kebutuhan kode tambahan untuk menghapus pemisah ekstra di akhir string yang digabungkan. Jadi, tidak adaif
pernyataan yang memperlambat iterasi dan tidak ada pemisah berlebihan yang perlu dirapikan.Ini menghasilkan panggilan fungsi elegan untuk bergabung dengan
vector
daristring
,integer
ataudouble
, dllSaya menulis dua versi: satu mengembalikan string; yang lainnya menulis langsung ke aliran.
#include <iostream> #include <sstream> #include <string> #include <vector> using namespace std; // Return a string of joined vector items. template<typename T> string join(const vector<T>& v, const string& sep) { ostringstream oss; const auto LAST = v.end() - 1; // Iterate through the first to penultimate items appending the separator. for (typename vector<T>::const_iterator p = v.begin(); p != LAST; ++p) { oss << *p << sep; } // Join the last item without a separator. oss << *LAST; return oss.str(); } // Write joined vector items directly to a stream. template<typename T> void join(const vector<T>& v, const string& sep, ostream& os) { const auto LAST = v.end() - 1; // Iterate through the first to penultimate items appending the separator. for (typename vector<T>::const_iterator p = v.begin(); p != LAST; ++p) { os << *p << sep; } // Join the last item without a separator. os << *LAST; } int main() { vector<string> strings { "Joined", "from", "beginning", "to", "end" }; vector<int> integers{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; vector<double> doubles{ 1.2, 3.4, 5.6, 7.8, 9.0 }; cout << join(strings, "... ") << endl << endl; cout << join(integers, ", ") << endl << endl; cout << join(doubles, "; ") << endl << endl; join(strings, "... ", cout); cout << endl << endl; join(integers, ", ", cout); cout << endl << endl; join(doubles, "; ", cout); cout << endl << endl; return 0; }
Keluaran
sumber