Pankaas pieni esimerkki vaikkapa linkitetyn listan tekemisestä. Onnistuuko?
Dynaamisen muistin varaus VB:llä
Janne
5411
0Äänestä
Muut lukivat myös
Odottaa vastausta
Näihin keskusteluihin ei ole vielä vastattu. Ole ensimmäinen.
Turvaa tilisi vahvistamalla puhelinnumerosi. Voit silloin palauttaa unohtuneen salasanan tekstiviestillä.
Näihin keskusteluihin ei ole vielä vastattu. Ole ensimmäinen.
Vastaukset 5
Vanhimmat
Miksi joku C-ohjelmoija kyselee VB:stä? Kun tuossa äsken sanoin VB:n olevan hyvä ohjelmointikieli, ei se tarkoita, että pitäisin muita ohjelmointikieliä huonona. Jos todella haluaisit kysyä neuvoa ohjelmointiongelmasta, toki kertoisit ongelman. Eli jos yleensä joku haluaa ratkaisun ja vain ratkaisu on tärkeä, ei tekotapa, hän kertoo ongelman, eikä sinun tavallasi vaadi ratkaisua tietyllä tavalla. Täsmennän vielä. Olet ymmärtänyt ohjelmoinnin väärin, jos vaadit ohjelmointiongelman ratkaisua tietyllä tavalla. Ohjelman käyttäjähän ei tiedä, mitä ohjelmakoodia ohjelma sisältää, joten ei ohjelman toimintoja tarvitse tietyllä tavalla tehdä. Eri ohjelmointikielissä kannattaa asiat ratkaista eri tavalla. C-kielessä on pointterit, joilla kyseinen asia onnistuu. C-räpeltäjät luulevat, että koska VB:ssä ei ole pointtereita, ei myöskään linkitetyn listan tekeminen onnistu.
Yrität provosoida jonkun vastaamaan, joten minä nyt vastaan (enhän voi pitää päätäni kiinni). Sanoit otsikossa ”Dynaamisen muistin varaus VB:llä”. Vastaan tuohon ensin, koska siihen on helppo vastata, sillä VB:ssä on Dim-käsky ja ReDim-käskyt, joilla muistia voidaan varata dynaamisesti. Kun käytetään ”ReDim Preserve” jää taulukkoon myös aikaisemmat arvot. Seuraavaa esimerkkiä varten, aloita uusi Projekti, lisää perusformiin yksi tekstikenttä oletusnimellä (Text1) ja kopioi formin ohjelmakoodiin allaoleva esimerkki. Teksikenttään syötät taulukon alkioiden maksimimäärän (esimerkissä rajattu arvoihin 1..30) ja painat enteriä. Tämän jälkeen ohjelmaa varaa dynaamisesti oikean kokoisen taulukon. Taulukon alkioihin lisätään aikaisempaan arvoon kirjain A:sta lähtien (ascii arvot 65..). Lopuksi taulukko tulostetaan ruudulle siten, että vierekkäin ensimmäisestä indeksistä suurimpaan ja toiseen suurimmasta pienimpään. Esim. jos ensin syötetään arvo 2 ja sitten 4, tulee taulukoiden arvoksi AA,BB,C,D. Koska vanha arvo jätetään pohjaksi.
Dim LKM, I
Dim Taulukko() As String
Private Sub Text1_KeyPress(KeyAscii As Integer)
If KeyAscii = 13 Then
LKM = Val(Text1.Text)
If LKM < 1 Or LKM > 30 Then Exit Sub
'määritellään taulukolle uusi koko
ReDim Preserve Taulukko(LKM)
TäytäTaulukko
TulostaTaulukko
KeyAscii = 0
End If
End Sub
Sub TäytäTaulukko()
For I = 1 To LKM
Taulukko(I) = Chr$(64 I)
Next
End Sub
Sub TulostaTaulukko()
Cls 'tyhjennetään ruutu
'tulostetaan taulukko ruutuun
For I = 1 To LKM
Print I, Taulukko(I), LKM - I 1, Taulukko(LKM - I 1)
Next
End Sub
Tuossa siis esimerkki dynaamisesta muistinvarauksesta. VB:ssähän tämä toimii loistavasti. Toki tuon tietää jokainen, joka on vähääkään VB:llä ohjelmoinnut.
Ja sitten toiseen kysymykseesi, eli esimerkki linkitetystä listasta. Linkitetty listahan on taulukko, joka viittaa toiseen taulukkoon, joten voidaan dynaamisesti lisätä arvoja. Juuri tässä kysymyksessä oleellista olisi ongelma, joka pitäisi ratkaista, jotta voisi kertoa kyseiseen ongelmaan parhaimman ratkaisun. Mutta pääsääntö VB:ssä on, että linkitettyä listaa ei tarvitse käyttää, koska tavallista taulukkoa voidaan käyttää linkitettynä listana. Eli edellinen esimerkki oli myös esimerkki linkitetystä listasta, kuten varmaan heti tajusitkin.
Laitan tähän loppuun vielä lyhyen esimerkin linkitetystä listasta. Tarvitset projektille vain yhden tekstikentän Text1-nimellä. Kun syötät kenttään tekstin ja painat enteriä (ascii 13), ohjelma varaa dynaamisesti Nimet$-taulukkoon uuden alkion ja laittaa syötetyn tekstin siihen. Taulukko tulostetaan ruutuun käänteisessä järjestyksessä jokaisen syötön jälkeen.
Dim LKM
Dim Nimet$()
Private Sub Text1_KeyPress(KeyAscii As Integer)
Dim i
If KeyAscii = 13 Then
KeyAscii = 0
LKM = LKM 1
ReDim Preserve Nimet$(LKM)
Nimet$(LKM) = Text1.Text
Cls
For i = LKM To 1 Step -1
Print i, Nimet$(i)
Next
End If
End Sub
Ylläoleva esimerkki osoittaa, kuinka kätevää on VB:ssä määritellä muistia dynaamisesti. Eikä linkitettyä listaa edes tarvita. Aikaisemmissa Basic-versioissa olen myös käyttänyt varsinaisia linkitettyjä listoja (taulukkoja, jotka viittaavat toiseen taulukkoon), mutta VB hoitaa ne helpommin. Ah, niin on hyvä ohjelmointikieli VB ja helppo sillä ongelmat ratkaista. Kirjoitin sille vielä lyhyen runon:
VB:llähän ohjelmia väsään
-------------------------------------
Kato VB:llä ohjelmia teen,
ongelmat ratkaisen,
hommat hoidan.
Kaunista tulosta helppo on tehdä,
beisikillä parhaat keinot,
asiat hoitaa,
vaivaton väsätä,
muistia varata
dynaamiset taulukot,
listat ja linkit,
sulavaa, joustavaa,
ketterää koodia.
Olisi pitänyt hiukan tarkemmin määritellä mitä tarkoitin. Linkitetyn listan etunahan on, että listan keskeltä voi tiputtaa alkion pois ja vapauttaa sen käyttämän muistin. Onnistuuko muuten kuin siirtämällä poistettavasta alkiosta lähtien taulukon alkioita pykälällä taaksepäin ja sitten pienentämällä taulukkoa?
Alkuperäinen kysymyksesi oli vain sen verran provosoiva.
Tuolla tavalla ainakin itse teen (siirrän taulukon alkioita pykälällä). Suurellakin tietomäärällä se tapahtuu nopeasti. Joskus olen käyttänyt yhtä merkkijonoa tuohon tarkoitukseen (VB:ssähän merkkijono voi olla megoja tai teroja, tavuja). Jos merkkijonot ovat eripituisia (tekstiä), olen laittanut kunkin merkkijonon alkuun esim. chr$(0) . Tiedon hakuun sitten Instr-käskyä. Mutta nykyään käytän suoraan taulukoita, koska koodi on selkeämpää ja kuitenkin nopeata.
Ja olen todellakin sitä mieltä, ettei tekotapa ole oleellinen, vaan se, että ratkaisu on selkeä ja toimii riittävän nopeasti. Ainahan sitä joutuu vääntämään koodia, joten turha takertua johonkin mielestäni filosofiseen kysymykseen ohjelmoinnissa.
> VB:ssähän merkkijono voi olla megoja tai teroja, tavuja
Korjaa jos olen väärässä mutta megoja kyllä, teroja ei, siksi nääs että 32-bit koneessa maks. osoiteavaruus on 4GT (2^32 T). Loppuu muisti kese...
Huh, kyllä sai taas pilkku kyytiä ;)
Ilmeisesti koneen muistin määrä rajoittaa. Ja minä olen luullut, että Windows käyttää virtuaalimuistia, jossa kovalevy on myös käytössä. Perskules, niin ei taida ollakaan.
Kun 128 MB:n muistilla tein 100 MB:n merkkijonon käskyllä A$ = String(100000000, "a"), alkoi tietokone menemään hitaaksi.
En nyt tiedä teoreettista maksimia, mutta eipä kannata ladata kaikkia suomalaisten nimiä kerralla koneen muistiin. Tai no ne taitaisivat kyllä sopia.