Elemente aus Array entfernen



  • Hallo zusammen,
    leider muss ich gerade für ein Projekt von Java auf C umsteigen und tu mich an einigen Stellen etwas schwer.

    Um die Frage einfach zu machen, poste ich nicht meinen Originalcode sondern ein einfaches Beispiel an dem ich meine Fragen und Probleme erklären kann (daher auch nichtssagende Variablennamen und die Speicherreservierung einfach für Größe 10):

    int *a;
      int i = 0;
      a = (int*) malloc(10 * sizeof(int));
    

    Zwei Fragen:

    1. Einfügen von Elementen in das Array.
    Um Elemente einzufügen habe ich in diesem Bsp die Variable i deklariert die ich jedes mal wenn ich ein Element einfüge inkrementiere um zu wissen an welchem Index das nächste Element eingefügt werden soll.
    Einfache Frage dazu: Macht man das so? (Also ist das vom Stil her korrekt?)

    2. Löschen von Elementen aus dem Array.
    Angenommen ich möchte ein Element aus dem Array löschen. Sagen wir z. B. das an Position 5. Wie mache ich das am besten? Intuitiv würde ich sagen, dass ich irgendwie den Zeiger vom 4 auf das sechste Element biegen muss.... alle nachfolgenden Elemente um eine Position weiter nach vorn zu verrutschen dürfte ja hochgradig ineffizient sein.

    Danke schon mal an alle, die was dazu sagen können.



  • Naja, sagen wir mal so:
    nach dem malloc hast Du Speicher für 10 int - Werte. Einfügen kannst Du da nicht wirklich was, diese 10 Werte sind bereits mit zufällig im Speicher vorhandenen Werten belegt, die Du mit Deinen Werten ersetzen kannst.
    Dazu kannst Du den Speicher mit
    a[0] - a[9] ansprechen.
    Ebensowenig wie Du etwas einfügen kannst, kannst auch etwas löschen, nämlich gar nicht. Du kannst auf die entsprechenden Plätze einen Wert setzen, der Dir anzeigt, dass dieser Platz nicht belegt sein soll, zB -1 falls -1 ansonsten kein gültiger Wert ist ...



  • Du fügst da nichts ein, du überschreibst den Wert vom Feldelement.

    Das kannst du über die Arrayschreibweise oder Zeigerarithmetik machen.

    int *a, *b;
      int i = 0;
      a = malloc(10 * sizeof(int)); 
      a[i] = 2;
    //oder
      *(a+i) = 2;
    //oder
      b = a;
      *b++ = 2;
    

    Wenn du wirklich ein Element aus deinem Speicher raus haben willst, musst du den Rest verschieben.
    Dadurch wird der Speicher aber nicht frei.
    Du hast am Ende des Feldes unbenutzten Speicher.



  • Danke belli und DirkB. Das leuchtet mir ein, ich konnte euren Ausführungen sehr gut folgen.
    Wenn ich also eines der Elemente raushaben möchte (und das ist für diesen Anwendungsfall nötig) muss ich den Rest also verschieben... also die nachfolgenden Elemente jeweils um ein Element nach vorn... denn sonst weiß ich ja nicht, wo ich das nächste Element einfügen kann, bzw. an welchen Positionen jetzt ein Platz frei ist... Also, nur um auf Nummer sicher zu gehen: soweit ich das jetzt verstehe, ist diese Vorgehensweise mit dem Elemente verschieben gar nicht all zu stümperhaft oder? Danke nochmal...



  • Das mit dem verschieben könntest du umgehen, indem du einen Wert als "unbenutzt" definierst. Bei int könnte das INT_MIN oder INT_MAX sein.

    (Bei Temperaturen z.B -300 oder bei der Kelvin-Skala ein negativer Wert)

    Wenn du verschieben willst, kannst du auch memmove() nutzen.



  • Newbie001 schrieb:

    leider muss ich gerade für ein Projekt von Java auf C umsteigen und tu mich an einigen Stellen etwas schwer.

    Verständlich, weil C einfach wesentlich näher am System ist und vom Programmierer andere Vorgehensweisen abverlangt. Für gewöhnlich ist es auch damit verbunden, dass man deutlich mehr von Datenstrukturen und Algorithmen kennt.

    Dafür kann man wesentlich effizienter entwickeln - aber auch mehr Fehler machen.
    Für irgendwelche Anwendungsprogramme auf dem PC ist es deshalb nicht erste Wahl.

    Wenn Du eine Liste brauchst, in die man einfügen oder aus der man löschen können muss, ist (ab einer vernünftigen Dimension!) ein Array nicht mehr der geeignete Datentyp, weil dann das Hin- und Her-Verschieben der anderen Werte "zu teuer" wird. (Sondern ebene eine einfach oder doppelt verzeigerte Liste.)

    Grundsätzlich ist das Holen und Freigeben von Speicherplatz per malloc/free auch nichts, was man für eine Handvoll Bytes machen würde. Und niemals ohne Test, ob der Funktionsaufruf erfolgreich war, und Freigabe des Speichers.

    Ciao, Allesquatsch



  • Newbie001 schrieb:

    Also, nur um auf Nummer sicher zu gehen: soweit ich das jetzt verstehe, ist diese Vorgehensweise mit dem Elemente verschieben gar nicht all zu stümperhaft oder? Danke nochmal...

    Wenn es nicht auf die Reihenfolge der Elemente ankommt, könntest Du einen Zeiger auf das letzte benutzte Element führen, und ein Element, dass nicht mehr benötigt wird, mit dem letzten vertauschen, dann den Zeiger auf das letzte Element dekrementieren. Ist etwas aufwendiger in der Verwaltung, spart aber das Verschieben von vielen Elementen - wobei ich das bei einem Array von 10 ints allerdings nicht schlimm finden würde, bei einem großen Array allerdings kostet das Verschieben möglicherweise viel Zeit, wenn es häufig vorkommt.

    Ja, ansonsten, wie schon erwähnt wurde, muss man evtl. überprüfen, ob nicht eine verkettete Liste die geeignetere Datenstruktur wäre.



  • Newbie001 schrieb:

    von Java auf C umsteigen

    Herb, nicht mal c++?

    Newbie001 schrieb:

    1. Einfügen von Elementen in das Array.
    2. Löschen von Elementen aus dem Array.

    Nun kenne ich den Anwendungsfall nicht, aber es stellt sich die Frage, ob ein Array das optimale Behältnis ist für Deine Daten, wenn es vorwiegend um das dynamische Aufnehmen / Löschen von Daten geht.

    Je nach Zweck ist eine verkettete Liste angesegt, deren Umsetzung Du dann aber in C erst selber entwickeln musst.

    Ciao
    MM


Log in to reply