Bagaimana membangun sebuah std :: string dari std :: vector <char>?


115

Singkatnya (yang sudah jelas) membangun string gaya C terlebih dahulu kemudian menggunakannya untuk membuat std :: string, apakah ada cara yang lebih cepat / alternatif / "lebih baik" untuk menginisialisasi string dari vektor karakter?


4
Bisakah ini dilakukan tanpa menyalin? Dengan kata lain sesuatu yang melakukan hal yang sama std::vector<char> v2(std::move(v))tetapi dengan a std::stringsebagai objek baru.
tobi_s

Jawaban:


197

Nah, cara terbaik adalah dengan menggunakan konstruktor berikut:

template<class InputIterator> string (InputIterator begin, InputIterator end);

yang akan menghasilkan sesuatu seperti:

std::vector<char> v;
std::string str(v.begin(), v.end());

41

Saya pikir Anda bisa melakukannya

std::string s( MyVector.begin(), MyVector.end() );

di mana MyVector adalah std :: vector Anda.


1
Kecuali di VS2013 yang menegaskan pada waktu proses tentang iterator yang tidak valid, kecuali jika Anda menyetelnya _ITERATOR_DEBUG_LEVEL=1(dalam hal ini tampaknya berfungsi dengan baik).
Cameron

35

Dengan C ++ 11, Anda dapat melakukan std::string(v.data())atau, jika vektor Anda tidak mengandung a '\0'di akhir std::string(v.data(), v.size()),.


Bahkan dengan C ++ 98, saya yakin Anda dapat melakukan std :: string (& v [0]). Ini, tentu saja, jika vektor diakhiri dengan null.
Jamie

1
@Jamie: By the way, di C ++ 98, string(&v[0], v.size())harus bekerja juga, tetapi hanya setelah assert(not v.empty());, karena jika vektor kosong, baik v[0]dan v.front()akan memanggil perilaku tidak terdefinisi. Itu, selain dari kesederhanaan sintaksis karena tidak harus menggunakan operator alamat, adalah manfaat nyata dari data()fungsi C ++ 11 , yang bekerja bahkan pada vektor kosong.
Adam H. Peterson

Sangat benar. Sayangnya, proyek saya terhenti di Visual Studio 2008 di masa mendatang. Benar tentang memeriksa panjang vektor terlebih dahulu.
Jamie

Jika vektor tidak mengandung '\ 0', std::string(v.data())mungkin menyebabkan string yang lebih panjang. Jadi jangan gunakan cara ini.
heLomaN

@heLomaN: Ada apa dengan std::string(v.data(), v.size()), yang secara eksplisit disebutkan dalam jawaban karena alasan yang tepat?
Sz.

12
std::string s(v.begin(), v.end());

Di mana v cukup banyak hal yang dapat diulang. (Secara khusus begin () dan end () harus mengembalikan InputIterator.)


3

Hanya untuk kelengkapan, cara lain adalah std::string(&v[0])(meskipun Anda perlu memastikan string Anda diakhiri null dan std::string(v.data())umumnya lebih disukai.

Perbedaannya adalah Anda dapat menggunakan teknik sebelumnya untuk meneruskan vektor ke fungsi yang ingin mengubah buffer, yang tidak dapat Anda lakukan dengan .data ().


Mengapa Anda tidak dapat menggunakan data()untuk mengubah buffer? Menurut saya, jika Anda memanggil data()vektor non-const, ia akan mengembalikan a T *(dan jika vektor Anda adalah const, 'v [0] `akan mengembalikan a T const &).
Adam H. Peterson

@ AdamH.Peterson tampaknya merupakan pengawasan dalam standar. Data std :: vector memiliki fungsi const dan non-const, sedangkan dalam standar saat ini, std :: string hanya memiliki fungsi const: en.cppreference.com/w/cpp/string/basic_string/data Perhatikan bahwa C ++ 17 menambahkan versi non-const, jadi ini mungkin tidak akan terjadi selamanya - namun, standar saat ini menyatakan "Memodifikasi array karakter yang diakses melalui data memiliki perilaku yang tidak ditentukan."
Kerusuhan

Itu akan benar jika vberupa string, tetapi tipe targetnya adalah string dan vvektor. (Tapi bagus untuk melihat bahwa C ++ 17 akan memberikan string paritas dengan vektor.)
Adam H. Peterson

@ AdamH.Peterson Anda benar tentu saja. Pertanyaan itu dijawab beberapa waktu yang lalu, saya berasumsi bahwa seluruh pertanyaan adalah tentang string secara eksklusif tanpa memeriksa.
Kerusuhan

2

Saya suka jawaban Stefan (11 Sep. '13) tetapi ingin membuatnya sedikit lebih kuat:

Jika vektor diakhiri dengan terminator null, Anda tidak boleh menggunakan (v.begin (), v.end ()): Anda harus menggunakan v.data () (atau & v [0] untuk yang sebelum C ++ 17) .

Jika v tidak memiliki terminator null, Anda harus menggunakan (v.begin (), v.end ()).

Jika Anda menggunakan begin () dan end () dan vektor memiliki nol penghentian, Anda akan berakhir dengan string "abc \ 0" misalnya, yang panjangnya 4, tetapi seharusnya hanya "abc".


1
vector<char> vec;
//fill the vector;
std::string s(vec.begin(), vec.end());

Bisakah Anda menambahkan beberapa penjelasan serta kodenya?
Paul Floyd

1
Template pustaka string C ++ 11 berjalan sebagai berikut default (1) string (); salin (2) string (const string & str); substring (3) string (const string & str, size_t pos, size_t len ​​= npos); dari c-string (4) string (const char * s); dari buffer (5) string (const char * s, size_t n); isi (6) string (size_t n, char c); range (7) template <class InputIterator> string (InputIterator pertama, InputIterator terakhir); daftar penginisialisasi (8) string (penginisialisasi_list <char> il); pindahkan (9) string (string && str) noexcept; kami mengikuti template ke-7.
TechCat

Hai @TechCat! Harap baca tentang menulis jawaban yang bagus sebelum menjawab pertanyaan Anda berikutnya. Nikmati masa tinggal Anda di SO!
Gali.

Bisakah Anda mengedit jawaban Anda dengan uraiannya?
Paul Floyd
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.