|
Das deutsche QBasic- und FreeBASIC-Forum Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
Dusky_Joe
Anmeldungsdatum: 07.01.2005 Beiträge: 1007 Wohnort: Regensburg/Oberpfalz
|
Verfasst am: 13.05.2005, 19:39 Titel: Komplettes Array in einem Schritt kopieren |
|
|
Hi Community!
Ich habe momentan ein Programm, indem aus einem Array ein Element gelöscht werden soll. REDIM PRESERVE fällt also aus.
Bis jetzt habe ich die Standard-QB-Lösung benutzt:
Temporäres Array erstellen, Elemene aus dem Original ins Temp kopieren, original redimensionieren, und wieder zurückkopieren.
Leider muss ich das nicht nur bei einem Array machen, sondern bei... 5 oder so...
Und eines davon ist als UDT (User defined Type) dimensioniert. Heißt: Viele Zeilen, unübersichtlicher Code, da die Sub, die's übernimmt noch andere Aufgaben hat...
Und ein zweites ist zweidimensional, was den aufwand nochmal steigert.
Außerdem denke ich, dass diese Lösung nicht gerade die schnellste ist...
Meine Frage: Ist es möglich, ein ganzes Array mit einem Schritt in ein anderes zu kopieren?
Die Lösung darf ruhig "fortgeschrittene Techniken" enthalten, ich muss mich damit sowiso auseinandersetzen.
Ansonsten versuch ich's, das ganze via Speicherzugriff zu lösen...
Größe des Arrays ermitteln (LEN, oder SIZEOF), String mit entsprechender Länge als TMP, und dann mit PEEK...
Im Voraus schon mal danke für die Ideen! _________________ fully biological degradable
Once, the big wave arrives, you've got two ways, you can go:
Either, you ride it, or you don't do.
But, if you don't ride, you'll never know wether you'd have gone wet. |
|
Nach oben |
|
|
PeterHarder
Anmeldungsdatum: 27.03.2005 Beiträge: 45 Wohnort: Deutschland
|
Verfasst am: 13.05.2005, 20:25 Titel: |
|
|
Zum verschieben der Inhalte kannst du die folgende API-Funktion nehmen, die in der "Kernel32.bi" deklariert ist:
Code: | Declare Sub MoveMemory Alias "RtlMoveMemory" (pDestination As ANY, pSource As ANY, ByVal cbLength As Integer) |
_________________ Deutsche Mailingliste für freeBASIC: de.groups.yahoo.com/group/free-basic.
Zum Anmelden einfach eine leere E-Mail an free-basic-subscribe@yahoogroups.de senden. |
|
Nach oben |
|
|
Dusky_Joe
Anmeldungsdatum: 07.01.2005 Beiträge: 1007 Wohnort: Regensburg/Oberpfalz
|
Verfasst am: 13.05.2005, 21:17 Titel: |
|
|
Danke, perfekt!
Ich nehme mal an, dass das unter Linux nicht funtkioniert, oder..?
Und cbLength gibt wohl die Länge in Bytes an, oder?
Du kennst dich anscheinend ziemlich gut mit den API-Funktionen aus. Kennst du eine besondere Seite, von der du die ganzen Infos holst, oder hast du dir das alles aus den Fingern (und den BI's) gesaugt?
Ich überlege nämlich, in die FB-Referenz eine kleine Sammlung an API-Funktionen mit Erklärung aufzunehmen, Thematisch geordnet, und da ich selbst bis jetzt noch nicht viel Erfahrung damit habe, bin ich für jeden Link und jedes Tutorial dankbar... _________________ fully biological degradable
Once, the big wave arrives, you've got two ways, you can go:
Either, you ride it, or you don't do.
But, if you don't ride, you'll never know wether you'd have gone wet. |
|
Nach oben |
|
|
volta
Anmeldungsdatum: 04.05.2005 Beiträge: 1875 Wohnort: D59192
|
Verfasst am: 13.05.2005, 22:06 Titel: |
|
|
Hallo,
mich würde sehr interessieren ob schon jemand Erfahrung mit der Funktion hat?
Ich leider nicht, aber nach der folgenden Beschreibung
@Dusky_Joe, schau mal unter http://www.vbarchiv.net/vbapi/_alpha.php
Zitat: | Declare Sub MoveMemory Lib "kernel32.dll" Alias "RtlMoveMemory" _
(Destination As Any, Source As Any, ByVal Length As Long)
Beschreibung:
Diese Funktion kopiert den Inhalt einer Variable in eine andere. Wird oftmals benötigt, wenn man die Variablen oder die Speicheradresse einer Variable einer Funktion übergeben muss.
Parameter:
Destination Zielvariable, in welche die Daten kopiert werden sollen. Wird ein Pointer zu einer Variable in Form eines Strings oder einer Long-Variable übergeben, so müssen diese Werte mit "ByVal" initialisiert werden.
Source Quellvariable, deren Daten (Inhalt) kopiert werden sollen. Wird ein Pointer zu einer Variable in Form eines Strings oder einer Long-Variable übergeben, so müssen diese Werte mit "ByVal" initialisiert werden.
Length Anzahl der zu kopierenden Bytes
|
würde ich so vorgehen...
; Array mit A B C D E F G . . . Elementen
; C wird gelöscht, D soll nach C, E->D usw G ist letzter Datensatz/Variable
1. prüfen ob Array gefüllt / angelegt ist. Wie (leider keine Ahnung, evtl bei 4. Length muss >0 sein)?
2. Destination = @C
3. Source = @D
4. Length = (@G - @C)-1 ( -> sollte gleiche Länge wie D bis Ende G sein)
5. MoveMemory
6. Datensatz/Variable von G löschen, da jetzt in F
Gruß
Volta _________________ Warnung an Choleriker:
Dieser Beitrag kann Spuren von Ironie & Sarkasmus enthalten.
Zu Risiken & Nebenwirkungen fragen Sie Ihren Therapeuten oder Psychiater.
Zuletzt bearbeitet von volta am 13.05.2005, 23:01, insgesamt einmal bearbeitet |
|
Nach oben |
|
|
PeterHarder
Anmeldungsdatum: 27.03.2005 Beiträge: 45 Wohnort: Deutschland
|
Verfasst am: 13.05.2005, 22:17 Titel: |
|
|
Der Tipp von Volta ist gut, vor allem, wenn es in Deutsch sein soll.
Falls es mehr sein soll und in Englisch sein darf: such mal per Google nach "Win32.hlp", evtl. kombiniert mit dem Suchbegriff "download". Da ist aber so viel drin, dass es dich erschlägt (außerdem in Englisch).
Praktische VB-Api-Beispiele findest du in der Offline-Version vom "Api-Guide", auch mal per Google nach suchen, die Beispiele kann man leicht nach freeBASIC umsetzen.
Außerdem empfehlenswert: Das PowerBasic-Offline-Forum mir 2500 Beispielcodes, kann man gut nach API-Schlüsselwörter durchsuchen, um praktische Programmierbeispiele zu finden:
http://www.reonis.com/POFFS/
Dort "POFFS v2.30" downloaden.
Liebe Grüße
Peter _________________ Deutsche Mailingliste für freeBASIC: de.groups.yahoo.com/group/free-basic.
Zum Anmelden einfach eine leere E-Mail an free-basic-subscribe@yahoogroups.de senden. |
|
Nach oben |
|
|
Dusky_Joe
Anmeldungsdatum: 07.01.2005 Beiträge: 1007 Wohnort: Regensburg/Oberpfalz
|
Verfasst am: 16.05.2005, 18:21 Titel: |
|
|
Zum testen der Funktion habe ich mal diesen Code eingegeben.
Im Idealfall sollte nach Ablauf des Codes jede der drei Variablen zehn werte (von 10 bis 1) enthalten.
Das Ergebnis sieht aber anders aus...
Code: |
'$DYNAMIC
Declare Sub MoveMemory Alias "RtlMoveMemory" (pDestination As ANY, _
pSource As ANY, _
ByVal cbLength As Integer)
dim a(9) as byte
dim b as byte ptr
dim c as string
for i = 0 to 9
a(i) = 10 - i
next
size = len(a) * (ubound(a) + 1)
b = allocate(size)
c = space$(size)
print "Vor der Speicheroperation"
print "Variable:", "Wert", "Adresse"
print "a(0)", a(0), @a(0)
print "b[0]", b[0], b
print
MoveMemory b, @a(0), size
poke byte, @a(0), 5
print "Vor der Redimensionierung"
print "Variable:", "Wert", "Adresse"
print "a(0)", a(0), @a(0)
print "b[0]", b[0], b
print
for i = 0 to size - 1
mid$(c, i + 1, 1) = chr$(b[i])
next
redim a(4)
print "Nach der Redimensionierung"
print "Variable:", "Wert", "Adresse"
print "a(0)", a(0), @a(0)
print "b[b]", b[0], b
print
print "der C-String:"
for i = 1 to size - 1
print asc(c, i); ",";
next
print asc(c, i)
getkey
|
Ergebnis:
Code: |
Vor der Speicheroperation
Variable: Wert Adresse
a(0) 10 3290912
b[0] 120 3290936
Vor der Redimensionierung
Variable: Wert Adresse
a(0) 5 3290912
b[0] 5 3290912
Nach der Redimensionierung
Variable: Wert Adresse
a(0) 0 3291056
b[b] 0 3290912
der C-String:
5,9,8,7,6,5,4,3,2,1 |
die 120 beim ersten b[0] dürfte einfach nur Speichermüll sein, der durch CALLOCATE unterdrückt werden sollte...
Interessant ist, dass bei "Nach dem Speicherzugriff" die Adresse von a und b die selbe ist.
Und der Umweg über den String ist natürlich für eine Benutzung in einem Programm zu lange...
Deswegen hab ich mir kurzerhand ne kleine Alternative geschrieben:
Code: |
Declare sub CopyMem (byval Ziel as integer, _
byval Quelle as integer, _
byval Bytes as integer)
dim a(9) as byte
dim b(9) as byte
for i = 0 to 9
a(i) = 10 - i
next
CopyMem @b(0), @a(0), 10
for i = 0 to 9
print a(i), b(i)
next
getkey
sub CopyMem (byval Ziel as integer, _
byval Quelle as integer, _
byval Bytes as integer)
for b = 0 to Bytes - 1
poke byte, Ziel + b, peek(byte, Quelle + b)
next
end sub |
Funktioniert Prima, nur fürchte ich, es ist nicht unbedingt der schnellste Code.
Habt Ihr Ideen zur Optimierung? _________________ fully biological degradable
Once, the big wave arrives, you've got two ways, you can go:
Either, you ride it, or you don't do.
But, if you don't ride, you'll never know wether you'd have gone wet. |
|
Nach oben |
|
|
PeterHarder
Anmeldungsdatum: 27.03.2005 Beiträge: 45 Wohnort: Deutschland
|
Verfasst am: 16.05.2005, 19:33 Titel: |
|
|
MoveMemory ist "ByRef" deklariert (weil nichts davor steht), d.h. die musst die Variable direkt übergeben und nicht den Pointer auf die Variable (als die @-Zeichen entfernen). Wenn du gerne die Pointer übergeben möchtest, dann deklariere explizit "ByVal", dann geht es auch mit StrPtr() oder @ einer einen Variablen, die den Pointer enthält.
Folgender Code liefert ein korrektes Ergebnis:
Code: | Declare Sub MoveMemory Alias "RtlMoveMemory" _
(pDestination As Any, _
pSource As Any, _
ByVal cbLength As Integer)
Dim a(9) As Byte
Dim b(9) As Byte
For i = 0 To 9
a(i) = 10 - i
Next
MoveMemory b(0), a(0), 10
For i = 0 To 9
Print a(i), b(i)
Next
GetKey |
_________________ Deutsche Mailingliste für freeBASIC: de.groups.yahoo.com/group/free-basic.
Zum Anmelden einfach eine leere E-Mail an free-basic-subscribe@yahoogroups.de senden. |
|
Nach oben |
|
|
Dusky_Joe
Anmeldungsdatum: 07.01.2005 Beiträge: 1007 Wohnort: Regensburg/Oberpfalz
|
Verfasst am: 16.05.2005, 19:48 Titel: |
|
|
Warum einfach, wenns auch kompliziert geht
Hat schon mal jemand getestet, wie die Win-Version im Vergleich zur PEEK/POKE-Version in Hinblick auf die Geschwindigkeit aussieht, bzw kann jemand Prognosen abgeben?
Und: Bei meinem (fehlerhaften) Code sieht man ja, dass nach dem Aufruf die Adresse von b und a die selbe ist. Wird dieser Effekt immer auftreten, wenn Pointer übergeben werden?
Thx! _________________ fully biological degradable
Once, the big wave arrives, you've got two ways, you can go:
Either, you ride it, or you don't do.
But, if you don't ride, you'll never know wether you'd have gone wet. |
|
Nach oben |
|
|
PeterHarder
Anmeldungsdatum: 27.03.2005 Beiträge: 45 Wohnort: Deutschland
|
Verfasst am: 17.05.2005, 17:47 Titel: |
|
|
Hallo Dusky,
ich hab' gestern noch was vergessen: Wenn ein Parameter "ByRef" deklariert ist, dann kannst du auch beim Aufruf "ByVal" davorschreiben - der Inhalt der Variablen wird dann trotz ByRef-Deklaration per ByVal übergeben. Das ist manchmal notwendig, wenn eine Api-Funktion die Adresse eines Speicherbereiches zurückgibt.
Die Adressen der beiden Variablen müssen natürlich weiterhin unterschiedlich sein, warum das bei deinem Beispiel nicht so war, habe ich aus Zeitgründen nicht weiter untersucht.
Hier das leicht geänderte Beispiel mit eingefügtem "ByVal" beim Aufruf (das @-Zeichen kann dann stehen bleiben):
Code: | Declare Sub MoveMemory Alias "RtlMoveMemory" _
(pDestination As Any, _
pSource As Any, _
ByVal cbLength As Integer)
Dim a(9) As Byte
Dim b(9) As Byte
For i = 0 To 9
a(i) = 10 - i
Next
MoveMemory ByVal @b(0), ByVal @a(0), 10
For i = 0 To 9
Print a(i), b(i)
Next
GetKey |
_________________ Deutsche Mailingliste für freeBASIC: de.groups.yahoo.com/group/free-basic.
Zum Anmelden einfach eine leere E-Mail an free-basic-subscribe@yahoogroups.de senden. |
|
Nach oben |
|
|
d.j.peters Gast
|
Verfasst am: 20.05.2005, 03:53 Titel: Linux und Windows |
|
|
Dusky_Joe hat Folgendes geschrieben: | ...Ich nehme mal an, dass das unter Linux nicht funtkioniert, oder..? |
Code: | declare sub mmxcopy alias "fb_hMemCpyMMX" (byval dest as any ptr, byval src as any ptr, byval size as integer) |
hi dusky,
hättest ruhig mal in der Yahoo Group posten können
also wenn Du obrigen Code in FreeBASIC schreibst dann hast Du unter Linux und Windows die so ziemlich schnellste Kopiermethode. Einzigste Voraussetzung die CPU muss MMX können.
Grüsse und noch eine schöne Zeit.
Joshy |
|
Nach oben |
|
|
Dusky_Joe
Anmeldungsdatum: 07.01.2005 Beiträge: 1007 Wohnort: Regensburg/Oberpfalz
|
Verfasst am: 21.05.2005, 12:30 Titel: |
|
|
Oje, die Y!G gibts ja auch noch... Ich komm zurzeit total durcheinander, alle Möglichen Emails müssen beantwortet werden, eigentlich sollte ich an nem Spiel rumprogrammieren, ...
Also ein Sorry an die Group!
Hmmm... werde das als Email senden, sonst siehts ja keiner
Am besten gleich mit der neuesten Version des Win-API-Tuts.
Ist Volta eigentich auch in der Group?
Die SUB fb_hMemCpyMMX ist also in jedem Kernel?
Wie auch immer.
Danke für die AW!
Have a nice day
Ciao _________________ fully biological degradable
Once, the big wave arrives, you've got two ways, you can go:
Either, you ride it, or you don't do.
But, if you don't ride, you'll never know wether you'd have gone wet. |
|
Nach oben |
|
|
d.j.peters Gast
|
Verfasst am: 21.05.2005, 14:00 Titel: |
|
|
Zitat: | ...Die SUB fb_hMemCpyMMX ist also in jedem Kernel? | Ne das hat nichts mit dem Kernel / OS zu schaffen sonst würde es ja auch nicht unter WINDOWS funktionieren. Wenn man sich die Arbeit macht und den FreeBASIC Quellcode bzw. einen Teil dessen anschaut dann kann man die SUB's die man auch benutzen möchte einfach mit DECLARE für eigene Programme nutzbar machen. Soll heissen wenn z.B. lillo (Entwickler der Grafiklib) einen Speicherbereich kopieren muss z.B. für Grafikbefehle dann benutzt er die beschriebene Copy Function und mit DECLARE machst Du sie einfach für Dein Programm sichtbar. Da es sich dabei um FreeBASIC interne Rotienen handelt laufen die dann auch unter Linux und WINDOWS. Ich denke Du weist was ich meine.
Noch eine schöne Zeit.
Joshy |
|
Nach oben |
|
|
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
|