Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: VB6: Muuttujataulukoista

Sivun loppuun

Lumi-ukkeli [09.01.2005 12:42:07]

#

Luin tuosta Microsoft Press: Microsoft Visual Basic 6.0 Ohjelmoijan käsikirja-kirjasta, että:

Muuttujataulukot ovat aina yhtäjaksoisia; toisin kuin ohjausobjektitaulukoista, muuttujataulukoista et voi poistaa
tai ladata elementtejä keskelle.

Ohjelmani lukee tekstitiedostosta tietoa tehtaista, joita voi olla
tuntematon määrä, ja jokaisesta tehtaasta se ottaa tietoja tähän tyyliin:

Type tTehdas
    nimi As String
    sijainti As String
    tyopaikat As Long
    tyontekijoita As Long
    palkka As Long
    verotus As Long
End Type

Public tehdas() as tTehdas

Ja sitten koodissa luetaan tietoa:

Open App.Path & "\Tekstit\" & yhtion_nimi & ".amt" For Input As #1
Dim i As Integer
Do While Not EOF(1)
    i = i + 1
    ReDim Preserve Tehdas(1 To i)
    Input #1, Tehdas(i).nimi
    Input #1, Tehdas(i).sijainti
    Input #1, Tehdas(i).tyopaikat
    Input #1, Tehdas(i).tyontekijoita
    Input #1, Tehdas(i).palkka
    Input #1, Tehdas(i).verotus
Loop
Close #1

Ongelma on se, että minkälaista koodia tulisi kirjoittaa
kun pelaaja (käyttäjä) sulkee yhden tehtaan, niin
miten sen voi poistaa taulukosta?

Ja sitten se taulukko pitäisi vielä järjestää niin, että siinä ei ole tyhjiä elementtejä.

Sitten pitäisi vielä pystyä perustamaan uusi tehdas.

Antti Laaksonen [09.01.2005 12:56:27]

#

Tapoja on useita. Jos tehtaiden järjestyksellä ei ole väliä, voit lisätä tyyppiin muuttujan "varattu As Boolean", jonka arvo on True silloin, kun sen kohdalla on toiminnassa oleva tehdas. Kun lisäät uuden tehtaan, käy taulukkoa läpi, kunnes vastaan tulee ensimmäinen vapaa kohta. Siihen merkitään tehtaan tiedot ja varattu-muuttujan arvoksi tulee True. Kun poistat tehtaan, merkitse varattu-muuttujan arvoksi False. Kun näytät kaikki pelaajan tehtaat, älä ota niitä tehtaita lukuun ollenkaan, joiden varattu-muuttuja on False.

muok: Tämä siis muuttumattoman kokoisella taulukolla.

Metabolix [09.01.2005 12:58:28]

#

Taulukkoon lisääminen onnistuu juuri tuolla jo käyttämälläsi ReDim-systeemillä, tehtaan tiedot vain otetaan eri paikasta.

Poistamisessa ehkä helpoin tapa on se, että siirrät viimeisen tehtaan sen poistettavan paikalle ja pienennät taulukkoa ReDimillä (kai niin voi tehdä?).

Toki noita voi pitää muunkin laisissa rakenteissa kuin taulukossa. En sitten tiedä, miten ne toimivat VB:ssä. Itse pidän linkitetystä listasta, kun silloin saa helposti lisättyä ja poistettua keskeltäkin. Taulukko voi kuitenkin olla helpompi ymmärtää ja VB:ssä möys käsitellä.

Lumi-ukkeli [09.01.2005 17:14:07]

#

Eikös boolean tietotyypin oletusarvo ole False?

Antti Laaksonen [09.01.2005 17:21:58]

#

Jo vain. (Asia on myös helppo tarkistaa. ;)

Lumi-ukkeli [09.01.2005 19:30:23]

#

Yksi onglema tuli. Kun minä lisään nuiden tehtaitten nimi-ominaisuudet tuohon listaan. Sitten siinä vieressä on semmoinen nappula josta voi poistaa tehtaan. Niin kun
aiemmin minulla oli koodissa:

For i = Lbound(tehdas) to Ubound(tehdas) Step 1
If tehdas(i).suljettu = False Then
list1.Additem tehdas(i).nimi
End If
Next

Ja sitten koodissa tuo nappula tunnistaa mikä tehdas
halutaan sulkea näin:

Tehdas(list1.listindex + 1).suljettu = True

Ei sitten enään toimi tuo kun ei enään kirjoita listalle
kaikkia tehtaita, niin tuo listindex + 1 ei vastaa
tehdas()-taulukon indexiä ja menee ihan sekaisin
sen toiminta.

Eikä sekään toiminut se otetaan viimeinen elementti ja
kirjoitetaan se poistettavan päälle, ja sitten
lyhennetään taulukkoa yhdellä elementillä.

Valitti: Type Mismatch

Antti Laaksonen [09.01.2005 19:56:18]

#

Tosiaan suoraan ListIndexin käyttö ei tule kysymykseen. Voit kuitenkin käyttää apuna ItemData-ominaisuutta, jolloin jokaiselle listan riville voi määrittää oman paikasta riippumattoman tunnusnumeron. Kun lisäät uuden rivin listalle, määritä siis heti perään sen ItemData-ominaisuus oikeaksi. Sitten voit poistaa rivin listalta ListIndexin perusteella mutta taulukosta ItemDatan perusteella.

hunajavohveli [09.01.2005 22:34:03]

#

Antti Laaksonen kirjoitti:

Jo vain. (Asia on myös helppo tarkistaa. ;)

Tarkistinpa tuon muuten ihan huvin vuoksi Printillä, jolloin se tulosti formille Booleanin arvosta riippuen "Tosi" tai "Epätosi" ihan suomeksi. Kumma juttu, sillä käyttikseni on ihan englanninkielinen, ja VB samoin. :)

