Array, Pointer, Übergabe Klappt nicht...



  • Hallo...
    Habe hier ein kleines Problem. 😉

    Ziel der "Aufgabe" ist es, alle Elemente <= pivot kommen ins linke Feld,
    alle > pivot ins rechte.

    Das ganze soll mit Pointern gemacht werden.

    int f[N];
        int liF[N];
        int reF[N] = {0};
        int n = N;
        srand(time(NULL));
        int pivot = rand() % 100;
        int anzli = 0;
        int anzre = 0;
    
        ----------------------------------
    
        printf("urspruengliches Feld:\n");
        printArray(f,n); //ausgabe passt
    
        printf("\nPivot: %d\n",pivot); //geht auch
    
        divide(f,n,liF,reF,pivot, &anzli, &anzre); 
        //irgendwie werden &anzli, &anzre nicht verändert.
        printf("\nanzli: %d",anzli); //Ausgabe: 0
        printf("\nanzre: %d",anzre); //Ausgabe: 0
        printArray(liF,anzli); //nichts
    
        printArray(reF,anzre); //nichts
    }
    void printArray(int *feld, int anzElemente)
    {
        int *pf = feld;
        for(pf; pf < feld+anzElemente; pf++ )
        {
            printf("%4d",*pf);
        }
    }
    void divide(int *feld, int n, int *lifeld, int *refeld, int pivot, int *anzli, int *anzre)
    {
        int *pf = feld;
        int *pfli = lifeld;
        int *pfre = refeld;
        int wert = 0;
        for(pf; pf < feld+n; pf++)
        {
            wert = *pf;
            if(wert <= pivot)
            {
                *pfli = wert;
                pfli++;
                *anzli++;
            }
            else
            {
                *pfre = wert;
                 pfre++;
                *anzre++;
            }
        }
    }
    

    Bitte helft mir, ich finde den Fehler einfach nicht 😞



  • //Edit

    int f[N];
        int liF[N];
        int reF[N];
    

    zu beginn 😉


  • Mod

    Hättest du vielleicht auch so etwas wie eine Fehlerbeschreibung?

    Falls das mal später Quicksort werden soll, bist du gerade eher auf dem Holzweg. Guck dir auf Wikipedia nochmal an, wie das geht.

    Hier noch etwas, das deinen Code an vielen Stellen deutlich besser lesbar macht:

    int *pf = feld;
    for(pf; pf < feld+anzElemente; pf++ )
    {
       printf("%4d",*pf);
    }
    // wird zu
    int i;
    for(i = 0; i < anzElemente; ++i)
    {
      printf("%4d", feld[i]);
    }
    

    Weiterhin solltest du sowohl ungarische Notation (d.h. Datentypkürzel am Anfang des Variablennamens) als auch kryptische Abkürzungen (pfli, pfre) vermeiden. Wenn du sprechende Namen benutzt, dann brauchst du auch keine UN mehr. Code wird deutlich häufiger gelesen als geschrieben, da lohnt sich der kleine Mehraufwand beim Tippen.
    Die meisten Variablennamen bei dir sind schon ok, aber gerade an den schwierigen Stellen (z.B Zeile 35-55) wird's unleserlich.



  • SeppJ schrieb:

    Hättest du vielleicht auch so etwas wie eine Fehlerbeschreibung?

    Falls das mal später Quicksort werden soll, bist du gerade eher auf dem Holzweg. Guck dir auf Wikipedia nochmal an, wie das geht.

    Hier noch etwas, das deinen Code an vielen Stellen deutlich besser lesbar macht:

    int *pf = feld;
    for(pf; pf < feld+anzElemente; pf++ )
    {
       printf("%4d",*pf);
    }
    // wird zu
    int i;
    for(i = 0; i < anzElemente; ++i)
    {
      printf("%4d", feld[i]);
    }
    

    Weiterhin solltest du sowohl ungarische Notation (d.h. Datentypkürzel am Anfang des Variablennamens) als auch kryptische Abkürzungen (pfli, pfre) vermeiden. Wenn du sprechende Namen benutzt, dann brauchst du auch keine UN mehr. Code wird deutlich häufiger gelesen als geschrieben, da lohnt sich der kleine Mehraufwand beim Tippen.
    Die meisten Variablennamen bei dir sind schon ok, aber gerade an den schwierigen Stellen (z.B Zeile 35-55) wird's unleserlich.

    Hallo SeppJ!

    Zu

    int *pf = feld;
    for(pf; pf < feld+anzElemente; pf++ )
    {
       printf("%4d",*pf);
    }
    // wird zu
    int i;
    for(i = 0; i < anzElemente; ++i)
    {
      printf("%4d", feld[i]);
    }
    

    Unsere Lehrerin verlangt aber, dass wir mit Pointern arbeiten sollen. Ich weiß, dass das natürlich viel einfacher geht 😉 (ist halt der Teststoff)

    Die Angabe:

    http://www.imagebanana.com/view/qb6lme15/Unbenannt.PNG
    

    Das einzige Problem ist, dass beim Aufruf von

    divide(f,n,liF,reF,pivot, &anzli, &anzre);
    
    void divide(int *feld, int n, int *lifeld, int *refeld, int pivot, int *anzli, int *anzre)
    

    anzli und anzre nicht verändert werden. Deren Wert bleibt bei 0, somit findet keine Ausgabe statt.

    Ich bin dir für jede Hilfe dankbar! 🙂

    C... ich hasse C verdammt! JAVA ist viel besser 😃


  • Mod

    iN3verM1nd schrieb:

    Unsere Lehrerin verlangt aber, dass wir mit Pointern arbeiten sollen. Ich weiß, dass das natürlich viel einfacher geht 😉 (ist halt der Teststoff)

    Sicher, dass du das richtig verstanden hast? Das ist ziemlicher Schwachsinn, das so zu machen. Wäre aber auch nicht der erste ahnungslose C-Lehrer, daher will ich nicht ausschließen, dass das wirklich so verlangt ist.

    Aber meine Variante benutzt auch Pointer, man sieht es nur nicht so deutlich (und das ist auch gut so!).

    Das einzige Problem ist, dass beim Aufruf von

    divide(f,n,liF,reF,pivot, &anzli, &anzre);
    
    void divide(int *feld, int n, int *lifeld, int *refeld, int pivot, int *anzli, int *anzre)
    

    anzli und anzre nicht verändert werden. Deren Wert bleibt bei 0, somit findet keine Ausgabe statt.

    Der Operator ++ (Postfix) bindet stärker als * .
    http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence



  • SeppJ schrieb:

    iN3verM1nd schrieb:

    Unsere Lehrerin verlangt aber, dass wir mit Pointern arbeiten sollen. Ich weiß, dass das natürlich viel einfacher geht 😉 (ist halt der Teststoff)

    Sicher, dass du das richtig verstanden hast? Das ist ziemlicher Schwachsinn, das so zu machen. Wäre aber auch nicht der erste ahnungslose C-Lehrer, daher will ich nicht ausschließen, dass das wirklich so verlangt ist.
    Ja

    Aber meine Variante benutzt auch Pointer, man sieht es nur nicht so deutlich (und das ist auch gut so!).

    Der Operator ++ (Postfix) bindet stärker als * .
    http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence

    Okay.
    Nur ich verstehe nicht, wie ich das jetzt codieren soll?

    if(wert <= pivot)
     {
                *pfli = wert;
                pfli++;
                *anzli++;
     }
    

    Danke..


  • Mod

    Zum Beispiel mit Klammern.



  • Mooooooment ..
    PointerARITHMETIK heißt nur, dass statt mit array[i] mit *(array+i) gearbeitet wird. Diese beiden Ausdrücke sind identisch.

    Aber es heißt nicht, dass ausschließlich die Kurzschreibweisen ++ und -- verwendet werden müssen!
    array++ ist gleichbedeutend zu array=array+1. Damit überschreibst du jedesmal deine Arraystartadresse. Wenn möglich sollte man sich die Ursprungsadresse merken!



  • SeppJ schrieb:

    Zum Beispiel mit Klammern.

    (*anzre)++;
    

    😃
    Danke



  • ...



  • Swordfish schrieb:

    @Lymogry: Ich weiß jetzt zwar nicht genau, was du nicht verstehst, aber sicherheitshalber: Ein Array ist kein Pointer. Ein Pointer ist kein Array.

    Wo läufst du im Speicher lang wenn du Pointer+i oder Pointer++ rechnest? Wie würdest du das nennen, wenn du es nicht Array nennen willst?



  • ...


  • Mod

    Lymogry schrieb:

    Wo läufst du im Speicher lang wenn du Pointer+i oder Pointer++ rechnest? Wie würdest du das nennen, wenn du es nicht Array nennen willst?

    Du läufst (hier) mit deinem Pointer über das Array. Aber deine Beine sind nicht die Straße über die sie laufen.

    Hehe, die Analogie funktioniert gut 🙂 . Ein paar weitere:
    Deine Beine können auch über andere Straßen gehen.
    Eine Straße bleibt immer wo sie ist.
    Deine Beine bleiben immer an dir, aber sie können woanders hinlaufen.
    Deine Beine können auch über etwas anders als eine Straße laufen.
    Eine Straße ist auch mal zu Ende. Manchmal kann man trotzdem weiterlaufen. Manchmal fällt man dabei aber auch auf die Schnauze.



  • Ein Array ist immernoch eine im Speicher direkt aufeinander folgende Menge von Variablen vom gleichen Typ und gleicher Größe.
    Wenn ich diesen Speicher langlaufe nenn ich das Pointerarithmetik.
    Will ich den Speicherblock nennen, nenn ich ihn Array.

    Du machst hier Folgendes: 😉

    char * foo = malloc( 10 );
    char * bar = foo;
    
    bar += 3;
    bar = bar - 1;
    bar = &bar[ 1 ];
    *bar = 47;
    

    Du nimmst dir ein Band foo von 0 bis 9. Und setzt deinen Zeiger bar auf das 0-te Element. (Das tut ein Array auch)
    Dann gehst du mit deinem Zeiger auf das 3. Element. Dann gehst du zurück auf das 2. Element. Dann springst du per Arrayaufruf(!) auf die nächste Stelle von bar und speicherst den Wert 47 ab.
    Eigentlich hast du also gar nichts gemacht, außer foo[3]=47 zu setzen. 😉
    Aber Achtung: bar[3] hat eine ganz andere Speicheradresse. Das meine ich damit, dass man sich den Anfang lieber merken sollte. Hast du also intuitiv foo in Ruhe gelassen oder war das Absicht?

    Ein Array ist ein reservierter Speicherblock mit einem Pointer auf das 0-Element.
    Ein Arrayelement mit *(array+i) aufzurufen ist Pointerarithmetik.

    Eine Turingmaschine, und darauf bauen alle modernen Sprachen auf, kann NUR auf einem Band laufen. Das Fundamentalste, was man also machen kann, ist per Pointerarithmetik im Speicher zu laufen und die Werte per + oder - zu verändern.
    Das ist wohl der didaktische Gehalt hinter dieser Aufgabe. 😉

    (die ganzen Edits resultieren aus der späten Stunde. Aber jetzt sollte es wohl stimmen. Wenn nichts, merk ichs morgen auch noch ... 😉 )



  • ...



  • Swordfish, ich rate einfach mal:

    Du hast Informatik studiert und warst in Theoretischer Informatik der Beste? 😃

    PS: Kritische Fragen mit "Wurst" und "Wayne" abzuschmettern ist auch sehr professionell...



  • ...



  • Swordfish du bist der Größte, Klügste und Beste 🤡



  • ...



  • Lymogry schrieb:

    ... auf einem Band laufen.

    sind wir hier im fitnessstudio beim joggen
    oda watt


Log in to reply