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.