String vs. char* vs. const char*



  • Hi,

    ich steh noch ziemlich am Beginn von C++. Die meisten Sorgen bereiten mir im Moment Strings und char*. Einerseits ist mir noch nicht ganz klar, wann ich was benutzen soll, andererseits sind es die Konvertierungen. Ich könnte jetzt noch einige Dinge aufzählen, aber ich will ja eure Geduld nicht überstrapazieren, daher EIN;) konkretes Problem:

    Ich habe eine Funktion mit einem string Parameter. Wenn ich diesen Parameter in der Funktion in einen const char* mittel c_str() umwandle enthälte er nur das erste Zeichen. Wenn ich aber in der Funktion dem Parameter einen Wert zuweise funktioniert es.

    Ich glaube mit Code ist es ein wenig verständlicher:

    void foo(string input)
    {
       cout << input << endl;   // String ist gefuellt
    
       const char* bar = input.c_str();
    
       cout << bar << endl;      // Nur das 1.Zeichen :( ?!?
    }
    

    Wenn ichs aber so versuche, funktioniert es:

    void foo(string input)
    {
       input = "blablab";
    
       const char* bar = input.c_str();
    
       cout << bar << endl;      // String ist gefüllt
    }
    

    Hat das was mit CallbyValue und CallbyReference zu tun? Bzw. wie bringe ich die erste Version zum Laufen?

    Bitte helft mir :)!

    mfg,
    soad



  • Du bist hier im C++/CLI-Forum, da sollte dir eigentlich die String-Klasse aus dem .NET-Framework zur Verfügung stehen.

    Wenn du hier nur fälschlicherweise gelandet bist und eigetnlich nach C++ wolltest folgende Antwort: Verwende einfach immer und überall std::string am Beginn - kann alles, du verwendest es ganz normal und fertig 🙂

    Nein, dass der leer ist kann ich jetzt nicht nachvollziehen. Sollte nicht der Fall sein.

    Nein, mit Call-By-Value/Call-By-Ref hat das nichts zu tun. Du verwendest hier für die string-Übergabe zwar tatsächlich ein sehr langsames und unnötiges Call-By-Value, allerdings hat std::string einen ordentlichen Kopierkonstruktor (Begriff wirst du später erlernen) und das funktioniert.

    MfG SideWinder



  • Ups, bin wirklich im falschen Forum 🙄.

    Wie gesagt, kämpfe noch ziemlich mit strings und char* und weiß nicht genau, wann man was verwenden soll, aber sag mir bitte, warum das unnötig und langsam ist. Wie macht man es richtig?

    mfg,
    soad



  • Wenn du einen String via Call-By-Value, also via:

    void func (std::string str)
    {
    }
    

    übergibst, wird der komplette Originalstring in den neuen String "str" kopiert (und das dauert). Besser bei größeren Objekten also Call-By-Ref verwenden:

    void func (std::string& str)
    {
    }
    

    Jetzt wird der String nicht mehr kopiert. Er bekommt nur innerhalb von func() den neuen Aliasnamen "str". Allerdings würden sich jetzt auch alle Änderungen auf den Original-String auswirken - wird ja nicht mit einer Kopie gearbeitet. Um das zu verhindern kann man Änderungen verbieten:

    void func (const std::string& str)
    {
    }
    

    Dank std::string benötigst du als Anfänger erstmal gar kein Wissen rund um char*, etc. Dir wird dann im Kapitel über Arrays ein Lichtlein aufgehen was ein String in C früher war und immer noch sein kann - nichts mehr als ein Array von Zeichen.

    MfG SideWinder



  • Dieser Thread wurde von Moderator/in Jochen Kalmbach aus dem Forum C++/CLI mit .NET in das Forum C++ verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • ok, danke!

    Zu meinem "Problem": der char* ist nicht leer, sondern enthält nur das erste Zeichen.

    Einen String übergebe ich eigentlich nur, weil ich zeilenweise mittels getline() einlese, oder könnte man das auch mit char* einfach lösen?

    mfg,
    soad



  • soad schrieb:

    ...könnte man das auch mit char* einfach lösen?

    mfg,
    soad

    lösen: Ja
    einfach: Nein

    Einfacheres als string findest Du nicht. 😃

    Gruß,

    Simon2.



  • void foo(string input)
    {
       cout << input << endl;   // String ist gefuellt
    
       const char* bar = input.c_str();
    
       cout << bar << endl;      // Nur das 1.Zeichen :( ?!?
    }
    

    es hat bi mir funktioniert



  • const char* gewinnt



  • So da sich kein anderer erbarmt hir Mal die Lösung für dein Problem. Ich hatte ein ähnliches, wodurch ich in diesem Fall Abstand von c_str() genommen habe:

    void foo(std::string cInput)
    {
        std::cout <<cInput<<" dies ist der \"string\"<<"\n";
        char *cBuffer=new char[cInput.length()];
        strcpy(cBuffer,cInput.c_str());
        std::cout <<cBuffer<<" dies ist der \"char*\"<<"\n";
    }
    

    Müsste eigentlich soweit funktionieren. Probier es aus.



  • netrobot schrieb:

    void foo(string input)
    {
       cout << input << endl;   // String ist gefuellt
       
       const char* bar = input.c_str();
    		
       cout << bar << endl;      // Nur das 1.Zeichen :( ?!?
    }
    

    es hat bi mir funktioniert

    Das Problem war, dass ich zuvor noch strtok() verwendet habe, ganz nachvollziehen kann ich es zwar noch nicht, aber ich hab es jetzt zumindestens (etwas unschön) gelöst ;).

    Kevinus schrieb:

    So da sich kein anderer erbarmt hir Mal die Lösung für dein Problem. Ich hatte ein ähnliches, wodurch ich in diesem Fall Abstand von c_str() genommen habe:

    void foo(std::string cInput)
    {
        std::cout <<cInput<<" dies ist der \"string\"<<"\n";
        char *cBuffer=new char[cInput.length()];
        strcpy(cBuffer,cInput.c_str());
        std::cout <<cBuffer<<" dies ist der \"char*\"<<"\n";
    }
    

    Müsste eigentlich soweit funktionieren. Probier es aus.

    Danke, schaut eigentlich jetzt eh nicht so kompliziert aus und es funkt 👍!



  • soad schrieb:

    netrobot schrieb:

    void foo(string input)
    {
       cout << input << endl;   // String ist gefuellt
       
       const char* bar = input.c_str();
    		
       cout << bar << endl;      // Nur das 1.Zeichen :( ?!?
    }
    

    es hat bi mir funktioniert

    Das Problem war, dass ich zuvor noch strtok() verwendet habe, ganz nachvollziehen kann ich es zwar noch nicht, ...

    Das mit dem strtok() ist die wesentliche Information dabei.
    Gemäß Schnittstelle garantiert sttok() nicht, dass es nicht doch versucht, den String, den es "tokenized" zu verändern.
    c_str() garantiert aber nur das erwartete ergebnis, solange der String unverändert bleibt ... deswegen gibt er auch einen const char* zurück (und nicht einen char* ).
    Der von Kevinus gezeigte Weg ist kein "Hack", sondern der kanonische Weg, zwischen einem String und einem veränderbaren char-Buffer zu vermitteln: Kopieren eben.
    (Allerdings ht er einen kleinen aber typischen Fehler drin - derseleb unterläuft mir auch immer:

    Kevinus schrieb:

    ...
        char *cBuffer=new char[cInput.length()+1]; // Ein Zeichen für "Nullbyte"
    

    ...

    Außerdem sollte der Speicher mit delete[] nach Gebrauch wieder freigegeben werden - die new/copy/delete-Kiste ist ein gutes Beispiel dafür, warum man besser string in seinen SChnittstellen verwenden sollte 😃 )

    Ist nicht besonders erstaunlich eigentlich, weil auch niemand auf die Idee käme, andere Typen würden eine "kopiefreie Konvertierung" überleben:

    void quadriere(int*);
    
    int main() {
       char s[] = "123";
       quadriere((int*) s); // wer erwartet, dass das klappt ?
    ...
    

    Ebensowenig ist das mit string->char* erstaunlich - es ist eher erstaunlich, dass es überhaupt bei einigen wenigen Typen funktioniert (ich wäre aber immer sehr skeptisch, ob das gutes Design ist).

    Gruß,

    Simon2.


Log in to reply