2010-02-20 7 views
9

hinzufügen Wie ich weiß, dass C++ nur 2 Strings hinzufügen können zusammen, das heißt: s = s1 + s2Wie viele Strings in C++

Aber wie kann ich viele Strings zusammen fügen? Wie:

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

Warum denken Sie, dass das nicht funktioniert? – bmargulies

+1

verwenden Sie die String-Klasse? – cpx

+0

Ja, ich merke, dass es nur funktioniert, wenn ich String-Klasse verwende. aber ich möchte so etwas in C++ tun #define St "blah3" s = s1 + "blah1" + "blah2" + St – root

Antwort

8

Wenn Sie versuchen, String-Objekte von std :: string Klasse anhängen, sollte diese Arbeit.

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

string s = s1 + s2 + s3; 

ODER

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

+1 - Denken Sie daran, wenn Sie 'operator + (std :: basic_string , std :: basic_string )' 'verwenden, wird exponentielle Zeit in C++ 03 anfallen. Die Verwendung der 'std :: basic_string :: append' Member-Funktion benötigt nur lineare Zeit im Vergleich. –

+0

Ich denke String s = String ("s1") + String ("s2") + String ("s3") ... ist etwas, das ich suche. Ich frage mich, warum es funktioniert? – root

+2

Weil Sie bei der Verwendung von string (x) sind, rufen Sie einen Konstruktor für die Standard-String-Klasse auf x auf. Sie erstellen ein temporäres String-Objekt, das dann mit seinem Operator + teilnehmen kann. (Diese Art von Arbeiten funktioniert wie eine Form der Besetzung) –

7

Vor allem können Sie die + sn Sache gut machen. Obwohl es dauert exponentiell Quadradik (siehe Kommentare) Zeit unter der Annahme, dass Sie std::basic_string<t> Strings auf C++ 03 verwenden.

Sie können std::basic_string<t>::append zusammen mit std::basic_string<t>::reserve verwenden, um Ihre Zeichenfolge in O (n) -Zeit zu verketten.

EDIT: Zum Beispiel

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

Es wird keine exponentielle Zeit benötigen, nur quadratisch. 'append' wird schneller sein, aber im Allgemeinen auch quadratisch, da es die Form von Zeit zu Zeit neu zuweisen muss. In den meisten Fällen werden beide Methoden jedoch nicht langsam genug sein, um wahrnehmbar zu sein. – sth

+0

Nein, es ist tatsächlich exponentiell, wie R Samuel Klatchkos Antwort zeigt. Sie addieren s1 und s2 zusammen, fügen dann das Ergebnis zu s3 hinzu und fügen dann das Ergebnis zu s4 ... usw. hinzu. Jede add fügt die komplette Länge aller vorhergehenden Strings in der Sequenz hinzu. Wenn Sie also K Strings der Länge N haben, haben Sie Sum_ {i = 1}^{K} (Sum_ {j = 1}^{i - 1} (N) + N), was exponentiell ist. 'std :: basic_string :: append' ist linear, wenn es mit' std :: basic_string :: reserve' verwendet wird, wie in meiner Antwort angegeben, weil 'std :: basic_string :: reserve' keine Neuzuweisung garantiert. –

+0

Hinweis: In meinem obigen Beispiel ist es quadratisch in Bezug auf K, aber exponentiell in Bezug auf N, also sind wir hier beide korrekt, wenn Sie das Problem anders betrachten. –

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

funktionieren, obwohl es eine Menge von Provisorien (ein guter optimierenden Compiler sollte helfen) schaffen könnte, weil es effektiv wie interpretiert wird:

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

Ein alternativer Weg, der garantiert nicht temporari erstellt wird es ist:

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

Ihr Beispiel ist nicht ganz das gleiche tmp1 muss ein Kopierkonstrukt sein. Es wäre das gleiche, wenn tmp1 'string const &' wäre. Obwohl ich zugeben muss, dass RVO die Kopie wahrscheinlich eliminieren würde. –

3

std::ostringstream ist dafür zu bauen, siehe Beispiel here. Es ist einfach:

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

Ich würde darauf hinweisen, dass die Verwendung von Stringstream zum Anhängen von Strings langsamer ist als nur das Anhängen an eine Zeichenfolge. stringstream eignet sich hervorragend zum Umwandeln von Zeichen in Zeichenfolgen. Wenn Sie jedoch nur Zeichenfolgen aus Zeichenfolgen erstellen, ist dies die weniger effiziente Methode. append() und + = sind der Weg zu gehen. –

+0

Ja, Sie haben Recht. Eine zusätzliche Kopie mindestens. –

+1

Eigentlich habe ich kürzlich ein Testprogramm dafür geschrieben und festgestellt, dass es etwa 2 1/2 mal so lange dauerte, Strings mit stringstream zusammenzufügen, als direkt an einen String anzuhängen - und das ist _ohne_ die Strings aus dem Stringstream zu bekommen, wenn Sie ' Wieder getan. Diese bestimmte Zahl stimmt wahrscheinlich nicht mit unterschiedlichen Umständen und all dem überein, aber es war ziemlich klar, dass das Konstruieren von Strömen mit Stringstream wesentlich langsamer ist als nur das Anhängen an eine Zeichenkette. –

1

Vorlage verwenden Strings hinzuzufügen, char * und char die eine Zeichenfolge

Strlen zu bilden: -

#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...); 
    } 

anhängt Saiten

// 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)); 
    } 

Haupt Beispiel

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

Sie sollten einen Vorschlag für die Standardisierung erstellen :) –