TIA Stringverarbeitung

Ralle

Super-Moderator , User des Jahres 2006-2007
Teammitglied
Beiträge
15.414
Reaktionspunkte
4.043
Zuviel Werbung?
-> Hier kostenlos registrieren
Hab mich gerade gewundert.
Folgender Code zur Wandlung einer DINT 7-stellig in einen String.
Ich weiß, es gibt DINT_TO_STRING, aber das Plus soll nicht dargestellt werden und führende Nullen sollen dargestellt werden.
Also mach ich das "zu Fuß".


Code:
                #nMontagenummer         := #Montagenummer;                    
                #strMontagenummer       := '0000000';   //7 Leerzeichen für 7-stelligen String
                #strMontagenummer[7]    := #nMontagenummer MOD 10 + 48;
                #nMontagenummer         := #nMontagenummer / 10;
                #strMontagenummer[6]    := #nMontagenummer MOD 10 + 48;
                #nMontagenummer         := #nMontagenummer / 10;
                #strMontagenummer[5]    := #nMontagenummer MOD 10 + 48;
                #nMontagenummer         := #nMontagenummer / 10;
                #strMontagenummer[4]    := #nMontagenummer MOD 10 + 48;
                #nMontagenummer         := #nMontagenummer / 10;
                #strMontagenummer[3]    := #nMontagenummer MOD 10 + 48;
                #nMontagenummer         := #nMontagenummer / 10;
                #strMontagenummer[2]    := #nMontagenummer MOD 10 + 48;
                #nMontagenummer         := #nMontagenummer / 10;
                #strMontagenummer[1]    := #nMontagenummer MOD 10 + 48;
                #I := LEN(#strMontagenummer);

Der Code funktioniert so erst einmal.
Für einen Test habe ich folgende Zeile geändert:

#strMontagenummer := ''; //7 Leerzeichen für 7-stelligen String --> kein Leerzeichen, also ein String der die Länge 0 hat.

Überprüft man das direkt nach dieser Zeile, dann hat der String tatsächlich die Länge 0.
Stellt man #I := LEN(#strMontagenummer); as Ende, dann ist die Länge 1.

Nach meiner Auffassung dürfte das nicht so sein, denn ich schreibe ja direkt auf die Bytes des Strings, was die Länge des Strings, die im 2. Kopfbyte stehen sollte nicht beeinflußt.
Also müßte bei '' als Startstring, die Länge 0 bleiben.

Fehler von mir, Siemens-Bug oder Feature???
 
Zuletzt bearbeitet:
Ich meine das dürfte nicht sein. Sieht für mich aus wie ein Bug.

Liegt #strMontagenummer in einem "optimierten" Speicher? Was für eine CPU ist das? Ist das Verhalten auch in PLCSIM?

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich habe gerade deinen Code einfach kopiert ... die Variablen sind so deklariert ?

Montagenummer DInt
nMontagenummer DInt
strMontagenummer String[7]
i Int

PS: Nutz du das für negative Zahlen ? Das funktioniert deine Routine nämlich nicht

-15 = '00000/+';
 
Zuletzt bearbeitet:
Nach meiner Auffassung dürfte das nicht so sein, denn ich schreibe ja direkt auf die Bytes des Strings, was die Länge des Strings, die im 2. Kopfbyte stehen sollte nicht beeinflußt.
Also müßte bei '' als Startstring, die Länge 0 bleiben.


300er + Step7 Classic oder 1500er + Tia Portal ?

Bei 1500er Steuerungen kannst du die Ist bzw Solllänge im String nicht mehr über Pointer auslesen sondern musst die LEN - Funktion nehmen.
 
