TIA TIA V17 For Schleife mit 2 Dimensionen

Bitte ein Bit

Level-2
Beiträge
77
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Kollegen,
ich hänge gerade bei einer Aufgabe fest. TIA V17

Am Formalparameter "dat" hängt mein DB: Array[0..3, 4..5] of Bool

Aufgabe: Es soll mir den Vektor anzeigen, welches gerade gesetzt ist. 1. Dimension, 2. Diemsion


//initialize counter
#temp1 := 0;
#temp2 := 0;

IF #tempRisingFlag THEN
// Check outer dimension
FOR #temp1 := LOWER_BOUND(ARR := #dat, DIM := 1) TO UPPER_BOUND(ARR := #dat, DIM := 1) DO
// Check inner dimension
FOR #temp2 := LOWER_BOUND(ARR := #dat, DIM := 2) TO UPPER_BOUND(ARR := #dat, DIM := 2) DO
IF #dat[#temp1, #temp2] <> 0 THEN
#Dim1Found := #temp1;
#Dim2Found := #temp2;
EXIT;
ELSE
#Dim1Found := #Dim2Found := 0;

END_IF;
END_FOR;
END_FOR;
END_IF;

Es erkennt auch, wenn ein Vektor gesetzt ist, aber ist alles null, kann ich es nicht ablöschen.

Bitte um Rat.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Was ist da fürn Unterschied??? beides gleiche Ausdrücke!
In manchen ProgrammierSprachen kann man diese "abgekürzte Schreibweise" ( a := b := c ; ) verwenden, in vielen aber nicht.
Die "ausführliche Schreibweise" ( a := c ; b := c ; ) mit vielen EinzelZuweisungen funktioniert immer.
Ich weiss nicht, wie es bei SCL ist und kann nur sagen : einen Versuch ist es wert.

Hier Dein OriginalCode aus #1 mit Einrückungen damit man's besser lesen kann:
Code:
//initialize counter
#temp1 := 0;
#temp2 := 0;

IF #tempRisingFlag THEN
    // Check outer dimension
    FOR #temp1 := LOWER_BOUND(ARR := #dat, DIM := 1) TO UPPER_BOUND(ARR := #dat, DIM := 1) DO
        // Check inner dimension
        FOR #temp2 := LOWER_BOUND(ARR := #dat, DIM := 2) TO UPPER_BOUND(ARR := #dat, DIM := 2) DO
            IF #dat[#temp1, #temp2] <> 0 THEN
                #Dim1Found := #temp1;
                #Dim2Found := #temp2;
                EXIT;
            ELSE
                #Dim1Found := #Dim2Found := 0;
            END_IF;
        END_FOR;
    END_FOR;
END_IF;

Das sollte vermutlich schneller ( "zielführender" ) sein:
Code:
// valid indices must be > 0
#Dim1Found := 0;
#Dim2Found := 0;

IF #tempRisingFlag THEN
    // increment outer dimension
    FOR #temp1 := LOWER_BOUND(ARR := #dat, DIM := 1) TO UPPER_BOUND(ARR := #dat, DIM := 1) DO
        // increment inner dimension
        FOR #temp2 := LOWER_BOUND(ARR := #dat, DIM := 2) TO UPPER_BOUND(ARR := #dat, DIM := 2) DO
            // check content of array element            
            IF #dat[#temp1, #temp2] <> 0 THEN
                #Dim1Found := #temp1;
                #Dim2Found := #temp2;
                EXIT;
            END_IF;
        END_FOR;
        IF #Dim1Found > 0 THEN
            EXIT;
        END_IF;
    END_FOR;
END_IF;

Mich wundert eher, dass die beiden Variablen nicht "ständig" ablöscht, da ich erwartet hätte, dass das Exit nur auf der 2. Schleife springt.
Hast natürlich Recht, das habe ich ja total übersehen, aber dank Deinem Hinweis jetzt nachgestrickt.
 
Zuletzt bearbeitet:
Besten Dank!
Das war die Lösung, dass man nicht sofort drauf kommt....man hängt sich immer mit den geringsten Problemen auf...Initialisierung!

//initialize counter
#temp1 := 0;
#temp2 := 0;
//initialize found
#Dim1Found := 0;
#Dim2Found := 0;

IF #tempRisingFlag THEN
// Check outer dimension
FOR #temp1 := LOWER_BOUND(ARR := #dat, DIM := 1) TO UPPER_BOUND(ARR := #dat, DIM := 1) DO //0 bis 3
// Check inner dimension
FOR #temp2 := LOWER_BOUND(ARR := #dat, DIM := 2) TO UPPER_BOUND(ARR := #dat, DIM := 2) DO //4 bis 5
IF #dat[#temp1, #temp2] <> 0 THEN
#Dim1Found := #temp1;
#Dim2Found := #temp2;
EXIT;
END_IF;
END_FOR;
END_FOR;
END_IF;
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Trag bitte zwischen den beiden Zeilen, in denen END_FOR; steht nocht die 3 Zeilen ...
IF #Dim1Found > 0 THEN
EXIT;
END_IF;
... nach!

PS:
Die Anweisungen #temp1 := 0; und #temp2 := 0; dürften überflüssig sein, da #temp1 und #temp2 in den FOR-Anweisungen definiert werden, ehe sie abgefragt werden.
 
Moin Bitte_ein_Bit,

setze Code doch bitte in Code-Tags (</>).

Besten Dank!
Das war die Lösung, dass man nicht sofort drauf kommt....man hängt sich immer mit den geringsten Problemen auf...Initialisierung!
Das ist zumindest eine Möglichkeit

//initialize counter
#temp1 := 0;
#temp2 := 0;
Das ist unnötig, da dies als Initialisierung in der FOR-Schleife erfolgt:
FOR #temp1 := LOWER_BOUND(ARR := #dat, DIM := 1) TO UPPER_BOUND(ARR := #dat, DIM := 1) DO //0 bis 3
// Check inner dimension
FOR #temp2 := LOWER_BOUND(ARR := #dat, DIM := 2) TO UPPER_BOUND(ARR := #dat, DIM := 2) DO //4 bis 5
IF #dat[#temp1, #temp2] <> 0 THEN
#Dim1Found := #temp1;
#Dim2Found := #temp2;
EXIT;
END_IF;
END_FOR;
END_FOR;
END_IF;


VG

MFreiberger
 
LOWER- und UPPER_BOUND würde ich nicht in der Schleife abfragen, sondern vorher auf Variablen legen.
Ja, aber, wenn LOWER- und UPPER-BOUND im FOR-SchleifenKopf abgefragt werden, dann wird doch zumindest LOWER-BOUND nicht bei jedem SchleifenDurchlauf abgefragt.
Bei UPPER-BOUND wäre ich mir allerdings auch nicht so sicher.
Könnte man mal mit Variablen testen, die man zwischen den SchleifenDurchläufen manipuliert.
 
Ja, aber, wenn LOWER- und UPPER-BOUND im FOR-SchleifenKopf abgefragt werden, dann wird doch zumindest LOWER-BOUND nicht bei jedem SchleifenDurchlauf abgefragt.
Bei UPPER-BOUND wäre ich mir allerdings auch nicht so sicher.
Könnte man mal mit Variablen testen, die man zwischen den SchleifenDurchläufen manipuliert.
Aber gewinnt man dadurch was? Der Vorschlag von @Onkel Dagobert finde ich zum einen übersichtlicher und man ruft die Funktionen nur jeweils einmal vor dem schleifenaufruf auf und nicht ggf. Mehrmals im schleifenkopf.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ja, aber, wenn LOWER- und UPPER-BOUND im FOR-SchleifenKopf abgefragt werden, dann wird doch zumindest LOWER-BOUND nicht bei jedem SchleifenDurchlauf abgefragt...

Warum sollte man auch die Arraygrenzen bei jedem Durchlauf abfragen? Die ändern sich doch nicht.
Man muss auch nicht unbedingt die temporären Variablen auf "0" initialisieren, da ja offensichtlich "optimiert" programmiert wird. Und man sollte bedenken, dass mit "EXIT" nur die direkt umgebende FOR-, WHILE- oder REPEAT-Schleife beendet wird. Falls mehrere Bits gesetzt sein können, würde nach dem ersten Fund die äußere FOR-Schleife weiter laufen.

Code:
// Initialisierung
#ANF1 := LOWER_BOUND(ARR := #DAT, DIM := 1);
#END1 := UPPER_BOUND(ARR := #DAT, DIM := 1);
#ANF2 := LOWER_BOUND(ARR := #DAT, DIM := 2);
#END2 := UPPER_BOUND(ARR := #DAT, DIM := 2);

// Array nach dem ersten gesetzten Bit durchsuchen, bei Dimension 1 beginnen 
IF #tempRisingFlag THEN
    FOR #temp1 := #ANF1 TO #END1 DO
        IF #FOUND THEN
            EXIT;
        END_IF;
        FOR #temp2 := #ANF2 TO #END2 DO
            IF #DAT[#temp1, #temp2] <> 0 THEN
                #Dim1Found := #temp1;
                #Dim2Found := #temp2;
                #FOUND := TRUE;
                EXIT;
            END_IF;
        END_FOR;
    END_FOR;
END_IF;
/CODE]
 
Warum sollte man auch die Arraygrenzen bei jedem Durchlauf abfragen?
Soll man doch gar nicht, Dagobert.
Ich denke nur, dass mancher Compiler sich auch diese Frage stellt und nicht bereits abgefragte Variablen stur bei jedem SchleifenDurchlauf wiederholt und deshalb unnötig abfragt.
Gerade bei FOR-Schleifen findet man oft Beschreibungen, die ein striktes Beibehalten des Anfangs- und EndWertes bei der "LaufVariable" erwarten lässt.
Die ändern sich doch nicht.
Die LOWER- und UPPER-BOUND-Werte (zum Leidwesen mancher Programmierer hier im Forum) sowieso nicht.
Aber ein Verlangen nach Manipulationen der LaufVariable und des EndWertes der LaufVariable taucht anscheinend auch auf vielen WunschZetteln auf.
Aber Du hast Recht, Dagobert. Programmiert man es so, wie Du vorschlägst, so nimmt man dem Compiler die Qual der Wahl und schreibt ihm vor, wie man es haben will. Klar und deutlich. ;)
 
Hallo Onkel Dug,
wie soll es die 1. Schleife überspringen mit Exit, wenn found in der 2. Schleife gesetzt wird? Die 1. For Schleife wäre für die Katz
 
Zuviel Werbung?
-> Hier kostenlos registrieren
wie soll es die 1. Schleife überspringen mit Exit, wenn found in der 2. Schleife gesetzt wird? Die 1. For Schleife wäre für die Katz
Grundsätzlich werden beide Indizes (Dimension 1 und Dimension 2 des Arrays) gleichzeitig in der INNEREN Schleife abgefragt.
Wird dabei ein Element gefunden, das <> 0 ist, wird zunächst die INNERE Schleife abgebrochen. Wurde die INNERE Schleife tatsächlich abgebrochen, so muss auch noch die ÄUSSERE Schleife abgebrochen werden. Dazu benötigt man in der ÄUSSEREN Schleife eine zusätzliche Abfrage.
D.h. das AbbruchKriterium wird zunächst in der INNEREN Schleife festgestellt und dann an die ÄUSSERE Schleife durchgereicht, wo es quasi nochmal abgefragt wird und zum Abbruch auch der ÄUSSEREN Schleife führt.

Siehe dazu ...
- Onkel Dagoberts Beitrag #15, wo es vor der INNEREN Schleife in der ÄUSSEREN Schleife abgefragt wird
oder
- meinen Beitrag #6, wo die Abfrage nach der INNREREN Schleife in der ÄUSSEREN Schleife passiert.

Deine Frage habe ich nicht verstanden und statt von 1. und 2. Schleife lieber von äusserer und innerer Schleife gesprochen, um Missverständnissen vorzubeugen.
 
... ich denke nur, dass mancher Compiler sich auch diese Frage stellt und nicht bereits abgefragte Variablen stur bei jedem SchleifenDurchlauf wiederholt und deshalb unnötig abfragt...
Ja, aber genau das tut tut doch der Compiler möglicherweise mit:
Code:
FOR #temp1 := LOWER_BOUND(ARR := #dat, DIM := 1) TO ...
Und genau das kann man verhindern, indem "LOWER_BOUND" und co. nur einmal vorher ausführt. Willst das nicht verstehen, oder tust du nur so?

.. meinen Beitrag #6, wo die Abfrage nach der INNREREN Schleife in der ÄUSSEREN Schleife passiert...
Das hatte ich ganz übersehen. Natürlich kann man es auch an dieser Stelle abfragen. Allerdings hat deine Version, "Dim1Found" auf ">0" abzufragen, auch wieder einen kleinen Haken, den es zu erraten gibt :).

.. Die LOWER- und UPPER-BOUND-Werte (zum Leidwesen mancher Programmierer hier im Forum) sowieso nicht...
Zum Leidwesen der Programmierer? Enstschuldige Heinileini, aber irgendwie bist du hier etwas aus der Spur. Wahrscheinlich hast du mit dem TIA-Portal nie wirklich gearbeitet? Allerdings habe auch ich nie "UPPER_BOUND" und "LOWER_BOUND" verwendet, da das leider nur in optimierten Bausteinen möglich ist. Es wäre doch höchst fatal, wenn sich Aktualparameter wie diese übergebenen Arraygrenzen zur Laufzeit im Baustein ändern würden.
 
Statement:
Ich fühle mich schuldig, hier für eine Missstimmung gesorgt zu haben.
Ich bin dankbar, für jeden Tip, sehr dankbar, dass es diesen Forum gibt.
Man lernt nie aus, bin seit 20 Jahren in der Automatisierung, kann aber nie behaupten, dass ich ausgelernt habe, dass ist es, was ich an diesem Job so liebe…jeder Tag bringt was neues. Vielleicht bin ich die rauhe Kommunikation auch nicht gewohnt, ich muss hier heinilein in Schutz nehnen…
Onkel Dug, du magst wie Otto Rehhagel oder Franzi für FC Bayern eine Kuktfigur hier sein…mit deiner Erfahrung kann hier keiner mithalten! An Lob an dich, gut dass es dich gibt! Also lehn dich zurück, ich spendiere dir ein Tee 👍
 
Zurück
Oben