Ohjelmointi 1 / 2009

Tentti / 5.12

Vastaa 4 tehtävään (max 24 pistettä). Tenttiaika 4 tuntia.
Tentissä on pääteemana tehdä ajopäiväkirja (prototyyppi), joka toimisi seuraavasti (esimerkissä käyttäjän syötteet ovat > ja [ret] välissä):
Tervetuloa, tämä on ajopäiväkirjasi.
Anna ensimmäisen alkulukeman kohdalle koko
mittarilukemasi. Seuraavilla kerroilla voit
antaa vain muuttuneet numerot.
Kun haluat lopettaa, kirjoita alkulukemaksi
teksti
  loppu

Anna alkulukema  (0)>200345[ret]
Anna loppulukema (200345)>95[ret]
Ajoit 50 km.
Yhteensä olet tänään ajanut 50 km.

Anna alkulukema  (200395)>14[ret]  // alkulukemana käytetään nyt 200414
Anna loppulukema (200414)>38[ret]
Ajoit 24 km.
Yhteensä olet tänään ajanut 74 km.

Anna alkulukema  (200438)>loppu[ret]

Kiitoksia käytöstä.  Tervetuloa uudelleen;
Ohjelman pääohjelma näyttäisi seuraavalta:
/**
 * Pääohjelma ajopäiväkirjaa varten.
 * @param args ei käytössä
 */
public static void main(String[] args) {
    esittely();
    kyseleLukemiaJaLaskeKilometreja();
    System.out.println("\nKiitoksia käytöstä.  Tervetuloa uudelleen;");
}
Tentin liitteenä on API-dokumentteja metodeista, joita ohjelmaa tehdessä saa käyttää. Kaikkiin ohjelmointitehtäviin liittyy arvostelukriteerinä myös koodin kommentointi, hyvin valitut muuttujien nimet ja koodin selkeys.
1.
a) Koodia: Kirjoita pääohjelman tarvitsema aliohjelma esittely. (2p)
b) Koodia: Kirjoita (poikkeuksellisesti ilman kommentteja) pienin mahdollinen kyseleLukemiaJaLaskeKilometreja() jotta pääohjelmasta saadaan kääntyvä. (1p)
c) Kirjoita seuraavissa mallikutsuissa tarvittavien aliohjelmien esittelyrivit (vastaava rivi kuin pääohjelman ensimmäinen rivi, taas poikkeuksellisesti ilman JavaDoceja) Java-kielellä (3p):
int i,j,k;
double d1,d2,d3;
...
i = summa(j,k);
d3 = suurin(d1,d2);
d2 = suurin(d1,i);
k = toisenAanPaikka("kissa istuu puussa");
2.
a) Miksi Java-aliohjelmien dokumentointi (JavaDoc) on tärkeää? Mitä JavaDoc dokumenteissa tulisi esittää? (3p)
b) Mitä tarkoittaa olion muuttuminen roskaksi? (1p)
c) Mitä hyötyä on automaattisesta testaamisesta? (1p)
d) Miksi käytetään mieluummin double -tyyppiä kuin float -tyyppiä? (1p)
3.
Koodia: Aliohjelmassa kyseleLukemiaJaLaskeKilometreja() voisi olla hyöytä funktioaliohjelmasta korjaaLukema (testiaineisto seuraavassa tehtävässä). Tämän apuna voisi olla hyötyä funktioaliohjelmasta seuraavaTasaluku. Kirjoita seuraavaTasaluku aliohjelma niin, että se toteuttaa alla olevat testitapaukset. Luvussa olevien numeroiden määrän saa selville matemaattisesti 10-kantaisella logaritmilla, mutta helpompi voi olla muuttaa luku merkkijonoksi ja katsoa merkkijonon pituus. (5p)
     * @example
     * <pre name="test">
     *    seuraavaTasaluku(0)    === 10;
     *    seuraavaTasaluku(1)    === 10;
     *    seuraavaTasaluku(9)    === 10;
     *    seuraavaTasaluku(10)   === 100;
     *    seuraavaTasaluku(99)   === 100;
     *    seuraavaTasaluku(100)  === 1000;
     *    seuraavaTasaluku(123)  === 1000;
     *    seuraavaTasaluku(1234) === 10000;
     * </pre>
