|
Fällt Ihnen irgendeine wirklich sinnvolle Verwendung der ab
Visual Basic 6 vorhandenen Funktion StrReverse ein? Zu
mehr als einem mehr oder eher weniger lustigen Gag scheint sie wohl
nicht zu gebrauchen zu sein. Denn ein InStrRev gibt es ja auch seit VB
6, so dass das Umkehren eines Strings auch nicht notwendig
ist, um ihn vom Ende her durchsuchen zu können.
Aber da ein String, auf Speicherebene betrachtet, schließlich
nichts anderes als eine Kette von Byte-Werten ist, die ASCII-/ANSI-Zeichen
repräsentieren... oder nichts anderes als eine Kette von
Integer-Werten ist, die Unicode-Zeichen repräsentieren...?
Richtig! Sie können die Funktion StrReverse dazu missbrauchen,
die Reihenfolge der Werte in einem Byte- oder in einem Integer-Array
umzukehren.
Bei einem Byte-Array ist die Angelegenheit harmlos und einfach.
Da die Visual Basic-Syntax es erlaubt, einen String einem Byte-Array
zuzuweisen, und umgekehrt, brauchen Sie sich lediglich um die
richtige Form der Zuweisung kümmern. Da VB intern einen String als
Unicode-String verarbeitet, jedes Zeichen also von 2 Bytes
repräsentiert wird, müssen Sie mit der Funktion StrConv und der
Konstanten vbUnicode dafür sorgen, dass jedes einzelne Byte als ein
Zeichen betrachtet wird. Nach der Umkehrung des Strings durch
StrReverse hat die Zuweisung in umgekehrten Sinne zu erfolgen, wobei
aus jedem Zeichen wieder ein Byte wird. Dafür sorgt wieder die
Funktion StrConv, diesmal mit der Konstanten vbFromUnicode.
Public Function ReverseArrayByte(Bytes() As Byte) As Byte()
Dim nStr As String
nStr = StrConv(Bytes, vbUnicode)
nStr = StrReverse(nStr)
ReverseArrayByte = StrConv(nStr, vbFromUnicode)
End Function
Die Umkehrung eines Integer-Arrays ist ein wenig komplizierter.
Sie müssen nämlich zunächst einmal dafür sorgen, dass das
Integer-Array in ein Byte-Array überführt wird, dann die Umkehrung
vornehmen, und anschließend das sich so ergebende Byte-Array wieder
in ein Integer-Array überführen. Wenn Sie diese Überführungen in
Schleifen erledigen wollten, könnten Sie auch gleich die umgekehrte
Zuordnung vornehmen - der Witz und die Notwendigkeit der
StrReverse-Funktion wären obsolet.
Aber wie Sie ja bereits wissen, sind auch die Integer-Arrays
lediglich eine Folge von Speicherstellen, wobei jeweils zwei
Speicherstellen, also zwei Bytes, eine Integer-Zahl repräsentieren.
Und diese Speicherstellen können blockweise kopiert werden - ein
Integer-Array-Block kann auf einen Byte-Array-Block kopiert werden.
Sie müssen einzig darauf achten, dass der Byte-Array-Block genau so
viele Bytes wie der Integer-Array-Block bereitstellt.
Gehen wir einmal davon aus, dass die Untergrenze eines
umzukehrenden Integer-Arrays standardmäßig 0 sein
soll, dann entspricht die Anzahl der Elemente der Obergrenze des
Arrays plus 1. Die Anzahl der Elemente mit 2
multipliziert ergibt die Anzahl der benötigten Bytes. Die
Obergrenze des Byte-Arrays muss nun wieder um ein (Byte!-)Element
kleiner sein, als die Anzahl der Bytes. Die Anweisung zur
Dimensionierung des Byte-Arrays lautet also:
ReDim ByteArray((UBound(IntegerArray) + 1) * 2 - 1)
Das Kopieren des Speicherblocks übernimmt die API-Funktion CopyMemory
(die eigentlich "RtlMoveMemory" heißt). Sie erwartet
als Parameter die Start-Speicheradresse des Ziels, die
Start-Speicheradresse der Quelle und die Anzahl der zu kopierenden
Bytes. Die Speicheradressen erhalten Sie vom jeweils ersten Element
der beiden Arrays über die undokumentierte VB-Funktion VarPtr.
Beachten Sie, dass die Speicheradressen als Wert zu übergeben sind,
also ausdrücklich mit der Angabe ByVal. Die Anzahl der zu
kopierenden Bytes ergibt sich ganz einfach aus der Obergrenze des
Byte-Arrays plus 1.
Da wir aber nicht auch die Reihenfolge der beiden Bytes eines
jeweiligen Integer-Elements auch umkehren dürfen, erübrigt sich
hier die zur Umkehrung eines Byte-Arrays benötigte
Unicode-Konvertierung. Es reicht, das Byte-Array einfach einem
String zuzuweisen, diesen mit StrReverse umzukehren, und ihn wieder
dem Byte-Array zuzuweisen.
Nun wird das Byte-Array wieder in ein Integer-Array der gleichen
Größe wie die des ursprünglichen Integer-Arrays zurückkopiert -
und schon macht auch ein Integer-Array einen Kopfstand...
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(pDest As Any, pSrc As Any, ByVal ByteLen As Long)
Public Function ReverseArrayInt(Ints() As Integer) As Integer()
Dim nBytes() As Byte
Dim nStr As String
Dim nInts() As Integer
ReDim nBytes((UBound(Ints) + 1) * 2 - 1)
CopyMemory ByVal VarPtr(nBytes(0)), ByVal VarPtr(Ints(0)), _
UBound(nBytes) + 1
nStr = nBytes
nStr = StrReverse(nStr)
nBytes = nStr
ReDim nInts(UBound(Ints))
CopyMemory ByVal VarPtr(nInts(0)), ByVal VarPtr(nBytes(0)), _
UBound(nBytes) + 1
ReverseArrayInt = nInts
End Function
Arrays anderer Datentypen lassen sich auf diese Weise allerdings
nicht umkehren - bei mehr als zwei Bytes je Element kann dieser
Trick ja nicht funktionieren.
|