char array vs. string



  • Ich stimme dir in den meisten Punkten zu. Ich habe die Klasse auch nicht zum Spaß geschrieben, sondern ich fand es einfach nur ZU arm, dass ich nicht mal nen einfachen Text mit variablen Werten darin erstellen konnte. Ich habe mich einfach maßlos über die Standard-stringklasse geärgert.
    Da meine Ausgabe nicht über cout funktioniert, sondern über Direct3D, war ich gezwungen, mir eine Möglichkeit zu suchen, ein passendes char-Array zusammenzubasteln.
    Ich habe mir dann eine ganze Weile mit stringstreams geholfen, aber irgendwann war mir das Ganze einfach zu hässlich.
    Zur Entwicklungszeit möchte ich sagen, dass das Ganze nicht länger als (insgesamt!) 5-6 Stunden gedauert hat und diese Zeit gewiss nicht verschwendet war.

    Mir wäre es auch lieber gewesen, std::string würde wenigstens so einfache Verknüpfungen (die trotz aller gegenteiligen Behauptungen kein hoch spezieller Wunsch meinerseits sind) unterstützen. Dann hätte ich mir den Aufwand auch sparen können, wie in anderen Programmiersprachen. Aber ja, es könnte ja sein, dass jemand bei <text> + <zahl> dann ne Verknüpfung <(zahl)text> + <zahl> = <zahl> haben möchte - lol.

    Das könnt ihr sehen wie ihr wollt, ich rate lediglich, std::string zu benutzen und wenn das nicht reicht, eine eigene Klasse zu schreiben (das war der Ausgangspunkt der Diskussion). Das ist ein einmaliger Aufwand.



  • Optimizer schrieb:

    Da meine Ausgabe nicht über cout funktioniert, sondern über Direct3D, war ich gezwungen, mir eine Möglichkeit zu suchen, ein passendes char-Array zusammenzubasteln.

    Alternativ könnte man auch einfach einen Wrapper um die dumme DirectX-Funktion basteln.



  • Optimizer schrieb:

    Mir wäre es auch lieber gewesen, std::string würde wenigstens so einfache Verknüpfungen (die trotz aller gegenteiligen Behauptungen kein hoch spezieller Wunsch meinerseits sind) unterstützen.

    nimm lexical_cast oder ähnliches - schreibs dir einfach selber:

    template<typename To, typename From>
    To convert(From const& from)
    {
      stringstream stream;
      stream<<from;
      To to;
      stream>>to;
      return to;
    }
    

    und schon kannst du
    string s = convert<string>(3);
    schreiben...

    sicher, es ist etwas langsamer, da der std Ctor aufgerufen werden muss - dafür hast du eine sau schneller string klasse (du hast scheinbar keine ahnung was da für jahrelange optimierungen drinnen stecken).

    Was stört dich an dem Convert?

    Das könnt ihr sehen wie ihr wollt, ich rate lediglich, std::string zu benutzen und wenn das nicht reicht, eine eigene Klasse zu schreiben (das war der Ausgangspunkt der Diskussion). Das ist ein einmaliger Aufwand.

    dann sollte man wohl eher zB flex_string von Alexandrescu verwenden 🙂
    Ne - also dieser einmalige Aufwand stimmt natürlich - aber warum die jahrelange Erfahrung der StdLibrary Implementierer (Implementatoren??) wegwerfen?

    Und durch eine (sorry, aber es stimmt) primitive Klasse ersetzen?
    Sicher, sie kann Zahlen verwalten, aber was ist mit neuen Zahlen? zB einen int128, int256,... und was ist mit krokodil und pinguin (um das Java Beispiel zu erweitern). Kannst ja einfach templates verwenden:

    template<typename Other>
    void string::append(Other const& other)
    {
      append(convert<string, Other>(other));
    }
    

    und schon hast du die selbe funktionalität 🙂

    somit könntest du wenigstens eine konvertierungen sinnvoll machen und nicht dauernd überladen...

    oder aber funktionen um dies für std::string zu ermöglichen.

    einziges Problem das ich sehe - sind so sachen wie GetWindowText, die einen buffer erwarten.

    Da schreibe ich aber immer einen wrapper - das ist natürlich etwas langsamer aber dafür kann man auch exception verwenden 🙂

    Für deinen Fall wäre vielleicht ein vector<char> besser?



  • // Operatoren '+=' zum Anhängen: 
        void operator+= (TCHAR *otherString); 
        void operator+= (const String &otherString); 
        void operator+= (__int32 int32Bit); 
        void operator+= (__int64 int64Bit); 
        void operator+= (bool value);
    

    Und was machst Du wenn der Anwender der Klasse einen std::string anfügen will ? Oder sogar eine eigene Klasse ?

    Ich verstehe halt nicht was dagegen spricht mit stringstream einen template operator<< und >> in einem namespace zu schreiben.

    Ansonsten sehe ich das so:

    Ich als einzelner Entwickler kann in 6h nicht das erschaffen was viele wesentlich fittere Leute über eine lange Zeit entwickeln.
    Es spricht ja generell nichts dagegen eine eigene Klasse zu schreiben. (Hab mir ja selbst die mühe gemacht eine Klasse zu schreiben die mit ini Dateien inkl. Kommentaren templates und verschatelten Inis klar kommt.... Inkl. Editor etc. Hab übrigens wesentlich länger als 6 Tage drann geknappert. Bin halt langsam 🤡.

    Generell sollte man verwenden was da ist und erst auf eigene Klassen umsteigen wenn es der Profiler zeigt oder die Anforderung an die Klasse wesentlich höher ist als die Klasse das leisten kann.

    Generell zu sagen: Bau eine eigene Klasse, erst danach verwende die Standardklassen finde ich schlichtweg falsch. Ich denke Du hättest einfacher und sicherer zu Deinem Ziel kommen können 🤡

    Aber irgendwie drehen wir uns im Kreis, die Aussagen sind immer wieder die gleichen 😕



  • DrGreenthumb schrieb:

    Sie taugen nicht als buffer. Wenn zum Beispiel die WinAPI einen string zu rückgeben will muss man zuerst einen char Array erstellen anschließend eine string Kopie anfertigen und dann Array wieder löschen. Wäre es nicht einfacher wenn man reserve aufrufen könnte und anschließend direkt in den Buffer schreiben könnte?

    Wie soll das gescheit funktionieren, dass eine Methode einen char* auf die internen Daten zurückgibt.
    So?

    str.erlaube_reinschreiben(100);
    schreib_rein(str.pointer());
    str.fertig_mit_schreiben();
    

    Dann kommt auf einmal irgend'ne Lib die einen, mit malloc() reservierten, Speicherbereich zurückgibt. Soll string dafür dann auch eine Methode haben, die danach wieder free() aufruft? Bashar hat das schon gut auf den Punkt gebracht.

    Es ist halt der C Weg und da C++ ja C compatible sein soll wäre das mit dem buffer schon schön. Aber notfals kann man das immer noch mit Vererbung hinzufügen.

    Das mit malloc und free wird auch nicht vorkommen weil die meisten Libs in eine Dll gepackt sind/werden können.

    Also meist löse ich das Problem so:

    class Str:public string{
        char*buf;
    public:
        Str():buf(0){}
        ~Str(){delete buf;}
    
        //inherit operator=
        template<class T>
        Str&operator=(T t){assign(t);return *this;}
    
        void set_size(const int i){delete buf;buf=new char[i+1];buf[0]=0;}
        void refresh(){assign(buf);delete buf;buf=0;}
    
        operator const char*(){return c_str();}
        operator char*(){return buf;}
    };
    

    Mir wäre es auch lieber gewesen, std::string würde wenigstens so einfache Verknüpfungen (die trotz aller gegenteiligen Behauptungen kein hoch spezieller Wunsch meinerseits sind) unterstützen.

    Bau std::string doch einfach aus. Wieso das ganze Rad neu erfinden wenn du nur einen Teil neu erfinden willst/musst?

    Alternativ könnte man auch einfach einen Wrapper um die dumme DirectX-Funktion basteln.

    Kommt darauf an wieviel dumme Funktionen es gibt. Sind es viele kann es schneller sein eine eigene string class zu schreiben oder die standard string class zu erweitern.



  • Für die kompatibilität zu C APIs gibt es aber vector!
    Den kann man als Buffer verwenden...



  • Irgendwer schrieb:

    Also meist löse ich das Problem so:
    ...

    Ja, dachte ich schon. Aber dann refresh() aufzurufen, statt delete tmp; ist irgendwie das selbe in grün.

    Kommt darauf an wieviel dumme Funktionen es gibt. Sind es viele kann es schneller sein eine eigene string class zu schreiben oder die standard string class zu erweitern.

    Weiß nicht, ob das aber auch besser ist. So einen Funktionsaufruf möchte ich sowieso nicht "frei" im Code haben. Lieber einen Wrapper rum, mit nur den wichtigen Parametern und gleich auch const string statt char*.



  • Bau std::string doch einfach aus. Wieso das ganze Rad neu erfinden wenn du nur einen Teil neu erfinden willst/musst?

    Klingt ja logisch. Aber es war jetzt eigentlich gar nicht so aufwändig, die Klasse zu schreiben. Und ich wollte mal was mit new und delete machen 😉 . Die meiste Zeit hab ich in der MSDN nach _tcslen ö.ä. gesucht, weil ich mit TCHAR arbeiten wollte. 🙄
    Der Rest, das ganze Überladen, sind fast alles 2-Zeiler.

    Mit Templates hab ich mich leider noch nicht beschäftigt, ich bezweifle nicht, dass da noch eine sehr viel elegantere Lösung möglich ist.
    Trotzdem verstehe ich nicht, was Hume mit "Operatorüberladung der Marke willkür" meint. Vielleicht könnte man das ja mal begründen, oder einen besseren Vorschlag machen, ich habe nie behauptet, dass meine Klasse die bestmögliche Lösung ist.



  • Die x= und die = Operatoren sollten zum Beispiel String & zurückgeben



  • Trotzdem verstehe ich nicht, was Hume mit "Operatorüberladung der Marke willkür" meint. Vielleicht könnte man das ja mal begründen, oder einen besseren Vorschlag machen, ich habe nie behauptet, dass meine Klasse die bestmögliche Lösung ist

    Ich habe einen sehr guten Vorschlag gemacht, wiederhole ihn aber gerne: Lies "Effective C++".

    Da du scheinbar überhaupt nicht verstehst oder berücksichtigst worum es in diesem Thread ursprünglich ging und da du aus diesem Grund offensichtlich nicht dazu in der Lage bist meine Aussagen einzuordnen - aus welchen Gründen kommt man sonst wohl zu merkwürdigen Einschätzungen wie:

    So wie du es gesagt hast, ist es das schlimmste was man machen kann, wenn man einmal in seinem Leben so ne Klasse schreibt und die immer wieder verwenden kann.

    - fehlt mir jede Lust hier noch weiter was zu schreiben.



  • Optimizer schrieb:

    Klingt ja logisch. Aber es war jetzt eigentlich gar nicht so aufwändig, die Klasse zu schreiben.

    Klingt vielleicht hart, aber die Klasse ist ja auch lahm...
    Lass mal n paar Peformance Tests gegen std::string laufen und du wirst schockiert sein.

    Ich hab da teilweise schon schöne Dinger gemacht, aber nicht mit STLPort mithalten können (die haben AFAIK die beste string Implementierung)

    Der Rest, das ganze Überladen, sind fast alles 2-Zeiler.

    Und was machst du bei einem __int256 Typ? die Klasse ändern?



  • Ich arbeite mich gerade in templates rein. Die PErformance ist bei dieser Klasse nicht so wichtig.


Anmelden zum Antworten