Ohjelmointi 1, syksy 2007 -- Demo 2

Tehtävät julkaistaan:
 Tiistain luennolla 18.9.2007
Palautus viimeistään:
 25.9.2007 klo 18
100% tehtävistä tarkoittaa:
 8 kpl tehty

Nyt harjaannutetaan syntaksin käsitettä, ja aletaan tuottaa itse Java-ohjelmia. Algoritmeja ajatellaan vielä myös arkihavainnon kautta ilman ohjelmointikieltä.

Contents

Syntaksin syvennystä

Tehtävä 1:

Jos et tiedä sellaista ennestään, keksi itse hyvä keino kuvailla syntaksi pelkkänä tekstinä (tekstitiedostossa). Määrittele sitten aukottoman täsmällisesti ''korkeimman tason elementistä aina kirjaimiin asti tarkentuen'' syntaksi, joka kuvaa demonpalautusohjelmallemme (se tähän asti monille tuskaa tuottanut ohj1) sallitut komentorivit (siis itse komento ja argumenttilista).

Saat jättää avaamatta syntaktisen elementin nimeltä TdstoNimenMerkki, joka oletetaan jo määritellyksi: se olisi mikä tahansa tiedostonimeen kelpuutettava merkki. Muuten syntaksisi tulee kyetä:

  • hyväksymään sanallisissa ja näytetyissä demo-ohjeissa tähän asti kuvatut palautukset

  • hylkäämään selkeästi Ohjelmointi 1:n syksyn 2007 kurssin kannalta väärältä näyttävät argumentit kuten:

    ohj1 demoTAPiIri kuustoista LauLau.java
    

Pyri täsmällisyyteen, joka vastaa luennoilla esiteltyä diagramminotaatiota, esim. rautatie6 tai Tarina -syntaksit. Ainoastaan tiedostonimiin tulevan yksittäisen merkin saat jättää avaamatta merkkivaihtoehdoiksi (niitä ''pylpyröitä'' btw. sanotaan päätesymboleiksi...)

Tiedon esitysmuodot

Tehtävä 2:

Binäärilukujärjestelmässä on kaksi numeroa, nolla ja yksi. Tätä sanotaan bitiksi (binary digit). Vähiten merkitsevä eli viimeisimmäksi kirjoitettu bitti tarkoittaa lukumäärää yksi, toiseksi vähiten merkitsevä bitti lukumäärää kaksi, kolmanneksi vähiten merkitsevä lukumäärää neljä ja niin edelleen aina kakkosen potensseja jatkaen (8, 16, 32, 64, ...). Kokonaisen binääriluvun ilmoittama lukumäärä saadaan kun summataan nämä yksittäisten bittien ilmoittamat lukumäärät toisiinsa. Esimerkiksi binääriluku 1000101 olisi kymmenjärjestelmässä:

1*64 + 0*32 + 0*16 + 0*8 + 1*4 + 0*2 + 1*1 == 69

Muunna seuraavat binääriluvut ihmiselle tutumpaan 10-järjestelmään:

  1. 10010
  2. 1001110001
  3. 1000000000000000
  4. 1010101010101011
  5. 10000000000000001
  6. 10000000000000010
  7. 10000000000000011

Nykytietokoneissa on tyypillistä jakaa muisti kahdeksan bitin mittaisiin tallennuspaikkoihin. Mikä on suurin kokonaisluku, jonka voit tallentaa kahden paikan kokoiseen tilaan (oletetaan että negatiivisia lukuja ei tarvitse esittää)? Entäpä jos pitää voida esittää positiivisia ja negatiivisia lukuja: mikä silloin on toisaalta pienin ja toisaalta suurin luku, joka kahden muistipaikan kokoiseen tilaan mahtuu?

Ohjelmakoodin ymmärtämistä

Tehtävä 3:

Seuraavassa on Java-ohjelma:

public class EsimerkkiLausekkeesta{
  public static void main(String[] args){
    int a = 000;
    int b = 006;
    int c = 016;
    int d = 106;
    int e = 0xe;

    int f = (a*b) + (a - (c+d) ) * (e + 0126);
  }
}

Tarkastele riviä, joka sijoittaa f:ään. Jäsennä siinä suoritettava laskutoimitus: mikä tai mitkä operaatiot tapahtuvat ensiksi presedenssisääntöjen mukaan, mitkä sitten ja niin edelleen, mikä aivan viimeksi. Lopullisen arvon näet kyllin helposti lisäämällä ohjelman loppuun tulostuksen, ja ajamalla sen. Mutta tässä tehtävässä kuvaile laskutoimituksen suorittuminen tietokoneella vaihe vaiheelta. Jokaisen operaation kohdalla, kerro seuraavat asiat:

  • mikä operaattori tässä operaatiossa suoritetaan
  • mikä lukuarvo kymmenjärjestelmässä ilmaistuna on operaattorin vasemmalla ja kumpi oikealla puolella (ts. mikä lukuarvo on vasen ja kumpi oikea operandi)
  • mikä on tuloksen lukuarvo (sehän menee jonkun seuraavan operaattorin operandiksi seuraavaksi; pidä kirjaa, minkä.)

