Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Dynaaminen muistinhallinta

Putkalainen [21.04.2010 18:57:33]

#

Yritän osoittimien käyttöä ja muistin varaamista harjoitella. Tein ohjelmaa joka tallentaa henkilön nimen ja iän muistiin sitä mukaan kun uusia henkilöitä syötetään.

#include <cstdlib>
#include <iostream>
#include <string>

using namespace std;

class Jono {

 public:
   Jono();
   ~Jono();
   void lisaaHenkilo(string nimi, int ika);
   void tulosta() const;

  private:

   struct Henkilo {
       string nimi;
       int ika;
       Henkilo* seuraava;
   };

   Henkilo* eka;

};

Jono::Jono() { eka = new Henkilo; }
Jono::~Jono() { }


void Jono::lisaaHenkilo(string nimi, int ika) {
	eka -> nimi = nimi;
	eka -> ika = ika;
}

//pitäisi tulostaa kaikki henkilöt
void Jono::tulosta() const {
	cout << "Nimi: " << eka -> nimi << " Ikä: " << eka -> ika << endl;
}

int main() {
   string nimi;
   int ika = 0;

   Jono uusi;
   while (true) {
       cout << "Nimi: ";
   	   cin >> nimi;
   	   cout << "Ikä: ";
   	   cin >> ika;
	   uusi.lisaaHenkilo(nimi, ika);
	   uusi.tulosta();
   }

   return EXIT_SUCCESS;
}

Miten tuota saisi laajennettua niin että tulostaisi kaikki syötetyt henkilöt?

Metabolix [21.04.2010 19:09:46]

#

Katsopa linkitettyihin listoihin mallia matopelioppaasta. Etsi kohdat, joissa mainitaa lista tai jaoke. (Jaoke tarkoittaa yhtä madon osaa.)

Nyt ohjelmassasi on tasan yksi henkilö. Oikeasti kuuluisi aina lisätessä luoda uusi henkilö ja muokata osoittimet järkevästi – kannattaa suunnitella paperilla. Linkitetyn listan päättymisen tunnistaa 0-osoittimesta. Muista myös tuhota kaikki henkilöt lopussa, nyt delete näyttää puuttuvan.

trilog [21.04.2010 19:14:48]

#

Ohjelmasi toimii virheellisesti. Nyt et varaa lainkaan uudelle henkilölle muistia, vaan korvaat eka-henkilön tiedot aina kun uusi henkilö "lisätään" eli vanha henkilö korvaantuu aina uudella. Tämän voi korjata niin, että varaat henkilön lisäyksessä muistin uudelle henkilölle (kuten olet konstruktorissa jo tehnyt), asetat uuden seuraava-osoittimeksi NULL ja etsit listasta paikan, johon uusi henkilö voidaan lisätä (eli alkion, jonka seuraava on NULL [tällöin alkio menee listan viimeiseksi]). Samalla periaatteella voit käydä myös listan läpi eli siirryt ensimmäisestä alkiosta lähtien aina seuraavaan alkioon niin kauan kunnes seuraava on NULL.

Edellä kuvattu toiminnallisuus on oikeastaan linkitetty lista, koska jonossa on tiedossa ensimmäinen ja viimeinen alkio, mutta periaate on sama. Muista vapauttaa myös jokaisen alkion muisti, se voidaan hoitaa samalla tavalla käymällä lista läpi.

Putkalainen [21.04.2010 19:34:15]

#

Kiitos avusta!

Tulostaminen hieman vielä epäselvää. Eli miten "liikun" seuraavaan osoittimeen.

void Jono::tulosta() const {
   //sain alla olevan toimimaan ok
   cout << "Nimi: " << eka -> nimi << endl;
   cout << "Nimi: " << eka -> seuraava -> nimi << endl;

   //miten nuo käydään silmukassa läpi?
   while (eka->seuraava != 0) {

   }
}

Metabolix [21.04.2010 19:41:26]

#

Sinun ei kuulu muokata eka-osoitinta vaan käyttää väliaikaista muuttujaa, kuten oppaani for-silmukassa.

for (Henkilo* h = eka; h != 0; h = h->seuraava) {
  // Tulosta h.
}

Henkilo* h = eka;
while (h != 0) {
  // Tulosta h.
  h = h->seuraava;
}

Teuro [21.04.2010 20:11:22]

#

Lisäksi tuon voi ensin toteuttaa ihan standardikirjaston std::list rakenteella toimivaksi ohjelmaksi, jonka jälkeen toteuttaa itse listan jollekin rakenteelle, ja lopuksi vaikka geneerisesti "kaikille" tyypeille. Tärkeintä kai olisi saada ensin rungoltaan toimiva rakenne, jotta opettelu olisi mielekästä.

Putkalainen [21.04.2010 21:07:00]

#

Osoittimet vaikeita ymmärtää minulle, mutta sain tuon toimimaan niin kuin halusin =) Kiitos

Vastaus

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

Tietoa sivustosta