2.7.4 Esimerkkejä silmukoista

Tarkastellaan ohjelmaa, joka laskee annettujen lukujen keskiarvon. Ongelmana tämän tyyppisessä ohjelmassa on syöttötietojen lukeminen. Etukäteen ei voida tietää, kuinka monta lukua käyttäjä aikoo syöttää, joten on sovittava jokin tunnus, jonka luettuaan ohjelma tietää lopettaa syöttötietojen luvun.

Syötön lopettamisesta kertovan tunnuksen valinta tuottaa hieman ongelmia. Ohjelmalle kelpaavat syötteeksi kaikki mahdolliset lukuarvot, se ei aseta mitään lukuarvoa erikoisasemaan, joten mikään lukuarvo ei suoraan käy lopetusmerkiksi (ilman erillistä testaamista). Lopetusmerkiksi ei käy myöskään merkkitieto, sillä tässä tapauksessa syötteeksi odotetaan liukulukua.

Yksinkertaisin, vaikkakaan ei kaunein, tapa on sopia jokin tietty luku, johon syöttäminen lopetetaan. Tämä tuo tietysti ohjelman toimintaan käytännön rajoituksen, joka on syytä huomata: valittua lukua ei voida käyttää lainkaan mukana itse laskennassa. Näin ollen luku on syytä valita siten, että se ei kuulu kaikkein yleisimpiin laskennassa mukana oleviin lukuihin. Sovitaan tässä ohjelmassa, että lukeminen lopetetaan, kun käyttäjä antaa luvun -9999. Sen testaaminen hoidellaan silmukan lopetusehdossa.

/* *********************************************************
LUVUT.CPP
  Lasketaan annettujen lukujen keskiarvo.
********************************************************* */

#include <iostream.h>

void esittele(void)
{
  cout << "\n\n";
  cout << "Lasken antamiesi lukujen keskiarvon.\n";
  cout << "Syöttötietojen lopetus luvulla -9999.\n" << endl;
}

void lue_ja_summaa(int &lkm, double &summa)
{
  double luku; // luettu luku

  cout << "Anna luku > ";
  cin >> luku;
  while (luku != -9999) { // Mitä huonoa tässä ehdossa on?
    lkm++;
    summa = summa + luku;
    cout << "Anna luku > ";
    cin >> luku;
  }
}

void laske_ja_tulosta(int lkm, double summa)
{
  double keskiarvo;

  cout << "\n";
  cout << "Annoit yhteensä " << lkm << " lukua.\n";
  if (lkm == 0)
    cout << "Keskiarvoa ei voitu laskea." << endl;
  else {
    keskiarvo = summa/lkm;
    cout << "Lukujen keskiarvo on " << keskiarvo << endl;
  }
}

int main(void)
{
  int lkm = 0;        // lukujen lukumäärä
  double summa = 0.0; // lukujen summa

  esittele();
  lue_ja_summaa(lkm, summa);
  laske_ja_tulosta(lkm, summa);

  return 0;
}

Esimerkkiajo:

Lasken antamiesi lukujen keskiarvon.
Syöttötietojen lopetus luvulla -9999.

Anna luku > 10.2
Anna luku > 12.3
Anna luku > 2.5
Anna luku > -9999

Annoit yhteensä 3 lukua.
Lukujen keskiarvo on 8.333333

Mitä huonoa on ehdossa (luku != -9999)? Miten muuttaisit sitä?

Lopuksi kirjoitetaan vielä painonvartijasta versio, jossa syöttötiedot tarkistetaan ja tarvittaessa kysytään uudestaan niin kauan kunnes annetaan järkevät arvot. Lisäksi kommentoidaan huolellisesti kaikki funktiot.

/* *********************************************************
PAINO6.CPP
  Lasketaan ihannepaino.
  Siististi kommentoitu versio.
********************************************************* */

#include <iostream.h>
#include <stdio.h>

/* ------------------------------------------------------ */
/*                  Käytettävät vakiot                    */
/* ------------------------------------------------------ */
#define SUHDELUKU   100.0   // ihannepainon laskentavakio
#define ALIN_PITUUS  10.0   // pituuden alaraja
#define YLIN_PITUUS 300.0   // pituuden yläraja
#define ALIN_PAINO    1.0   // painon alaraja
#define YLIN_PAINO  350.0   // painon yläraja

/* ------------------------------------------------------ */
/* tulosta_esittely - tulostetaan näytölle ohjelman       */
/*                    esittelyteksti                      */
/* ------------------------------------------------------ */
void tulosta_esittely(void)
{
  cout << "\n\n";
  cout << "       Ihannepaino\n\n";
  cout << "Ohjelma laskee ihannepainosi\n";
  cout << "pituutesi perusteella.\n" << endl;
}

/* ------------------------------------------------------ */
/* kysy_pituus - luetaan näppäimistöltä käyttäjän pituus  */
/*             - tarkistetaan pituuden järkevyys          */
/*             - palautetaan pituus parametrissa          */
/* ------------------------------------------------------ */
void kysy_pituus(double &pituus)
{
  cout << "Anna pituutesi sentteinä > ";
  cin >> pituus;
  while (pituus < ALIN_PITUUS || pituus > YLIN_PITUUS) {
    cout << "Antamasi pituus on järjetön!\n";
    cout << "Anna pituutesi sentteinä > ";
    cin >> pituus;
  }
}

/* ------------------------------------------------------ */
/* kysy_paino - luetaan näppäimistöltä käyttäjän paino    */
/*            - tarkistetaan painon järkevyys             */
/*            - palautetaan paino parametrissa            */
/* ------------------------------------------------------ */
void kysy_paino(double &paino)
{
  cout << "Anna painosi kiloina     > ";
  cin >> paino;
  while (paino < ALIN_PAINO || paino > YLIN_PAINO) {
    cout << "Antamasi paino on järjetön!\n";
    cout << "Anna painosi kiloina     > ";
    cin >> paino;
  }
}

/* ------------------------------------------------------ */
/* laske_ihanne - lasketaan ihannepaino vähentämällä      */
/*                pituudesta suhdeluku                    */
/*              - pituus tuodaan parametrina              */
/*              - paluuarvona ihannepaino                 */
/* ------------------------------------------------------ */
double laske_ihanne(double pituus)
{
  return (pituus - SUHDELUKU);
}

/* ------------------------------------------------------ */
/* laske_erotus - lasketaan painon ja ihannepainon erotus */
/*              - painot tuodaan parametreina             */
/*              - paluuarvona erotus                      */
/* ------------------------------------------------------ */
double laske_erotus(double paino, double ihanne)
{
  return (paino - ihanne);
}

/* ------------------------------------------------------ */
/* tulosta_painot - tulostetaan näytölle paino,           */
/*                  ihannepaino ja näiden erotus          */
/*                - arvot tuodaan parametreina            */
/* ------------------------------------------------------ */
void tulosta_painot(double paino, double ihanne, double erotus)
{
  printf("\n");
  printf("Nykyinen painosi %5.1lf kg\n", paino);
  printf("Ihannepainosi    %5.1lf kg\n", ihanne);
  printf("Erotus           %5.1lf kg\n", erotus);
}

/* ------------------------------------------------------ */
/*                      Pääohjelma                        */
/* ------------------------------------------------------ */
int main(void)
{
  double pituus, paino, ihanne, erotus;

  tulosta_esittely();
  kysy_pituus(pituus);
  kysy_paino(paino);
  ihanne = laske_ihanne(pituus);
  erotus = laske_erotus(paino, ihanne);
  tulosta_painot(paino, ihanne, erotus);

  return 0;
}