Entwickler-Ecke
Sonstiges (Delphi) - HEX - Bestimmte stelle ändern
fuba - Mi 21.11.07 07:13
Titel: HEX - Bestimmte stelle ändern
hi,
Nehmen wir mal man, mein HEX code ist dieser: $000133FF als Fixwert.
Bzw -> 00 01 33 FF
Nun kommt ne schleife.
In dieser soll nach jedem durchlauf, die Stelle wo jetzt $33 steht aus 0001
33FF um $05 (also HEX 5) erhöhen werden.
Beispiel:
Schleife hat 3 durchgänge:
Durchgang 1 -> aus $000133FF wird $000138FF
Durchgang 2 -> aus $000138FF wird $00013DFF
Durchgang 3 -> aus $00013DFF wird $000142FF
also meine anfangszahl ist $000133FF und meine endzahl währe dann $000142FF
3x$5 = $0F also $33 + $0F = $42
deswegen wird aus $000133FF auch $000142FF
aber egal was passiert, es soll IMMER die stelle, wo mal
33 war verändert werden.
Gibts da ne einfache variante?
Moderiert von
jasocul: Topic aus Delphi Language (Object-Pascal) / CLX verschoben am Mi 21.11.2007 um 08:06
Kroko - Mi 21.11.07 08:07
Wo ist das Problem?
(1) Stelle suche -> merken
(2) Schleife
oder
(1) Schleife
(2) Stelle+5*I suchen -> ändern
jasocul - Mi 21.11.07 08:11
Hat das einen besonderen Grund, warum Du nicht gleich um $0F erhöhst?
Falls Du es wirklich in 3 Durchläufen machen musst, dann musst Du Dir im ersten Durchlauf alle Stellen merken. Dafür bietet sich z.B. ein dynamisches Array an.
fuba - Mi 21.11.07 08:56
| Zitat: |
Wo ist das Problem?
(1) Stelle suche -> merken
(2) Schleife
oder
(1) Schleife
(2) Stelle+5*I suchen -> ändern
|
wie soll ich das machen?
die HEX Zahl $000133FF ist nur ein beispiel, was währe wenn die HEX Zahl aber 00111111 ist, dann hätte ich 3 stellen die 11 enthalten -> 00
11 11 11
wie soll ich das machen, genau diesen wer immer zu erhöhen -> 00 11
11 11 ?
weil wenn ich den Wert: 00 11
11 11 um 1 erhöhe, sollte dann 00 11 12 11 rauskommen.
Nechste runde will ich 00 11
12 11 um 1 erhöhen -> also auf 00 11 13 11
usw..
wobei der wert "1" um den ich erhöhen will nur ne "Hausnummer" ist, dies kann auch 2,3,4 oder gar AF, 1F, oder ähnliches sein.
Aber nur DER eine wert soll erhöht werden, das will ich damit genau fragen :)
Sorry wenn ich das etwas unverständlich schreibe!
| Zitat: |
Hat das einen besonderen Grund, warum Du nicht gleich um $0F erhöhst?
Falls Du es wirklich in 3 Durchläufen machen musst, dann musst Du Dir im ersten Durchlauf alle Stellen merken. Dafür bietet sich z.B. ein dynamisches Array an.
|
Ne ich könnte genausogut auch gleich um $0F erhöhen, oben hab ich das nur als beispiel geschrieben, um allen klar zu machen, ich möchte IN JEDEM FALL nur diese stelle (anfangs 33) erhöhen.
Kroko - Mi 21.11.07 09:12
Steht die Zahl (4Byte) denn wenigstens immmer auf einer Position für die (Position mod 4)=0 ist? Ansonsten sehe ich schwarz!
jasocul - Mi 21.11.07 09:59
Wenn Du nicht alle gleichen Werte verändern willst, sondern nur einen, obwohl noch andere gleiche existieren, dann musst Du vorher wissen, wo er steht. Ansonsten kannst Du den zu ändernden Wert ja nicht mal finden.
fuba - Mi 21.11.07 10:13
Kroko hat folgendes geschrieben: |
| Steht die Zahl (4Byte) denn wenigstens immmer auf einer Position für die (Position mod 4)=0 ist? Ansonsten sehe ich schwarz! |
wenn du damit meinst, ob die selle an der
33 anfangs stand, immer an der stelle bleibt, egal ob diese über FF oder unter FF geht, dann ja.
also:
anfangs -> 00 11
11 11
nach xx erhöhung -> 00 11
xx 11
xx bleibt immer an der gleichen stelle und wander
nicht einen wert vor.
also wird nicht zu: 01 1
x x1 11
gelöst ahbe ich das ganze ja schon, ABER die lösung gefällt mir garnicht, keine ahnung warum, aber ich hab nen schlechtes gefühl dabei :D
Hier wird der HEXCode aber nicht gesplittet übergeben also nicht 00 11 11 11 sondern 00111111.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| function test(aHexCode: string): string; var HexBH: string; DecBH, myPos: integer; begin myPos:=Length(aHexCode)-3; HexBH := copy(aHexCode, myPos, 2); DecBH := StrToInt('$'+HexBH) -$17; HexBH := format('%x', [DecBh]); if Length(HexBH) > 2 then Delete(HexBH, 1, Length(HexBH)-2); Delete(aHexCode, myPos, 2); insert(HexBH, aHexCode, myPos); result := aHexCode; end; |
Das is ein wenig komplizierter, da ich in meiner funktion nicht addiere sondern subtrahiere ;)
Kroko - Mi 21.11.07 10:28
Und warum wandelst du die Hex-werte in Strings um? Die kommen doch sicherlich aus einer Datei/einem Stream, Lies diese in ein array of Byte, bestimme die Position und ändere den entsprechenden Wert mit Inc/Dec!
fuba - Mi 21.11.07 10:58
Kroko hat folgendes geschrieben: |
| Und warum wandelst du die Hex-werte in Strings um? Die kommen doch sicherlich aus einer Datei/einem Stream, Lies diese in ein array of Byte, bestimme die Position und ändere den entsprechenden Wert mit Inc/Dec! |
und da haben wir den salat :P
ich hab NULL ahnung von arrays :(
warum ich das so macht -> HEX to String ist genau deswegen...
aber das gefällt mir schon sehr gut, ich meine die idee alleine :)
was muss ich aber bei arrays beachten bzw was muss ich tun um das zu verstehen?
Kroko - Mi 21.11.07 13:27
(1) Du kennst die Länge der Arrays schon zur Programmierung -> statisches Array ->
Delphi-Quelltext
1: 2: 3: 4:
| type TMyArray = array[0..Laenge-1] of Byte; var A: TMyArray; |
oder
(1) Du kennst die Länge des Arrays erst während der Laufzeit -> dynamisches Array ->
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| type TMyArray = array of Byte; var A: TMyArray;
procedure InitArray(const ALen: Integer); begin SetLength(A,ALen); end;
procedure DoneArray; begin Finalize(A); end; |
so dass war es schon der Zugriff erfolgt in beiden Fällen über
und schaust Du
dort [
http://www.dsdt.info/grundlagen/sprache/komdatentypen.php]
fuba - Mi 21.11.07 17:18
hmm, eine frage noch
wie bekommte ich den gesammten code aus einem array raus?
mein statisches array ist:
array[0..3] of byte
Key[0]:=$00;
Key[1]:=$01;
Key[2]:=$11;
Key[3]:=$11;
rechenvorgang funzt auch.
aber wenn ich jetzt den gesammten KEY haben will, sollte dieser dann (unbearbeitet) $00011111 sein... nur wie?
ich kann den zwar mit:
Delphi-Quelltext
1: 2: 3: 4: 5:
| s:=''; for i:=0 to high(key) do begin s:=s+IntToHex(Key[i],2); end; |
rausholen, aber so soll das ja auch nicht sein oder?
Kroko - Mi 21.11.07 17:41
so
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| function ArrayToKey(const A: array[0..3] of Byte): Cardinal; var I: Integer; begin Result := 0; for I := 0 to 3 do begin Result := (Result shl 8) or A[I]; end; end; |
fuba - Mi 21.11.07 19:07
danke dir, deine funktion funzt
zwar musste ich bei array die [0..3] wegnehmen, aber es geht :D
nur jetzt hab ich bemerkt, ich hab doch nen fehler in meiner routine...
und zwar:
KEY[2]:=$11
KEY[3]:=$11
wenn ich KEY[3] um ff erhöhe bekomme ich 110 und dann sollte ich KEY[2] auf 12 erhöhen wobei KEY[3] 10 wird.
Das passiert aber nicht, weil ich ier nur mit den einzellnen array rechne, und nicht mit dem gesammten.
was ich eigentlich will:
FFFFFFFF aufteilen in FF FF FF FF und jede einzellne stelle extra rechnen können,
aber sollte eine stelle über FF gehen die nächste stelle mit einbezogen werden.
dachte nicht dass das so schwer wird :/
Kroko - Mi 21.11.07 19:15
dann lass es mit dem Array und nimm ein Cardinal und
Delphi-Quelltext
1: 2: 3: 4:
| A := A+AByte ; A := A+($100*AByte); A := A+($10000AByte); A := A+($1000000*AByte); |
ungetestet ev. musst Du AByte erst einem Cardinal zuweisen
fuba - Do 22.11.07 06:54
Kroko hat folgendes geschrieben: |
dann lass es mit dem Array und nimm ein Cardinal und
Delphi-Quelltext 1: 2: 3: 4:
| A := A+AByte ; A := A+($100*AByte); A := A+($10000*AByte); A := A+($1000000*AByte); |
ungetestet ev. musst Du AByte erst einem Cardinal zuweisen |
das funktioniert wenn ich den ganzen hex in der rechenroutine verwenden will, aber nicht wenn ich nur 1 byte hex ändern will.
----
Meine neue idee:
Da mich das array of byte schonmal näher gebracht hat, dachte ich mir:
1.)
array of byte deffinieren -> is klar
2.)
normaler rechenvorgang mit hex plus hex -> 00011111 + FF = 00011210 -> is klar
(hier will ich ja noch die GANZE hexzahl ändern, also wenn eine Zahl größer ist als FF darf diese überspringen)
3.)
HexZahl welche bei mir 00011210 ist, in array of byte laden. -> keine ahnung wie?
sodas diese gesplittet ist also würde ich es per hand ins array eintragen.
Sollte dann circa so aussehen:
Ganzes Array = 00111210
array[0]:=$00;
array[1]:=$01;
array[2]:=$12;
array[3]:=$10;
4.)
array[3] welches dann $12 sein soll minus $22 rechnen was dann $F0 erbibt, da das ergbinis nicht überspringen kann.
5.)
dann wieder array of byte (das komplette) in eine ganze zahl speichern (integer oder cardinal).
dafür hast du mir ja schon die funktion geopstet und diese funktioniert auch!
----
Das problem liegt jetzt alleine an dem:
Wie bekomme ich meine GANZE HEXZahl (00011210), geteilt in ein array of byte?
Wenn ich das schaffe, dann sollte das ganze funktionieren.
P.S
Tut mir echt leid dich damit so lange zu quelen... :)
PPS.
Konnte gestern nicht mehr zurückschreiben, war völlig tot am abend :P
fuba - Do 22.11.07 10:18
so, hab das jetzt geschafft.
Hex in array of byte speichern wie ich es mir dachte, also so:
00012233 in array of byte:
array[1]:=$00;
array[2]:=$01;
array[3]:=$22;
array[4]:=$33;
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
| var a: array of byte;
implementation
{$R *.dfm}
...
var tempStr, Hex: string; i, len: integer; begin Hex:='EE01FF44';
Len := Length(Hex) div 2; SetLength(a, Len+1); for i := 1 to Len do begin tempStr:='$'+copy(Hex, i*2-1, 2); a[i]:=byte(StrToInt(tempStr)); end; end; |
und wieder zurück in cardinal bzw von chardinal nach HexString:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| var c, i: integer; Hex: string; begin for i:=low(a) to high(a) do begin c:= (c shl 8) or a[i]; end; hex:=IntToHex(c, 8); |
nur verstehe ich noch nicht, was genau dein code macht.
also das hier:
Delphi-Quelltext
1:
| c:= (c shl 8) or a[i]; |
kannst du mir das genauer beschreiben?
ich weis zwar SHL bedeuter, das du (hier "c") um 8 stellen nach links verschiebst.
aus der Delphi-Hilfe:
Quelltext
1: 2: 3:
| SHL Logische Linksverschiebung. Beide Ausdrücke müssen absolute, direkte Werte sein. Das Ergebnis ist ebenfalls ein absoluter direkter Wert. |
aber warum machst du das und was mach das OR?
habe zwar aus der Delphi-Hilfe das:
Quelltext
1: 2: 3:
| OR Bitweises OR. Beide Ausdrücke müssen absolute, direkte Werte sein. Das Ergebnis ist ebenfalls ein absoluter direkter Wert. |
aber das versteh ich nicht.
Kroko - Do 22.11.07 11:50
(1) zu SHL mal Bitweise aufgesplittet
Delphi-Quelltext
1: 2: 3: 4: 5:
| A := 1; B := A shl 1; C := A shl 2; D := A shl 8; |
usw. usf.
d.h shl 8 entspricht einer Multiplikation mit $100=256, nur eben schneller
(2) entpricht dem logischen OR nur Bitweise, man kann auch den Wert addieren, da nach dem shl 8 rechts die 8 Bits = 0 sind
Delphi-Quelltext
1: 2: 3: 4:
| A := 2; B := A shl 8; C := B or $34;D := B + $34; |
TProgger - Do 22.11.07 11:58
Der einfachste Weg wäre doch, die Zahl als Ganzes zu nehmen (Cardinal).
Hexwert in Zahl umwandeln:
Delphi-Quelltext
1:
| StrToInt('$'+HexString); |
Will man die linken zwei Stellen erhöhen, addiert man zur Zahl z.B. 3 * 1048576. (Ergebnis in Hex: 03000000).
Will man die nächsten zwei Stellen erhöhen, addiert man zur Zahl z.B. 3 * 65536. (Ergebnis in Hex: 00030000).
Will man die nächsten zwei Stellen erhöhen, addiert man zur Zahl z.B. 3 * 256. (Ergebnis in Hex: 00000300).
Will man die rechten zwei Stellen erhöhen, addiert man zur Zahl einfach den Wert, z.B. 3. (Ergebnis in Hex: 00000003).
Vorteil: man brauch nur mit einer ganzen Zahl zu arbeiten und IntToHex liefert dann wieder die Hex-Anzeige.
fuba - Do 22.11.07 12:12
achso, das ist schon ein bisschen verständlicher :)
aber wenn dem so ist, hast du nen schreibfehler :D
dein code:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| A := 1; B := A shl 1; C := A shl 2; D := A shl 8; E := A shl 4 |
--
und das OR ist im prinzip ne einfache addition oder kann ich z.b:
$1000 or 10 = $1000 +$10 ?
oder muss ich das wie ein einfaches PLUS handhaben, also:
$1000 or $10 = $1000 + $10 ?
fuba - Do 22.11.07 12:20
TProgger hat folgendes geschrieben: |
Der einfachste Weg wäre doch, die Zahl als Ganzes zu nehmen (Cardinal).
Hexwert in Zahl umwandeln:
Delphi-Quelltext 1:
| StrToInt('$'+HexString); |
Will man die linken zwei Stellen erhöhen, addiert man zur Zahl z.B. 3 * 1048576. (Ergebnis in Hex: 03000000).
Will man die nächsten zwei Stellen erhöhen, addiert man zur Zahl z.B. 3 * 65536. (Ergebnis in Hex: 00030000).
Will man die nächsten zwei Stellen erhöhen, addiert man zur Zahl z.B. 3 * 256. (Ergebnis in Hex: 00000300).
Will man die rechten zwei Stellen erhöhen, addiert man zur Zahl einfach den Wert, z.B. 3. (Ergebnis in Hex: 00000003).
Vorteil: man brauch nur mit einer ganzen Zahl zu arbeiten und IntToHex liefert dann wieder die Hex-Anzeige.
|
sollte die zahl über oder unter FF gehen, also:
sagn wir mal ich habe in HEX:
22FA3333
jetzt addiere ich zu den FA mal $07 dazu, würde ja die zahl dann so aussehen:
23013333
also kurz:
22FA3333 + 00070000 = 23013333
und genau das will ich nicht.
so wie ich es mache, sieht dann die zahl so aus: 22013333
weil ich nur die stelle erhöche, wo vorher FA war und nicht die nähste auch noch.
Kroko - Do 22.11.07 12:58
fuba hat folgendes geschrieben: |
...
// mein zusatz
E := A shl 4 // müsste dann 16 sein oder?
[/delphi] |
Richtig!
Schreibfehler: na klar, muss 4 sein
fuba hat folgendes geschrieben: |
--
und das OR ist im prinzip ne einfache addition oder kann ich z.b:
$1000 or 10 = $1000 +$10 ?
oder muss ich das wie ein einfaches PLUS handhaben, also:
$1000 or $10 = $1000 + $10 ? |
Bitweise schon, in anderen Fällen gibt es Probleme
$10+$10 = $20
$10 or $10 = $10
fuba - Do 22.11.07 13:58
hmm, glaub das mit OR muss ich mir noch genauer ansehen, aber da ist eine andere geschichte :)
Danke dir vielmals für deine hilfe!
TProgger - Do 22.11.07 14:09
ach du willst nur Byteweise rechnen?
Dann zerleg den String in Zweiergruppen, nimm die zwei Zeichen die du willst, rechne sie mit Zahl:=IntToStr('$'+Zeichen) in eine Zahl um, rechne deinen Wert dazu, wenn das ergebnis grüßer 255 ist, subtrahiere einfach 256, dann wieder IntToHex(Zahl,2) und füg sie wieder ein. Das müsste genau das machen, was du willst ;)
fuba - Do 22.11.07 15:33
TProgger hat folgendes geschrieben: |
ach du willst nur Byteweise rechnen?
Dann zerleg den String in Zweiergruppen, nimm die zwei Zeichen die du willst, rechne sie mit Zahl:=IntToStr('$'+Zeichen) in eine Zahl um, rechne deinen Wert dazu, wenn das ergebnis grüßer 255 ist, subtrahiere einfach 256, dann wieder IntToHex(Zahl,2) und füg sie wieder ein. Das müsste genau das machen, was du willst ;) |
das mache ich ja indem ich den hex in array of byte lade.
Dort kann ich dann mit jeder 2er gruppe einzelln rechnen und dann gebe ich das wieder als ganzen hex aus.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:
| var a: array of byte; Dec, Len, j: integer; HexBH: string;
...
hex:='0001FA11';
Len := Length(Hex) div 2; SetLength(a, Len+1);
for j:=1 to Len do begin HexBH := '$'+copy(Hex, j*2-1, 2); a[j] := byte(StrToInt(HexBH)); end;
a[3] := a[3] + $07; for j:= low(a) to high(a) do begin dec := (dec shl 8) or a[j]; end;
hex:=IntToHex(Dec, 2); |
oder gibts da ne einfachere methode?
Ich mein "zerleg den String in Zweiergruppen, nimm die zwei Zeichen die du willst, rechne sie mit" ist ja schön gesagt, nur wie mache ich das?
00011111 in 2er gruppen zerlegen -> 00 01 11 11 aber wie?
und wenn ich dann die 2er gruppen habe, wie fürge ich diese wieder in einen ganzen Hex?
also kurz:
0001FA11 -> 00 01 FA 11 -> 00 01 (FA+07) 11 -> 00 01 01 11 -> 00010111
wenns dafür ne einfache methode gibt ... und du die kennst ... währe das natürlich echt toll :)
TProgger - Do 22.11.07 15:59
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| / Rechenvorgang in 2er gruppe a[3] := a[3] + $07; for j:= low(a) to high(a) do begin dec := (dec shl 8) or a[j]; end;
hex:=IntToHex(Dec, 2); |
Warum nicht so:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| var Z: Integer; hex: String;
ResultString := a[0]+a[1]+a[2]+a[3]... Z:=StrToInt('$'+a[3]); Z := Z + DeineZahl; if Z > 255 then Z := Z - 256;
hex:=IntToHex(Z, 2); a[3]:=hex; |
So würde ich das machen, ganz ohne Schieberei :)
fuba - Do 22.11.07 16:41
TProgger hat folgendes geschrieben: |
Warum nicht so:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| var Z: Integer; hex: String;
ResultString := a[0]+a[1]+a[2]+a[3]... Z:=StrToInt('$'+a[3]); Z := Z + DeineZahl; if Z > 255 then Z := Z - 256;
hex:=IntToHex(Z, 2); a[3]:=hex; |
So würde ich das machen, ganz ohne Schieberei :) |
hmm, im großen und ganzen speicherst du dann den Hex in ein array of string oder?
wenn ja, könnte man es auch so machen:
mein Anfangs Hex = 00011111
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| var Hex, Hex2: string; z: integer; begin Hex:='00011111'; z:=StrToInt('$' + Hex[5] + Hex[6]);
z := z - $17; if z > 255 then z:= z - 256; if z < 0 then z:= z + 256;
Hex2:=IntToHex(z, 2);
Hex[5]:=Hex2[1]; Hex[6]:=Hex2[2]; end; |
mein End Hex = 00010122
hmm ... verdammt, warum bin ich da nicht früher draufgekommen, also sind arrays eigentlich garnicht nötig....
Aber danke für deine rechenformal, die hat mir da sehr geholen, sonnst könnte ich das garnicht so machen ^_^
// edit
obwohl ich gerade bemerkt habe:
00 01
11 11
diese $11 - $17 ergibt -> FF FF FF FA und das auch mit deiner methode
habe das aber auch schon im obrigen code gelöst, hoffe das stimmt so.
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!