Was liefert denn die SiemensMontagsNummer in #I bei:
Code:
                #nMontagenummer         := #Montagenummer;                    
                #strMontagenummer       := '';   //7 LeerString
                #strMontagenummer[7]    := #nMontagenummer MOD 10 + 48;
                [B]#I := LEN(#strMontagenummer);[/B]
                #nMontagenummer         := #nMontagenummer / 10;
                #strMontagenummer[6]    := #nMontagenummer MOD 10 + 48;
                #nMontagenummer         := #nMontagenummer / 10;
                #strMontagenummer[5]    := #nMontagenummer MOD 10 + 48;
                #nMontagenummer         := #nMontagenummer / 10;
                #strMontagenummer[4]    := #nMontagenummer MOD 10 + 48;
                #nMontagenummer         := #nMontagenummer / 10;
                #strMontagenummer[3]    := #nMontagenummer MOD 10 + 48;
                #nMontagenummer         := #nMontagenummer / 10;
                #strMontagenummer[2]    := #nMontagenummer MOD 10 + 48;
                #nMontagenummer         := #nMontagenummer / 10;
                #strMontagenummer[1]    := #nMontagenummer MOD 10 + 48;
???

PS:
Bei 1500er Steuerungen kannst du die Ist bzw Solllänge im String nicht mehr über Pointer auslesen sondern musst die LEN - Funktion nehmen.
Ja, aber genau das tut Ralle doch!?!
 
Zuletzt bearbeitet:
Welch ein prompter Service, Bl000b3r. Danke!
Also ist das Ergebnis auch noch vom Index des angesprochenen Bytes abhängig.
Da kann man sich also wegen der Ursache nicht nur einen Wolf suchen, sondern gleich zwei!

 
TIA V14 SP1 UPd6
1515F V2.1

Ich hab an der Stelle nur positive DINT bis 7 Stellen, daher reicht mir das so.
Aber klar, bei nagativen Zahlen müßte man noch den Betrag aus der Ziffer bilden, bevor mein ein Char daraus zaubert!
Ist ein FB, der "optimiert" ist, DB sind auch "optimiert".
 
Zuletzt bearbeitet:
Bei 1500er Steuerungen kannst du die Ist bzw Solllänge im String nicht mehr über Pointer auslesen sondern musst die LEN - Funktion nehmen.
Wieso bzw. wieso nicht? Wenn der String in Speicher mit Standard-Zugriff liegt, dann kann man die Stringlänge auch mit Pointer auslesen. Oder man überlagert den String per AT mit einer Struktur (BYTE + BYTE + CHAR-Array[...]) und kann dann sogar symbolisch auf die Stringlänge zugreifen.


:confused: Was hast Du denn da beobachtet? Oder was für (Fantasie?) Werte zeigt TIA da an?
Bei der Zuweisung "#strMontagenummer[7] := #nMontagenummer MOD 10 + 48;" kann doch nicht 0 ('$00') rauskommen.
Oder braucht TIA daß man da Angst-Klammern setzt? "#strMontagenummer[7] := (#nMontagenummer MOD 10) + 48;"


Ist ein FB, der "optimiert" ist, DB sind auch "optimiert".
:roll: "optimiert" - für mich das Marketing-Wort für "voller Bugs" ;)

Harald
 
ja TIA = total im arsch

Klammern machen keinen Unterschied :D
Vorallem ist komisch, dass jedes Zeichen ein "Nullzeichen" ist, aber nur beim [1]er die Berechnung korrekt ist ...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wieso bzw. wieso nicht? Wenn der String in Speicher mit Standard-Zugriff liegt, dann kann man die Stringlänge auch mit Pointer auslesen. Oder man überlagert den String per AT mit einer Struktur (BYTE + BYTE + CHAR-Array[...]) und kann dann sogar symbolisch auf die Stringlänge zugreifen.



:confused: Was hast Du denn da beobachtet? Oder was für (Fantasie?) Werte zeigt TIA da an?
Bei der Zuweisung "#strMontagenummer[7] := #nMontagenummer MOD 10 + 48;" kann doch nicht 0 ('$00') rauskommen.
Oder braucht TIA daß man da Angst-Klammern setzt? "#strMontagenummer[7] := (#nMontagenummer MOD 10) + 48;"



