Zuviel Werbung? - > Hier kostenlos beim SPS-Forum registrieren

Ergebnis 1 bis 8 von 8

Thema: Einfügen / Ändernd von Arrayindexen

  1. #1
    Registriert seit
    16.03.2014
    Beiträge
    358
    Danke
    74
    Erhielt 45 Danke für 38 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Hallo zusammen,
    habe da wieder etwas im Kopf ausgegraben:
    Ich habe ein Array mit z.Bsp. Int-Werten.
    Es hat die Größe von Bsp.: MyArray : array [1..10] of INT;

    Nun folgende Idee:
    Ich benötige manchmal einen "Insert" innerhalb der Reihenfolge und manchmal einen "Delete" in der Reihe.
    Ich würde dann gerne ohne mühsam in einer Schleife alles weiterzuschieben bzw. zusammenzuschieben gerne
    irgendwas mit Adressen und Pointern machen...

    Genaueres Beispiel:
    Myarr[1] = 5
    Myarr[2] = 3
    Myarr[3] = 2
    Myarr[4] = 7

    Nun möchte ich einen "Del" der [2] machen:
    Danach also fogendes erhalten:
    [1] = 5
    [2] = 2
    [3] = 7
    Die "freiwerdenden" erhalten Default, bsp: 0
    Bei einem Insert halt alle einen "Rauf" und der "obere" fliegt raus...
    (Wobei der "Insert" halt wisen muss ab wo "verschoben" werden soll)
    Geht das nicht irgendwie mit Memcopy und / Oder Pointern und Bitschiebeoperationen ?

    Wie immer: Codesys V2.11

    Besten Dank fürs mitgrübeln.

    LG
    Shrimps
    Zitieren Zitieren Einfügen / Ändernd von Arrayindexen  

  2. #2
    Registriert seit
    22.03.2007
    Ort
    Detmold (im Lipperland)
    Beiträge
    11.708
    Danke
    398
    Erhielt 2.397 Danke für 1.997 Beiträge

    Standard

    Hallo,
    da wirst du wohl nicht um vor- bzw. zurückschieben herum kommen.
    Befehle wie MemCopy oder BlockMove mögen es nicht, wenn dich der Quell- und der Zielbereich überlappen - was bei dir ja der Fall ist.
    Eine Andere Alternative wäre, wenn du zusätzlich noch ein Bit-Array (z.B.) in gleicher Größe und hier mit einem TRUE festlegst, welche Einträge aus dem Daten-Array verwendet werden dürfen.
    Oder ... wenn du z.B. nur positive Zahlen in deinem Daten-Array hast dann setz den Index-Wert der nicht zu verwendenden Speicherstelle auf -1. Auch damit signalisierst du dann deinem Programm, das dieser Eintrag nicht verwendet wird - bzw. noch belegt werden kann ...

    Gruß
    Larry

  3. Folgender Benutzer sagt Danke zu Larry Laffer für den nützlichen Beitrag:

    shrimps (09.02.2015)

  4. #3
    Registriert seit
    27.05.2004
    Ort
    Thüringen/Berlin
    Beiträge
    12.218
    Danke
    533
    Erhielt 2.696 Danke für 1.948 Beiträge

    Standard

    Ich würde eine Funktion schreiben, die diese Aufgaben übernimmt. Insert oder Delete an Position X, der Rest wird entsprechend verschoben und aufgefüllt/gelöscht. Es kann pro Vorgang immer nur ein Element gelöscht oder eingeschoben werden. Das Hauptwerk vollbringt dann eine Schleife (wenn die Array nicht zu groß sind).

    Oder: Wenn es denn Memcopy sein soll und das auf sich selbst kopieren problematisch ist, könnte ich mit auch vorstellen, dass man 2 Speicherbereiche nutzt und 2 Mal memcopy ausführt, also einmal hin und ein zweites Mal zurück, dann überlappt sich das nicht mit sich selbst. Die Sonderbehandlung der eingefügten Zeile (Wert X übergeben) oder der letzten Zeile bei Delete (Wert 0 übergeben) ist dann aber trotzdem noch nötig.
    Gruß
    Ralle

    ... there\'re 10 kinds of people ... those who understand binaries and those who don\'t …
    and the third kinds of people … those who love TIA-Portal

  5. Folgender Benutzer sagt Danke zu Ralle für den nützlichen Beitrag:

    shrimps (09.02.2015)

  6. #4
    Registriert seit
    03.02.2015
    Ort
    Hatten
    Beiträge
    183
    Danke
    16
    Erhielt 32 Danke für 29 Beiträge

    Standard

    Hi Shrimps,

    guck mal in die OSCAT-Basic-Bibliothek: http://www.oscat.de
    Im Handbuch sind ab Kapitel 26 Listen-Funktionen beschrieben.
    Die Liste wird als String gespeichert und verarbeitet. Die Elemente sind mit Trennzeichen getrennt.
    Vielleicht helfen Dir diese fertigen Funktionen weiter.

    Gruß
    JS

  7. Folgender Benutzer sagt Danke zu JSEngineering für den nützlichen Beitrag:

    shrimps (09.02.2015)

  8. #5
    shrimps ist offline Erfahrener Benutzer
    Themenstarter
    Registriert seit
    16.03.2014
    Beiträge
    358
    Danke
    74
    Erhielt 45 Danke für 38 Beiträge

    Standard

    Hallo zusammen,
    erstmal besten Dank für die Ideen !

    Oscat habe ich mir angesehen und zum Speichern von Integern (in meinem Fall) macht Stringverarbeitung keinen Sinn, da extrem Resourcen verbraten werden.
    Zumindest war dies bei PC-Sprachen wenn ich ständig str_to_int und zurück wandele...
    Dann noch das Concat etc...

    Daher habe ich mich mal an die andere Idee mit den zwei Speichbereichen und den mehrfachen memcopy´s gemacht.
    Z. Zt. schreibe ich einen kleinen fb welcher mit das ganze erledigt.
    Gerne setze ich ihn mal hier rein, wenn er durchgetestet ist.
    Die ersten Versuche mit dem memcpy waren schon ganz flott...
    Nachteil meiner Umsetzung wird der Speicherverbrauch sein, aber heutzutage


    Bis bald
    Shrimps

  9. #6
    Registriert seit
    29.03.2004
    Beiträge
    5.731
    Danke
    143
    Erhielt 1.685 Danke für 1.225 Beiträge

    Standard

    Du kannst dir auch selber aus einer Array-Struktur (ohne Zeiger) eine einfach oder doppelt verkettete Liste programmieren. Man muss aber genau hinschauen welche Operationen auf dem Array/Liste bei dir überwiegen, dass die Operationen (lesen/einfügen/löschen) auf einer Liste schneller sind als auf ein Array. Ein Mehr an Speicherbedarf hast du auf jeden Fall.

    Den Anwendungsfall für diese String-Listen aus Oscat habe ich bisher noch nicht gefunden. Ich glaube das ist eher was für CSV-Dateien und nichts für eine Liste als Datenstruktur.

  10. #7
    shrimps ist offline Erfahrener Benutzer
    Themenstarter
    Registriert seit
    16.03.2014
    Beiträge
    358
    Danke
    74
    Erhielt 45 Danke für 38 Beiträge

    Standard

    Hallo nochmals,
    ich habe meine Idee mit dem "Arrayschieber" gemäß einiger Ideen hier mit der Memory-Copy gelösst.
    Läuft recht flott...
    Ich schiebe den Code mal komplett hier rein und ggf. hat der eine oder andere ja noch ein paar Optimierungsideen ?
    Ich kommentiere meine Sourcen möglichst umfangreich, aber beim Cut & n Paste hierhin wird es wegen der Schriftart und dem Twincateditor leider auseinandergerissen...
    Das passiert leider auch, wenn ich die Dokumentationsfunktion im Twincat nutze und als PDF ausgebe...
    Nur im Editor ist alles schon eingerückt / Tabuliert.

    Hier nun der Code
    LG
    Shrimps
    Code:
    PROGRAM MAIN
    VAR
        Schritt : INT;
        fbData    : _fbData;
        Index    : USINT;
        tmp         : INT;
        fbZufall    : DRAND;
    END_VAR
    CASE Schritt OF
    0:;
        FOR Index := 1 TO 10 DO
            fbZufall(seed := Tmp);
            tmp := LREAL_TO_INT(fbZufall.Num * 100);
            fbData(Code := 1, Value := tmp, Index := Index);
        END_FOR
        Schritt := 10;
    
    10:;
        (* Test DEL *)
        fbData(code := 3,  Value := tmp, Index := 1);
        Schritt := 20;
    
    20:;
        (* Test INS *)
        tmp := 99;
        fbData(code := 2,  Value := tmp, Index := 1);
        Schritt := 30;
    
    30:;
    
    END_CASE
    
    FUNCTION_BLOCK _fbData
    VAR_INPUT
        Index        : UINT;        (* Der gewünschte Index *)
        Code        : BYTE (0..3) ;    (* 0 = Lesen, 1 = Schreiben, 2 = INS, 3 = DEL*)
    END_VAR
    VAR_IN_OUT
        Value        : INT;        (* Der Eingabe oder Ausgabewert, je nach Wunsch *)
    END_VAR
    VAR_OUTPUT
        n            : UINT;        (* Wieviel Elemente sind aktuell drin *)
        OldValue    : INT;        (* Luxus: Der Wert des letzten gelöschen Elementes *)
    END_VAR
    VAR CONSTANT
        MaxArray : USINT    := 10;    (* Hier wird der Speicher verschwendet *)
    END_VAR
    VAR
        daten    : ARRAY [1..MaxArray] OF INT ;    (* Unsere Datengrube *)
        memory    : ARRAY [1..MaxArray] OF INT;    (* Das Paralleluniversum *)
        nSize    : BYTE;                        (* Die Größe der Type in Bytes *)
        dest    , src : UDINT;                        (* Ziel und Quelladressen für das Kopieren *)
        nBytes    : UDINT;                        (* Wieviele Bytes dürfen es werden *)
        bInit         : BOOL    := TRUE;                (* Kleiner Init des FB *)
    END_VAR
    
    IF bInit THEN                    (* Luxus, falls mal eine andere Type benutzt wird *)
        nSize := SIZEOF(Value);    (* Wieviel Bytes ist die Var gross ? *)
        bInit := FALSE;            (* Init abgeschlossen *)
    END_IF
    
    IF  Index > 0 AND Index <= MaxArray THEN
    
    CASE Code OF
    
    0:    (* Es soll ein Wert vom Index gelesen werden *)
        Value := daten[Index];
    
    1:    (* Es soll ein Wert in den Index geschrieben werden *)
        daten[Index] := Value;
        n := n +1 * BOOL_TO_INT(n < MaxArray);        (* Den Zähler raufzählen *)
    
    
    2:    (* Es ist ein INS auf ein Index gewünscht, die Reihe muss also schrumpfen *)
        OldValue := daten[MaxArray];                (* Wir merken uns den alten Wert, falls es jemand später braucht. *)
        MEMSET(ADR(memory), 0, nSize * MaxArray);    (* Wir löschen unser memory *)
    
        IF Index = 1 THEN                            (* Bei 1 ist immer alles anders *)
            dest := ADR(memory[2]);                (*  Das Ziel ist daher die 2 *)
            src    := ADR(daten[1]);                    (* Die Quelle muss 1 sein *)
            nBytes    := nSize * MaxArray -1;            (* Wir müssen Anzahl -1 Daten schaufeln *)
        ELSE
            dest := ADR(memory[1]);                (* Es ist ein Eintrag > 1 gewünscht, daher *)
            src    := ADR(daten[1]);                    (* Müssen wir den unteren Teil *)
            nBytes    := nSize * (Index -1);            (* bis vor der Position retten und *)
            MEMCPY(dest,src,nBytes);                (* Nun den vorderen Teil kopieren *)
    
            dest := ADR(memory[Index+1]);            (* Jetzt den hinteren Teil *)
            src    := ADR(daten[Index]);                (* Adressieren und *)
            nBytes    := nSize * (MaxArray - Index +1);    (* Die Menge berechnen *)
        END_IF
    
            MEMCPY(dest,src,nBytes);                (* Wir schaufeln den hinteren Teil rüber *)
    
            dest := ADR(daten[1]);                    (* Fertig, nun alles *)
            src    := ADR(memory[1]);                (* Für das Rücksichern *)
            nBytes    := SIZEOF(daten);                (* Aller Daten, das dürfte schneller sein *)
            MEMCPY(dest,src,nBytes);                (* Nun alles in die Originaldaten schaufeln *)
    
            n := n +1 * BOOL_TO_INT(n < MaxArray);    (* Den Zähler runterzählen *)
            daten[Index] := Value;                    (* Hier nun endlich den gewünschten Wert eintragen *)
    
    
    3:    (* Es ist ein DEL auf ein Index gewünscht, die Reihe muss also schrumpfen *)
        OldValue := daten[Index];                    (* Wir merken uns den alten Wert, falls es jemand später braucht. *)
        MEMSET(ADR(memory), 0, nSize * MaxArray);    (* Wir löschen unser memory *)
        IF Index = 1 THEN                            (* Wenn der erste ! Eintrag gelöscht werden soll, dann: *)
            dest := ADR(memory[1]);                (* Ist das Ziel die 1 und *)
            src    := ADR(daten[2]);                    (* Die Quelle die 2 !!! *)
            nBytes    := nSize * MaxArray -1;            (* Wir müssen Anzahl -1 Daten schaufeln *)
        ELSE
            dest := ADR(memory[1]);                (* Es ist ein Eintrag > 1 gewünscht, daher *)
            src    := ADR(daten[1]);                    (* Müssen wir den unteren Teil *)
            nBytes    := nSize * (Index -1);            (* Bis vor der Position retten und *)
            MEMCPY(dest,src,nBytes);                (* Nun den vorderen Teil kopieren *)
            dest := ADR(memory[Index]);            (* Jetzt den hinteren Teil *)
            src    := ADR(daten[Index+1]);            (* Adressieren und *)
            nBytes    := nSize * (MaxArray - Index );    (* Die Menge berechnen *)
        END_IF
    
        MEMCPY(dest,src,nBytes);                    (* Wir schaufeln den hinteren Teil rüber *)
        dest := ADR(daten[1]);                        (* Fertig, nun alles *)
        src    := ADR(memory[1]);                    (* Für das Rücksichern *)
        nBytes    := SIZEOF(daten);                    (* Aller Daten, das dürfte schneller sein *)
    
        MEMCPY(dest,src,nBytes);                    (* Nun alles in die Originaldaten schaufeln *)
        n := n -1 * BOOL_TO_INT(n > 0);                (* Den Zähler runterzählen *)
    END_CASE
    
    ELSE
        Value := -999;                                (* Wenn der Index Müll war bekommt er halt Müll *)
    END_IF

  11. #8
    Registriert seit
    27.05.2004
    Ort
    Thüringen/Berlin
    Beiträge
    12.218
    Danke
    533
    Erhielt 2.696 Danke für 1.948 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Ohne den Code jetzt ganz ausführlich durchgesehen zu haben, würde ich noch vorschlagen ein Startbit als Input zu verwenden, aus dem dann im FB eine Flanke zum Starten der Aktion erzeugt wird. So wie der Baustein im Moment aufgebaut ist, muß man selbst dafür sogen, dass er nur einen Zyklus lang aufgerufen wird, damit nicht in jedem Zyklus eine Aktien ausgeführt wird. Du machst das in der Case-Anweisung in FB-Main. Aber das ist ein wenig eine Frage des eigenen Programmierstils.
    Gruß
    Ralle

    ... there\'re 10 kinds of people ... those who understand binaries and those who don\'t …
    and the third kinds of people … those who love TIA-Portal

  12. Folgender Benutzer sagt Danke zu Ralle für den nützlichen Beitrag:

    shrimps (13.02.2015)

Ähnliche Themen

  1. Programm von PLC Control in System Manager einfügen
    Von selly im Forum CODESYS und IEC61131
    Antworten: 1
    Letzter Beitrag: 10.02.2011, 11:58
  2. Flex08, einfügen von Variablen
    Von c.wehn im Forum HMI
    Antworten: 3
    Letzter Beitrag: 17.08.2010, 12:58
  3. Editirte Seiten einfügen (E3 von Cim-Team)
    Von gingele im Forum E-CAD
    Antworten: 1
    Letzter Beitrag: 22.04.2010, 09:17
  4. Einfügen von Bildern im Text
    Von JandeFun im Forum Stammtisch
    Antworten: 3
    Letzter Beitrag: 13.06.2007, 13:25
  5. Antworten: 5
    Letzter Beitrag: 27.01.2005, 14:12

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •