Step 7 Strings vergleichen mit EQ_STRNG

Spilkware

Level-1
Beiträge
3
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Zusammen,
hab mich erst gerade bei Euch eingefunden wiel ich auf mein Problem nichts praktisches gefunden habe.
Folgendes möchte ich realisieren:
In einem FC möchte ich in einer Schleife (0..15) einen String mit einem String in einem DB vergleichen.
Im DB ist der Soll String in einem Array untergebracht.
"DB_TRAYS".Set[0].Code[0] // es dreht sich um BarCodes.

Wie kann ich den IEC Aufruf für EQ_STRNG gestalten damit ich die Codes 0-15 mit einer Schleife vergleichen kann?

Ich habs schon mit Pointer und ANY probiert - komm da aber nicht wirklich weiter!

vorab Danke!
 
Welches Array ist das String-Array? Set[x] oder Code[x]?
Sind die Strings alle gleich lang? Wie lang? Muß die Länge variierbar sein?

Du könntest SCL verwenden, da kannst Du direkt Deinen String mit "DB_TRAYS".Set[0].Code vergleichen.
Du könntest in der Schleife die 16 Vorlagestrings jeweils in einen (temporären) Vergleichsstring kopieren und immer mit dem Vergleichsstring vergleichen.
Du könntest 16 EQ_STRNG-Aufrufe schreiben und eine Fallunterscheidung nach dem Schleifenzähler.
Du könntest anstatt EQ_STRNG einen eigenen Stringvergleichs-FC schreiben, dem Du mindestens einen der beiden Strings als Pointer übergibst, dann kannst Du in der Schleife einen Pointer auf die Vorlagestrings basteln.

Wenn die Strings zusammen nicht länger als 254 Byte sind, dann könntest Du die Strings direkt lückenlos hintereinander in nur einem String ablegen und mit der FIND-Function den Sollstring in dem Gesamtstring suchen. Falls gefunden dann schauen, ob die Fundstelle an einem Stringanfang liegt und an welchem. Allerdings braucht man dafür keine Schleife ;)

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Harald,
Das String Array ist das Code[].
Im Set[] habe ich den SetNamen String[16], Array of String[13] (EAN Barcodes) und Array of String[8] für Dateinamen.

So ähnlich wie Du das in SCL beschrieben hast wollte ich das auch in AWL lösen ... , da ich vorab ein vergleich mit ...Set[n].Code[0] machen sollte.
Hab mich dann erst mal auf ...Code[0..15] reduziert.
Mein Handycap ist eine ältere 314 CPU mit vielleicht 32kB und wenn ich jetzt für jeden Vergleich (8x Set[] * 16x Code) das Runtertippe wird es ganz schön knapp.

Ich denke die zweite Variante könnte für mich passend sein, ich wollte allerdings nicht Strings kopieren wenn ich die "nur" vergleichen will.
Die Find-Variante könnte klappen 16x 13Zeichen warum nicht? Würde für die erste Suche - Find - im Set[0..7].File[0..15] (in diesem Fall Array[0..127] of char) bestimmt schneller gehen!

Danke erstmal für deine Anregungen!
 
Da ich gerade wieder an einem älteren Projekt arbeite, hier mal eine Lösung in SCL.
Die kannst du sicher adaptieren.

Code:
FUNCTION FC250 : INT


Title = 'S_Matrix'
//
// Zuordnung von Bits aus einer Tabelle an Hand eines Namens heraussuchen
// die Bits der erste Fundstelle werden ausgegeben 
//
Version : '1.0'
author  : rk
name    : SMATRIX
family  : SYSTEM


VAR_INPUT
  // Eingangsparameter
  De_Part_NO: STRING[8];    //De-Part-No
END_VAR


VAR_OUTPUT // Ausgangsparameter
  Output_1: Bool;    //Scannermatrix Ausgang 1 
  Output_2: BOOL;    //Scannermatrix Ausgang 2
END_VAR


VAR_TEMP
    // temporäre Variablen
  I: INT;
  EQ: BOOL;
  Temp_String1: STRING[8];
  Temp_String2: STRING[8];
  Scannmatrix: BYTE;
  ATScannmatrix AT Scannmatrix: ARRAY[1..8] OF BOOL;
END_VAR


FC250 := 0;
EQ := 0;
Output_1 := False;
Output_2 := False;


// Anweisungsteil
FOR I := 1 TO 50 DO
  
   Temp_String1 := "S12_Scannertabelle".Scannmatrix[I].De_Part_No;
   Temp_String2 := De_Part_NO;
    
   EQ := EQ_STRNG(S1 := Temp_String1 // IN: STRING
                             ,S2 := Temp_String2  // IN: STRING
                             ); // BOOL
   IF EQ THEN
      Scannmatrix := "S12_Scannertabelle".Scannmatrix[I].Scannmatrix;
      Output_1 := atScannmatrix[1];
      Output_2 := atScannmatrix[2];
      FC250 := I;
      EXIT;
   END_IF; 
END_FOR;   
  
END_FUNCTION

Im DB ist ein Array of Struct definiert, das in jeder Struct auch den String enthält.

Code:
Scannmatrix	ARRAY[1..50]	
STRUCT			
   De_Part_No	STRING[8]	''		
   Scannmatrix	BYTE	B#16#0		
END_STRUCT
Es wird auf den String verglichen und dann eine zugordnete Scanmatrix (Byte) ausgelesen, die für die weitere Arbeit genutzt werden soll.
 
Hallo Ralle,
Ja so liese sich das kompakt in SCL lösen!
In AWL habe ich es nun auch gelöst (alle unsere Programme sind in AWL). Eigentlich genau wie in deinem SCL. Der Trick liegt darin, den String via Any-Pointer und BlockMove (Dabei kann per Schleife der/die Array indizies durlaufen werden) in die Lokaldaten zu speichern und dem EQ_String (Find_String) für IN1 und/oder IN2 einen "Const." String vorzugaukeln.

Danke für eure Hilfe
Dirk

Code:
FUNCTION "CheckBCR" : VOID
TITLE =
VERSION : 0.1


VAR_TEMP
  RV_BLKMove : INT ;    
  RV_FindString : INT ;    
  DB_APointer : ANY ;    
  CodeOffset : DINT ;    
  EofOffset : DINT ;    
  FileOffset : DINT ;    
  strDBCode : STRING  [14 ];    
END_VAR
BEGIN
NETWORK
TITLE =

      U     "M_Chk_BCRSet"; 
      SPBN  xChk; 
      R     "M_Chk_BCRSet"; 

// Offset berechnen
      L     "MB_TraySet"; // wird nach Einlegen der Speicherkarte initialisiert
      L     L#426; 
      *D    ; 
      L     L#10; 
      +D    ; 
      T     #CodeOffset; 
// Bereichsende berechnen
      L     L#240; 
      +D    ; 
      T     #EofOffset; 
// Dateinamen Offset berechnen
      L     #CodeOffset; 
      L     L#256; 
      +D    ; 
      T     #FileOffset; 


// Erster von 10 Rx-Barcodes setzt Dateiname und Vergleichscode für folgende Barcodes
      L     "MB_EnumTSet"; 
      L     0; 
      ==I   ; 
      SPBN  nTCk; 

// Barcode in Trayset enthalten?

[FONT=courier new]// Zeiger auf DB29.Set[0].Code[0] String[14] ausrichten
      LAR1  P##DB_APointer; 
      L     B#16#10;           // S7 Syntax
      T     LB [AR1,P#0.0]; 
      L     B#16#2;            // Datentyp (eigentlich String, hier Byte)
      T     LB [AR1,P#1.0]; 
      L     16;                // Wiederholung 16 Bytes kopieren mit BLKMove
      T     LW [AR1,P#2.0];    // EAN Code 13 Zeichen bei Code39 auch mal mehr
      L     29;                // DB Nummer
      T     LW [AR1,P#4.0]; 
      L     #CodeOffset;       // Byte Position im DB
      SLD   3; // Umwandeln in Pointer
      T     LD [AR1,P#6.0]; 
      L     B#16#84; 
      T     LB [AR1,P#6.0];    // Codierung Speicherbereich (DB -> h84) 
// ab hier Zeiger auf "DB_TRAYS".Set[n].Code[0]

Loop: NOP   0; 

// String aus DB,Array in lokale Temp kopieren
      CALL "BLKMOV" (
           SRCBLK                   := #DB_APointer,
           RET_VAL                  := #RV_BLKMove,
           DSTBLK                   := #strDBCode);

      L     #RV_BLKMove; 
      L     0; 
      <I    ; 
      S     M     37.3;  // Störungs Hilfsmerker
      SPB   nGef; 

// lokaler String mit DB String (kein Array) vergleichen
// Anstatt EQ_Strng verwende Find, um CR und LF usw. zu vernachlässigen
      CALL "FIND" (
           IN1                      := "DB_Rx_BC1".Puffer,
           IN2                      := #strDBCode,
           RET_VAL                  := #RV_FindString);

      L     #RV_FindString; 
      L     1; 
      ==I   ; 
      SPBN  Vgl0; // weiteres Array

// Barcode in Sollcode-Puffer kopieren 
      CALL "BLKMOV" (// Left(DB_Trays.Set[n].Code[x],16,DB_RS232.Sollcode)
           SRCBLK                   := #strDBCode,
           RET_VAL                  := #RV_BLKMove,
           DSTBLK                   := "DB_RS232".SollCode);

      L     #RV_BLKMove; 
      L     0; 
      <I    ; 
      S     M     37.4; 
      SPB   nGef; 

// Zeiger auf DB_Trays.Set[n].File[x] ausrichten
      LAR1  P##DB_APointer; 
      L     B#16#2;              // Datentyp (eigentlich String, hier Byte)
      T     LB [AR1,P#1.0]; 
      L     10;                  // Wiederholung (8 Zeichen + 2Byte String Header)
      T     LW [AR1,P#2.0]; 
      L     #FileOffset;         // Byte Position im DB
      SLD   3;                   // Umwandeln in Pointer
      T     LD [AR1,P#6.0]; 
      L     B#16#84; 
      T     LB [AR1,P#6.0];      // Codierung Speicherbereich (DB h84) 

// Dateiname in Drucker Schnitstelle kopieren
      CALL "BLKMOV" (// Left(DB_Trays.Set[n].File[x],10,"DB_Tx_TCU".Datei)
           SRCBLK                   := #DB_APointer,
           RET_VAL                  := #RV_BLKMove,
           DSTBLK                   := "DB_Tx_TCU".Datei);

      L     #RV_BLKMove; 
      L     0; 
      <I    ; 
      S     M     37.5; 
      SPB   nGef; 

      SPA   Gefu; 

Vgl0: NOP   0; 
      L     #CodeOffset; 
      L     #EofOffset; 
      >=D   ; 
      S     M     37.6; 
      SPB   nGef; // loop nach 16 "Vergleichen" beenden.

// Zeiger auf DBx.Set[n].Code[x=x+1] ausrichten
      LAR1  P##DB_APointer; 
      L     B#16#2;              // Datentyp (eigentlich String, hier Byte)
      T     LB [AR1,P#1.0]; 
      L     16;                  // Wiederholung 16 Bytes kopieren mit BLKMove
      T     LW [AR1,P#2.0];      // EAN Code 13 Zeichen bei Code39 auch mal mehr
      L     #CodeOffset;         // Byte Position im DB
      L     L#16; 
      +D    ; 
      T     #CodeOffset;         // Für nächsten Durchlauf sichern
      SLD   3;                   // Umwandeln in Pointer
      T     LD [AR1,P#6.0]; 
      L     B#16#84; 
      T     LB [AR1,P#6.0];      // Codierung Speicherbereich (DB h84) 

      L     #FileOffset;         // Offset auf Dateinamen  berechnen
      L     L#10; 
      +D    ; 
      T     #FileOffset; 

      SPA   Loop; // Achtung mögliche Endlos-Schleife

nGef: NOP   0; 
      SET   ; 
      S     "Err_BCR_noMatch"; 
      S     "St_Störung"; 
      SPA   xChk; 

Gefu: NOP   0; 
      SET   ; 
      S     "M_Freig_Schachtel"; 
      L     "MB_EnumTSet"; 
      +     1; 
      T     "MB_EnumTSet"; 
      SPA   xChk; 

nTCk: NOP   0; 

      CALL "FIND" (
           IN1                      := "DB_Rx_BC1".Puffer,
           IN2                      := "DB_RS232".SollCode,
           RET_VAL                  := #RV_FindString);

      L     #RV_FindString; 
      L     1; 
      ==I   ; 
      SPBN  nMat; // no Match -> ERR Codeleser
      S     "M_Freig_Schachtel"; 
      L     "MB_EnumTSet"; 
      +     1; 
      T     "MB_EnumTSet"; 
      L     10; 
      ==I   ; 
      SPBN  xChk; // noch keine 10 Schachteln, kein Init
      L     0; 
      T     "MB_EnumTSet"; 
      SPA   xChk; 

nMat: NOP   0; 
      SET   ; 
      S     M     37.2; 
      S     "St_Störung"; 

xChk: NOP   0; 


END_FUNCTION

[/FONT]
 
Zuletzt bearbeitet:
Zurück
Oben