Blaze [09.01.2005 22:41:38]

#

Lokalisaatio se iskee joka paikkaan. Ärsyttää, kun kaikki installerit kattoo, että "Haa! maa-asetuksena on Suomi, toi haluaa varmaan lukee suomee, vaikka käyttiksen kieli on englanti" ja tarjoilee jotain kökkösuomennosta.

dooDle [10.01.2005 00:27:43]

#

Mun käyttis on suomeks ja kuitenkin antaa false tai true. kumma juttu.. :)

Lumi-ukkeli [10.01.2005 17:41:07]

#

Mulla on kans suomeksi ja true ja false tulee englanniksi.

Voisko tuossa hunajavohvelin tilanteessa tehdä näin:
Dim a as boolean
a = epätosi

hunajavohveli [10.01.2005 17:53:56]

#

Lumi-ukkeli kirjoitti:

Mulla on kans suomeksi ja true ja false tulee englanniksi.

Voisko tuossa hunajavohvelin tilanteessa tehdä näin:
Dim a as boolean
a = epätosi

En nyt oikein käsitä, mitä ajat takaa. Eihän se minua tietenkään haittaa, vaikka se tulostaisikin suomeksi, kun tulostin sen vain testimielessä. Tuo koodi vain asettaisi aan arvoksi saman, joka on epätosi-nimisessä muuttujassa.

Lumi-ukkeli [12.01.2005 21:49:43]

#

Miten tuo ongelma olisi tarkoitus ratkaista, kun en minä osaa käyttää sitä ItemDataa?

Menee niin monimutkaiseksi, ettei tuosta ymmärrä.

Vähän esimerkkiä?

Antti Laaksonen [12.01.2005 22:02:22]

#

Tässä tulee esimerkki, jossa lomakkeella on lista (List1). Aluksi listalle lisätään neljä nimeä, joiden tiedot tallennetaan myös taulukkoon. Kun nimen kohdalta painetaan, se katoaa listalta ja taulukosta. Tätä voinet soveltaa myös omassa pelissäsi.

' nimien maksimimäärä
Const NIMIMAARA = 50

' nimet sisältävä taulukko
Dim nimet(NIMIMAARA) As TNIMI

' nimitaulukon tyyppi
Private Type TNIMI
    nimi As String
    varattu As Boolean
End Type

' tyhjentää koko nimitaulukon
Sub TyhjennaNimet()
    Dim i As Integer
    ' muutetaan kaikki nimet vapaiksi
    For i = 0 To NIMIMAARA
        nimet(i).varattu = False
    Next
End Sub

' lisää nimen taulukkoon ja listalle
Sub LisaaNimi(nimi As String)
    Dim i As Integer
    ' käydään läpi taulukkoa
    For i = 0 To NIMIMAARA
        ' jos paikka on vapaa...
        If Not nimet(i).varattu Then
            ' muutetaan se varatuksi ja pannaan siihen nimi
            nimet(i).varattu = True
            nimet(i).nimi = nimi
            ' lisätään nimi listalle
            List1.AddItem nimi
            ' kirjoitetaan ItemDataan vastaava kohta taulukossa
            List1.ItemData(List1.ListCount - 1) = i
            Debug.Print nimi & " lisätty."
            ' poistutaan aliohjelmasta
            Exit Sub
        End If
    Next
    Debug.Print "Nimi ei mahtunut taulukkoon!"
End Sub

' poistaa nimen taulukosta
Sub PoistaNimi(tunnus As Integer)
    ' muutetaan nimen paikka vapaaksi
    nimet(tunnus).varattu = False
    Debug.Print nimet(tunnus).nimi & " poistettu."
End Sub

Private Sub Form_Load()
    ' lisätään listalle neljä nimeä
    LisaaNimi "Erkki"
    LisaaNimi "Liisa"
    LisaaNimi "Pauli"
    LisaaNimi "Pentti"
End Sub

Private Sub List1_Click()
    ' poistetaan nimi taulukosta
    PoistaNimi List1.ItemData(List1.ListIndex)
    ' poistetaan nimi listalta
    List1.RemoveItem List1.ListIndex
End Sub

Debug-alkuiset rivit kirjoittavat tietoja Debug-ikkunaan. Ne voit poistaa lopullisesta koodista. Mutta määritä taulukko niin suureksi, että tila ei lopu kesken!

Lumi-ukkeli [16.01.2005 12:04:19]

#

hunajavohveli kirjoitti:

Lumi-ukkeli kirjoitti:

Mulla on kans suomeksi ja true ja false tulee englanniksi.

Voisko tuossa hunajavohvelin tilanteessa tehdä näin:
Dim a as boolean
a = epätosi

En nyt oikein käsitä, mitä ajat takaa. Eihän se minua tietenkään haittaa, vaikka se tulostaisikin suomeksi, kun tulostin sen vain testimielessä. Tuo koodi vain asettaisi aan arvoksi saman, joka on epätosi-nimisessä muuttujassa.

Siis tarkoitin että jos tuo olisi niin kuin tavallisesti, niin sehän menisi

Dim a as boolean
a = False

mutta ajattelin, että jos sinulla käy tuo sama myös suomeksi, niin menisi näin

Dim a as boolean
a = epätosi

Eikä se epätosi mikään muuttuja ole.

Blaze [16.01.2005 12:15:22]

#

Ei käy, tuo suomennos vaikuttaa (jos vaikuttaa) vain siihen, jos printtaat boolean-tyyppisen muuttujan johonkin.
Esim.

Dim a As Boolean
a = False
Print a 'Printtaa "False" tai "Epätosi"

Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta