# String in Array



## bige (26 Juli 2010)

Habe ein wenig Twincat ST Erfahrung aber keine mit Stringverarbeitung. Meine Aufgabe: Ein String (via Rs232) mit folgendem Aufbau:

<Int1>;<Int2>;<Int3>;....<Int100>$R

Die einzelnen Werte sollen in ein Array abgelegt werden.
Was ich bisher habe:

FUNCTION fIntPflFindParameter : UDINT
VAR_INPUT
    Input: STRING;
END_VAR

VAR
    FirstPos: INT;    (* first position of parameter *)
    LastPos: INT;    (* last position of parameter *)
    Length: INT;    (* length of parameter *)
    StringToReturn: STRING;
END_VAR
----
    (* find first position of parameter *)
    FirstPos := FIND (Input,';') + 1;
    (* find last position of parameter *)
    LastPos := FIND (Input,'$R');
    (* length of parameter *)
    Length := LastPos - FirstPos;
    StringToReturn := MID (Input, Length, FirstPos);

    fIntPflFindParameter := STRING_TO_UDINT(StringToReturn);
    RETURN;

Kann mir da jemand einen Tip (Code) geben?


----------



## Larry Laffer (26 Juli 2010)

Hallo,
ich würde da so vorgehen :
- übergebenen String in internen String übernehmen
- Datenausgabe der Prozedur ist ein Array of INT
- nach der Position des ";" suchen - wenn nicht gefunden nach "$R" suchen
- den Wert von 1 bis Pos-1 mit LEFT ausschneiden und in einen INT wandeln und den in dein Ausgabe-Array schreiben
- deinen Hilfsstring um die ausmaskierten Zeichen verkleinern (RIGHT)
- hattest du die Position nur über "$R" bekommen oder gar nicht, so ist dein Durchlauf beendet.
- sonst Durchlauf wiederholen.

Gruß
Larry


----------



## bige (26 Juli 2010)

Danke für Dein Tip. Diese Find Function ist für nur einen Wert ausgelegt, müsste also 'umgebaut' werden für die Ausgabe als Array. Seh ich das richtig? Wenn ja, wie.....
merci


----------



## Larry Laffer (26 Juli 2010)

... wie ich schon beschrieben hatte ... du mußt dir mittels einer Wiederholschleife den beschriebenen Ablauf erstellen. Dann ist es ja nicht schlimm, dass du immer nur das erste ";" findest - es ist dann ja jedes Mal ein "Neues".

By the Way :  (wegen der Art der Rückfrage) wie schätzt du deine Programmierkenntnisse (und -Motivation) ein ?

Gruß
Larry


----------



## bige (26 Juli 2010)

Programmierkenntnisse: S5; S7; seit 1 Jahr Sporadisch Twincat PL
Motivation: gehe in 4 Wochen in Pension......

Du meinst die ganze Function in einer Schleife mehrmals aufrufen?


----------



## Larry Laffer (26 Juli 2010)

... du mußt dir das Pendant zu einer SPLIT-Funktion bauen. Diese dann nicht mehrmals aufrufen sondern eher so oft (in sich) wiederholen, bis der String komplett zerlegt ist - also *Repeat ... Until*

Gruß
Larry


----------



## ebt'ler (26 Juli 2010)

Hallo,

hast du immer nur eine Zeile, die in ein eindimensionales Array soll?
Oder kommen mehrere dieser durch "$R" getrennte Zeilen die zweidimensional in ein Array sollen?

Für die erste Variante könnes du folgendes Verwenden:


```
PROGRAM PLC_PRG
VAR
    in_string: STRING := '100;200;400;500;100;323;234;344;23;123';
    out_array: ARRAY [1..max_anzahl_werte] OF INT;
    i: INT;
    position: INT;
    hilfs_string: STRING;
END_VAR
VAR CONSTANT
    max_anzahl_werte: INT := 10;
END_VAR

___________________________________________________________


hilfs_string := in_string;
FOR i:= 1 TO max_anzahl_werte DO
position:= FIND(hilfs_string , ';');
out_array[i] := STRING_TO_INT(LEFT(hilfs_string , position -1));
IF (position = 0) THEN
out_array[i] := STRING_TO_INT(hilfs_string);
hilfs_string:='';
END_IF
hilfs_string := RIGHT(hilfs_string , LEN(hilfs_string) - position);
END_FOR
```
Aber dazu müsstest zuvor noch das "$R" herauslöschen.

Für die zweite Variante könntest du den String erstmal nach "$R" spliten und die Teilstrings analog zu Variante eins weiter verwerten.


----------



## Larry Laffer (26 Juli 2010)

@Ebtler:
ich habe das nicht unbedingt so verstanden, dass die Wertezahl eine Konstante ist - ich klönnte mir auch vorstellen, dass die sich von Mal zu mal ändert ...

Gruß
Larry


----------



## ebt'ler (26 Juli 2010)

Da die Array-Größe sowieso fest vorgegeben sein muss ist es glaube ich besser so. 

Sollten weniger (Mess-)Werte im String auftauchen wird das Array an den entsprechenden Stellen einfach mit 0 gefüllt. 
Würde eine Repeat-Schleife nur solange laufen wie der Teilstring noch Trenner enthält könnte es bei einer veränderlichen Anzahl von Werten dazu kommen dass das Array noch alte Werte enthält. Da es für die Stelle keine aktuellen Zuweisungen gibt.


----------



## bige (26 Juli 2010)

