Newsgroup: it.comp.lang.visual-basic
Titolo: VB Porting

Lo so, in VB non esistono i puntatori, però dovrei trovare il modo (se
possibile) di tradurli in qualche modo, anche a costo di triplicare le linee
di codice  rispetto al C.
Questo è il frammento che dovrei tradurre:
Se qualcuno di voi mi aiutasse a capire come fare gli sarei molto grato.
Grazie in anticipo.
   typedef struct element
   {  int xP, yQ, dx, dy, E; element *next;
   }  *eltptr;
   eltptr p, start, end, p0, q;
    p = start;
      while (p != end)
      {  if (p->yQ == y)
         {  // Cancella l'elemento della lista *p:
            if ((q = p->next) == end) end = p; else *p = *q;
            delete q;
ecc..
Fabio Guerrazzi

...

Per implementare i puntatori in VB devi ovviamente ricorrere alle API. Di
queste le fondamentali sono
GlobalAlloc -> restituisce un handle ad un blocco di memoria globale
GlobalLock    -> restituisce (dato l'handle precedente) il puntatore
(indirizzo di memoria) del blocco allocato
GlobalFree    -> libera il blocco di memoria
CopyMemory    -> trasferisce un blocco di memoria da un puntatore ad
un'altro.
Breve disgressione sulle chiamate API da VB
Se il parametro che passi è stato dichiarato come ByVal tu passi il valore
che è contenuto nella variabile.
es x = 5
declare sub Pippo(ByVal f as long)    -> stai passando il valore 5
al contrario se il parametro è stato dichiarato come ByRef(opzionale) quello
che passi è l'indirizzo di memoria
Ciò posta la gestione dei puntatori è molto semplice infatti
Data una generica struttura MyStruct, un puntatore alla struttura sarà
pt = gloallock(globalalloc(0, lenB(MyStruct))
Per riempire il blocco di memoria allocata con una struttura, si aggiusta la
CopyMemory nel seguente modo
Declare Sub MemorizzaElemento Lib "kernel32" Alias "RtlMoveMemory" (ByVal
dest As Long, source As Any, ByVal numBytes As Long)
e quindi
MemorizzaElemento pt, MyStruct, lenb(MyStruc)
N.B. avendo posto ByVal dest as long, alla libreria gli arriva il valore di
pt e tale valore è un puntatore
Se vogliamo dato un puntatore risalire all'oggetto, ridichiariamo la
CopyMemory nel seguente modo
Declare Sub RestituisciElemento Lib "kernel32" Alias "RtlMoveMemory" (dest
As Any, ByVal source As Long, ByVal numBytes As Long)
RestituisciElemento MyStruct, pt, lenb(MyStruct)
N.B. in questo caso ho applicato il giochetto precedente al contrario, passo
la destinazione per riferimento, è quindi ne passo il puntatore, mentre
passo il source per valore, ed essendo il suo valore un puntatore funziona
tutto
Di seguito ti posto un programmino che crea una lista di strutture, e ti
consente di eliminarle a tuo piacimenti
Devi inserire in un form 3 commandButton e 1 listbox
*************************************
Option Explicit
Private Declare Function GlobalHandle Lib "kernel32" (wMem As Any) As Long
Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long,
ByVal dwBytes As Long) As Long
Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As
Long
Private Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As
Long
Private Declare Sub RestituisciElemento Lib "kernel32" Alias "RtlMoveMemory"
(dest As Any, ByVal source As Long, ByVal numBytes As Long)
Private Declare Sub MemorizzaElemento Lib "kernel32" Alias "RtlMoveMemory"
(ByVal dest As Long, source As Any, ByVal numBytes As Long)
Private Declare Sub ImpostaPrev Lib "kernel32" Alias "RtlMoveMemory" (ByVal
dest As Long, source As Any, ByVal numBytes As Long)
Private Type Elemento
    xP As Integer
    yQ As Integer
    dx As Integer
    dy As Integer
    E As Integer    ' rango dell'elemento della lista   N.B. First.E = 0
    next As Long    ' puntatore al prossimo elemento    N.B. se next = 0
esci
End Type
' variabili globali
Dim First As Long   ' puntatore al primo elemento della lista
Dim Last As Long
Dim Index As Integer    ' *indice dell'elemento aggiunto*
Private Sub Command1_Click()
    ' se First = 0 devo aggiungere il primo elemento
    ' se First <> 0 aggiungo un nuovo elemento e aggiorno l'elemento
precedente
    Dim NewElemento As Elemento, oldLast As Elemento
    Dim newPt As Long
    Dim successivo As Long
    Index = Index + 1
    NewElemento.E = Index
    NewElemento.next = 0 ' non è necessario ma esplicita la convenzione di
fine lista
    newPt = Puntatore(NewElemento)
    If newPt = 0 Then
        MsgBox "Errore"
        Exit Sub
    End If ' restituzione di puntatore fallita
    If First = 0 Then
        First = newPt
        Last = First
    Else
        RestituisciElemento oldLast, Last, LenB(oldLast)
        oldLast.next = newPt
        MemorizzaElemento Last, oldLast, LenB(oldLast)
        Last = newPt
    End If
    MsgBox "Aggiunto elemento di rango " & CStr(Index)
End Sub
Private Function Puntatore(newElement As Elemento) As Long
    ' restituisce 0 in caso di errore
    Dim Pt As Long
    Pt = GlobalLock(GlobalAlloc(0, Len(newElement)))
    MemorizzaElemento Pt, newElement, LenB(newElement)
    Puntatore = Pt
End Function
Private Sub Command2_Click()
    ' rimuove l'n.esimo elemento dalla lista
    ' n.esimo = list1.listindex +1
    Dim Index As Integer
    Dim tempElemento As Elemento
    Dim tempIndex As Long, LastIndex As Long, nextNew As Long
    Index = List1.ListIndex + 1
    If Index < 1 Then Exit Sub
    tempIndex = First
    Do
        RestituisciElemento tempElemento, tempIndex, LenB(tempElemento)
        If tempElemento.E = Index Then  ' devo eliminare l'elemento dalla
lista
            Select Case tempIndex
                Case First
                    First = IIf(tempElemento.next <> 0, tempElemento.next,
0)
                Case Last
                    RestituisciElemento tempElemento, LastIndex,
LenB(tempElemento)
                    tempElemento.next = 0
                    MemorizzaElemento LastIndex, tempElemento,
LenB(tempElemento)
                    Last = LastIndex
                Case Else
                    nextNew = tempElemento.next
                    RestituisciElemento tempElemento, LastIndex,
LenB(tempElemento)
                    tempElemento.next = nextNew
                    MemorizzaElemento LastIndex, tempElemento,
LenB(tempElemento)
            End Select
            Exit Do
        End If
        LastIndex = tempIndex
        tempIndex = tempElemento.next
    Loop Until tempIndex = 0
    ' libero la memoria dell'elemento cancellato
    If (GlobalFree(tempIndex) = 0) Then
        MsgBox "Rimosso l'elemento di rango " & CStr(Index)
    Else
        MsgBox "Memoria corrotta"
    End If
End Sub
Private Sub Command3_Click()
    Dim temp As Elemento
    Dim TempNext As Long
    List1.Clear
    If First = 0 Then Exit Sub
    TempNext = First
    Do
        RestituisciElemento temp, TempNext, LenB(temp)
        List1.AddItem "Rango dell'elemento = " & CStr(temp.E)
        TempNext = temp.next
    Loop Until TempNext = 0
End Sub
Private Sub Form_Load()
    Command1.Caption = "Aggiungi elemento"
    Command2.Caption = "Rimuovi elemento"
    Command3.Caption = "Visualizza lista"
End Sub
Ciao Bruno

 Grazie in anticipo.
Non devi triplicare le righe, ma centuplicarle.
Devi fare una classe clsElement che dichiara:
public Xp&
public yQ&
public dx&
public dy&
public E&
public element as clsElement;
Ed usarla come se fosse una struttura, dove il puntatore e' element.
Per crare una nuova classe (un nuovo nodo):
	dim NewElement	as clsElement
	set NewElement=new clsElement
	Set UltimoNodo.element = NewElement
	set NewElement=nothing
Per eliminare un nodo:
	dim DelElement	as clsElement
	Set DelElement = NodoPrecedente.element
	Set NodoPrecedente.element = DelElement.element
	set DelElement = nothing
Per analizzare la lista:
	dim ActElement	as clsElement
	dim NextElement as clsElement
	Set ActElement = PrimoNodo
	Do
		if ActElement.element is nothing then exit do
		.....
		analizzo il nodo corrente ActElement
		.....
		Set ActElement = ActElement.element
	Loop
 
le ho scritte al volo, quindi sono passibili di errori.
-- 
Hi, Ciao
Ettore                 By -MES-
http://freeweb.aspide.it/freeweb/ilmes
Il sito comune di programmatori VB
http://members.xoom.com/it_lang_vb
 

 Resto del msg di Ettore
    Concordo pienamente nell'usare le classi Vb come strutture C, puoi
implementare le operazioni su queste strutture come se fossero metodi propri
della classe. Ti sconsiglio di utilizzare le chiamate dirette alle APi per
gestirti i puntatori come farebbe il compilatore C, dovresti stare attento a
non perderteli o non sporcare memoria non tua. I puntatori i C sono croce e
fortuna dei programmatori.
--
*-*-*-*-*-*-*-*-*-*-
*-*-* GGHI *-*-*
_*_*_*_*_*_*_*
* * * * Anti Spam: Rimuovere i numeri per l'indirizzo corretto * * * *
222gg...@hotmail.com
Sito comune programmatori Visual Basic
http://members.xoom.com/it_lang_vb
Ettore Maronese ha scritto nel messaggio <01bdddcb$4ac58480$64c0c0c0@mes>...
