Bir std :: vector <char> 'dan bir std :: string nasıl oluşturulur?


115

İlk olarak bir C stili dizginin (apaçık) oluşturulmasından sonra bunu bir std :: dizge oluşturmak için kullanılmasından kısa, bir karakter vektöründen bir dizgeyi başlatmak için daha hızlı / alternatif / "daha iyi" bir yol var mı?


4
Bu kopyalamadan yapılabilir mi? Başka bir deyişle , yeni nesneyle aynı şeyi yapan std::vector<char> v2(std::move(v))bir şey std::string.
— tobi_s

Yanıtlar:


197

Peki, en iyi yol aşağıdaki yapıcıyı kullanmaktır:

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

bu da şöyle bir şeye yol açar:

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

41

Bence yapabilirsin

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

MyVector, std :: vektörünüzdür.


1
Siz ayarlamadığınız sürece, çalışma zamanında geçersiz yineleyiciler hakkında iddiada bulunan VS2013 hariç _ITERATOR_DEBUG_LEVEL=1(bu durumda iyi çalışıyor gibi görünüyor).
— Cameron

35

C ++ 11 ile yapabilir std::string(v.data())veya vektörünüzün '\0'sonunda a içermiyorsa std::string(v.data(), v.size()),.


C ++ 98 ile bile std :: string (& v [0]) yapabileceğinizi düşünüyorum. Bu, elbette, vektörün sıfır sonlu olması durumudur.
— Jamie

1
@Jamie: Bu arada, C ++ 98 yılında, string(&v[0], v.size())aynı zamanda çalışacaktır ama sonra assert(not v.empty());, vektör boş, hem eğer bu yana v[0]ve v.front()tanımsız davranış çağırmak olacaktır. Bu, adres operatörünü kullanmak zorunda olmamanın sözdizimsel basitliğinin yanı sıra, data()boş bir vektörde bile çalışan C ++ 11 işlevinin gerçek faydasıdır.
— Adam H. Peterson

Çok doğru. Maalesef, projem öngörülebilir gelecek için Visual Studio 2008'de takılı kaldı. Önce vektör uzunluğunu kontrol etmekle ilgili.
— Jamie

Vektör bir '\ 0' içermiyorsa, std::string(v.data())daha uzun bir dizeye yol açabilir. Öyleyse bu şekilde kullanmayın.
— heLomaN

@heLomaN: std::string(v.data(), v.size())Tam da bu nedenle cevapta açıkça belirtilen neyin yanlış ?
— Sz.

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

V neredeyse yinelenebilir bir şeydir. (Özellikle begin () ve end (), InputIterators döndürmelidir.)


3

Tamlık için, başka bir yol da std::string(&v[0])(dizenizin boş sonlandırılmış olmasını sağlamanız gerekmesine rağmen std::string(v.data())genellikle tercih edilmelidir.

Aradaki fark, vektörü arabelleği değiştirmek isteyen işlevlere geçirmek için eski tekniği kullanabilmenizdir, ki bunu .data () ile yapamazsınız.


data()Arabelleği değiştirmek için neden kullanamıyorsunuz ? Bana data(), const olmayan bir vektörü çağırırsanız , a döndürür gibi görünüyor T *(ve vektörünüz const ise, 'v [0] " T const &yine de a döndürür ).
— Adam H. Peterson

@ AdamH.Peterson standartta bir gözetim gibi görünüyor. Std :: vector verilerinin hem const hem de const olmayan işlevleri vardır, oysa mevcut standartta std :: string yalnızca bir const işlevine sahiptir: en.cppreference.com/w/cpp/string/basic_string/data C ++ 17 const olmayan bir sürüm ekler, bu nedenle bu süresiz olarak geçerli olmayabilir - ancak, mevcut standart "Veriler aracılığıyla erişilen karakter dizisini değiştirmek tanımsız davranışa sahiptir" demektedir.
— Riot

vBir dizge olsaydı bu doğru olurdu , ancak hedef türü bir dizedir ve vbir vektördür. (Ama C ++ 17'nin dizelere vektörle eşitlik vereceğini görmek güzel.)
— Adam H. Peterson

@ AdamH.Peterson tabii ki haklısın. Soru bir süre önce cevaplanmıştı, tüm sorunun sadece kontrol edilmeden dizelerle ilgili olduğunu varsaymıştım.
— Riot

2

Stefan'ın cevabını beğendim (11 Eylül 2013) ama biraz daha güçlü hale getirmek istiyorum:

Vektör boş bir sonlandırıcı ile biterse, (v.begin (), v.end ()) kullanmamalısınız: v.data () (veya C ++ 17'den öncekiler için & v [0] kullanmalısınız) .

V'nin boş bir sonlandırıcısı yoksa, (v.begin (), v.end ()) kullanmalısınız.

Begin () ve end () kullanırsanız ve vektörün sonlandırıcı bir sıfıra sahipse, örneğin 4 uzunluğunda bir "abc \ 0" dizesi elde edersiniz, ancak gerçekten sadece "abc" olmalıdır.


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

Kodun yanı sıra bazı açıklamalar da ekleyebilir misiniz?
— Paul Floyd

1
C ++ 11 dizge kitaplığı şablonu aşağıdaki gibidir default (1) string (); copy (2) string (const string & str); substring (3) string (const string & str, size_t pos, size_t len ​​= npos); c-string (4) dizesinden (const char * s); arabellekten (5) string (const char * s, size_t n); fill (6) string (size_t n, char c); aralık (7) şablon <sınıf InputIterator> string (önce InputIterator, InputIterator son); başlatıcı listesi (8) string (initializer_list <char> il); hareket (9) dizge (dizge && dizge) noexcept; 7. şablonu takip ediyoruz.
— TechCat

Merhaba @TechCat! Lütfen bir sonraki sorunuzu cevaplamadan önce iyi bir cevap yazmayı okuyun . SO'daki konaklamanızın keyfini çıkarın!
— Diggy.

Cevabınızı açıklama ile değiştirebilir misiniz lütfen?
— Paul Floyd
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.