Mitä erikoistapauksia ei ole testeissä otettu huomioon? (1p)
4.
Koodia: Kirjoita funktioaliohjelma korjaaLukema, joka toteuttaa alla olevat testitapaukset ja käyttää hyväkseen seuraavaTasaluku -funktiota. (6p)
     * @example
     * <pre name="test">
     *   korjaaLukema(200345,95)   === 200395;
     *   korjaaLukema(200395,14)   === 200414;
     *   korjaaLukema(200345,0)    === 200350;
     *   korjaaLukema(200395,6)    === 200396;
     *   korjaaLukema(200395,414)  === 200414;
     *   korjaaLukema(200395,214)  === 201214;
     *   korjaaLukema(200395,2214) === 202214;
     *   korjaaLukema(-3,2214)     ===   2214;
     *   korjaaLukema(200395,-3)   === 200395;
     *   korjaaLukema(23,2214)     ===   2214;
* </pre>
5.
Koodia: Kirjoita aliohjelma kyseleLukemiaJaLaskeKilometreja() jotta ajopäiväkirjan pääohjelma saadaan toimivaksi. (6p)
6.
Tutki esimerkkien avulla että miksi negatiivisten lukujen esittämisessä on päädytty 2-komplementtiesitykseen. Muita tutkittavia vaihtoehtoja olisi käyttää
1) pelkästään ensimmäistä bittiä etumerkin esittämiseen, muuten
   positiivisen ja negatiivisen luvun bitit olisivat samanlaiset
2) 1-komplementtia, eli negatiivisen luvun jokainen bitti on
   päinvastoin kuin positiivisessa luvussa.
Erityisesti tutki seuraavia asioita:
1) Kahden positiivisen luvun yhteenlasku
2) Erimerkkisten lukujen yhteenlasku kun se tuottaa positiivisen
   ja toisessa tapauksessa negatiivisen tuloksen
3) kahden negatiivisen luvun yhteenlasku
Päättele toimivatko laskutoimitukset automaattisesti eri tapauksissa? Miten eri tapauksissa voidaan havaita lukualueen loppuminen? Vinkki: sovi vaikka 4 bitin luvut ja kirjoita näkyville kaikki 4 bittiset luvut ja mitä mikäkin luku tarkoittaa kussakin tulkinnassa. (6p)
Bonus: Voiko jonkin toimimattoman tapauksen korjata toimivaksi jollakin yksinkertaisella automatisoitavalla toimenpiteellä? (+2p)

Liite 1, API-dokumentit

Syotto.kysy

public static Stringkysy(String kysymys, String oletus)
Aliohjelmalla kysytään käyttäjältä arvo merkkijonolle. Tulostetaan oletusarvo. Jos käyttäjä painaa pelkästään ret, palautetaan oletusarvo
Parameters:
kysymys - käyttäjälle tulostettava kysymys
oletus - arvo jota käytetään jos painetaan pelkkä ret
Returns:
käyttäjän syöttämä merkkijono

Syotto.kysy

public static int kysy(String kysymys,int oletus)
Kysytään kokonaisluku. Jos annetaan ei-luku, kysytään uudelleen. Oletusarvo tulostetaan sulkuihin.
Parameters:
kysymys - näytölle tulostettava kysymys
oletus - arvo jota käytetään jos painetaan pelkkä Ret
Returns:
käyttäjän kirjoittama kokonaisluku

Mjonot.erotaInt

public static int erotaInt(String jono, int oletus)
Ottaa merkkijonosta seuraavan kokonaisluvun
Parameters:
jono - merkkijono josta luku otetaan, jono ei muutu
oletus - arvo jota käytetään jos jonossa ei ole yhtään numeroa
Returns:
otettu kokonaisluku

println

public void println(String x)
Print a String and then terminate the line. This method behaves as though it invokes print(String) and then println().
Parameters:
x - The String to be printed.

String: length

public int length()
Returns the length of this string. The length is equal to the number of 16-bit Unicode characters in the string.
Specified by:
length in interface CharSequence
Returns:
the length of the sequence of characters represented by this object.

String: substring

public Stringsubstring(int beginIndex, int endIndex)
Returns a new string that is a substring of this string. The substring begins at the specified beginIndex and extends to the character at index endIndex - 1. Thus the length of the substring is endIndex-beginIndex.
Examples:
"hamburger".substring(4, 8) returns "urge"
"smiles".substring(1, 5) returns "mile"
Parameters:
beginIndex - the beginning index, inclusive.
endIndex - the ending index, exclusive.
Returns:
the specified substring.
Throws:
IndexOutOfBoundsException - if the beginIndex is negative, or endIndex is larger than the length of this String object, or beginIndex is larger than endIndex.

Integer.toString

public static StringtoString(int i)
Returns a String object representing the specified integer. The argument is converted to signed decimal representation and returned as a string, exactly as if the argument and radix 10 were given as arguments to the toString(int, int) method.
Parameters:
i - an integer to be converted.
Returns:
a string representation of the argument in base 10.

Tosin 
  String s = Integer.toString(i);
voi lyhentää
  String s = ""+i;  // joka on hieman suorituksen hitaampi...