:roll: "optimiert" - für mich das Marketing-Wort für "voller Bugs" ;)

Harald

Ja, bei mir sieht das im Beobachten-Modus auch anders aus:

Screenshot 2018-10-18 um 15.07.23.jpg

Aber, wenn ich den String zu so angeben '', dann sieht es aus, wie bei Bl000b3r.

PS String nehme ich aus Faulheit, da man mit INSERT das Ganze so schon zusammenbauen kann und dann auch noch die korrekte Länge bekommt. Danach in ein Chat-Array gewandelt und ab zum LASER.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Mit
Code:
#myString:= '';
ist der String leer und hat deshalb die länge 0, da hilft es auch nicht auf die plätze indiziert zuzugreifen wenn die actual länge 0 ist....
Wenn dann muss man hier mit
Code:
#myString := concat([COLOR=#333333][FONT=Courier]#nMontagenummer, #myString[/FONT][/COLOR]);
arbeiten und den String mit sich selbst verknüpfen, dann wird auch die länge entsprechend gesetzt, oder eben wie ganz am Anfang einen Defaultwert eintragen - Nullen oder Leerzeichen - und dann mit indiziertem Zugriff.

Debug / Test / Veranschaulichung
Wenn man eine Nummer (1234567) verwendet - nicht 0 - um in den String zu schreiben und den String anschließen zum test serialisiert, wird man sehen dass die ersten beiden Bytes die maximal Len und actual Len enthalten und anschließend die erwarteten Werte, wobei die actual len immer noch 0 ist --> String = leer - deswegen zeigt die Beobachtungstabelle auch nichts an :)

eine andere Lösung wäre die werte in ein byte/char array zu packen und anschließen mit
Code:
chars_to_string
(oder so ähnlich) in den String wandelt

VG
Bastian
 
Zuletzt bearbeitet:
Ich hab auch die Erfahrung gemacht, dass TIA indizierte Zugriffe auf Elemente jenseits der aktuellen Länge bei der 1500er irgendwie nicht mag.

Gruß
Blockmove
 
Ich hab auch die Erfahrung gemacht, dass TIA indizierte Zugriffe auf Elemente jenseits der aktuellen Länge bei der 1500er irgendwie nicht mag.

Gruß
Blockmove

das ist aber in anderen Hochsprachen nicht anders, nehmen wir als Bsp. C / C++, da ist der String mit \0 terminiert, greife ich dahinter rein werde ich das im Programm oder beim beobachten auch nicht sehen. Das ist ehr die korrekte Verwendung der Datentypen die hier ein Problem darstellt.
Wenn man eine Datei löscht auf einem PC, wird auch nur der Datei Index entfernt, nicht aber die eigentlichen taten, ein beschreiben des Datenbereichs ändert aber auch nichts an der Tatsache das die Datei nicht vorhanden / bekannt ist, ein "ähnliches" verhalten ist mit String := ''; wobei der String vorhanden ist aber definiert mit länge 0 und damit leer.

Für mich ist das verhalten so wie es sich hier darstellt absolut nachvollziehbar.

VG
Red-Cali
 
Für mich ist das verhalten so wie es sich hier darstellt absolut nachvollziehbar.
In einen String der aktuellen Länge 0 wird symbolisch hinter dem aktuellen Ende in die für die maximale Länge reservierten Zeichen geschrieben und dadurch meldet der String auf einmal eine aktuelle Länge von 1 - das findest Du nachvollziehbar in Ordnung?

Harald
 
Nachvollziehbar in dem sinn, das nichts sinnvolles rauskommt...

Beim beobachten werden die einzelnen Indexes auch mit '$00' angezeigt.
Das am ende der erste Index dann erkannt wird habe ich glatt übersehen und werde es morgen nachtesten - danke für den hinweis
Möglich das TIA es als concat erkennt wenn man den String von vorn befüllt, also bei eins beginnt...

VG
Red-Cali
 
Zurück
Oben