Ole tarkkaavainen literaalien kirjoitusmuodon ja muuttujien arvojen suhteen! Sopiva vastausformaatti voisi alkaa esim:

Ensiksi suoritetaan (a*b), jossa:
     operaattori on *
     vasemman operandin arvo on 0
     oikean operandin arvo on ...

Ohjelmien kirjoittamista

Tehtävä 4:

Tämä koodi ei taida ole hyvän koodauskäytännön mukaista. Selvitä, mitä ohjelma tekee, ja korjaa siitä kommentit ja muuttujien sekä metodien nimet sellaisiksi, että ohjelma on välittömästi ymmärrettävissä:

/** Yrittanytta ei laiteta, vaikka katajaan kapsahtaisi!
  * @author N.N.
  * @version 1.0
  */
public class PieleenMeneeKaikki{
    /** Kommentoisin Nightwishin solistia tässä. */
    public static double voimisteleIte(double gVoima,
            double inertia, double viskositeetti){
        return gVoima * inertia * viskositeetti;
    }
    public static void main(String[] args){
        double h1ltun3n = 15;
        double voo_voo  = 7.8;
        double kUUs1st0 = 2.5;
        double maamiina = voimisteleIte(h1ltun3n, voo_voo, kUUs1st0);
        System.out.printf("Vastaus on %.4f kuutiometria", maamiina);
    }
}

Tehtävä 5:

Edellisessä demossa kirjoitit itsestäsi esittelyn tekstitiedostoon. Ota se pohjaksi, ja muuta se Java-ohjelmaksi, joka tulostaa yhden rivin kerrallaan standardiulostuloon.

Otsikon (tai jokaisen otsikon, jos on monta) ja jokaisen yksittäisen tekstikappaleen tulostaminen tulee tapahtua omassa aliohjelmassa. Itse pääohjelma main() ei saa tulostaa mitään.

Kerta kiellon päälle. Tee ohjelmasta vielä sellainen, että se tulostaa tekstin kaksi kertaa peräjälkeen.

Huomaa jo tässä ja tästedes kaikissa Java-ohjelmissa:

  • Ohjelman tulee olla toimiva Java-ohjelma; siis sen pitää sellaisenaan kääntyä ja se pitää pystyä suorittamaan Java virtuaalikoneessa.
  • Ohjelmassa tulee olla javadoc-kommentit (eli /** ... */) jokaisessa luokassa ja metodissa. Ja niiden on kuvattava dokumentoidun osion merkitys yleisen Java-käytänteen suosittelemalla tavalla. Tiedoston alussa on ilmettävä tekijän nimi ja ohjelman versio javadoc-tageilla (@author ja @version)
  • Ohjelman tulee olla sisennetty merkityksen mukaan ja muutenkin sen pitää olla yleisten Java-käytänteiden mukainen.
  • Sisennykseen on käytettävä välilyöntejä eikä tabulaattorimerkkejä.
  • Kannattaa ryhtyä vaivihkaa selvittelemään ja tiedostamaan, mitä merkistöä oikein käyttää kirjoittaessaan - jos nimittäin aikoo kirjoittaa ääkkösiä.

Tehtävä 6:

Toteuta aliohjelma, joka muuntaa Celsius-asteina annetun lämpötilan Fahrenheit-asteiksi. Muunnoskaava on:

fahrenheitit = (9/5)*celsiukset + 32

Tätä käyttäen toteuta pääohjelma, joka tulostaa viiden desimaalin tarkkuudella Fahrenheit-asteet Celsius-astemäärille 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ja 10.

Algoritmeja

Tehtävä 7:

Tee algoritmi eli toimintaohje, jolla kuvaat, miten puhelinluettelosta etsitään tietyn henkilön nimi. Entä millaisella algoritmilla puhelinluettelosta löytyy tietyn numeron omistaja? Kumpi algoritmeista on nopeampi ja miksi?

Tehtävä 8:

Pitäydy tässä tehtävässä vielä irti Javasta ja muista ohjelmointikielestä. Kuvaile suomen kielellä tai korkeintaan ''pseudokoodilla'', miten jakaisit seuraavat tehtävät yhtä pykälää tarkemmiksi osatehtäviksi. Jaa sitten vielä kukin osatehtävä seuraavalle tasolle pienemmiksi osatehtäviksi. Käytä jotakin luonnollisia ilmauksia toistolle ja päätöstilanteille ("jos ... niin ... mutta muussa tapauksessa ..."):

  1. Tiskaaminen
  2. Kahvin keittäminen
  3. Nimilappujen lajitteleminen aakkosjärjestykseen
  4. Yatzyn eli 5 samaa numeroa saaminen Yatzy-pelissä mahdollisimman vähillä heitoilla ottaen huomioon että jokainen uusi heitto antaa ennalta tuntemattoman, satunnaisen tuloksen.
  5. Maksimaalisen täyskäden eli kolme kutosta ja kaksi vitosta saaminen vastaavasti kuin edellä.