Wie mit *pString uebergebenen Wert in Funktion aendern?



  • So, nachdem meine Gehversuche mit C nicht mehr gar so wackelig ausafallen, beschaeftige ich mich jetzt mal wieder ein wenig mit C++.

    Da klappt es eigentlich auch schon ganz gut, nur mit den Pointern habe ich - wie wohl jeder Anfaenger - noch so meine Probleme. Also habe ich mir zum besseren Verstaendis mal ein voellig sinnloses Stueck Code geschrieben, bei dem natuerlich auch gleich wieder Fragen auftauchen:

    #include <fstream>
    #include <string>
    #include <iostream>
    
    using namespace std;
    
    int test( int *pNumber, char *pZeichen, char *pArray, string *pString ) {
    
        *pNumber = 4712;
        *pZeichen = 'B' ;
    
        //*pArray[0] = 'H';
        //*pString = "Hallo Welt!";
    
        *pString = strdup("Hello World!");
    
        return 0;
    }
    
    int main() {
        int    Number = 4711;
        char   Zeichen = 'A';
        char   Array[] = { 'T','E','S','T' };
        string String = "Hello World!";
    
        int    *pNumber;
        char   *pZeichen;
        char   *pArray;
        string *pString;
    
        pNumber  = &Number;
        pZeichen = &Zeichen;
        pArray   = &Array[0];
        pString  = &String;
    
        cout << "### Hier die urspruenglichen Werte: ###" << endl;
        cout << *pNumber << endl;
        cout << *pZeichen << endl;
        cout << *pArray << endl;
        cout << *pString << endl;
    
        test( pNumber, pZeichen, pArray, pString );
    
        cout << "### Und hier die geaenderten Werte: ###" << endl;
        cout << *pNumber << endl;
    
        cout << *pZeichen << endl;
        cout << *pArray << endl;
        cout << *pString << endl;
    
        return 0;
    }
    

    Also, das mit den Pontern ist mir jetzt doch wesentlich klarer geworden, aber ich habe ein Problem mit den Zeilen 12 und 13: Wie veraendere ich denn unter C++ die Werte fuer Array und String? Bei String habe ich's zwar mit strdup() geschafft, bin mir aber wirklich nicht sicher ob das so der richtige Weg ist. Beim Array habe ich's bisher leider ueberhaupt nicht geschafft.

    Wer kann mir denn da mal ein wenig auf die Spruenge helfen?

    Guenther



  • Bei Zeile 12 ist der * überflüssig - der Index-Zugriff dereferenziert den Zeiger gleich mit. Zeile 13 sollte eigentlich korrekt sein (was sagt denn der Compiler?).



  • CStoll schrieb:

    Bei Zeile 12 ist der * überflüssig - der Index-Zugriff dereferenziert den Zeiger gleich mit. Zeile 13 sollte eigentlich korrekt sein (was sagt denn der Compiler?).

    Zeile 12 klappt ohne * jetzt wunderbar und bei Zeile 13 - sorry - muss ich vorher was uebersehen haben, denn da klappt's jetzt auch bestens.

    Whow, wieder ein Stueck weiter ....

    *D*A*N*K*E*



  • Sorry, eine Frage dazu habe ich noch:

    Macht unter C++ ein "char array[]" ueberhaupt noch Sinn oder ist da "string" allgemein die bessere Alternative?



  • Imho ist 'string' die bessere Alternative (aber sicher gibt's auch ein paar Situationen, in denen char-Arrays ausreichen).

    PS: Übrigens würde ich in C++ eher mit Referenzen arbeiten als mit Zeigern 😉



  • CStoll schrieb:

    Übrigens würde ich in C++ eher mit Referenzen arbeiten als mit Zeigern 😉

    Na, das schau ich mir doch gleich mal an ... 😋



  • Ich habe mich mal mit einer verkuerzten Fassung von dem Source oben an der Verwendung von Referenzen statt Pointern versucht, leider nicht sonderlich erfolgreich .... 😕

    #include <fstream>
    #include <string>
    #include <iostream>
    
    using namespace std;
    
    int test( int rNumber ) {
    
        rNumber = 48;
    
        return 0;
    }
    
    int main() {
        int Number   = 47;
        int &rNumber = Number;
    
        test( rNumber );
    
        // Hier sollte jetzt eigentlich eine 48 ausgegeben werden, tut's aber nicht ...
        cout << Number << endl;
    
        return 0;
    }
    

    Schaetze mal, ich habe da irgendwo was grundlegend missverstanden, denn statt der 48 aus der Funktion hat Number immer noch den Wert 47?

    Aber vielleicht sollte ich auch einfach nur mal 'ne Pause einlegen ... 😉

    Guenther



  • =>

    // ...
    int test( int& rNumber ) {
    // ...
    
    int main() {
        int Number   = 47;
    
        test( Number );
    
        // Hier sollte jetzt eigentlich eine 48 ausgegeben werden, tut's aber nicht ...
    

    Die Funktion (= Das "Aufgerufene") braucht eine Referenz und nicht der Aufrufer.

    Der Aufrufer braucht auch nicht extra "Übergabevariablen" zu definieren (das sind die Funktionsparameter schon selbst) ... weswegen sich Dein "Pointerbeispiel" auch verkürzen lässt:

    ...
    int main() {
        int    Number = 4711;
        char   Zeichen = 'A';
        char   Array[] = { 'T','E','S','T' }; 
        // oder : char   Array[] = "TEST";
        string String = "Hello World!";
    
        test( &Number, &Zeichen, Array, &String ); 
       // char[] wird automatisch zum char* beim Funktionsaufruf
    
        cout << "### Und hier die geaenderten Werte: ###" << endl;
        cout << Number << endl;
    
        cout << Zeichen << endl;
        cout << Array << endl;
        cout << String << endl;
    
        return 0;
    }
    

    Ist doch schon übersichtlicher, oder ? 😃

    Gruß,

    Simon2.

    P.S.: Nutz doch bitte wieder die cpp-Tags (statt "code") - das macht das Lesen für uns einfacher. 😃



  • Simon2 schrieb:

    Das "Aufgerufene") braucht eine Referenz und nicht der Aufrufer.

    Du meinst so:

    #include <string>
    #include <iostream>
    
    using namespace std;
    
    int test( int &number ) {
    
        number = 4711;
    
        return 0;
    }
    
    int main() {
        int number   = 47;
    
        test( number );
    
        cout << number << endl;
    
        return 0;
    }
    

    So einfach geht das .....??? 🙄

    Scheint ja fast so, denn zumindest zeigt Zeile 19 nach dem Aufruf der Funktion jetzt den richtigen - geaenderten - Wert an.

    Kann ich das denn glauben? Das waere ja nahezu genial einfach .... 😋

    Ist doch schon übersichtlicher, oder ? 😃

    Ja, in der Tat!!

    P.S.: Nutz doch bitte wieder die cpp-Tags (statt "code") - das macht das Lesen für uns einfacher. 😃

    Sorry, war ein Versehen von mir, werde ich drauf achten.

    Gruss

    Guenther



  • Sorry, hab' noch was vergessen:

    Wie ist das, muss ich in dem vorgenannten Beispiel noch irgendwie den Speicherplatz wieder freigeben oder geht das automatisch?



  • Um Speichermanagement musst du dich nur kümmern, wenn du ein new bzw. ein new[] in deinem Code nutzt, denn "zu jedem new gehört ein delete und zu jedem new[] ein delete[]" (Einfacher, aber praktischer Merksatz ) 😃



  • gboelter schrieb:

    ...
    So einfach geht das .....??? 🙄

    ...
    Kann ich das denn glauben? Das waere ja nahezu genial einfach .... 😋 ...

    Ja - C++ eben: 😋 🕶 😃

    gboelter schrieb:

    ...

    P.S.: Nutz doch bitte wieder die cpp-Tags (statt "code") - das macht das Lesen für uns einfacher. 😃

    Sorry, war ein Versehen von mir, werde ich drauf achten....

    Kein Problem ! War wirklich nur eine winzige Randbemerkung.

    gboelter schrieb:

    ...
    Wie ist das, muss ich in dem vorgenannten Beispiel noch irgendwie den Speicherplatz wieder freigeben oder geht das automatisch?

    Wie von Kenny schon gesagt: Hier geht's automatisch.
    Seine Merkregel kann ich nur unterstützen 👍 !!

    ... und noch ergänzend anmerken, dass es bereits Konstrukte/Konzepte gibt, die einem selbst bei einem new/new[] ein "manuelles delete/delete[]" automatisiert abnehmen (Stichworte RAII, smart_pointer, ...). Die kommen nicht wirklich "ohne delete/delete[]" aus, "verstecken" es aber vor den Benutzer, damit der nichts mehr falsch machen kann.
    Letztlich gibt es auch Klassen, die komplette dynamisch Speicherverwaltung "hinter den Kulissen" machen (std::string, std::vector, ...).
    Überflüssig, zu sagen, dass man das Alles natürlich auch in seinen Klassen machen kann.

    Gruß,

    Simon2.


Anmelden zum Antworten