2.10.5 Tietuetaulukot

Taulukoita voidaan muodostaa minkä tyyppisistä muuttujista tahansa, kunhan vain kaikki taulukon alkiot ovat keskenään samantyyppisiä. Siten myös tietuemuuttujia voidaan koota yhteen taulukoksi.

Palataan takaisin tämän luvun alussa mainittuun hiihtokilpailun tuloslaskentaan. Määritellään tietuetyyppi

struct kilpailija {
  string nimi;
  int numero;
   .
   .  // muut tarvittavat kentät
   .
};

jota käytetään yhden kilpailijan tietojen tallentamiseen. Sen jälkeen voidaan määritellä taulukko, johon tallennetaan kaikkien kilpailijoiden tiedot:

#define MAXLKM 100
...
kilpailija kilp[MAXLKM];

Tällöin ensimmäisen kilpailijan tiedot ovat tietuemuuttujassa kilp[0], toisen kilpailijan tiedot muuttujassa kilp[1], jne. Siis viittaus taulukon alkioihin tapahtuu aina täsmälleen samalla tavoin riippumatta alkioiden tyypistä. Samoin yksittäisen kilpailijan kenttiin viitataan kuten minkä tahansa tietuemuuttujan kenttiin: esimerkiksi, kolmannen kilpailijan nimi on kenttämuuttujassa kilp[2].nimi (joka on merkkijono) ja viidennen kilpailijan kilpailunumero on kenttämuuttujassa kilp[4].numero (kokonaisluku). Tietuetaulukoissa ei siis ole mitään uutta edellä esitettyyn; yhdistetään vain se, mitä on opittu taulukoista ja tietueista.

Seuraavaa esimerkkiohjelmaa voitaisiin käyttää (vaihtelun vuoksi) vaikkapa tikanheittokilpailun tuloslaskennassa. Kustakin kilpailijasta tallennetaan nimi ja tulos, ja kilpailijat järjestetään tuloksen mukaan paremmuusjärjestykseen. Lajittelussa käytetään aikaisemmin esitettyä kuplalajittelua (esimerkkiohjelma KUPLA.CPP). Huomaa, että lajittelu tehdään täsmälleen samalla tavoin kuin ennenkin, nyt vain lajiteltavien alkioiden tyyppi on kilpailija (aikaisemmin int). Ainoat oleelliset muutokset ovat funktiossa vertaa.

/* *********************************************************
KISA.CPP
  Lukee näppäimistöltä kilpailijoiden tiedot, järjestää
  kilpailijat paremmuusjärjestykseen kuplalajittelulla, ja
  tulostaa lopputulokset näytölle.
********************************************************* */

#include <iostream.h>
#include <string>

#define MAXLKM 100

using namespace std;

struct kilpailija {
  string nimi;
  int tulos;
};

void lue_tiedot(kilpailija kisaajat[], int &lkm)
{
  int i;

  cout << "\n\n";
  do {
    cout << "Anna kilpailijoiden lukumäärä (1-" << MAXLKM << ") > ";
    cin >> lkm;
  } while (lkm < 1 || lkm > MAXLKM);
  /* edellinen cin ei ohita syötössä annettua rivinvaihtomerkkiä;
     ilman ohitusta seuraava merkkijonon lukeminen menisi pieleen */
  cin.ignore(80, '\n');

  for (i=0; i<lkm; i++) {
    cout << "Anna kilpailijan no. " << (i+1) << " tiedot:\n";
    cout << "Nimi  > ";
    getline(cin, kisaajat[i].nimi);
    cout << "Tulos > ";
    cin >> kisaajat[i].tulos;
    cin.ignore(80, '\n'); // kuten edellä
  }
}

/* Alkioiden vertailufunktio. Palauttaa
   -1, jos a:n pitäisi olla ennen b:tä,
    0, jos a ja b ovat samanarvoiset,
   +1, jos a:n pitäisi olla b:n jälkeen. */

int vertaa(kilpailija a, kilpailija b)
{
  int vertailu;

  vertailu = b.tulos - a.tulos; // vertaillaan tuloksia
  if (vertailu == 0) {          // jos samat tulokset,
    if (a.nimi < b.nimi)        //  laitetaan aakkosjärjestykseen
      vertailu = -1;
    else if (a.nimi > b.nimi)
      vertailu = 1;
  }

  return vertailu;
}

/* Alkioiden vaihtofunktio. */
void vaihda(kilpailija &a, kilpailija &b)
{
  kilpailija apu;

  apu = a;
  a = b;
  b = apu;
}

/* Siirtää taulukon "painavimman" alkion viimeiseen paikkaan. */
void siirra_painavin(kilpailija taulukko[], int koko)
{
  int i, vertailu;

  for (i=0; i<koko-1; i++) {
    vertailu = vertaa(taulukko[i], taulukko[i+1]);
    if (vertailu > 0)
      vaihda(taulukko[i], taulukko[i+1]);
  }
}

/* Kuplalajittelu kilpailija-taulukolle. */
void jarjesta(kilpailija taulukko[], int koko)
{
  int pituus;

  for (pituus=koko; pituus>1; pituus--)
    siirra_painavin(taulukko, pituus);
}

void tulosta_tulokset(kilpailija kisaajat[], int lkm)
{
  int i;

  cout << "\n\n";
  cout << "Tulokset:\n";
  for (i=0; i<lkm; i++) {
    cout << "\t" << kisaajat[i].tulos;
    cout << "\t" << kisaajat[i].nimi << endl;
  }
}

int main(void)
{
  kilpailija kisaajat[MAXLKM];
  int lkm;

  lue_tiedot(kisaajat, lkm);
  jarjesta(kisaajat, lkm);
  tulosta_tulokset(kisaajat, lkm);

  return 0;
}

Esimerkkiajo:

Anna kilpailijoiden lukumäärä (1-100) > 3
Anna kilpailijan no. 1 tiedot:
Nimi  > Aku Ankka
Tulos > 35
Anna kilpailijan no. 2 tiedot:
Nimi  > Mikki Hiiri
Tulos > 23
Anna kilpailijan no. 3 tiedot:
Nimi  > Hessu Hopo
Tulos > 42


Tulokset:
    42  Hessu Hopo
    35  Aku Ankka
    23  Mikki Hiiri