2010-02-20 8 views
9

में कई तार जोड़ने के लिए मुझे पता है के रूप में है कि सी ++ केवल 2 तार एक साथ जोड़ने की अनुमति देता, यानी: s = s1 + s2कैसे C++

लेकिन यह कैसे मैं कई तार एक साथ जोड़ सकते हैं? पसंद:

s = s1 + s2 + s3 + s4 + ... + sn 
+9

आपको ऐसा क्यों लगता है कि यह काम नहीं करता है? – bmargulies

+1

क्या आप स्ट्रिंग क्लास का उपयोग कर रहे हैं? – cpx

+0

हाँ, मुझे लगता है कि यह केवल तभी काम करता है जब मैं स्ट्रिंग क्लास का उपयोग करता हूं। लेकिन मैं इस तरह कुछ ऐसा करना चाहता हूं जो सी ++ # परिभाषित करें "blah3" s = s1 + "blah1" + "blah2" + St – root

उत्तर

8

आप std :: स्ट्रिंग वर्ग की स्ट्रिंग वस्तुओं संलग्न करने के लिए प्रयास कर रहे हैं के लिए, यह काम करना चाहिए।

string s1 = "string1"; 
string s2 = "string2"; 
string s3 = "string3"; 

string s = s1 + s2 + s3; 

या

string s = string("s1") + string("s2") + string("s3") ... 
+6

+1 - जब आप 'ऑपरेटर + (std :: basic_string , std :: basic_string ) का उपयोग करते हैं तो बस ध्यान रखें)' आपको C++ 03 में घातीय समय लगेगा। 'Std :: basic_string :: ऐपेंड 'सदस्य फ़ंक्शन का उपयोग करके तुलना में केवल रैखिक समय लगता है। –

+0

मुझे लगता है कि स्ट्रिंग एस = स्ट्रिंग ("एस 1") + स्ट्रिंग ("एस 2") + स्ट्रिंग ("एस 3") ... कुछ ऐसा है जिसे मैं ढूंढ रहा हूं। मुझे आश्चर्य है कि यह क्यों काम करता है? – root

+2

क्योंकि जब आप स्ट्रिंग (x) का उपयोग करते हैं, तो आप एक्स पर मानक स्ट्रिंग क्लास के लिए एक कन्स्ट्रक्टर का आह्वान करते हैं। आप एक अस्थायी स्ट्रिंग ऑब्जेक्ट बनाते हैं जो उसके ऑपरेटर + के साथ भाग ले सकता है। (इस तरह के काम कास्ट के रूप में काम करता है) –

7

सबसे पहले, आप + स्न चीज़ को ठीक कर सकते हैं। हालांकि यह घातीय क्वाड्रैडिक (टिप्पणियां देखें) लेने वाला है, यह मानते हुए कि आप C12+ 03 पर std::basic_string<t> स्ट्रिंग का उपयोग कर रहे हैं।

आप ओ 12 (एन) समय में अपनी स्ट्रिंग को जोड़ने के लिए std::basic_string<t>::reserve के साथ संगीत कार्यक्रम में std::basic_string<t>::append का उपयोग कर सकते हैं।

संपादित करें: उदाहरण के

string a; 
//either 
a.append(s1).append(s2).append(s3); 
//or 
a.append("I'm a string!").append("I am another string!"); 
+1

यह घातीय समय नहीं लेगा, केवल वर्गबद्ध। 'संलग्न' तेजी से होगा, लेकिन सामान्य रूप से वैसे भी क्योंकि इसे समय-समय पर फॉर्म आवंटित करने की आवश्यकता है। सबसे अधिक मामलों में, दोनों विधियां ध्यान देने योग्य होने के लिए पर्याप्त धीमी नहीं होंगी, हालांकि। – sth

+0

नहीं, यह वास्तव में घातीय है, क्योंकि आर सैमुअल क्लैचको का जवाब दर्शाता है। आप एस 1 और एस 2 को एक साथ जोड़ते हैं, फिर परिणाम को एस 3 में जोड़ें, फिर परिणाम को एस 4 में जोड़ें ... आदि। प्रत्येक जोड़ अनुक्रम में पिछले सभी स्ट्रिंग्स की पूरी लंबाई जोड़ता है। इसलिए, लंबाई एन के के तारों को देखते हुए, आपके पास Sum_ {i = 1}^{K} (Sum_ {j = 1}^{i - 1} (N) + N) होगा जो घातीय है। 'std :: basic_string :: append' रैखिक है यदि' std :: basic_string :: रिजर्व' के साथ मेरे उत्तर में बताया गया है, क्योंकि 'std :: basic_string :: रिजर्व 'गारंटी नहीं देता है। –

+0

नोट: यह मेरे उपरोक्त उदाहरण में के के संबंध में चतुर्भुज है, लेकिन एन के संबंध में घातीय, इसलिए यदि आप किसी अन्य तरीके से समस्या को देखते हैं तो हम दोनों यहां सही हैं। –

4
s = s1 + s2 + s3 + .. + sn; 

काम हालांकि यह (एक अच्छा अनुकूलन संकलक की मदद करनी चाहिए) temporaries का एक बहुत बना सकते हैं जाएगा क्योंकि यह प्रभावी रूप से मान लिया जाएगा:

