จะสร้าง std :: string จาก std :: vector <char> ได้อย่างไร?


115

สั้น ๆ (ที่ชัดเจน) การสร้างสตริงสไตล์ C ก่อนจากนั้นจึงใช้สิ่งนั้นเพื่อสร้างสตริง std :: มีวิธีที่เร็วกว่า / ทางเลือก / "ดีกว่า" ในการเริ่มต้นสตริงจากเวกเตอร์ของอักขระหรือไม่?


4
สามารถทำได้โดยไม่ต้องคัดลอกหรือไม่? กล่าวอีกนัยหนึ่งคือสิ่งที่ทำเช่นเดียวกับstd::vector<char> v2(std::move(v))แต่std::stringเป็นวัตถุใหม่
tobi_s

คำตอบ:


197

วิธีที่ดีที่สุดคือใช้ตัวสร้างต่อไปนี้:

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

ซึ่งจะนำไปสู่บางสิ่งเช่น:

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

41

ฉันคิดว่าคุณสามารถทำได้

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

โดยที่ MyVector คือ std :: vector ของคุณ


1
ยกเว้นใน VS2013 ซึ่งยืนยันรันไทม์เกี่ยวกับตัววนซ้ำที่ไม่ถูกต้องเว้นแต่คุณจะตั้งค่า_ITERATOR_DEBUG_LEVEL=1(ซึ่งในกรณีนี้ดูเหมือนว่าจะทำงานได้ดี)
Cameron

35

ด้วย C ++ 11 ที่คุณสามารถทำได้std::string(v.data())หรือหากเวกเตอร์ของคุณไม่ได้มีที่สิ้นสุด'\0'std::string(v.data(), v.size())


แม้จะใช้ C ++ 98 ฉันเชื่อว่าคุณสามารถทำ std :: string (& v [0]) ได้ แน่นอนว่านี่คือถ้าเวกเตอร์สิ้นสุดด้วยโมฆะ
Jamie

1
@ Jamie: อย่างไรก็ตามใน C ++ 98 string(&v[0], v.size())ควรใช้งานได้เช่นกัน แต่หลังจากassert(not v.empty());นั้นเนื่องจากถ้าเวกเตอร์ว่างเปล่าทั้งสองอย่างv[0]และv.front()จะเรียกใช้พฤติกรรมที่ไม่ได้กำหนด นอกเหนือจากความเรียบง่ายทางวากยสัมพันธ์ที่ไม่ต้องใช้แอดเดรสของตัวดำเนินการแล้วยังเป็นประโยชน์ที่แท้จริงของdata()ฟังก์ชันC ++ 11 ซึ่งทำงานได้แม้ในเวกเตอร์ว่างเปล่า
Adam H. Peterson

จริงแท้แน่นอน. น่าเสียดายที่โครงการของฉันติดอยู่ใน Visual Studio 2008 สำหรับอนาคตอันใกล้ เกี่ยวกับการตรวจสอบความยาวเวกเตอร์ก่อน
Jamie

หากเวกเตอร์ไม่มี "\ 0" std::string(v.data())อาจทำให้สตริงยาวขึ้น ดังนั้นอย่าใช้วิธีนี้
heLomaN

@heLomaN: มีอะไรผิดปกติstd::string(v.data(), v.size())ซึ่งได้รับการกล่าวถึงอย่างชัดเจนในคำตอบด้วยเหตุผลที่แท้จริง?
Sz.


3

