tutorials.de Buch-Aktion 05/2012
Like Tree3Danke
  • 2 Beitrag von sheel
  • 1 Beitrag von sheel
ERLEDIGT
NEIN
ANTWORTEN
8
ZUGRIFFE
578
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    Tomsen1410 Tomsen1410 ist offline Mitglied Silber
    Registriert seit
    Oct 2008
    Beiträge
    75
    Hey,
    ich habe hier eine Lern DVD von video2brain üer C++.
    So jetzt hat hier der nette Herr im Video ein Tutorialvideo gezeigt, das ich nciht ganz verstanden habe
    Nämlich geht es um Pointer.
    Und um das noch zu verschönern, geht es um Pointer auf Pointer...
    Ich weiß nciht wirklich wozu man das braucht und verstehe das Beispiel Programm auch nicht sehr. Vor allem bei der "eintragen" funktion mit dem Pointer auf einen Pointer.
    Wäre sehr nett wenn mir einer das Schritt für Schritt erklären würde. Hier das BspProgramm:


    PHP-Code:
    #include <iostream>
    #include <string>
    using namespace std;

    // Baumstruktur für Sortierung

    struct link_str {
        
    string *pbegriff;
        
    link_str *left;
        
    link_str *right;
    };

    void eintragen(link_str **pstartstring s1)
    // einsortieren an bestehende liste
        
    link_str *pliste;
        
    pliste = *pstart// Startwert 
        // 1. sonderfall
        
    if (pliste == NULL) {
            
    pliste = (link_str *) malloc(sizeof(link_str));
            
    pliste->pbegriff = new string(s1);            
            
    pliste->left NULL;
            
    pliste->right NULL;
            *
    pstart pliste;
            return;
        }
        
    // suchen nach leerem Eintrag
        
    while (pliste != NULL) {
            if (
    s1 <= *(pliste->pbegriff)) { // lexiographic kleiner oder gleich
                
    if (pliste->left != NULL) {
                    
    pliste pliste->left;
                } else {
                    
    pliste->left =  (link_str *) malloc(sizeof(link_str));
                    
    pliste pliste->left;
                    
    pliste->pbegriff = new string(s1);
                    
    pliste->left NULL;
                    
    pliste->right NULL;
                    
    pliste NULL// schleife zueende
                
    }
            } else {
    // lexigraphisch groesser
                
    if (pliste->right != NULL) {
                    
    pliste pliste->right;
                } else {
                    
    pliste->right =  (link_str *) malloc(sizeof(link_str));
                    
    pliste pliste->right;
                    
    pliste->pbegriff = new string(s1);
                    
    pliste->left NULL;
                    
    pliste->right NULL;
                    
    pliste NULL// schleife zueende
                
    }
            }
        } 
    // while 
        // ende
    }

    void ausgabe(link_str *pliste)
    // rekursiv 
        
    if (pliste == NULL) return;
        
    ausgabe(pliste->left);
        
    cout << "Sortiert: " << *( pliste->pbegriff) << endl;
        
    ausgabe(pliste->right);
    }

    void freigeben(link_str *pliste)
    {
        if (
    pliste == NULL) return;
        
    freigeben(pliste->left);
        
    freigeben(pliste->right);
        
    delete pliste->pbegriff;
        
    free(pliste);
    }

    int main()
    {
        
    link_str *pstart NULL
        
    link_str *pliste NULL;
        
    string s1;
        
    // Fuellen der Liste
        
    do {
            
    getline(cin,s1,'\n');
            if (
    s1 != "QUIT") {
                
    eintragen(&pstart,s1);
            }
        } while (
    s1 != "QUIT");

        
    // AUSGABE der Liste
        
    ausgabe(pstart);
        
    // FREIGABE der Liste
        
    freigeben(pstart);
        
    pstart NULL;
        return(
    0);

     

  2. #2
    Avatar von sheel
    sheel sheel ist offline Moderator
    tutorials.de Moderator
    Registriert seit
    Jul 2007
    Beiträge
    4.501
    Hi

    Ein Pointer ist generell einmal eine Speicheradresse.
    Die Speicherplätze im Arbeitsspeicher sind alle durchnummeriert (ganze Zahlen, also 1, 2, 3 usw.)
    die Adresse einer Variable ist dann die Nummer von ihrem "Platz".

    Ein Pointer wie "link_str *pstart" ist daher in Wirklichkeit eine int-Zahl mit einer Adresse.
    Ob es jetzt link_str * oder float * oder... ist entscheidet,
    welche Variablenart an dieser Adresse zu finden ist.
    Der Pointer selbst ist immer ein int (weil die Adress ja immer eine ganze Zahl ist,
    egal ob sie die Adresse iner float-Variable oder sonstwas ist).

    Mit "pstart=..." kann man dem int eine neue Adresse zuweisen,
    mit "*pstart" auf die Variable dieser Adresse dann zugreifen.

    So ein float-Pointer hat drei Möglichkeiten, auf was er zeigen kann:
    a) auf NULL, bedeutet: Zeigt auf keine Variable.
    b) auf eine existierende Variable wie "float abc;", deren Adresse man mit "&abc" bekommt.
    c) oder man besorgt sich mit new eine neue Variable. Damit man auf die auch zugreifen kann
    (da sie nicht wie abc einen eigenen Namen hat), kommt die Adresse in einen Pointer.


    Ein häufiger Grund für Pointer: Wenn man eine Variable an eine Funktion übergibt,
    diese dort geändert wird, und die Änderung auch nach der Funktion noch da sein soll.
    Beim Übergeben wird nämlich eine Kopie der Variable gemacht, nur die wird geändert.
    Wenn die Funktion fertig ist, ist die Kopie wieder weg,
    und das Original hat noch immer den alten Wert.

    Eine Lösung wäre der Returnwert.
    Problem: Geht nur mit einer Variable.
    Was ist, wenn zehn Übergebene geändert werden?

    Bessere Lösung: Man übergibt einen Pointer auf die Variable, also die Adresse (&...).
    Dann wird eine Kopie von der Adresse gamacht. Ein Original-1234 ist als Kopie aber noch immer 1234 und "zeigt" auf die selbe Speicherstelle. Die eine, unkopierte Speicherstelle.


    Warum jetzt Doppelpointer?
    Mit dem Übergeben von Normalpointern erreicht man also, dass Änderungen der Variable
    nicht verloren gehen. In der Funktion besorgt man sich mit new aber erst eine neue Variable.
    Auf einer neuen Adresse. Dh.: Nicht nur die Wertvariable selber, sondern auch die Adresse,
    also der int-Wert vom Pointer wird geändert.
    Deshalb noch eine Ebene weiter: Ein Pointer auf den Pointer,
    damit die neue Adresse nicht nur in der Kopie vom Pointer-int gespeichert wird...

    Gruß
    Bratkartoffel und Tomsen1410 bedanken sich. 
    Netiquette (vA §15) und Nutzungsregeln (vA §4.8) einhalten! Programmcode in Codetags/Codeboxen.
    Sehr gute Beiträge bitte Bewerten (Stern darunter oder "Danke").
    "Funktioniert nicht" ist zu ungenau! Code, Fehlermeldungen, Verhalten des Programms, ...?

  3. #3
    Tomsen1410 Tomsen1410 ist offline Mitglied Silber
    Registriert seit
    Oct 2008
    Beiträge
    75
    Danke schonmal
    Die Grundlagen der Pointer wusste ich schon, aber trotzdem danke
    Möchte nun gerne noch wissen, wozu man in der Funktion einen Pointer auf einen Pointer erzeugte?
     

  4. #4
    Avatar von MSVCplusplus
    MSVCplusplus MSVCplusplus ist offline Mitglied Brokat
    Registriert seit
    Dec 2010
    Ort
    Hessen
    Beiträge
    336
    Also in einer Funktion verwende ich das, um im Funktionskopf einen Pointer zurückzugeben.
    Oder um ein Pointer Array zu übergeben.
    Also quasie so:
    Code cpp:
    1
    2
    3
    4
    5
    
    void blabla(int eingang, int **ausgang)
    {
       int *ausgang;
       ausgang = &eingang;
    }
    Hoffe ich habe nichts falsches gesagt
    MfG
     
    Fehlermeldung bitte!
    Google - Dein Freund und Helfer

  5. #5
    Avatar von Bratkartoffel
    Bratkartoffel Bratkartoffel ist offline gebratene Kartoffel
    tutorials.de Premium-User
    Registriert seit
    Jun 2007
    Ort
    Passau (Niederbayern)
    Beiträge
    1.394
    Hi,

    Zitat Zitat von sheel Beitrag anzeigen
    [...]Der Pointer selbst ist immer ein int (weil die Adress ja immer eine ganze Zahl ist,
    egal ob sie die Adresse iner float-Variable oder sonstwas ist).[...]
    <klugsch...>Ein Pointer ist nicht immer ein int, die Größe ist je nach Architektur unterschiedlich. Es kann also gut sein, dass ein "int" 32 Bit und ein Pointer 64 Bit hat. Quelle: Klick</klugsch...>


    Aber ansonsten eine gute und detaillierte Erklärung des Themas.

    Gruß,
    BK
    Geändert von Bratkartoffel (13.12.11 um 16:10 Uhr)
     
    Über eine gute Bewertung freut sich jeder ;)
    Bitte erledigte Threads als "Erledigt" markieren.

    "Though a program be but three lines long, someday it will have to be maintained.''
    -- Geoffrey James, "The Tao of Programming"

  6. #6
    Avatar von sheel
    sheel sheel ist offline Moderator
    tutorials.de Moderator
    Registriert seit
    Jul 2007
    Beiträge
    4.501
    So, oben den Rest noch dazugeschrieben.
    Die Grundlagen waren nur zum besseren Verstehen

    @Bk: Sicher, ein int kann unterschiedlich groß sein.
    ...
    Geändert von sheel (13.12.11 um 16:11 Uhr) Grund: Teil entfernt, weil ich meinen Text selbst nicht mehr versteh :D
    Tomsen1410 bedankt sich. 
    Netiquette (vA §15) und Nutzungsregeln (vA §4.8) einhalten! Programmcode in Codetags/Codeboxen.
    Sehr gute Beiträge bitte Bewerten (Stern darunter oder "Danke").
    "Funktioniert nicht" ist zu ungenau! Code, Fehlermeldungen, Verhalten des Programms, ...?

  7. #7
    Tomsen1410 Tomsen1410 ist offline Mitglied Silber
    Registriert seit
    Oct 2008
    Beiträge
    75
    Ich hab das mit dem Doppelpointer jz so verstanden, das sman ihn braucht, WEIL er eine Adresse eines Pointers erhält(siehe main).
    Also erställt man so einen neuen Pointer auf dem Pointer in der "main" der auf NULL steht.
    Dann wird der Pointer *pliste mit dem Wert des Doppelpointers versehen.
    Und da dann *pliste = NULL ist (s. main) tritt der Sonderfall ein, -->
    daher wird der Pointer *pliste mit einem beliebigen freien neuen Speicherpunkt versehen, mit der Art von link_str und erhält den Wert des Strings den man angegeben hat.
    Außerdem wird dann der Pointer *pstart mit dem Inhalt oder der Adresse des *plist Pointers versehen (?), weiß nicht genau. Jedenfalls ist dann der Pointer *pstart definiert, welcher auf den Pointer in der main zeigt, der auch *pstart heißt, der jz nciht mehr auf NULL steht.

    Danach geht es denke ich so weiter, dass jenachdem der Eingegebene String "größer" oder "kleiner" als der des Ersten ist. Falls kleiner dann wird ein neues Objekt nach "links" erstellt, bei dem der Pointer *links des ersten Objekts zeigt, danach wird der Pointer *pliste dem neu erstelltem Objekt zugeteilt und es fängt von vorne an....
    PUUH.
    Hoffentlich habe ich das richtig verstanden.
    Falls jemand die Zeit hätte den Schrott hier zu lesen ( ) und auszuwerten, wäre ich sehr dankbar.
     

  8. #8
    Avatar von sheel
    sheel sheel ist offline Moderator
    tutorials.de Moderator
    Registriert seit
    Jul 2007
    Beiträge
    4.501
    Ja, ein**- Pointer ist ein int mit einer Dresse.
    An dieser Adresse findet man wieder wieder ein int mit einer Adresse (*-Pointer).
    An dieser Adresse ist dann eine Variable.
    ...Das kann man auch drei- oder viermal verschachteln,
    wenns lustig ist (macnhmal auch benötigt).


    Das mit dem Wert des Oppelp. in den P.: Hm, nein.
    Am Anfang gibts den *Pointer, wird auf NULL gesetzt: Also zeigt er vorerst auf keine Variable.

    Und dann will man den Pointer auf etwas zeigen lassen.
    Aber nicht auf eine vorhandene Variable, sondern man erzeugt sich mit new eine Neue.
    Dazu würde man zunächst mal keine **Pointer brauchen, ein einfaches
    Code cpp:
    1
    
    p = new ...;
    würde reichen.

    new macht eine neue Variable (die im Code aber keinen Namen hat).
    Man kann während der Programmlaufzeit beliebig viel Variablen mit new erstellen,
    zusätzlich zu den fixen im Code.
    Und mit dem "p=" weist man dem Pointer-int die Adresse der neuen Variable zu.

    Jetzt soll das new-Zeug aber in einer Funktion passieren.
    Falsche Variante:
    Man übergibt den Pointer, der auf nichts zeigt.
    Beim Übergeben wird eine Kopie gemacht, wie immer beim Übergeben.
    Jetzt gibts in der Funktion einen anderen Pointer, der auch auf nichts zeigt,
    so wie der Pointer aus main. Aber es sind verschiedene.
    Dann wird dem Kopiepointer von new die Adresse der neuen Variable gegeben.
    Am Ende der Funktion verschwindet der Kopiepointer mit seiner Adresse wieder.
    Und das Original im main zeigt noch immer auf NULL/Nichts.

    Richtige Variante:
    Man übergibt nicht das Pointer-int, sondern die Adresse vom Pointer-int.
    Diese Adresse wird kopiert.
    Die Kopie "zeigt" aber noch immer auf das selbe Pointerint, das auf nichts zeigt...
    Das selbe Pointerint wie das im main.
    Und die new-Adresse geht nicht verloren.
     
    Netiquette (vA §15) und Nutzungsregeln (vA §4.8) einhalten! Programmcode in Codetags/Codeboxen.
    Sehr gute Beiträge bitte Bewerten (Stern darunter oder "Danke").
    "Funktioniert nicht" ist zu ungenau! Code, Fehlermeldungen, Verhalten des Programms, ...?

  9. #9
    Avatar von saftmeister
    saftmeister saftmeister ist offline Der Saft sei mit dir
    tutorials.de Premium-User
    Registriert seit
    May 2006
    Ort
    There is no place like 127.0.0.1
    Beiträge
    3.516
    Eine Pointer-Variante wurde vergessen: Zeiger auf Funktion. *Wollte auch mal klug******en*
     
    Grüße
    --
    Qualität des Codes wird in WTF's/Min gemessen: Je mehr, desto schlechter der Code ;-)

Ähnliche Themen

  1. [c++] Pointer auf konstanten Pointer-Parameter setzen
    Von digitalFreeman im Forum C/C++
    Antworten: 4
    Letzter Beitrag: 18.02.09, 11:11
  2. Invalid Pointer Addition.. wo is denn da n pointer !
    Von GartenUmgraben im Forum Borland CBuilder und VCL
    Antworten: 3
    Letzter Beitrag: 29.07.06, 16:48
  3. Antworten: 4
    Letzter Beitrag: 07.07.06, 13:34
  4. Antworten: 1
    Letzter Beitrag: 22.12.05, 09:27
  5. Antworten: 6
    Letzter Beitrag: 02.11.03, 21:23

Stichworte