Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - String hinten an String anhängen
walter_b - Mi 16.07.08 12:04
Titel: String hinten an String anhängen
Hallo zusammen
Welches ist die optimalste Anwendung, um einem String hinten einen anderen anzuhängen? Ich möchte meinem String gerne 14 Nullen anhängen. Und ich habe mich gefragt, welche der verschiedenen Möglichkeiten die schnellste ist:
Delphi-Quelltext
1:
| str:= str+'00000000000000'; |
oder
Delphi-Quelltext
1:
| Insert('0000000000000', str, 1000); |
Oder gibt es eine bessere Lösung? Vielen Dank.
Fabian E. - Mi 16.07.08 12:16
Mit Insert kannst du als letzten Parameter den Index angeben wo der String eingefügt werden soll.
Da musst du halt die Länge der ursprünglichen Strings angeben.
walter_b - Mi 16.07.08 12:21
Und wenn ich die Länge nicht kenne, da sie variabel ist?
Und welche der beiden Varianten ist optimaler?
Fabian E. - Mi 16.07.08 12:22
Die Länge kann man über Length() herrausfinden.
Jerk - Mi 16.07.08 12:37
Ich würd die erste benutzen, da brauch man nich wissen wie Lang der String is.
Narses - Mi 16.07.08 12:45
Titel: Re: String hinten an String anhängen
Moin!
walter_b hat folgendes geschrieben: |
| Welches ist die optimalste Anwendung, um einem String hinten einen anderen anzuhängen? Ich möchte meinem String gerne 14 Nullen anhängen. Und ich habe mich gefragt, welche der verschiedenen Möglichkeiten die schnellste ist: |
Von der Geschwindigkeit her sollte es bei sowas eigentlich egal sein, Probleme gibt es bei diesen "Aktionen" aber an einer anderen Stelle: beim Speicherverbrauch! :shock:
Das ist ist üblicherweise unkritisch:
walter_b hat folgendes geschrieben: |
Delphi-Quelltext 1:
| str:= str+'00000000000000'; | |
Du solltest nur nicht
die Nullen einzeln an den String anfügen, da dann unverhältnismäßig viel Speicher belegt wird. :idea:
cu
Narses
BenBE - Mi 16.07.08 12:47
Je nach dem, wie Du den String aufbaust, kann es aber auch durch Speicher-Zugriffe recht schnell erledigt werden. Voraussetzung dafür ist jedoch, dass Du die entgültige Länge des Strings im Vorhinein kurz berechnen kannst.
In dem Fall kann man nämlich auch das in der Form bauen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| var S: String; PS: ^PChar absolute S; L : Integer; begin L := SetLength(S, L); Inc(PS, L - 14); FillChar(PS^, '0', 14); Inc(PS, 14);
end; |
Zur Erklärung: Durch das Vorausberechnen der Länge erspart man sich das ständige Realloziieren des Stringpuffers.
Alternativ sieht man häufig auch, dass der String auf eine viel größere Länge initialisiert wird, als wirklich benötigt und im Nachhinein auf die eigentliche Länge reduziert wird. Effekt ist ähnlich der Vorgehensweise wie das Vorausberechnen der Länge, jedoch mit dem Unterschied, dass zwei Aufrufe des Speichermnagers notwendig sind, jedoch mit dem Vorteil, dass diese Methode auch mit nicht im Vorhinein bekannten Längenangaben funktioniert, sofern man die maximal mögliche Länge nach OBEN abschätzen kann.
@Narses: Der Speicherverbrauch ist etwa das Doppelte des Resultierenden Strings (incl. Padding). Problematisch ist eher die Speicherfragmentierung, die den Speichermanager unnötig lahm macht.
walter_b - Mi 16.07.08 12:48
Ach so, okee, danke. Aber wegen der Auswirkung: Wenn das 1 Mia mal durchgeführt wird (und das wird es!), dann könnte da ein kleiner Effekt vielleicht doch grössere Auswirkungen haben, deshalb habe ich gefragt.
Boldar - Mi 16.07.08 14:19
ich würde das so lösen:
Delphi-Quelltext
1:
| a:= concat (s1, '0000000000'); |
Dass ist glaube ich die schnellste Variante
nagel - Mi 16.07.08 15:53
Laut Delphi-Hilfe ist + schneller als Concat.
BenBE - Mi 16.07.08 16:10
Und + ist langsamer als direkt im String zu arbeiten ...
walter_b - Mi 16.07.08 20:31
Habe noch festgestellt, dass ich
+#0+#0+#0+#0+#0+#0+#0+#0+#0+#0+#0+#0+#0+#0 schreiben muss, anstelle der 14 Nullen, da ich Null-Bytes brauche und nicht Nullen. Oder gibt es einen eleganteren Weg dafür?
Yogu - Mi 16.07.08 20:52
Nehm doch anstatt von
'0' die zwei Zeichen
#0 - dann wird das Zeichen zum ASCII-Code 0 eingefügt. :idea:
------------------------------------------
Du hast es anscheinend schon selbst herausgefunden.
Eleganter könnte es evlt. so gehen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| var Len: Integer; begin Len := Length(S); SetLength(S, Len+14); FillChar(S[Len+1], 14, #0); end; |
walter_b - Mi 16.07.08 21:04
Wenn ich ehrlich bin: Eleganz ist mir egal. Welches ist von der Geschwindigkeit her schneller?
Fabian E. - Mi 16.07.08 21:57
walter_b hat folgendes geschrieben: |
| Oder gibt es einen eleganteren Weg dafür? |
walter_b hat folgendes geschrieben: |
| Wenn ich ehrlich bin: Eleganz ist mir egal. Welches ist von der Geschwindigkeit her schneller? |
:lol:
Ne aber probiers doch einfach aus was schneller ist ;)
Lass das ganze 1.000.000 mal laufen und guck was schneller war ;)
Boldar - Mi 16.07.08 23:01
Yogu hat folgendes geschrieben: |
Eleganter könnte es evlt. so gehen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| var Len: Integer; begin Len := Length(S); SetLength(S, Len+14); FillChar(S[Len+1], 14, #0); end; | |
Dass ist wohl definitiv der Schnellere Weg, da es "Hardwarenäher" ist
walter_b - Do 17.07.08 16:55
BenBE hat folgendes geschrieben: |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| var S: String; PS: ^PChar absolute S; L : Integer; begin L := SetLength(S, L); Inc(PS, L - 14); FillChar(PS^, '0', 14); Inc(PS, 14);
end; | |
Hab es Ausprobiert. Funktioniert Soweit auch, jedoch wird mir nach FillChar(PS^, '0', 14); und Inc(PS, 14); die Variabeln S und Wort gelöscht. Hier mein Skript:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| var S: String; PS: ^PChar absolute S; L : Integer;
[...]
writeln(wort); L:=14; SetLength(S, L); S:=Wort; writeln(wort); writeln(s); Inc(PS, L - 14); writeln(s); FillChar(PS^, 14, '0'); Inc(PS, 14); writeln(S); writeln(wort); |
Die Ausgaben dazwischen: A, A, A, A, *nichts*, 0 (und beim nächsten Durchgang ist Wort plötzlich 1.)
Edit: kann ich auch anstelle von 0 einen Null-byte reinsetzen? #0 akzeptiert er nicht.
Boldar - Do 17.07.08 17:08
Delphi-Quelltext
1:
| FillChar(PS^, 14, chr(0)); |
walter_b - Do 17.07.08 17:44
Okee, jetzt ist zwar das mit dem Null-byte da, aber die Variabeln werden mir immernoch gelöscht. Warum das? Was läuft hier falsch?
walter_b - Do 17.07.08 19:48
Ich habe jetzt das Skript von Yogu ausprobiert, doch auch hier läuft etwas schief.
Folgendes ist der Code:
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| Len := Length(Wort); SetLength(Wortchen, Len+14); wortchen:=Wort; writeln(Len); FillChar(wortchen[Len+1], 14, 'g' ); writeln(wortchen); |
Diese Werte werden ausgegeben:
Len bei den ersten 10 Durchgängen 1 (richtig so)
Bei wortchen geht er dem Alphabet nach (so wie es das Programm vorschreiben würde). Doch wieso setzt er das G nicht? Ersetze ich diese Zeile durch
Delphi-Quelltext
1:
| FillChar(wortchen[Len], 14, 'g' ); |
dann habe ich immer an der ersten Stelle ein g, während der rest normal weitergeht. Aber wieso ignoriert er die 14?
BenBE - Do 17.07.08 21:32
Sorry, bei dem PChar absolut S war ein ^ zu viel ... Ohne sollte es gehen ...
walter_b - Do 17.07.08 22:37
---
Moderiert von
Narses: Beiträge zusammengefasst---
BenBE hat folgendes geschrieben: |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| var S: String; PS: PChar absolute S; L : Integer; begin L := SetLength(S, L); Inc(PS, L - 14); FillChar(PS^, '0', 14); Inc(PS, 14);
end; | |
Wie genau stellst du dir das füllen des Strings vor? Mit S:=Wort; löscht es bei mir die Variabel Wort.
Und L ist die schlussendliche Länge des ganzen Strings, also nach einfüllen der 0en und allem, oder?
Hier nochmal mein Skript, habe noch bisschen rumgespielt, aber geht irgendwie nicht.
So gibt es eine Invalid Pointer Operation. Wird wortchen:=S auskommentiert, "funktioniert" es zwar, jedoch wird die Variabel Wort manipuliert, stimmt also nicht mehr. Wahrscheinlich aufgrund von Pointer!?
Edit: Danke an Narses, wollte das erste Posting eigentlich löschen, aber ging nicht ;)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!