String-Funktion



  • Hi allerseits!
    Bin noch etwas neu auf dem C++ gebiet, hab bis jetzt nur PHP programmiert. Die ganzen Typen, Zeiger usw. bei c++ machen mich schon wahnsinnig *g*

    Ich hab folgende simple Frage: Ich übergebe einer Funktion einen String und will in diesem jetzt einen Text speichern (vereinfachte Version jetzt):

    Mein Versuch, das so

    void SetzeString(char* s)
    {
        lstrcpy(s, "abcd");
    }
    
    char* s;
    SetzeString(s);
    

    zu machen, funktioniert nicht.

    Was mache ich falsch?

    Vielen Dank schonmal fürs durchlesen 🙂



  • mach doch mal das l vor strcpy wegg und #include <string.h> nicht vergessen.



  • Bloops schrieb:

    Ich hab folgende simple Frage: Ich übergebe einer Funktion einen String

    Falsch. Du übergibst einen Zeiger auf char. Und die Funktion schreibt dort, wo der Zeiger hinzeigt, den String "abcd" hin. Offensichtlich geht die Funktion von der Annahme aus, dass an der Stelle, wo s hinzeigt, 5 Bytes ("abcd" + abschließendes Nullbyte) oder mehr reserviert sind und bereit stehen, um den String aufzunehmen.

    Der Code, der die Funktion aufruft, mißachtet diese Vorbedingung allerdings, und übergibt einen uninitialisierten Zeiger. Der wird nun nach Lust und Laune irgendwo zufällig in der Weltgeschichte herumzeigen, jedenfalls nirgendwohin, wo 5 beschreibbare Bytes stehen. Also stellen wir das ab:

    char s[5];
    SetzeString(&s[0]); // übergib der Funktion die Adresse des ersten Elements des Arrays
    

    btw gibts in C++ keine lstrcpy-Funktion, aber es gibt eine strcpy-Funktion. Ich hab mal angenommen, dass die das gleiche tun, wenn nicht, entsprechend umdenken :p



  • Ups, ich habe den Aufruf der Funktion ganz übersehen.
    So müsste es auch gehen:

    #include <string.h>
    void SetzeString(char* s) 
    { 
     s = new char[strlen("abcd") +1];    
     strcpy(s, "abcd"); 
    } 
    char* s = "leer";
    SetzeString(s);
    cout << s;
    

    Ne, geht nicht .
    Wieso nicht ? Mein Gott, ich bin echt so doof und bekomme nach >1 Jahr C++ noch nicht mal so was einfaches hin 😞 .



  • Wow, mit nem doppelten Zeiger gehts irgendwie:

    #include <iostream.h>
    #include <string.h>
    void SetzeString(char** s)
    {
    delete[] s;
    *s = new char[strlen("abcd") +1];
    strcpy(*s, "abcd");
    }
    
    int main()
    {
     char* s = "leer";
     SetzeString(&s);
     cout << s;
     cin.get();
     return 0;
    }
    

    Ich kann nur nicht erklären wieso es mit einem einfachen Zeiger nicht auch geht.
    Anscheinend wird der Zeiger bei der Übergabe irgendwie kopiert, obwohl das eigentlich nicht so sein sollte.
    Ein eindeutiger Beweis dafür, dass ich die Zeigerproblematik immer noch nicht richtig verstanden habe.



  • Versuchs mal so:

    #include <iostream>
    #include <string.h>
    
    using namespace std;
    
    void wait()
    {
     cin.clear();
     cin.ignore(cin.rdbuf()->in_avail());
     cin.get();
    }
    
    void SetzeString(char* s)
    {
     s = new char[strlen("abcd") +1];
     strcpy(s, "abcd");
    }
    
    int main()
    {
     char* s;
     SetzeString(s);
     cout << s;
     delete[] s;
     wait();
    }
    

    [EDIT]std::cin korrigiert



  • Was wird das wenn's fertig ist? Kreative Abstürze? Ich glaube nicht, dass das in dem Thread hier was zu suchen hat, das hilft dem Fragesteller wahrscheinlich nicht gerade weiter.



  • Hi,

    jetzt komme ich als dummer Programmierer daher, weiss das es eine Funktion
    'SetzeString' gibt, welche genau das tut was ich suche, weiss aber nicht,
    dass fuer den Zeiger innerhalb der Funktion Speicher reserviert habe.

    Und dann knallt es!

    mfg
    v R



  • fit schrieb:

    Anscheinend wird der Zeiger bei der Übergabe irgendwie kopiert, obwohl das eigentlich nicht so sein sollte.

    auch ein zeiger wird by value uebergeben, oder siehst du irgendwo eine referenz?



  • C Newbie schrieb:

    Versuchs mal so:

    #include <iostream>
    #include <string.h>
    
    using namespace std;
    
    void wait()
    {
     cin.clear();
     std::cin.ignore(std::cin.rdbuf()->in_avail());
     std::cin.get();
    }
    

    es würd mich nun sehr intressieren wozu du :
    1. einmal cin und einmal std::cin schreibst
    2. warum du "using namespace std;" schreibst und dann noch std:: verwendest

    wirkt irgendwie wien Zwiegespaltener Mensch der Namespaces net verstanden hat.



  • Oh man, in einem C++-Forum noch mit C-Funktionen arbeiten... anstatt dem Neuling mal zu zeigen wie man sicherer und einfacher mit std::string arbeiten kann und sollte.



  • Ähm, dieser Mensch hat ein grundsätzliches Verständnisproblem mit Zeigern. Ich glaube nicht, dass man dem abhelfen kann, indem man sagt, befass dich erstmal mit der string-Klasse und frag in einem halben Jahr dieselbe Frage nochmal ...



  • Hi,

    Oh man, in einem C++-Forum noch mit C-Funktionen arbeiten... anstatt dem
    Neuling mal zu zeigen wie man sicherer und einfacher mit std::string arbeiten
    kann und sollte.

    Du hast Recht, wie gut dass du gleich ein Beispiel gebracht hast...

    Hier ein Beispiel:

    void SetzeString(std::string &Str) 
    {     
        Str = "irgendwas";
    }  
    
    std::string MeinString;
    SetzeString(MeinString);
    

    mfg
    v R



  • Shade Of Mine schrieb:

    fit schrieb:

    Anscheinend wird der Zeiger bei der Übergabe irgendwie kopiert, obwohl das eigentlich nicht so sein sollte.

    auch ein zeiger wird by value uebergeben, oder siehst du irgendwo eine referenz?

    Jo, aber der Zeiger müsste doch dann aber trotzdem auf die gleiche Adresse im Speicher zeigen, wieso tut er das aber bei 1) und 2) nicht :

    #include <iostream.h>
    #include <string.h>
    void SetzeString(char* s)
    {
     delete s;
     s = new char[strlen("abcd") +1];
     strcpy(s, "abcd");
     cout << "2) Adresse von s: " << &s <<endl;
    }
    
    int main()
    {
     char* s = "leer";
     cout << "1) Adresse von s: " << &s <<endl;
     SetzeString(s);
     cout << s << endl;
     cin.get();
     return 0;
    }
    

    So funzt es dann wieder:

    void SetzeString(char*& s)
    {
     delete s;
     s = new char[strlen("abcd") +1];
     strcpy(s, "abcd");
     cout << "2) Adresse von s: " << &s <<endl;
    }
    


  • Wow! 😮

    So schnell so viele Antworten! Danke!

    Aber leider hat mir keine so wirklich 100% bis jetzt geholfen. *g*

    Bashar schrieb:

    Ähm, dieser Mensch hat ein grundsätzliches Verständnisproblem mit Zeigern. Ich glaube nicht, dass man dem abhelfen kann, indem man sagt, befass dich erstmal mit der string-Klasse und frag in einem halben Jahr dieselbe Frage nochmal ...

    Genau das habe ich und jetzt ist dieses halbe Jahr rum. 😃

    Mit std::string ist das kein Problem, aber ich will es jetzt OHNE lösen.

    fit schrieb:

    ...
    
     s = new char[strlen("abcd") +1];
    
    ...
    

    An diese Methode hab ich auch schon gedacht, aber dann muss ich ja außerhalb der Funktion wieder delete aufrufen, und gerade das will ich ja umgehen! Ich möchte, dass s nur im Gültigkeitsbereich der die Funktion aufrufenden Routine liegt und nicht auf dem Heap.



  • fit schrieb:

    Shade Of Mine schrieb:

    auch ein zeiger wird by value uebergeben, oder siehst du irgendwo eine referenz?

    Jo, aber der Zeiger müsste doch dann aber trotzdem auf die gleiche Adresse im Speicher zeigen, wieso tut er das aber bei 1) und 2) nicht :

    void SetzeString(char* s)
    {
     delete s;
     s = new char[strlen("abcd") +1];
     strcpy(s, "abcd");
     cout << "2) Adresse von s: " << &s <<endl;
    }
    

    Du weist innerhalb der Funktion an s einen neuen Wert zu (s = new ...). Da s by-value übergeben wird, ändert sich dadurch nur die lokale Kopie von s. Der Pointer ausserhalb der Funktion wird nicht verändert -> Speicherleck.

    Bloops schrieb:

    Aber leider hat mir keine so wirklich 100% bis jetzt geholfen. *g*

    Dann stell nochmal spezifische Fragen. Genug Antworten hast du ja bekommen.



  • Also im Prinzip gehts um folgendes (vielleicht ist das ja mit C++ auch gar nicht möglich...):

    void func1(char *s)
    {
        // Größe des Strings, auf den s zeigt auf n Bytes einstellen
    }
    
    void func2(void)
    {
        char *string;
        func1(char);
        // 1. der String auf den string zeigt, soll nun n Bytes haben
        // 2. in dieser Funktion (func2) soll KEIN new / delete verwendet werden
        // 3. string soll NUR in func2 Gültigkeit haben, danach soll der Speicher wieder freigegeben werden.
    }
    

    Wie muss func1 aussehen, damit func2 so stehen bleiben kann? Geht das überhaupt?



  • ... es funktioniert, man muss nur ausreichend Zeiger verwenden



  • // 1. der String auf den string zeigt, soll nun n Bytes haben
    // 2. in dieser Funktion (func2) soll KEIN new / delete verwendet werden

    Du musst aber new/delete verwenden, wenn string nun n Bytes belegen soll
    So geht es:

    void SetzeString(char*& s)
    {
     delete[] s;
     s = new char[strlen("abcd") +1];
     strcpy(s, "abcd");
    }
    

    // 3. string soll NUR in func2 Gültigkeit haben, danach soll der Speicher wieder freigegeben werden.

    dann halt so:

    void SetzeString(char*& s)
    {
    
     s = new char[strlen("abcd") +1];
     strcpy(s, "abcd");
    //...code...
     delete[] s;
    }
    


  • nein. nicht mit einem einfachen dummen pointer. entweder nimm einen smart pointer oder std::string.


Anmelden zum Antworten