Dynamische Felder in Funktionen per zeiger an andere Funktionen übergeben



  • Hallo
    Ich bin neu im C++ Geschäft und verzweifle gerade an einer Studienaufgabe.
    Ich soll in einer Funktion ein dynamsiches Feld erzeugen und dieses Feld mit "Zeiger auf Zeiger ", übergeben. Das Land der Zeiger ist "wundervoll" für Neulinge wie mich aber es nutze ja alles nichts :). habe mir auch schon zahlreiche Webseiten dazu angelesen aber so wirklch verstanden habe ich es anscheinend nicht. Ich habe folgendes probiert:

    #include<iostream>
    
    using namespace std;
    
    // Feld erzeugen mit Zeiger auf Zeiger //
    
    void feld_erzeugen (int **xy, int n)
    {
    
     xy = new int* [n];
     srand (time(NULL));
     for (int i=0;i<n;i++)
    *(xy+i)=rand()%100
    
      for (int i=0;i<n;i++)
             {if (!(i%10))
                 cout<<endl;
              cout.width(4);
            cout<< *(xy+i);
    }
    // Feld ausgeben mit Zeiger auf Zeiger //
    
    void feld_ausgeben(int **xy, int n)
    {
         for (int i=0;i<n;i++)
             {if (!(i%10))
                 cout<<endl;
              cout.width(4);
              cout<< *(xy+i);          
             }     
    }
    
    int main () 
    {
      int *zeiger=0;    
      int  m=0;
    
      cout<<"Bitte groesse des Feldes eingeben"<<endl;
      cin>>m;
      feld_erzeugen (&zeiger,m);
      feld_ausgeben (&zeiger,m);  
     return 0;   
    }
    

    Meine Fragen: 1. Ist die Art wie ich das verusche überhaupt korrekt?
    und 2. Wenn ja wo liegt der Fehler? ist es vll Syntax bedingt ?.

    Vielen Dank schonmal für eure Hilfe. Ich warte gespannt .

    Gruß Cid



  • Dein Schnippsel mit meinen Kommentaren:

    cidburner schrieb:

    void feld_erzeugen (int **xy, int n)
    {
      xy = new int* [n];     // Erzeugt ein dyn. Array aus Zeigern
                             // --> nicht das, was Du willst
      srand (time(NULL));
      for (int i=0;i<n;i++)
         *(xy+i)=rand()%100; // *(xy+i) ist dasselbe wie xy[i]
      ...                    // aber xy[i] referenziert einen Zeiger auf int
    

    Ich glaube, Du wolltest so etwas haben:

    void feld_erzeugen (int **xy, int n)
    {
      assert(xy != 0);
      *xy = new int [n];     // Erzeugt ein dyn. Array aus ints
                             // und speichert den Zeiger in *xy
      srand (time(NULL));
      for (int i=0;i<n;i++)
        (*xy)[i] = rand()%100;
      ...
    

    Mit einer lokalen Referenz ist das vielleicht noch einfacher:

    void feld_erzeugen (int **xy, int n)
    {
      assert(xy != 0);
      int* & izref = *xy;
      izref = new int [n];   // Erzeugt ein dyn. Array aus ints
                             // und speichert den Zeiger in izref
      srand (time(NULL));
      for (int i=0;i<n;i++)
        izref[i] = rand()%100;
      ...
    

    wobei "izref" für "int-zeiger-referenz" steht -- eine Referenz auf einen Zeiger auf int.



  • Super schick , es läuft , es läuft, Dickes Danke

    Nun noch damit ich das ganze auch verstehe

    warum muss ich das so schreiben ?

    *xy = new int [n];

    Auch noch nicht ganz verstanden: Eventuell ne andere Erklärung ?
    //
    *(xy+i) ist dasselbe wie xy[i]
    ... // aber xy[i] referenziert einen Zeiger auf int
    //

    Und zu dem Problem zeiger auf Zeiger, wie es in der Aufgaben Stellung verlangt ist. Bedeutet das ich den einen Zeiger global anlegen muss oder ? . So wie ichs oben gemacht habe, ne andere Möglichkeit gibt es nicht ?. Unser Tutor meinte mal in einer e-mail, etwas von globale Zeiger wären unnötig, was genau er damit meinte ist mir wie gesagt nicht ganz klar, daher frag ich hier nochmal nach.

    gruß Cid



  • cidburner schrieb:

    warum muss ich das so schreiben ?

    *xy = new int [n];

    Weil sonst der geänderte Wert des Zeigers verloren geht. Siehe Call-by-Value (vs. Call-by-Reference. Wobei du kein CbR nimmst, obwohl es das in C++ gibt und hier verständlicher wäre.)

    Und zu dem Problem zeiger auf Zeiger, wie es in der Aufgaben Stellung verlangt ist.

    Wo ist das Problem?

    Bedeutet das ich den einen Zeiger global anlegen muss oder ? . So wie ichs oben gemacht habe, ne andere Möglichkeit gibt es nicht ?.

    global anlegen? wovon sprichst du?

    P.S. zu jedem new[] gehört ein delete[] 😡



  • hm wie gesagt bin neu im c++

    also

    int main ()

    int *zeiger = ; // Ist also nicht global ?? //

    ich habe am ende vom Programm delete [] zeiger; reicht das um das komplette Feld zu löschen ?

    Zeiger auf Zeiger: hat sich geklärt



  • int a; // <-- global
    
    int main() {
      int b; // <-- lokal
    }
    


  • ah ok , danke

    die sache mit speicherfreigabe, ist die ok ?



  • cidburner schrieb:

    warum muss ich das so schreiben ?

    *xy = new int [n];

    Am besten malst Du es Dir mal auf, was wo wie im Speicher steht und von welchem Typ alles ist. Du rufst feld_erzeugen ja mit einem Zeiger auf einen Zeiger auf int auf, damit die Funktion den Zeiger auf int verändern kann. Der Zeiger auf int ist nunmal *xy, xy selbst ist der Zeiger auf Zeiger auf int.

    cidburner schrieb:

    Auch noch nicht ganz verstanden: Eventuell ne andere Erklärung ?
    // *(xy+i) ist dasselbe wie xy[i]
    // aber xy[i] referenziert einen Zeiger auf int

    Zum ersten gibt es nicht viel zu erklären. Z[X] ist einfach eine Akbürzung für *(Z+X) , falls Z von einem "eingebauten" Typ (wie zB ein normaler Zeiger) ist. Da xz ein Zeiger auf Zeiger auf int ist, ist *xy ein Zeiger auf int. Damit ist xy[i] auch ein Zeiger auf int und nichts, in dem Du Ganzzahlen speichern kannst.

    cidburner schrieb:

    Und zu dem Problem zeiger auf Zeiger, wie es in der Aufgaben Stellung verlangt ist. Bedeutet das ich den einen Zeiger global anlegen muss oder ?

    Nö, das hat damit nichts zu tun.

    int main() {
      int   i  = 99;
      int*  z  = 0;
      int** zz = &z;
      * zz = &i;
      **zz += 1;
      cout << b << '\n';
    }
    

    ergibt 100 als Programmausgabe.



  • [quote="krümelkacker"]

    cout << b << '\n';
    

    sollte i statt b sein



  • jo ok , so langsam ergibt das sinn 🙂 , danke nochmal an alle Beteiligten, ich setzt mich heute abend nochmal ran um das ganze nach zu vollziehen, falls ich fragen habe , melde ich mich wieder

    gruß cid


Anmelden zum Antworten