char array mit Seperator alphabetisch sortieren


  • Mod

    volkard schrieb:

    Woher mögen die krummen Zahlen kommen?

    Ausrichtung an 4kB-Seiten - free-storeverwaltungsoverhead - 1 Byte Terminator schätze ich mal. Vermutlich mag default-new Speicheranforderungen, die (fast) Vielfache von 4kB sind.


  • Mod

    GCC 4.9.0, basic_string.tcc

    append(const basic_string& __str)
        {
          const size_type __size = __str.size();
          if (__size)
    	{
    	  const size_type __len = __size + this->size();
    	  if (__len > this->capacity() || _M_rep()->_M_is_shared())
    	    this->reserve(__len);
    	  _M_copy(_M_data() + this->size(), __str._M_data(), __size);
    	  _M_rep()->_M_set_length_and_sharable(__len);
    	}
          return *this;
        }
    

    Wo ist hier die Verdopplung versteckt?


  • Mod

    Arcoth schrieb:

    Wo ist hier die Verdopplung versteckt?

    In _S_create, mit ausführlichem Kommentar.



  • volkard schrieb:

    Bisher wenig. Denke, Du solltest die chars in einem vector<char> erst sammeln und dann Schwuppdiwupps in den Zielstring kopieren oder erst die Zeichen zählen (endlich accumulate), den Zielstring mit dieser Zeichenanzahl anlegen und dann die Quellstrings alle reinkopieren.

    edit: Mit http://www.cplusplus.com/reference/string/string/reserve/ vorher genug Platz reservieren, dann ist die Laufzeit von join/accumulate/schleife optimal.

    Beim String steht nämlich nicht http://www.cplusplus.com/reference/vector/vector/push_back/

    std::string schrieb:

    Complexity
    Constant (amortized time, reallocation may happen).

    If a reallocation happens, the reallocation is itself up to linear in the entire size.

    Moment, das geht mir gerade etwas zu schnell.

    Also die Wörter sammel ich jetzt in einem vector<string>, das passt nehme ich an? Diesen konvertiere ich dann bei Bedarf mittels join in eine Form die die dll akzeptiert.

    Also geht es momentan nur um die Implementierung der join Funktion, das prinzipielle Vorgehen ist so ok, hab ich das richtig verstanden?

    Dann weiter: Dass ich mittels string::reserve genug Platz reserviere macht Sinn, aber wenn ich davor die Zeichen mit accumulate zählen muss, muss ich selbiges doch wieder verwenden, was wie ich dachte quadratische Laufzeit hat?

    EDIT:

    Hab noch folgendes Snippet beim googlen gefunden:

    string join(const vector<string> & vec,const string & sep)
    {
        if(vec.size()==0)
            return "";
        string::size_type size=sep.length()*vec.size();
        for(unsigned int i=0;i<vec.size();i++)
        {
            size+=vec[i].size();
        }
    
        string tmp;
        tmp.reserve(size);
        tmp=vec[0];
        for(unsigned int i=1;i<vec.size();i++)
        {
            tmp=tmp+sep+vec[i];
        }
        return tmp;
    }
    

    Ist das besser als meins?



  • von std::string den Speicher bei += geometrisch wachsen läßt.

    Warum sollte es anders als bei std::vector sein? Ich dachte du meinst, die Anzahl der Kopieroperationen/kopierten Zeichen.



  • happystudent schrieb:

    Dann weiter: Dass ich mittels string::reserve genug Platz reserviere macht Sinn, aber wenn ich davor die Zeichen mit accumulate zählen muss, muss ich selbiges doch wieder verwenden, was wie ich dachte quadratische Laufzeit hat?

    accumulate selber ist linear mit der anzahl der zu summierenden objekte. aber wenn das += des strings auch linear zur länge des ergebnisstrings ist, wird das zusammen quadratisch. also accumulate auf string ist sünde. accumulate auf size_t ist klasse.
    wübei die sünde halb so wild wohl ist. gcc rechnet damit, daß gesündigt wird und bleibt schnell. wenn ms auch damit rechnet, dann ist das schon ein quasistandard und.



  • knivil schrieb:

    von std::string den Speicher bei += geometrisch wachsen läßt.

    Warum sollte es anders als bei std::vector sein?

    Damit ich als Benutzer nicht so gequält werde. vector benutze ich fast immer mit push_back, da ist das geometrische Wachstum gut (sorg für amortisiert lineare Wachstumskosten). Und ich bin so frei, das reserve vorher sogar wegzulassen, was hier im Forum anscheinend leider zu sowas wie einer Pflichtübung geworden ist. Bei string sieht das ganz anders aus. Da baue ich mal eine sql-query zusammen oder einen vector/set/map von Dateinamen.
    Wir sind uns hoffentlich einig, daß die Schnittstelle der DLL komisch ist, eine saulange Stringliste als EINEN riesigen leerzeichengetrennten String haben zu wollen. Für was braucht man sonst schnelles += auf riesige Strings? Also ich nicht. Da bin ich dann Fan von Speichersparen.



  • happystudent schrieb:

    Hab noch folgendes Snippet beim googlen gefunden:

    string join(const vector<string> & vec,const string & sep)
    {
        if(vec.size()==0)
            return "";
        string::size_type size=sep.length()*vec.size();
        for(unsigned int i=0;i<vec.size();i++)
        {
            size+=vec[i].size();
        }
    
        string tmp;
        tmp.reserve(size);
        tmp=vec[0];
        for(unsigned int i=1;i<vec.size();i++)
        {
            tmp=tmp+sep+vec[i];
        }
        return tmp;
    }
    

    Ist das besser als meins?

    Ja, insofern, daß es sich nicht auf spezielle Implementierungen der Standradbibliothek verläßt, die mehr versprechen als im Standard garantiert ist.
    Ich würde sie noch anpassen auf Dich.

    string join(const vector<string> & vec/*,const string & sep//weg, ist bei Dir ' '*/)
    {
        string tmp;//hoch damit, dann kann sogar der weltdümmste compiler die rückgabe optimieren
    /*    if(vec.size()==0) //weg, kommt bei Dir eh nicht vor. 
            return "";*/
        string::size_type size=vec.size();//sep.length weg
        for(size_t i=0;i<vec.size();i++)//schon size_t nehmen
        {
            size+=vec[i].size();
        }
    
        tmp.reserve(size);
    //    tmp=vec[0];//häßlich, oder?
        for(unsigned int i=0;i<vec.size();i++)//zum ausgleich bei 0 starten
        {
            tmp=tmp+sep+vec[i];
        }
        return tmp;
    }
    


  • Cool, danke für die Erklärungen und die Anpassungen. 👍
    Werd ich gleich mal einbauen.



  • for(unsigned int i=0;i<vec.size();i++)//quatsch, besser begin() und end()
    
    //tmp=tmp+sep+vec[i];//vollquatsch
    tmp+=vec[i];
    tmp+=' ';
    


  • Und ich bin so frei, das reserve vorher sogar wegzulassen, was hier im Forum anscheinend leider zu sowas wie einer Pflichtübung geworden ist.

    Jap, bei meinen Tests (firmenintern, problemspezifisch, etc. ) zeigte sich auch kein Performancevorteil von reserve .

    Wir sind uns hoffentlich einig ...

    Ja.



  • Und ich bin so frei, das reserve vorher sogar wegzulassen, was hier im Forum anscheinend leider zu sowas wie einer Pflichtübung geworden ist.

    Ich dachte es war Konsenz, dass vector ausser in wenigen Sonderfällen kein reserve braucht.


Anmelden zum Antworten