SLODUG
Spletno mesto uporabniške skupine slovenskih razvijalcev programskih rešitev

Kazalci v VB.NET

ocenilo 0 uporabnikov
Ta prispevek ima 7 odgovorov | 3 sledilcev

Med prvih 50 po prispevkih
Ženski
newdrim Objavljeno: 03-21-2006 10:39 | Zabeleženo

Da tale forum ne bo tako sameval Wink [;)]

Saj veste kako je s kazalci v C ali C++: kazalcu prirediš lokacijo spremenljivke in potem z njim počneš kar hočeš. Preko njega lahko dostopaš do vrednosti spremenljivke ali pa mu prirediš lokacijo druge spremenljivke. Ali obstaja kaj takega v VB.NET?

Konkreten primer:

Recimo, da imam razred Node, ki mi predstavlja vozlišče v trojiškem drevesu (vsako vozlišče ima vrednost tipa String in največ 3 sinove):

Class Node

   Public left As Node   'polja bi seveda morala biti property-i... pa pustimo to

   Public middle As Node

   Public right As Node

      Public value As String

End Class

Seveda lahko kličem proceduro in podam node po referenci:

Sub KrNeki (ByRef myNode As Node)

Pri tem klicu se bo myNode res obnašal kot kazalec.

Kaj pa drug primer: recimo, da bi rada znotraj procedure preverila, kateri od sinov vozlišča vsebuje niz nekNiz in tistega od sinov zamenjala z drugim vozliščem:

Dim theNode as Node   'sin, ki vsebuje vrednost nekNiz

If myNode.left.value = nekNiz Then

   theNode = myNode.left

ElseIf myNode.middle.value = nekNiz Then

   theNode = myNode.middle

ElseIf myNode.right.value = nekNiz Then

   theNode = myNode.right

End If

theNode = GenerateRandomNode("new node value")

Skratka, če je veljalo myNode.middle.value = nekNiz, potem bi rada, da se to vozlišče zamenja z novim in velja myNode.middle.value = "new node value". Vendar se to ni zgodilo. Vozlišče theNode sicer ima novo vrednost, vendar ta ne vpliva na vozlišče myNode.middle, ki je ostalo takšno kot prej.

Če bi imela na voljo kazalce, bi v kazalec shranila referenco na myNode.middle in ne bi bilo nobenih problemov.

A sem kaj spregledala? Vem, da obstaja razred Pointer, ampak VB.NET ne dovoli uporabe njegovih metod.

Lp, Andreja
MihaM V odgovor na 03-21-2006 15:53 | Zabeleženo

Živjo Andreja,

V tvojem primeru je theNode samo reference na enega od otrok medtem ko myNode ohrani svoje reference. Kakorkoli, tako bo pa delalo:

theNode = GenerateRandomNode("new node value")

If myNode.left.value = nekNiz Then

   myNode.left = theNode

ElseIf myNode.middle.value = nekNiz Then

   myNode.middle = theNode

ElseIf myNode.right.value = nekNiz Then

   myNode.right = theNode

End If

 

Miha Markic RighHand .net consulting and software development

Med prvih 50 po prispevkih
Ženski
newdrim V odgovor na 03-21-2006 20:52 | Zabeleženo

Ah, saj sem vedela, da bi si morala izmisliti boljši primer. Pa reciva, da tega ne moreš narediti, ker so operacije, ki jih nameravaš izvesti nekako odvisne od lastnosti theNode. Recimo, da

theNode = GenerateRandomNode("new node value")

zamenjam z

theNode = PrerazporediSinove(theNode)

Če se pa se želim iterativno (torej brez rekurzije) sprehajati po takem drevesu glede na vrednosti v vozliščih in vmes vstavljati nova vozlišča, lahko postane kar zabavno Smile [:)]

V mojem primeru sem tiste stvari, ki sem jih hotela narediti z vozliščem, dala kar v svojo proceduro, ki sem ji podala vozlišče po referenci. Procedura je zato lahko spremenila karkoli, vključno z zamenjavo vozlišča, ampak bi si želela narediti zadevo s kazalci, če je to mogoče.

IntPtr sicer predstavlja referenco na košček memorije, samo ne vem, kako bi mu priredila naslov kakšnega objekta.

 

 

Lp, Andreja
Med prvih 25 po prispevkih
Moški
Nisem povsem prepričan, da razumem, kaj želiš izvesti v metodi PrerazporediSinove(Node), a če želiš da se sprememba parametra kot zamenjava objekta, na katerega ta kaže (torej kot zamenjava vrednosti kazalca), odrazi navzven, potem se moraš pač poslužiti prenosa po referenci. V primeru prenosa po vrednosti se bodo nasprotno odrazile le spremembe v objektu, ne pa tudi parametra samega.
 