So bin wieder da, Danke für das rege interresse..
Inzwischen bin ich etwas 'schlauer': ist ein fixer String wo sich nur die Werte nach dem ersten ' ; ' ändern. wird nur auf Commando ausgelesen. Erster Wert vor dem ' ; ' ist das Commando als replay. Mit folgender Function habe ich das Commando und das Stringendezeichen $R bereits herausgefiltert. 
FUNCTION fIntPflFindParameter : INT
VAR_INPUT
Input: STRING;
END_VAR
VAR
FirstPos: INT; (* first position of parameter *)
LastPos: INT; (* last position of parameter *)
Length: INT; (* length of parameter *)
StringToReturn: STRING;
END_VAR
---
(* find first position of parameter *)
FirstPos := FIND (Input,';') + 1;
(* find last position of parameter *)
LastPos := FIND (Input,'$R');
(* length of parameter *)
Length := LastPos - FirstPos;
StringToReturn := MID (Input, Length, FirstPos);
fIntPflFindParameter := STRING_TO_INT(StringToReturn);
RETURN;
Ergebnis ist der INT Wert, aber eben nur der erste. Werde mal die Variante von Ebt'ler probieren und melde mich dann morgen, erstmal merci an alle.

Ach ja sind erstmal nur 3 Werte, später dann maximal 10 Werte.

Bin neu hier im Forum, Wie bekommt ihr den Code in ein blau hinterlegtes Fenster?


----------



## bige (26 Juli 2010)

Merci Ebt'ler
so geht's! muss ich jetzt nur noch mit meiner Filterfunction verheiraten


----------



## ebt'ler (26 Juli 2010)

Ok, gut 

Um den Code in solch ein Feld zu bekommen musst du ihn markieren und dann im Editor über den Textfeld auf # klicken.


----------



## bige (27 Juli 2010)

*Status*

OK, bin wieder da. Dank eurer Hilfe bin ich schon fast fertig:


```
VAR
 Parameter:    STRING; (* max Anzahl (Nutz)Messwerte in Integer format,
          einschliesslich Steuerzeichen z.B: 3 Nutz)Werte
          51;111;222;333$R
          51 und $R gefiltert
          *)
 sListPulseDuration51:  STRING; (* Hilfsvar. *)
   ListDurationPulsArray :ARRAY[0..max_anzahl_werte] OF INT; (* Ausgabe Messwerte in Array *)
    i:       INT; (* Index *)
    FirstPos:     INT; (* first position of parameter *)
 LastPos:     INT; (* last position of parameter *)
 Length:     INT; (* length of parameter *)
END_VAR
VAR CONSTANT
    max_anzahl_werte: INT := 5; (* vorläufig 3 *)
END_VAR
___________________
(*Test 1*)
 (* string of RS232 *)
 sListPulseDuration51 := Parameter;
 FOR i:= 0 TO max_anzahl_werte DO
  (* find first position of parameter *)
  FirstPos:= FIND(sListPulseDuration51,';');
  (* find last position of parameter *)
  LastPos := FIND (sListPulseDuration51,'$R');
  (* length of parameter *)
  Length := LastPos - FirstPos;
  ListDurationPulsArray[i] := STRING_TO_INT(LEFT(sListPulseDuration51 , FirstPos -1));
  IF (FirstPos = 0) THEN
   ListDurationPulsArray[i] := STRING_TO_INT(sListPulseDuration51);
   sListPulseDuration51:='';
  END_IF
  sListPulseDuration51 := RIGHT(sListPulseDuration51 , LEN(sListPulseDuration51) - FirstPos);
 END_FOR
(*  Eingabe: Parameter= 51;111;222;333$R
 Ergebiss: 0= 51
    1= 111
    2= 222
    3= 0
    4= 0
    5= 0
*)
```
Aktuelles ist Problem ist noch die Filterung, bitte letzten Kommentar im Code anschauen.
Merci Gerd


----------



## ebt'ler (27 Juli 2010)

Ich nehme mal an es geht um Index 3 des Arrays. Dort steht eine Null, da beim spliten im letzten Teilstring noch 333$R bleibt, was nicht zu Integer konvertierbar ist.
Am einfachsten wäre es $R gleich vor der FOR- Schleife zu löschen:


```
position := FIND ( hilfs_string , '$R');
hilfs_string := DELETE ( hilfs_string , 2 , position );
```
Sollte $R mehrfach vorkommen müsste das Löschen auch in eine Schleife, dass sollte aber nach deiner Beschreibung nicht der Fall sein.

Alternativ könnte man es auch beim spliten selbst herausfiltern. Aber ich denke so ist es am einfachsten.


----------



## bige (27 Juli 2010)

Grosses Dankeschön, alles Tiptop.
Werde es mal Kommentiert zusammenschreiben und hier veröffentlichen, denke es ist von Allgemeinem Nutzen. Diese Variante String in Array auflösen habe ich noch nirgends gefunden.
Gruss Gerd und merci


----------



## onikos (2 Juli 2014)

bige schrieb:


> ...Wie bekommt ihr den Code in ein blau hinterlegtes Fenster?



Über dem Fenster, in dem du schreibst, ist dieses Zeichen   #    
Mit einem Klick darauf wird  [ C O D  E ]     [ / C O D E ] eingefügt (ohne Leerzeichen).

Zwischen ] [  schreibst du deinen Code und es erscheint in diesem blauen Fenster.

Cheers,
Niko


----------



## LargoD (2 Juli 2014)

@onikos
wie Du in Beitrag #13 lesen kannst, hat bige das schon vor fast vier Jahren gelernt.
Gruß
Erich


----------



## weißnix_ (2 Juli 2014)

bin auch drauf reingefallen


----------

