Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht Das deutsche QBasic- und FreeBASIC-Forum
Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
 
FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen  RegistrierenRegistrieren
ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin
Zur Begleitseite des Forums / Chat / Impressum
Aktueller Forenpartner:

Komplettes Array in einem Schritt kopieren

 
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC.
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
Dusky_Joe



Anmeldungsdatum: 07.01.2005
Beiträge: 1007
Wohnort: Regensburg/Oberpfalz

BeitragVerfasst am: 13.05.2005, 18:39    Titel: Komplettes Array in einem Schritt kopieren Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
PeterHarder



Anmeldungsdatum: 27.03.2005
Beiträge: 45
Wohnort: Deutschland

BeitragVerfasst am: 13.05.2005, 19:25    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Dusky_Joe



Anmeldungsdatum: 07.01.2005
Beiträge: 1007
Wohnort: Regensburg/Oberpfalz

BeitragVerfasst am: 13.05.2005, 20:17    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
volta



Anmeldungsdatum: 04.05.2005
Beiträge: 1874
Wohnort: D59192

BeitragVerfasst am: 13.05.2005, 21:06    Titel: Antworten mit Zitat

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, 22:01, insgesamt einmal bearbeitet
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
PeterHarder



Anmeldungsdatum: 27.03.2005
Beiträge: 45
Wohnort: Deutschland

BeitragVerfasst am: 13.05.2005, 21:17    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Dusky_Joe



Anmeldungsdatum: 07.01.2005
Beiträge: 1007
Wohnort: Regensburg/Oberpfalz

BeitragVerfasst am: 16.05.2005, 17:21    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
PeterHarder



Anmeldungsdatum: 27.03.2005
Beiträge: 45
Wohnort: Deutschland

BeitragVerfasst am: 16.05.2005, 18:33    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Dusky_Joe



Anmeldungsdatum: 07.01.2005
Beiträge: 1007
Wohnort: Regensburg/Oberpfalz

BeitragVerfasst am: 16.05.2005, 18:48    Titel: Antworten mit Zitat

Warum einfach, wenns auch kompliziert geht zwinkern

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
Benutzer-Profile anzeigen Private Nachricht senden
PeterHarder



Anmeldungsdatum: 27.03.2005
Beiträge: 45
Wohnort: Deutschland

BeitragVerfasst am: 17.05.2005, 16:47    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
d.j.peters
Gast





BeitragVerfasst am: 20.05.2005, 02:53    Titel: Linux und Windows Antworten mit Zitat

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 mit den Augen rollen
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

BeitragVerfasst am: 21.05.2005, 11:30    Titel: Antworten mit Zitat

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 Zunge rausstrecken
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
Benutzer-Profile anzeigen Private Nachricht senden
d.j.peters
Gast





BeitragVerfasst am: 21.05.2005, 13:00    Titel: Antworten mit Zitat

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
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC. Alle Zeiten sind GMT + 1 Stunde
Seite 1 von 1

 
Gehe zu:  
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.

 Impressum :: Datenschutz