เพื่อความสมบูรณ์อีกวิธีหนึ่งคือstd::string(&v[0])(แม้ว่าคุณจะต้องแน่ใจว่าสตริงของคุณสิ้นสุดด้วยค่าว่างและstd::string(v.data())โดยทั่วไปเป็นที่ต้องการ

ความแตกต่างคือคุณสามารถใช้เทคนิคเดิมในการส่งเวกเตอร์ไปยังฟังก์ชันที่ต้องการแก้ไขบัฟเฟอร์ซึ่งคุณไม่สามารถทำได้ด้วย. data ()


ทำไมคุณdata()ถึงใช้เพื่อแก้ไขบัฟเฟอร์ไม่ได้? สำหรับฉันดูเหมือนว่าถ้าคุณเรียกdata()ใช้เวกเตอร์ที่ไม่ใช่ const มันจะส่งกลับ a T *(และถ้าเวกเตอร์ของคุณเป็น const 'v [0] `ก็จะส่งกลับค่าT const &)
Adam H. Peterson

@ AdamH.Peterson ดูเหมือนจะเป็นผู้กำกับดูแลในมาตรฐาน ข้อมูลของ Std :: vector มีทั้งฟังก์ชัน const และ non-const ในขณะที่ในมาตรฐานปัจจุบัน std :: string มีเฉพาะฟังก์ชัน const: en.cppreference.com/w/cpp/string/basic_string/data โปรดทราบว่า C ++ 17 เพิ่มเวอร์ชันที่ไม่ใช่ const ดังนั้นจึงอาจไม่เป็นเช่นนั้นไปเรื่อย ๆ - อย่างไรก็ตามสถานะมาตรฐานปัจจุบัน "การแก้ไขอาร์เรย์อักขระที่เข้าถึงผ่านข้อมูลมีพฤติกรรมที่ไม่ได้กำหนดไว้"
Riot

นั่นจะเป็นจริงถ้าvเป็นสตริง แต่ประเภทเป้าหมายเป็นสตริงและvเป็นเวกเตอร์ (แต่เป็นเรื่องดีที่เห็นว่า C ++ 17 จะให้ความเท่าเทียมกันของสตริงกับเวกเตอร์)
Adam H. Peterson

@ AdamH Peterson คุณพูดถูกแน่นอน คำถามได้รับคำตอบเมื่อไม่นานมานี้ฉันคิดว่าคำถามทั้งหมดเกี่ยวกับสตริงโดยเฉพาะโดยไม่ต้องตรวจสอบ
Riot

2

ฉันชอบคำตอบของสเตฟาน (11 ก.ย. 56) แต่อยากจะทำให้เข้มแข็งขึ้นอีกหน่อย:

หากเวกเตอร์ลงท้ายด้วยตัวยุติโมฆะคุณไม่ควรใช้ (v.begin (), v.end ()): คุณควรใช้ v.data () (หรือ & v [0] สำหรับสิ่งที่อยู่ก่อน C ++ 17) .

ถ้า v ไม่มีเทอร์มิเนเตอร์ว่างคุณควรใช้ (v.begin (), v.end ())

หากคุณใช้ start () และ end () และเวกเตอร์มีศูนย์การยุติคุณจะลงท้ายด้วยสตริง "abc \ 0" ซึ่งมีความยาว 4 แต่ควรเป็น "abc" เท่านั้น


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

คุณช่วยเพิ่มคำอธิบายและโค้ดได้ไหม
Paul Floyd

1
เทมเพลตไลบรารีสตริง C ++ 11 เป็นไปตามค่าเริ่มต้น (1) string (); คัดลอก (2) สตริง (สตริง const & str); สตริงย่อย (3) สตริง (สตริง const & str, size_t pos, size_t len ​​= npos); จากสตริง c (4) สตริง (const char * s); จากบัฟเฟอร์ (5) สตริง (const char * s, size_t n); เติม (6) สตริง (size_t n, ถ่าน c); range (7) template <class InputIterator> string (InputIterator first, InputIterator last); รายการเริ่มต้น (8) สตริง (initializer_list <char> il); ย้าย (9) สตริง (สตริง && str) noexcept; เรากำลังติดตามเทมเพลตที่ 7
TechCat

สวัสดี @TechCat! โปรดอ่านเกี่ยวกับการเขียนคำตอบที่ดีก่อนที่จะตอบคำถามถัดไปของคุณ เพลิดเพลินกับการเข้าพักที่ SO!
Diggy

คุณช่วยแก้ไขคำตอบพร้อมคำอธิบายได้ไหม
Paul Floyd
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.