VB.NET je v tem pogledu skladen z delovanjem Jave in C#, konceptualno pa se mi to tudi ne zdi toliko drugačno od kazalcev v C/C++, čeprav priznam, da sem v tem jeziku že malo zarjavel.
 
Ob ponovnem branju svojega odgovora upam, da sem dovolj jasen, sicer pa je najbolje, da podaš celoten primer, kaj želiš doseči.

LP, Damir

Mogoče ni direktno povezano s tvojim vprašanjem, ampak tvoj problem bi bil znal biti rešljiv tudi z uporabo LinkedList(Of string), z nekaj "dodatne opreme". Če ne drugega, je vsaj za pogledat kot princip referenc in povezanih vozlišč...

Andrej
Microsoft MVP: Client Application Development
ANT Andrej Tozon s.p., Solution development and consulting
http://www.tozon.info | http://www.tozon.info/blog/

Med prvih 50 po prispevkih
Ženski
newdrim V odgovor na 03-22-2006 10:55 | Zabeleženo

ExAmigan, moje vprašanje se v resnici ne nanaša na vsebino problema (operacije nad drevesom), ampak na kazalce kot take. Problem z drevesom je dodan le kot ilustracija (očitno ne preveč dobra). Kot sem napisala v zadnjem postu, sem zadevo rešila točno tako kot si sam svetoval: klicala sem metodo, ki je sprejela parameter po referenci, namesto po vrednosti. Hec je v tem, da se mi zdijo kazalci bolj naravni za take operacije.

Glede na to, da sem zbudila toliko zanimanja (hvala, fantje - makes me feel special Wink [;)]), vam bom pa še razkrila kako dejansko izgleda koda. Imam drevo, ki ima naslednjo (zelo neuporabno) lastnost: v vozliščih so naravna števila. Če je ostanek pri deljenju s 3 enak 0, spada število v levo poddrevo, če je enak 1 spada v srednje poddrevo in če je enak 2 spada v desno poddrevo. Če neposredno pod trenutnim vozliščem ni prostora (ker ima vozlišče že sina v danem poddrevesu), se spustim nivo nižje in spet delim s 3 (zato imam v spodnji kodi spremenljivki guide in remainder). Skratka, spodnja koda je rešitev problema in IMHO deluje b.p. Vprašanje je le, ali v VB.NET obstajajo kazalci (ker bi raje delala z njimi ko bom imela naslednjič podobno situacijo).

Pa še to: seveda se da zadevo veliko bolj elegantno in brez kakršne koli potrebe po kazalcih rešiti rekurzivno. Tudi to sem že naredila Smile [:)]. Zanimajo me samo kazalci (sem izbirčna, kaj?).

Public Sub InsertIterative(ByRef rootNode As TreeNode, ByVal value As Integer)
   Dim wasInserted As Boolean = False
   Dim guide As Integer = value
   Dim node As TreeNode = rootNode

   'če je rootNode = Nothing, ustvarimo novo vozlišče
   wasInserted = CreateNewNode(rootNode, value)

   'sicer poiščemo ustrezno mesto za novo vozlišče
   While Not wasInserted
      Dim remainder As Integer = guide Mod 3
      guide = guide \ 3
      If guide = 0 Then guide = value

      Select Case remainder
         Case 0
            wasInserted = CreateNewNode(node.Left, value)
            node = node.Left
         Case 1
            wasInserted = CreateNewNode(node.Middle, value)
            node = node.Middle
         Case 2
            wasInserted = CreateNewNode(node.Right, value)
            node = node.Right
      End Select
   End While

End Sub

'če je node = Nothing, popravimo referenco tako, da kaže na novo ustvarjeno vozlišče in
'vrnemo true; sicer vrnemo false in ne naredimo ničesar
Private Function CreateNewNode(ByRef node As TreeNode, ByVal value As Integer) As Boolean

   If node Is Nothing Then
      node = New TreeNode(value)
      Return True
   End If

   Return False
End Function

Lp, Andreja
Med prvih 50 po prispevkih
Ženski
newdrim V odgovor na 03-22-2006 11:26 | Zabeleženo

AndrejT: ne razumem, kako bi si pomagala z LinkedList... a zato, da bi v njem hranila sinove vozlišča ali kako?

 

Lp, Andreja
AndrejT V odgovor na 03-22-2006 11:55 | Zabeleženo
Ja, LinkedList ti omogoča delo z množico nekih elementov recimo v tvojem primeru števil), ki so med seboj povezane (lahko v drevo) in se po njih lahko sprehajaš preko referenčnih povezav. Po drugem tvojem postu pa vidim, da te to ne zanima Smile [:)]

Andrej
Microsoft MVP: Client Application Development
ANT Andrej Tozon s.p., Solution development and consulting
http://www.tozon.info | http://www.tozon.info/blog/

Stran 1 od 1 (8 predmetov) | RSS
© 2004-2008 SLODUG
Powered by Community Server (Commercial Edition), by Telligent Systems