C-Strings vergleichen



  • Löl.
    Ich kann und will das einfach nicht als Argument gegen ein Buch akzeptieren. Egal welches Buch.
    Wenn du ein Haus baust, fängst du dann mit dem Dach an ? Wohl kaum.

    C-String gehören genauso zu C wie zu C++, also kann man schlecht von einem Mischmasch aus beiden Sprachen reden. Natürlich stammen C-String aus C, aber man benutzt sie trotzdem sehr häufig in C++. Also macht es Sinn, darauf einzugehen.
    Außerdem geht er beim Erwähnen der String-Klasse direkt ganz darauf ein. Sollte er das etwa gleich bei den Basisdatentypen int, char, etc. machen ? Wohl kaum ...

    Und nun erklär mir bitte noch, wie das das Vertändnis eines Programmieranfängers durcheinander bringt ? Die Tatsache, dass der Autor vor Strings auf C-String eingeht ?


  • Administrator

    Felixxx schrieb:

    Und nun erklär mir bitte noch, wie das das Vertändnis eines Programmieranfängers durcheinander bringt ? Die Tatsache, dass der Autor vor Strings auf C-String eingeht ?

    Ich zeige es dir an deinem eigenen Beitrag auf.

    Felixxx schrieb:

    C-String gehören genauso zu C wie zu C++, also kann man schlecht von einem Mischmasch aus beiden Sprachen reden. Natürlich stammen C-String aus C, aber man benutzt sie trotzdem sehr häufig in C++. Also macht es Sinn, darauf einzugehen.

    Das stimmt nicht. Ich benutze grundsätzlich gar nie mehr C Strings, schon nur deshalb weil sie nicht RAII Konform sind. Die Funktionen aus dem <cstring> Header benutze ich überhaupt nie.

    In C++ wirst du in erster Linie std::string oder std::vector verwenden. Du wirst nur in seltenen Ausnahmen auf C-Strings oder C-Arrays ausweichen.
    Wie ein std::string intern funktioniert gehört daher ans Ende des Buches. Es sollte erst dann erwähnt werden, wenn der Anfänger normalerweise für eine Aufgabe zuerst std::string nimmt.

    Grüssli


  • Mod

    Felixxx schrieb:

    Löl.

    Hör lieber auf unskilled, er weiß wovon er spricht.

    Wenn du ein Haus baust, fängst du dann mit dem Dach an ? Wohl kaum.

    Unpassender Vergleich. Besser wäre: Wenn du ein Haus baust, fängst du dann auch damit an, zuerst eine Strohhütte zu bauen?

    C-String gehören genauso zu C wie zu C++,

    Unsinn. Es gibt sie, aber sie gehören nicht wirklich dazu. Wenn J.W. bei dir einen anderen Eindruck erweckt hat, dann ist dies genau eine der Sachen auf die sich diese Kritik bezieht.

    warum dies Unsinn ist, erkläre ich unten.

    also kann man schlecht von einem Mischmasch aus beiden Sprachen reden.

    Doch. C-Strings benutzt man in C sehr oft, in C++ nie (zumindest nie so, dass man es merkt), daher ist es Sprachmischmasch sie in C++ zu benutzen.

    Natürlich stammen C-String aus C, aber man benutzt sie trotzdem sehr häufig in C++.

    Dies ist ganz einfach ein falscher Fakt. In C++ benutzt man C-Strings für 3 Sachen: Im Sinne von Stringliteralen um damit std::strings zu initialisieren. Im diesem Falle merkt man nichts von der C-String Natur. Zweitens bei der Übergabe von Kommandozeilenargumenten an main. Dies ist ein nerviges Überbleibsel aus alten Zeiten, dass nicht geändert werden kann. Üblicherweise wird daher sofort ein String mit diesen Werten initialisiert. Drittens um bestimmte Funktionen damit aufzurufen, die C-Strings haben müssen. Hier reicht ein c_str(), von dem man wissen muss, dass man es braucht, aber nicht was es macht. In allen Fällen muss man nicht wissen, was ein C-String ist, man bekommt idealerweise nicht einmal mit, was da passiert.

    Also macht es Sinn, darauf einzugehen.

    Ja, als kleiner Exkurs im Anhang für Interessierte.

    Und nun erklär mir bitte noch, wie das das Vertändnis eines Programmieranfängers durcheinander bringt ? Die Tatsache, dass der Autor vor Strings auf C-String eingeht ?

    Du selbst, und auch die vielen anderen Opfer hier im Forum, lieferst genügend Stoff für Argumente. Alleine schon die Tatsache, dass du C-Strings als normalen Teil von C++ ansiehst ist für einen C++-Programmierer eher amüsant. Aber du siehst dies natürlich gar nicht ein, weil dies in deinem Buch anders steht und dies ist alles was du kennst.

    Die einzige Wahl die du hast, ist dich zu entscheiden wem du glaubst: Jemandem der am laufenden Band Anfängerbücher zu verschiedensten Themen raushaut (wie gut wird er wohl recherchiert haben?) und dabei sogar Fehler macht die für Anfänger offensichtlich sind (die Syntaxfehler) oder der geballten Meinung aller regelmäßigen Teilnehmer im größten deutschen C++-Forum.

    Ich möchte dich jedoch auch noch darauf aufmerksam machen, dass Menschen bekanntermaßen ihre vergangenen Fehlentscheidungen gutreden und neue Fehlentscheidungen damit rechtfertigen: Ich habe jetzt schon tausende von Euros in die Reperatur meines Wagens gesteckt, weil ich mir damals eine Schrottmühle gekauft habe, jetzt kann ich auch nochmal 1000€ reinstecken, um durch den TÜV zu kommen. Ich habe jetzt schon 40 Euro für ein Buch ausgegeben welches mir schaden soll, jetzt kann ich es wenigstens durchlesen.



  • Ja, ich weiß dass ihr wisst, wovon Ihr sprecht.

    Aber ich denke es ist doch mal Geschmackssache, ob man std::string oder char array[50] verwendet.

    Außerdem übersiehst du eine Sache für die es gut sein könnte, es zu wissen :

    Deine C-Strings liegen immernoch im speicher und werden sogar verdopelt wenn du nen std::string damit initialiesiert. Das sollte man zumindest wissen um Schpeicherlecks zu vermindern. Oder sehe ich das falsch ?

    Btw: Die Sache mit dem Geld : Es geht mir nicht ums Geld. Wie schon öfter erwähnt habe ich garnicht vor das Buch weiterzulesen. Aber aus anderen Gründen. Die geballte Kritik verstärkt den Entschluss nurnoch.
    Aber ich fand das Buch bis dato not bad.



  • Felixxx schrieb:

    Aber ich denke es ist doch mal Geschmackssache, ob man std::string oder char array[50] verwendet.

    Ist es denn auch Geschmackssache, ob man ein sicheres oder unsicheres Rennauto fährt?

    Wenn man schon auf std::string verzichtet, dann kann man auch gleich in C programmieren. Denn das was std::string bietet macht C++ aus; wer sich dagegen wehrt, der wehrt sich gegen die Sprache an sich.


  • Mod

    Felixxx schrieb:

    Aber ich denke es ist doch mal Geschmackssache, ob man std::string oder char array[50] verwendet.

    Eben nicht. Das eine ist narrensicher, das andere ist fehleranfällig. Das eine ist kurz und elegant, das andere ist umständlich (es gibt ein paar Situationen in denen C-Strings kürzer und elganter sein können, aber dies ist eher die Ausnahme). Das eine ist vom Stil her konsistent zum Rest der Sprache, das andere nicht. Das eine ist etwas mit denen andere C++ Programmierer sich bestens auskennen, das andere nicht. Das eine hat eine intuitive Semantik (überladene Operatoren), das andere nicht. Beim einen wird alles automatisch für einen gemacht, beim anderen muss man selber auf alles aufpassen (und wehe man macht etwas falsch!). Beim einen hat man ohne Kosten die Flexibilität etwas ganz anderes zu machen (wusstest du zum Beispiel, dass man Strings mit int als Basis (anstatt char) haben kann? Das geht sogar mit eigenen Datentypen. Und man kann trotzdem alles so benutzen wie einen normalen std::string), beim anderen nicht.

    Deine C-Strings liegen immernoch im speicher und werden sogar verdopelt wenn du nen std::string damit initialiesiert. Das sollte man zumindest wissen um Schpeicherlecks zu vermindern. Oder sehe ich das falsch ?

    Das siehst du falsch. Wo du das her hast, kann man sich ja denken 😃



  • Hmm true.

    Aber :

    Für mich macht es immernoch Sinn bzw. ist es nicht schlimm, auf C-Strings in einem Buch vor std::string einzugehen. Ich möchte nicht nomal wiederholen warum ich denke, dass er das so macht ( auf string äher eingehen ... ) und es so auch durchaus Sinn macht.
    Außerdem :
    C ist Basis von C++.
    Es ist also nicht grausam und programmier-schadend C-Strings als eine Alternative zu std::string zu halten.



  • Das sehe ich falsch ? Was sehe ich falsch ?

    Und du hast recht, was die Verwendung von string in komplexen Programmen betrifft, in dem man sehr viel damit rumhantiert.
    Aber in Programmen, wo sie eher eine kleine Rolle spielen, kann man ruhig C-String nehmen, da schneller.



  • Felixxx schrieb:

    Oder sehe ich das falsch ?

    Ja und nein.

    Felixxx schrieb:

    Deine C-Strings liegen immernoch im speicher und werden sogar verdopelt wenn du nen std::string damit initialiesiert.

    Ja. Deswegen mache ich sowas nicht grundsätzlich. Bei mir leben C-Strings und std::string harmonisch nebeneinander. Das sind keine Gegner. Es sind auch nicht Vorgänger und Nachfolger. Manchmal sind C-Strings auch in C++ angemessen. Aber sauselten. Vielleicht so selten, daß es gescheit wäre, sie weit nach std::string zu bringen. Dazu müßte man auch die Beispielprogramme umsortieren und das erste, das argv[] benutzt, nach hinten schieben. So Sachen halt und es wird rund.

    Felixxx schrieb:

    Das sollte man zumindest wissen um Schpeicherlecks zu vermindern.

    Keine Speicherlöcher sichtbar. Welches meinst Du? Ich sehe keins.



  • Es ist in einigen Situationen sogar erforderlich mit C Strings zu arbeiten.
    Das betrifft insbesondere in C geschriebene Schnittstellen, wie der WinAPI.

    Du hast also insofern recht, dass man sich auch mit den C Strings auseinandergesetzt haben sollte. Aber ob es pädagogisch sinnvoll ist zunächst auf diese einzugehen, halte ich für sehr fraglich. Bieten sie doch viel mehr Fallstricke, als std::string es tut. Versuch doch mal zwei C Strings mit == zu vergleichen. Das ist für einen Anfänger alles andere als intuitiv, sondern einfach nur frustrierend! So macht programmieren keinen Spaß.

    Im übrigen versucht man von C Arrays (wenn es anders nicht geht) schnell wieder zu std::string zu kommen. Man schreibt sich einfach Wrapper, die diese hässlichen und unsicheren Dinge wegkapseln.

    Und ob C Basis von C++ ist. Wenn das mal kein Flamewar auslöst.

    Und das Argument mit der Geschwindigkeit ist lächerlich. Eine solch zeitkritische Anwendung musst du erst mal programmieren müssen. Sehr unwahrscheinlich.



  • Naja,
    der speicher für das char array wird zB nicht automatisch freigegeben das heißt man muss das selbst erldigen.
    Aber viele wissen nicht einmal, dass jedesmal wenn du iwo "bla" schreibst eig nen char array erstellt wird.



  • Ja das Argument mit der Zeit ist natürlich etwas schwach 😛 Aber ich meinte, dass man C-Strings in eben solchen Programmen verwendet.

    Und das mit == geht natürlich auch nicht. Aber wozu gibts strcmp. Wobei das natürlich wieder umständlicher ist, als bei std::string, wo der Operator schon schön überladen wurde 🙂 Trotzdem ...



  • Versuch doch einfach mal mit C Strings ein Programm zu realisieren, welches zwei C Strings einliest und anschließend miteinander verknüpft. Der neu entstandene C String soll dann rückwärts ausgegeben werden.

    Damit du weißt, worum es geht. Hier eine mögliche Lösung mit std::string :

    #include <iostream>
    #include <algorithm>
    #include <string>
    #include <iterator>
    
    int main()
    {
    	std::cout << "S1: ";
    	std::string s1;
    	std::getline(std::cin, s1);
    
    	std::cout << "S2: ";
    	std::string s2;
    	std::getline(std::cin, s2);
    
    	std::cout << "S3: ";
    	std::string s3 = s1 + s2;
    	std::copy(s3.rbegin(), s3.rend(), std::ostream_iterator<char>(std::cout, ""));
    
    	return 0;
    }
    

    Die Frage die du dir danach stellen solltest: Sind C Strings den Aufwand wert?



  • ,,,, schrieb:

    Es ist in einigen Situationen sogar erforderlich mit C Strings zu arbeiten.
    Das betrifft insbesondere in C geschriebene Schnittstellen, wie der WinAPI.

    Aber nur wenn die API einen veränderbaren Zeiger auf den C-String erwartet (d.h. char* ). Sonst gibt es ja die Funktion c_str , die man immer verwenden kann, wenn ein nur-lese-string erwartet wird (d.h. const char* ).



  • Felixxx schrieb:

    Naja,
    der speicher für das char array wird zB nicht automatisch freigegeben das heißt man muss das selbst erldigen.
    Aber viele wissen nicht einmal, dass jedesmal wenn du iwo "bla" schreibst eig nen char array erstellt wird.

    void foo()
    {
      const char tmp[] = "bla";
    }
    

    erzeugt also ein speicherleck? ich glaube nicht...

    um auf deine frage zu antworten, ob man std::string zusammen mit int, char, ... dem leser "bekannt" machen sollte: kann man - würde ich als autor vrmtl auch tun.
    kapitel datentypen oder so und dann fängt man halt an:
    ganzzahlen: int
    gleitkommazahlen: float
    _einzelne_ zeichen: char
    zeichenketten("strings"): std::string (erfordert #include <string>)

    einziges problem ist hier halt, dass man namespaces und includes noch gar nicht wirklich kennt.
    stroustrup macht es glaube in seinem (neueren) buch so, dass er ein file hat, was man immer includiert(darin werden sämtliche stl-header included und der namespace std im globalen ausgeleert) und dann kann er einfach schreiben:
    zeichenketten: string.

    C ist Basis von C++

    es geht nicht um die syntax. es sind die versch. paradigmen der sprachen

    Es ist in einigen Situationen sogar erforderlich mit C Strings zu arbeiten.
    Das betrifft insbesondere in C geschriebene Schnittstellen, wie der WinAPI.

    hatten wir bereits: std::string::c_str
    und du willst mir doch nicht erzählen, dass man als anfänger zu allererst die winapi-fkt nutzen muss o.ä.

    Ja das Argument mit der Zeit ist natürlich etwas schwach

    bleiben also noch deine anderen vielen argumente:

    • nichts

    (wenn der zeit-faktor natürlich eine rolle spielt, dann bring doch mal ein bsp. für so etwas.)

    Und das mit == geht natürlich auch nicht. Aber wozu gibts strcmp. Wobei das natürlich wieder umständlicher ist, als bei std::string, wo der Operator schon schön überladen wurde

    ja - es gibt eben wieder irgendwo eine funktion, die das kann - aber es ist nicht intuitiv. und noch immer einer der beliebtesten anfängerfehler.

    std::copy(s3.rbegin(), s3.rend(), std::ostream_iterator<char>(std::cout, ""));
    das nem anfänger zu präsentieren finde ich auch ein wenig.. naja - optimistisch 😉

    bb


  • Mod

    Felixxx schrieb:

    Das sehe ich falsch ? Was sehe ich falsch ?

    Das Speicherloch.

    Felixxx schrieb:

    Naja,
    der speicher für das char array wird zB nicht automatisch freigegeben das heißt man muss das selbst erldigen.

    Umgekehrt wird ein Schuh daraus: Speicher von std::string wird automatisch freigegeben, bei char-Arrays nur wenn man statische benutzt. Üblicherweise tut man dies aber nicht. Benutzt man dynamische Arrays (und dies ist der Normalfall) muss man wie Hölle aufpassen, diese wieder freizugeben. Dies geht sogar so weit, dass man seinen Programmierstil entsprechend anpassen muss - nicht unbedingt zum Besseren. Und richtig lustig wird's mit Exceptions.

    Aber viele wissen nicht einmal, dass jedesmal wenn du iwo "bla" schreibst eig nen char array erstellt wird.

    Das ist ja auch falsch. Das "Bla" steht dann irgendwo im Datensegment vom Programm. Technisch gesehen ist es ein C-String, aber wo wäre dieses Wissen von irgendeiner Bedeutung?



  • ,,,, schrieb:

    std::copy(s3.rbegin(), s3.rend(), std::ostream_iterator<char>(std::cout,
    

    Das gefällt mir nicht.

    ,,,, schrieb:

    Die Frage die du dir danach stellen solltest: Sind C Strings den Aufwand wert?

    Ja. Da werde ich eine strrev-Funktion schon finden oder im Zweifelsfall ergoogeln oder in 2 Minuten selber schreiben.

    Aber gibt's sowas Tolles nicht auch in C++?

    Mir widerstrebt es, "den string rückwärts auszugeben" statt "den string umzudrehen und dann auszugeben".

    Ich kenne natürlich die Fälle, wo man "rückwärts ausgeben" braucht.



  • #include <iostream>
    
    using namespace std; // Das Gönn ich mir :D 
    
    int main() {
    cout<<"Lets go ..."<<endl;
    // JA , hier wirds auch wieder kritik geben ...
    char carray1[50],carray2[50],carray3[50],addedArray[160];
    cout<<"Carray 1 : ";
    cin.getline(carray1,sizeof(carray1) );
    cout<<"Carry 2 : ";
    cin.getline(carray2,sizeof(carray2) );
    cout<<"Carray 3 : ";
    cin.getline(carray3,sizeof(carray3) );
    strcpy(addedArray,carray1);
    strcat(addedArray,carray2);
    strcat(addedarray,carray3);
    cout<<"Added Array: ";
    for(int i = strlen(addedArray); i>=0; i--)
    cout<<addedArray[i];
    
    cout<<endl;
    system("pause"); // Meintwegen auch cin.get();
    return 0;
    }
    

    Joa, schon etwas umständlicher. Auch feste Grössen required. ( Natürlich nicht unbedingt aber wäre bisl weiterer Aufwand )

    Strev() ? Nicht ergoogled 😛 Wollte aber jetzt auch nicht extra nach was Sinvollem googeln ...
    Hab den C-String auch nicht zwischengespeichert sondern nur ausgegeben. Anderes wars aber auch nicht verlangt ! 😃



  • das geht viel schöner:

    #include <iostream>
    #include <iterator>
    #include <algorithm>
    
    int main()
    {
      const int max = 255;
      char s[max];
      int len = 0;
      std::cout << "S1: ";
      std::cin.getline(s, max);
      len += std::cin.gcount();
    
      std::cout << "S2: ";
      std::cin.getline(s+len, max-len);
      len += std::cin.gcount();
    
      std::cout << "S3: ";
      std::reverse_copy(s, s+len, std::ostream_iterator<char>(std::cout, ""));
    
      return 0;
    }
    


  • Trotzdem hast du das sehr schön gemacht. Vorallem die Tatsache, dass es keinen Überlauf geben kann beeindruckt mich durchaus. Ich hätte das jetzt anders erwartet. 😉

    Die fixen Größen sind natürlich nicht unbedingt realistisch. Denn man weiß nicht immer, wie groß die zu erwartenen Daten sind und will diese auch nicht einschränken. Entsprechend müsstest du dann mit dynamischem Speicher hantieren und dann wird im Zusammenhang mit C Strings so richtig ekelig.

    Fazit: Es ist gut, wenn man sich mit C Strings auskennt, aber dann wird man auch wissen, dass sie gefährlich sein können und entsprechend auf std::string umschwenken.


Anmelden zum Antworten