string tmp1 = s1 + s2; 
string tmp2 = tmp1 + s3; 
string tmp3 = tmp2 + s4; 
... 
s = tmpn + sn; 

एक वैकल्पिक तरीका है कि अस्थायी बनाने की गारंटी नहीं है तों है:

s = s1; 
s += s2; 
s += s3; 
... 
s += sn; 
+0

आपका उदाहरण बिल्कुल समान नहीं है tmp1 प्रतिलिपि बनाना चाहिए। यह वही होगा यदि tmp1 'स्ट्रिंग कॉन्स' था। हालांकि मुझे यह मानना ​​है कि आरवीओ शायद प्रतिलिपि को खत्म कर देगा। –

3

std::ostringstream कि के लिए निर्माण, उदाहरण के here देखते हैं। यह आसान है:

std::ostringstream out; 
out << "a" << "b" << "c" << .... << "z"; 
std::string str(out.str()); 
+1

मैं इंगित करता हूं कि तारों को जोड़ने के लिए स्ट्रिंगस्ट्रीम का उपयोग केवल एक स्ट्रिंग में जोड़ने से धीमा है। स्ट्रिंगस्ट्रीम चीजों को तारों में परिवर्तित करने के लिए बहुत अच्छा है, लेकिन यदि आप जो कुछ भी कर रहे हैं वह तारों से स्ट्रिंग का निर्माण कर रहा है, तो यह करने का यह कम प्रभावी तरीका है। संलग्न करें() और + = जाने का रास्ता हैं। –

+0

हाँ, आप सही हैं। कम से कम एक अतिरिक्त प्रति। –

+1

दरअसल, मैंने हाल ही में इसके लिए एक टेस्ट प्रोग्राम लिखा था और पाया कि स्ट्रिंग को सीधे स्ट्रिंग में जोड़ने की तुलना में स्ट्रिंग्स के साथ तारों को एक साथ रखने में लगभग 2 1/2 बार लगते हैं - और यह _without_ स्ट्रिंगस्ट्रीम से बाहर स्ट्रिंग प्राप्त कर रहा है जब आप ' फिर से किया यह विशेष आंकड़ा आम तौर पर अलग-अलग परिस्थितियों और सभी के साथ सटीक नहीं है, लेकिन यह स्पष्ट था कि स्ट्रिंगस्ट्रीम के साथ धाराओं का निर्माण करना केवल स्ट्रिंग में शामिल होने से काफी धीमा है। –

1

एक स्ट्रिंग

strlen बनाने के लिए तार, चार * और चार के जोड़ने के लिए एक टेम्पलेट का उपयोग करें: -

#include <iostream> 
#include <cstring> 

// it_pair to wrap a pair of iterators for a for(:) loop 
template<typename IT> 
class it_pair 
    { 
    IT b; 
    IT e; 
public: 
    auto begin() const 
     { 
     return b; 
     } 
    auto end() const 
     { 
     return e; 
     } 
    }; 

// string length 
template<typename S> auto strlen(const S& s) -> decltype(s.size()) 
    { 
    return s.size(); 
    } 

auto strlen(char c) -> size_t 
    { 
    return 1u; 
    } 

auto strlen(const std::initializer_list<char>& il) -> size_t 
    { 
    return il.size(); 
    } 

template<typename IT> 
auto strlen(const it_pair<IT>& p) 
    { 
    auto len = size_t{}; 
    for(const auto& s:p) 
     len += strlen(s); 
    return len; 
    } 

template<typename S, typename ...SS> auto strlen(S s, SS&... ss) -> size_t 
    { 
    return strlen(s) + strlen(ss...); 
    } 

जोड़कर तार

// terminate recursion 
template<typename TA, typename TB> 
void append(TA& a, TB& b) 
    { 
    a.append(b); 
    } 

// special case for a character 
template<> 
void append<std::string, const char>(std::string& a, const char& b) 
    { 
    a.append(1, b); 
    } 

// special case for a collection of strings 
template<typename TA, typename TB> 
void append(TA& a, const it_pair<TB>& p) 
    { 
    for(const auto& x: p) 
     a.append(x); 
    } 

// recursion append 
template<typename TA, typename TB, typename ...TT> 
void append(TA& a, TB& b, TT&... tt) 
    { 
    append(a, b); 
    append(a, tt...); 
    } 

template<typename ...TT> 
std::string string_add(const TT& ... tt) 
    { 
    std::string s; 
    s.reserve(strlen(tt...)); 
    append(s, tt...); 
    return s; 
    } 

template<typename IT> 
auto make_it_pair(IT b, IT e) 
    { 
    return it_pair<IT>{b, e}; 
    } 

template<typename T> 
auto make_it_pair(const T& t) 
    { 
    using namespace std; 
    return make_it_pair(cbegin(t), cend(t)); 
    } 

मुख्य उदाहरण

int main() 
    { 
    const char * s[] = {"vw", "xyz"}; 
    std::vector<std::string> v{"l", "mn", "opqr"}; 
    std::string a("a"); 
    std::string b("bc"); 
    std::string c("def"); 
    std::cout << string_add(a, b+c, "ghij", make_it_pair(v), 'k', make_it_pair(s)); 
    } 
+0

आपको मानकीकरण के लिए एक प्रस्ताव बनाना चाहिए :) –