Tämä materiaali on lisensoitu Creative Commons BY-NC-SA-lisenssillä, joten voit käyttää ja levittää sitä vapaasti, kunhan alkuperäisten tekijöiden nimiä ei poisteta. Jos teet muutoksia materiaaliin ja haluat levittää muunneltua versiota, se täytyy lisensoida samanlaisella vapaalla lisenssillä. Materiaalien käyttö kaupalliseen tarkoitukseen on ilman erillistä lupaa kielletty.
Tekijät: Arto Vihavainen ja Matti Luukkainen
Tämä materiaali on tarkoitettu Helsingin yliopiston tietojenkäsittelytieteen laitoksen kursseille ohjelmoinnin perusteet ja ohjelmoinnin jatkokurssiohjelmoinnin MOOC-kurssille. Materiaali pohjautuu Helsingin yliopistolla vuodesta 2010 käytettyihin kurssimateriaaleihin, joiden sisältöön ovat vaikuttaneet muun muassa Matti Paksula, Antti Laaksonen, Pekka Mikkola, Juhana Laurinharju, Martin Pärtel, Joel Kaasinen ja Mikael Nousiainen.
Lue materiaalia siten, että teet samalla lukemasi esimerkit itse. Esimerkkeihin kannattaa tehdä pieniä muutoksia ja tarkkailla, miten muutokset vaikuttavat ohjelman toimintaan. Äkkiseltään voisi luulla, että esimerkkien tekeminen ja muokkaaminen hidastaa opiskelua. Tämä ei kuitenkaan pidä paikkansa. Ohjelmoimaan ei ole vielä tietääksemme kukaan ihminen oppinut lukemalla (tai esim. luentoa kuuntelemalla). Oppiminen perustuu oleellisesti aktiiviseen tekemiseen ja rutiinin kasvattamiseen. Esimerkkien ja erityisesti erilaisten omien kokeilujen tekeminen on parhaita tapoja "sisäistää" luettua tekstiä. Käytetyssä ohjelmointiympäristössä, Test My Codessa (TMC), on kokeiluja varten tehtäväpohja, jonka nimi on "Hiekkalaatikko".
Pyri tekemään tai ainakin yrittämään tehtäviä sitä mukaa kuin luet tekstiä. Jos et osaa heti tehdä jotain tehtävää, älä masennu, sillä saat ohjausta tehtävän tekemiseen IRC:ssä kanavilla #ohpe ja #mooc.fi.
Tekstiä ei ole tarkoitettu vain kertaalleen luettavaksi. Joudut varmasti myöhemmin palaamaan jo aiemmin lukemiisi kohtiin tai aiemmin tekemiisi tehtäviin. Tämä teksti ei sisällä kaikkea oleellista ohjelmointiin liittyvää. Itse asiassa ei ole olemassa mitään kirjaa josta löytyisi kaikki oleellinen. Eli joudut joka tapauksessa ohjelmoijan urallasi etsimään tietoa myös omatoimisesti. Kurssin harjoitukset sisältävät jo jonkun verran ohjeita, mistä suunnista ja miten hyödyllistä tietoa on mahdollista löytää.
Materiaalissa on myös screencasteja, eli videoita, joita katsomalla voi pelkän valmiin koodin lukemisen sijaan seurata miten ohjelma muodostuu. Tämän lisäksi materiaalissa on kyselyjä, joiden vastauksia käytetään osana Helsingin yliopistolla tehtävää ohjelmoinnin oppimisen tutkimusta. Kyselyt ja tehtävät saa auki klikkaamalla kyselyn tai tehtävän nimeä.
Kurssilla on tehtäviä, joiden tekeminen on oleellinen osa kurssin suoritusta. Ensimmäisellä viikolla alkavat ohjelmointitehtävät, ja toisesta viikosta lähtien ohjelmointitehtävien lisäksi materiaalissa on myös selitystehtäviä, joissa annettuun kysymykseen tai ongelmaan tulee kirjoittaa selitys ohjeiden mukaan. Kurssin toisesta viikosta lähtien mukana on myös muutamia viikoittaisia tehtäviä, jotka tehdään pariohjelmointina pajassa. Katso kurssisivultakurssisivulta tarkempaa tietoa kurssin arvostelusta ja suoritustavoista.
Ohjelmointi- ja selitystehtävien lisäksi materiaalissa on tutkimuskysymyksiä ja kyselyitä. Kyselyihin vastaamalla tuet ohjelmoinnin oppimiseen liittyvää tutkimusta.Vastaamalla rehellisesti kaikkiin materiaalissa oleviin tutkimuskysymyksiin ja -kyselyihin saat lisäpisteitä, joilla voit paikata tekemättä jääneitä tehtäviä.
Näet tehtävien ja kyselyjen sisällön klikkaamalla niiden nimeä.
Tietokoneohjelmia verrataan usein leipomiseen. Tietokone on leipuri, tietokone-ohjelma resepti, ja tietokoneen resurssit -- esimerkiksi näyttö ja verkkokortti -- raaka-aineita. Leipurilla ja tietokoneella on kuitenkin merkittävä ero siinä, että vaikka leipuri kehittyy reseptejä toistaessa ja osaa esimerkiksi kokeilla uusia raaka-aineita, tietokoneella ei tällaista taitoa ole. Tietokone noudattaa ohjeita säntillisesti, jopa tyhmästi. Jos reseptissä on kirjoitusvirhe, tietokone ei tiedä miten toimia. Se ei myöskään osaa reagoida vaikkapa rikkinäiseen uuniin, ellei resepti kerro täsmällisesti mitä uunin rikkoutuessa tulee tehdä.
Toisin kuin leipuri, tietokone ei myöskään kehity siinä mielessä, että se oppisi virheistä. Ohjelmoijat, reseptien -- tai lähdekoodin -- kehittäjät, onneksi kuitenkin oppivat ja kehittyvät.
Ohjelma -- resepti -- muodostuu lähdekoodista. Tietokone suorittaa lähdekoodissa olevia komentoja pääsääntöisesti rivi riviltä ylhäältä alaspäin ja vasemmalta oikealle. Lähdekoodi on ohjelmoijan kirjoittamaa, ja se tallennetaan tekstimuodossa. Jokaisen komennon yhteydessä tietokone toimii komennon määräämällä tavalla. Esimerkiksi tekstin (merkkijono) "Hei maailma" tulostuksessa käytetään komentoa:
System.out.println("Hei maailma");
Komento System.out.println
tulostaa sille sulkeiden sisällä hipsuissa annetun merkkijonon. Komennon pääte ln
on lyhenne sanasta line, eli komento tulostaa merkkijonon jälkeen myös rivinvaihdon. Komennon loppuun kirjoitetaan puolipiste ;
.
Javassa ohjelmat käynnistetään kurssin aikana tutuksi tulevan rungon sisältä. Ohjelman "Esimerkki" runko on seuraavanlainen.
public class Esimerkki { public static void main(String[] args) { System.out.println("Tulostettava teksti"); } }
Ohjelmarunko sijaitsee .java-päätteisessä tekstitiedostossa, jonka nimi on sama kuin ohjelman nimi -- tässä Esimerkki -- "public class Esimerkki". Ohjelma Esimerkki sijaitsee siis tiedostossa, jonka nimi on Esimerkki.java
.
Tietokone aloittaa ohjelman suorituksen riviä public static void main(String[] args) {
seuraavalta riviltä, ja käy komentoja yksitellen läpi. Ohjelmakoodin suoritus päättyy sulkevaan aaltosulkuun }
. Tällä hetkellä ainoa suoritettava komento on System.out.println("Tulostettava teksti");, mikä tulostaa tekstin "Tulostettava teksti".
Jatkossa materiaalin esimerkeissä ei aina erikseen näytetä ohjelmarunkoa, mutta voit olettaa, että se tarvitaan.
Nykyaikainen ohjelmointi tapahtuu lähes poikkeuksetta ohjelmointiympäristössä. Ohjelmointiympäristö sisältää joukon ohjelmoijaa auttavia aputoimintoja. Se ei rakenna ohjelmaa ohjelmoijan puolesta, mutta se muunmuassa vinkkaa helpoista virheistä ohjelmakoodissa ja auttaa ohjelmoijaa hahmottamaan ohjelman rakennetta.
Ennen kuin tiedät mitä teet, toimi täsmälleen ohjeen kuvaamalla tavalla. Useimmat seuraavista tehtävänannoista näyttävät mitä pyydetyn tehtävän tulisi tulostaa ruudulle toimiakseen oikein.
HUOM: älä tee tehtäviä siten että pelkästään kirjoitat koodia ja painelet testinappia. Suorita myös koodia normaaliin tapaan (vihreällä nuolella) ja katso mitä ruudulle tulostuu. Erityisesti jos ohjelma ei meinaa mennä testeistä läpi, kannattaa varmistaa normaalisti suorittamalla että ohjelma toimii silmämääräisesti niinkuin sen pitäisi.
Seuraavassa tehtävässä harjoitellaan tuntuman saamista NetBeansiin ja ruudulle tulostamista. Näet tehtävänannon klikkaamalla tehtävän nimeä
Tehtäväpohjassa on seuraavanlainen ohjelmarunko:
public class Nimi { public static void main(String[] args) { // Kirjoita ohjelmasi tähän alle } }
Rivi "// Kirjoita ohjelmasi tähän alle" on kommenttirivi, jota tietokone ei ota huomioon ohjelmaa suoritettaessa.
Lisää kommenttirivin alle komento, joka tulostaa nimesi ja suorita ohjelma. Ohjelman tulostus voi olla seuraava:
Essi Esimerkki
Tai vaikkapa seuraava:
Oskari Opiskelija
Kun olet suorittanut ohjelman ja ohjelma tulostaa nimesi, palauta tehtävä TMC:lle.
Tulostamiseen on käytännössä kaksi komentoa:
System.out.println("sana"); tulostaa tekstin "sana" ja loppurivinvaihdon
System.out.print("sana");
tulostaa tekstin "sana" ilman loppurivinvaihtoaTulostettavan tekstin osana voi olla myös erikoismerkkejä, joista tärkein on rivinvaihto, eli \n
. Erikoismerkkejä on muitakin.
System.out.println("Ensimmäinen\nToinen\nKolmas");
Ylläoleva komento tulostaa seuraavaa:
Ensimmäinen Toinen Kolmas
Puolipisteellä ;
erotetaan komennot toisistaan. Voisimme oikeastaan kirjoittaa koko ohjelman yhdelle riville -- mikä ei kuitenkaan ole kovin ymmärrettävää.
Esimerkki puolipisteiden käytöstä
System.out.print("Hei "); System.out.print("maailma"); System.out.print("!");
Hei maailma!
Vaikka ohjelma toimii myös ilman rivinvaihtoja, on niiden käyttö hyvin tärkeää muita ajatellen. Selkeä lähdekoodin osien erottelu vaatii rivinvaihtojen käyttöä. Tätä ja muita lähdekoodin luettavuuteen liittyviä seikkoja tullaan painottamaan tällä kurssilla.
Komennon käsittelemä tieto eli komennon parametrit lähetetään komennolle lisäämällä ne komennon perässä olevien sulkujen ()
sisään. Esimerkiksi System.out.println
-komennon parametriksi annetaan merkkijono hei hipsujen sisällä seuraavasti: System.out.println("hei")
.
Lähdekoodin kommentit ovat kätevä tapa merkitä asioita muistiin. Kommentti on mikä tahansa rivi, joka alkaa kahdella vinoviivalla //
. Kaikki kommenttimerkkiä seuraava samalla rivillä oleva teksti tulkitaan kommentiksi.
// Tulostamme tekstin "Hei maailma" System.out.print("Hei maailma"); System.out.print(" ja kaikki sen ihmiset."); // Lisäämme samalle riville tekstiä. // System.out.print("tätä riviä ei suoriteta koska se on kommentoitu ulos");
Hei maailma ja kaikki sen ihmiset.
Esimerkissä alin rivi esittelee erityisen kätevän käyttökohteen kommenteille: kirjoitettua koodia ei tarvitse poistaa jos haluaa tilapäisesti kokeilla jotain.
Tee ohjelma, jonka tulostus on seuraava:
Hei Maailma! (Ja Mualima!)
Vaikka tietokone ja käyttämämme ohjelmointikieli ei aseta rajoituksia kirjoitettavan ohjelmakoodin ulkoasulle, olemme osana ohjelmoinnin opetuksen ja oppimisen tutkimista huomanneet että ohjelmoijan -- tai opiskelevan ohjelmoijan -- kirjoittaman koodin ulkoasulla on merkitystä myös oppimisen kannalta. Esimerkiksi lähdekoodin luettavuus ja sisennyksen säännönmukaisuus ovat asioita, jotka vaikuttavat lähdekoodin ymmärrettävyyteen, ja sitä kautta myös oppimistuloksiin. Seuraava koodi on säännönmukaisesti sisennettyä.
public class Esimerkki { public static void main(String[] args) { System.out.println("Heippa vaan! Tämä koodi on siististi sisennetty."); System.out.println("public class -- ei sisennystä."); System.out.println("public static -- neljän merkin sisennys."); System.out.println("public static ... sisällä -- kahdeksan merkin sisennys -- tai enemmän."); } }
Tämä koodi taas ei ole kovin ymmärrettävää.
public class Esimerkki { public static void main(String[] args) { System.out.println("Heippa vaan! Tämä koodi on siististi sisennetty."); System.out.println("public class -- ei sisennystä."); System.out.println("public static -- neljän merkin sisennys."); System.out.println("public static ... sisällä -- kahdeksan merkin sisennys -- tai enemmän.");}}
Kurssilla käytettävässä Test My Code-ympäristössä tulee mukana Checkstyle-niminen työväline, joka ohjaa hyvään ohjelmointityyliin. Checkstyle tarkistaa mm. koodin sisennystä, metodien nimeämistä, tyhjiä lohkoja ja paljon muuta -- kurssin edetessä nämä käsitteet tulevat tutuiksi. Tällä kurssilla Checkstyle tarkistaa lähes ainoastaan tyylivirheitä -- ohjeita tulee kurssin edetessä.
Tyylivirheet näytetään ohjelmointiympäristössä keltaisella, ja normaalit testi-ilmoitukset punaisella. Kurssilla tutuksi tuleva tehtävän edistymispalkki muuttuu myöskin keltaiseksi, jos koodissa havaitaan tyylivirheitä. Vaikkakin näppäinyhdistelmä alt + shift + f (OS X control + shift + f) auttaa useimpien tyylivirheiden korjaamiseen, on koodia syytä kirjoittaa oikein alusta alkaen.
Tee ohjelma, jonka tulostus on seuraava:
* *** ***** ******* ********* *
HUOM: kirjoitit todennäköisesti aika monta kertaa System.out.println("...")
. Kokeile kirjoittaa NetBeans:iin (main:in sisään) tyhjälle riville sout ja paina tabulaatoria (näppäin q:n vasemmalla puolella). Mitä tapahtuu? Tämä pieni apuväline säästänee jatkossa runsaasti aikaasi.
Tehtäväpohjaan on liitetty valmis komponentti Ohjain
jonka avulla on mahdollista ohjata pientä robottia.
Pääohjelma "importoi" eli ottaa komponentin käyttöönsä lisäämällä koodin yläosaan import robotti.Ohjain;
. Komennolla Ohjain.kaynnista();
robottiohjain käynnistää robotin, ja luo ikkunan, jossa robotin kulkemista voi seurata.
Robottia liikutetaan komennoilla Ohjain.ylos();
, Ohjain.oikealle();
, Ohjain.alas();
, ja Ohjain.vasemmalle();
. Seuraavassa on esimerkkiohjelma robottiohjaimen käytöstä siten, että robottia siirretään kaksi ruutua ylöspäin:
import robotti.Ohjain; public class Paaohjelma { public static void main(String[] args) { // käynnistetään robotti Ohjain.kaynnista(); Ohjain.ylos(); Ohjain.ylos(); // sammutetaan robotti Ohjain.sammuta(); } }
Yllä oleva ohjelma päätyy seuraavaan tilanteeseen:
Kuten huomaat, robotti jättää liikkuessaan jäljen kohtiin, missä se on käynyt.
Tehtävänäsi on tehdä ohjelmarunkoon ohjelma, joka kuljettaa robottia siten, että lopputilanne on seuraavanlainen.
Yllä suuremman suorakulmion leveys on 7 askelta ja korkeus on 5 askelta, ja pienemmän suorakulmion leveys on 3 askelta, ja korkeus 2 askelta. Kun olet lähettänyt tehtävän tarkastettavaksi ja palautusautomaatti hyväksyy sen, voit muokata koodia ja tehdä vapaasti erilaisia kuvioita!
Keskeinen käsite ohjelmoinnissa on muuttuja. Muuttujaa kannattaa ajatella lokerona, johon voi tallettaa annetun tyyppistä tietoa. Tiedolla on aina tyyppi. Tyyppejä ovat esimerkiksi teksti eli merkkijono (String
), kokonaisluku (int
) ja liukuluku (double
) eli desimaaliluku. Muuttujaan asetetaan arvo yhtäsuuruusmerkillä (=
).
int kuukausia = 12;
Yllä olevassa lauseessa asetetaan kokonaisluku-tyyppiä (int) olevaan muuttujaan nimeltä kuukausia arvo 12. Lause luetaan "muuttuja kuukausia saa arvon 12".
Muuttujan arvo voidaan yhdistää merkkijonoon +
-merkillä seuraavan esimerkin mukaisesti.
String teksti = "sisältää tekstiä"; int kokonaisluku = 123; double liukuluku = 3.141592653; System.out.println("Tekstimuuttuja: " + teksti); System.out.println("Kokonaislukumuuttuja: " + kokonaisluku); System.out.println("Liukulukumuuttuja: " + liukuluku);
Tulostus:
Tekstimuuttuja: sisältää tekstiä Kokonaislukumuuttuja: 123 Liukulukumuuttuja: 3.141592653
Tehtäväpohja sisältää ohjelman, joka tulostaa seuraavaa.
Kanoja: 3 Pekonia (kg): 5.5 Traktori: Ei ole! Tässä vielä tiivistelmä: 3 5.5 Ei ole!
Muuta ohjelmaa annetuista kohdista niin että tuloste on:
Kanoja: 9000 Pekonia (kg): 0.1 Traktori: Zetor Tässä vielä tiivistelmä: 9000 0.1 Zetor
Muuttuja säilyttää arvonsa kunnes siihen asetetaan toinen arvo. Huomaa että muuttujan tyyppi kirjoitetaan vain kun muuttuja esitellään ohjelmassa ensimmäistä kertaa.
int luku = 123; System.out.println("Muuttujan arvo on " + luku); luku = 42; System.out.println("Muuttujan arvo on " + luku);
Tulostus:
Muuttujan arvo on 123 Muuttujan arvo on 42
Tarkastellaan edellisen ohjelmakoodin suoritusta askel askeleelta. Kun muuttuja esitellään ohjelmakoodissa ensimmäistä kertaa, eli sekä muuttujan tyyppi (tässä int
) että sen nimi (tässä luku
) kerrotaan, tietokone luo muuttujaa varten nimetyn lokeron. Tämän jälkeen yhtäsuuruusmerkin oikealla puolella oleva arvo kopioidaan tähän nimettyyn lokeroon.
Kun ohjelmakoodissa viitataan muuttujaan sen nimellä -- tässä halutaan tulostaa merkkijono "Muuttujan arvo on " sekä muuttujan luku
arvo, muuttujan luku
arvo haetaan sen nimellä löytyvästä lokerosta.
Kun muuttujaan asetetaan arvo (tässä luku = 42
), tarkistetaan ensin löytyykö muuttujan nimistä lokeroa. Jos lokero löytyy, uusi arvo kopioidaan lokeroon vanhan arvon tilalle ja vanha arvo katoaa. Jos muuttujan nimellä ei löydy lokeroa, ohjelman suoritus päättyy virheilmoitukseen tai ohjelmaa ei voida käynnistää.
Seuraavaksi ohjelmakoodissa viitataan taas muuttujaan sen nimellä -- tässäkin halutaan tulostaa merkkijono "Muuttujan arvo on " sekä muuttujan luku
arvo. Toimitaan kuten normaalisti, eli haetaan muuttujan luku
arvo sen nimellä löytyvästä lokerosta.
Kun muuttujan tyyppi on kertaalleen määritelty, ei se enää muutu. Esimerkiksi merkkijonoa ei voi asettaa kokonaislukutyyppiseen muuttujaan, eikä merkkijonomuuttujaan voi asettaa kokonaislukua.
String merkkijono = "Hei maailma!"; merkkijono = 42; // Ei onnistu int luku = 10; merkkijono = luku; // Ei myöskään onnistu
Poikkeus kuitenkin löytyy: liukulukutyyppiseen muuttujaan voi asettaa kokonaisluvun, sillä Java osaa muuttaa kokonaisluvun liukuluvuksi asetuksen yhteydessä.
double liukuluku = 0.42; liukuluku = 1; // Onnistuu int luku = 10; liukuluku = luku; // Onnistuu myös
Liukulukua ei kuitenkaan voi asettaa kokonaislukuun, sillä emme halua että desimaaliarvot leikkautuisivat vahingossa pois.
int luku = 4.2; // Ei onnistu double liukuluku = 0.42; luku = liukuluku; // Ei myöskään onnistu
Muuttujan nimeämistä rajoittavat tietyt ehdot. Vaikka muuttujan nimessä voidaan käyttää ääkkösiä, on parempi olla kayttamatta niita, sillä merkistökoodauksesta saattaa tulla ongelmia.
Muuttujan nimessä ei saa olla tiettyjä erikoismerkkejä, kuten huutomerkkejä (!). Välilyönti ei ole sallittu, sillä se erottaa komentojen osat toisistaan. Välilyönti kannattaa korvata camelCase-tyylillä, jolloin nimi muistuttaneeKamelia
. Huom! Muuttujien nimien ensimmäinen kirjain kirjoitetaan aina pienellä:
int camelCaseMuuttuja = 7;
Numeroita voidaan käyttää muuttujan nimessä, kunhan nimi ei ala numerolla. Nimi ei myöskään voi koostua pelkistä numeroista.
int 7muuttuja = 4; // Ei sallittu! int muuttuja7 = 4; // Sallittu, mutta ei kuvaava muuttujan nimi
Muuttujan nimi ei myöskään saa olla jo entuudestaan käytössä. Tälläisiä nimiä ovat mm. aikaisemmin määritellyt muuttujat ja komennot, kuten System.out.print
ja System.out.println
.
int camelCase = 2; int camelCase = 5; // Ei sallittu -- muuttuja camelCase on jo käytössä!
Muuttuja kannattaa nimetä siten, että sen käyttötarkoitus on selvää ilman kommentteja tai miettimistä. Tällä kurssilla muuttujat pitää nimetä kuvaavasti.
Huom! Älä myöskään käytä ääkkösiä muuttujien nimissä!
Laskentaoperaatiot ovat varsin suoraviivaisia: +
, -
, *
ja /
. Laskentajärjestys on myös varsin suoraviivainen: operaatiot lasketaan vasemmalta oikealle sulut huomioon ottaen. Kuitenkin *
ja /
lasketaan ennen +
ja -
operaatioita, samoin kuin perus- tai kansakoulumatematiikassa on tullut tutuksi. Tässä vielä tarkemmin laskujärjestyksestä javassa. Linkin takana oleva materiaali ei ole kuitenkaan aloittelijan kannalta kovin oleellista.
int eka = 2; System.out.println(eka); // tulostaa 2 int toka = 4; System.out.println(toka); // tulostaa 4 int summa = eka + toka; // muuttujaan summa asetetaan muuttujien eka ja toka arvojen summa System.out.println(summa); // tulostaa 6
Laskujärjestystä voi muokata sulkujen avulla. Sulkujen sisällä olevat laskuoperaatiot suoritetaan ennen niiden ulkopuolella olevia laskuoperaatioita.
int laskuSuluilla = (1 + 1) + 3 * (2 + 5); System.out.println(laskuSuluilla); // tulostaa 23 int laskuSuluitta = 1 + 1 + 3 * 2 + 5; System.out.println(laskuSuluitta); // tulostaa 13
Yllä olevan sulkuesimerkin voi suorittaa myös askeleittain.
int laskuSuluilla = (1 + 1); System.out.println(laskuSuluilla); // tulostaa 2 laskuSuluilla = laskuSuluilla + 3 * (2 + 5); System.out.println(laskuSuluilla); // tulostaa 23 int laskuSuluitta = 1 + 1; laskuSuluitta = laskuSuluitta + 3 * 2; laskuSuluitta = laskuSuluitta + 5; System.out.println(laskuSuluitta); // tulostaa 13
Laskentaoperaatioita voidaan suorittaa lähes missä tahansa kohdassa ohjelmakoodia.
int eka = 2; int toka = 4; System.out.println(eka + toka); // tulostaa 6 System.out.println(2 + toka - eka - toka); // tulostaa 0
Täydennä tehtäväpohjassa olevaa ohjelmaa siten, että se laskee kuinka monta sekuntia on vuodessa. Voit olettaa, että vuodessa on 365 päivää (eli ei ole karkausvuosi).
Ohjelman tulostus on seuraava:
Vuodessa on X sekuntia.
X:n kohdalle tulee ohjelmasi laskema tulos. Huom! Hyödynnä tässä tehtävässä muuttujia :)
Tarkastellaan vielä lähemmin merkkijonojen yhdistämistä +
-merkinnän avulla.
Jos operaatiota +
sovelletaan kahden merkkijonon välille, syntyy uusi merkkijono, jossa kaksi merkkijonoa on yhdistetty. Huomaa nokkela välilyönnin käyttö lauseen "muuttujien" osana!
String tervehdys = "Hei "; String nimi = "Matti"; String hyvastely = ", ja näkemiin!"; String lause = tervehdys + nimi + hyvastely; System.out.println(lause);
Hei Matti, ja näkemiin!
Jos toinen operaation +
kohteista on merkkijono, muutetaan myös toinen operaation kohteista merkkijonoksi. Alla olevassa esimerkissä kokonaisluku 2
on muutettu merkkijonoksi "2", ja siihen on yhdistetty merkkijono.
System.out.println("tuossa on kokonaisluku --> " + 2); System.out.println(2 + " <-- tuossa on kokonaisluku");
tuossa on kokonaisluku --> 2 2 <-- tuossa on kokonaisluku
Edellä esitellyt laskusäännöt pätevät täälläkin:
System.out.println("Neljä: " + (2 + 2)); System.out.println("Mutta! kaksikymmentäkaksi: " + 2 + 2);
Neljä: 4 Mutta! kaksikymmentäkaksi: 22
Edellisiä tietoja yhdistelemällä pystymme tulostamaan muuttujan arvoja ja tekstiä sekaisin:
int x = 10; System.out.println("muuttujan x arvo on: " + x); int y = 5; int z = 6; System.out.println("y on " + y + " ja z on " + z);
Tulostus:
muuttujan x arvo on: 10 y on 5 ja z on 6
Tee ohjelma, jonka avulla voidaan laskea kahden kokonaisluvun summa. Ohjelman alussa määritellään kaksi muuttujaa, jotka sisältävät summattavat luvut. Voit tarvittaessa käyttää myös muita muuttujia.
Esimerkiksi jos muuttujissa on luvut 5 ja 4, ohjelman tulostus on seuraava:
5 + 4 = 9
Jos taas muuttujissa on luvut 73457 ja 12888, ohjelman tulostus on seuraava:
73457 + 12888 = 86345
Tee edellistä ohjelmaa vastaava ohjelma, joka laskee kahden kokonaislukumuuttujaan sijoitetun arvon kertolaskun.
Esimerkiksi jos muuttujissa on luvut 2 ja 8, ohjelman tulostus on seuraava:
2 * 8 = 16
Jos taas muuttujissa on luvut 277 ja 111, ohjelman tulostus on seuraava:
277 * 111 = 30747
Kuinka suuren kertolaskun ohjelmasi pystyy laskemaan?
Kokonaislukujen jako on hieman hankalampi operaatio. Liukuluku ja kokonaisluku menevät helposti sekaisin. Jos kaikki laskuoperaatiossa olevat muuttujat ovat kokonaislukuja, on tulos myös kokonaisluku.
int tulos = 3 / 2; System.out.println(tulos); // Huom! tulostaa 1 (kokonaisluku), sillä 3 ja 2 ovat myös kokonaislukuja
int eka = 3: int toka = 2; double tulos = eka / toka; System.out.println(tulos); // nytkin tulostus on 1, sillä eka ja toka ovat kokonaislukuja
Jos jakolaskun jakaja tai jaettava (tai molemmat!) ovat liukulukuja, tulee tulokseksi myös liukuluku
double kunJaettavaOnLiukuluku = 3.0 / 2; System.out.println(kunJaettavaOnLiukuluku); // tulostaa 1.5 double kunJakajaOnLiukuluku = 3 / 2.0; System.out.println(kunJakajaOnLiukuluku); // tulostaa 1.5
Kokonaisluku voidaan tarvittaessa muuttaa liukuluvuksi lisäämällä sen eteen tyyppimuunnosoperaatio (double)
:
int eka = 3; int toka = 2; double tulos1 = (double) eka / toka; System.out.println(tulos1); // tulostaa 1.5 double tulos2 = eka / (double) toka; System.out.println(tulos2); // tulostaa 1.5 double tulos3 = (double) (eka / toka); System.out.println(tulos3); // tulostaa 1
Jälkimmäisessä tulos pyöristyy väärin sillä laskuoperaatio kokonaisluvuilla suoritetaan ennen tyyppimuunnosta.
Jos jakolaskun tulos asetetaan kokonaislukutyyppiseen muuttujaan, on tulos automaattisesti kokonaisluku
int tulosKokonaislukuKoskaTyyppiKokonaisluku = 3.0 / 2; // tulos automaattisesti kokonaisluku: 1
Seuraava esimerkki tulostaa "1.5", sillä jaettavasta tehdään liukuluku kertomalla se liukuluvulla (1.0 * 3 = 3.0) ennen jakolaskua.
int jaettava = 3; int jakaja = 2; double tulos = 1.0 * jaettava / jakaja; System.out.println(tulos);
Tehtäväpohjassa on ohjelma, jossa on kolme muuttujaa. Ohjelman tulostus on tällä hetkellä seuraava.
eka: 3 toka: 5 kolmas: 5
Muokkaa ohjelmaa siten, että ohjelma tulostaa myös muuttujien keskiarvon.
eka: 3 toka: 5 kolmas: 5 keskiarvo: 4.333333333333333
Huom! Jos muuttujien arvoja muutetaan, tulee myös tulostuksen muuttua.
eka: 5 toka: 7 kolmas: 4 keskiarvo: 5.333333333333333
Mitä seuraava tulostaa?
int jaettava = 3; int jakaja = 2; double tulos = jaettava / jakaja * 1.0; System.out.println(tulos);
Tehtäväpohjassa on ohjelma, jossa on kaksi muuttujaa. Ohjelman tulostus on tällä hetkellä seuraava.
1 + 3 = 4
Muokkaa ohjelmaa siten, että ohjelma laskee myös lukujen erotuksen, tulon, ja jakolaskun.
1 + 3 = 4 1 - 3 = -2 1 * 3 = 3 1 / 3 = 0.33333
Huom! Jos muuttujien arvoja muutetaan, tulee myös tulostuksen muuttua.
5 + 3 = 8 5 - 3 = 2 5 * 3 = 15 5 / 3 = 1.66666
Huom! Tehtävässä ei ole testejä jotka kertovat onko tulostus oikein vai ei. Tarmista että ohjelmasi toimii oikein ennen tehtävän palautusta suorittamalla se useammalla muuttujien arvoilla.
Kun tietokone suorittaa ohjelmakoodia, suorittaa se sitä käsky kerrallaan, edeten aina täsmälleen siten, kuin ohjelmakoodissa sanotaan. Kun muuttujaan asetetaan arvo, tapahtuu aina sama asia, eli yhtäsuuruusmerkin oikealla puolella oleva arvo kopioidaan yhtäsuuruusmerkin vasemmalla puolella olevan muuttujan arvoksi, eli muuttujan nimeämään paikkaan.
On tärkeää, että ohjelmoija ymmärtää, että arvon asettaminen muuttujaan tekee aina saman asian.
Kolme yleistä väärinkäsitystä, jotka liittyvät muuttujan arvon asettamiseen ovat seuraavat:
eka = toka
suorituksen jälkeen ajatellaan, että muuttujan toka
arvo on siirtynyt muuttujan eka
arvoksi, jonka jälkeen muuttujalla toka
ei ole enää arvoa, tai sen arvo on esimerkiksi nolla. Tämä ei pidä paikkansa, sillä ohjelmakoodin eka = toka
suorituksessa muuttujan toka
nimeämässä paikassa oleva arvo kopioidaan muuttujan eka
nimeämään paikkaan. Muuttujan toka
arvo ei siis muutu.eka = toka
suorituksen jälkeen ajatellaan, että mikä tahansa muutos muuttujaan toka
vaikuttaa automaattisesti myös muuttujaan eka
. Tämä ei pidä paikkansa, sillä asetus -- kopiointi -- on yksittäinen tapahtuma. Se tapahtuu vain silloin, ohjelmakoodi eka = toka
suoritetaan.eka = toka
suorituksessa ajatellaan, että muuttujan toka
arvoksi kopioidaan muuttujan eka
arvo. Tämä näkyy myös tilanteina, missä ohjelmoija voi vahingossa kirjoittaa esimerkiksi 42 = arvo
-- onneksi ohjelmointiympäristöt tukevat myös tässä.Ehkäpä paras tapa tietokoneen ohjelmakoodin suorittamisen ymmärtämiseen on paperin ja kynän käyttäminen. Kun luet ohjelmakoodia, kirjoita paperille uusien muuttujien nimet, sekä kirjoita ylös rivi riviltä, miten ohjelmakoodissa olevien muuttujien arvot muuttuvat. Havainnollistetaan suoritusta seuraavalla ohjelmakoodilla:
rivi 1: int eka = (1 + 1); rivi 2: int toka = eka + 3 * (2 + 5); rivi 3: rivi 4: eka = 5; rivi 5: rivi 6: int kolmas = eka + toka; rivi 7: System.out.println(eka); rivi 8: System.out.println(toka); rivi 9: System.out.println(kolmas);
Alla on kirjoitettu ylläolevan ohjelmakoodin suoritus auki.
rivi 1: luodaan muuttuja eka rivi 1: kopioidaan muuttujan eka arvoksi laskun 1 + 1 tulos rivi 1: muuttujan eka arvo on 2 rivi 2: luodaan muuttuja toka rivi 2: lasketaan 2 + 5, 2 + 5 -> 7 rivi 2: lasketaan 3 * 7, 3 * 7 -> 21 rivi 2: lasketaan eka + 21 rivi 2: kopioidaan muuttujan eka arvo laskuun, muuttujan eka arvo on 2 rivi 2: lasketaan 2 + 21, 2 + 21 -> 23 rivi 2: kopioidaan muuttujan toka arvoksi 23 rivi 2: muuttujan toka arvo on 23 rivi 3: (tyhjä, ei tehdä mitään) rivi 4: kopioidaan muuttujan eka arvoksi 5 rivi 4: muuttujan eka arvo on 5 rivi 5: (tyhjä, ei tehdä mitään) rivi 6: luodaan muuttuja kolmas rivi 6: lasketaan eka + toka rivi 6: kopioidaan muuttujan eka arvo laskuun, muuttujan eka arvo on 5 rivi 6: lasketaan 5 + toka rivi 6: kopioidaan muuttujan toka arvo laskuun, muuttujan toka arvo on 23 rivi 6: lasketaan 5 + 23 -> 28 rivi 6: kopioidaan muuttujan kolmas arvoksi 28 rivi 6: muuttujan kolmas arvo on 28 rivo 7: tulostetaan muuttuja eka rivi 7: kopioidaan muuttujan eka arvo tulostettavaksi, muuttujan eka arvo on 5 rivi 7: tulostetaan arvo 5 rivi 8: tulostetaan muuttuja toka rivi 8: kopioidaan muuttujan toka arvo tulostettavaksi, muuttujan toka arvo on 23 rivi 8: tulostetaan arvo 23 rivi 9: tulostetaan muuttuja kolmas rivi 9: kopioidaan muuttujan kolmas arvo tulostettavaksi, muuttujan kolmas arvo on 28 rivi 9: tulostetaan arvo 28
Kirjota allaolevan ohjelmakoodin suoritus auki.
int toka = 32; int eka = toka; toka = 17;
Mikä muuttujan eka
arvo on lopuksi?
Seuraavaksi tutustumme syötteen lukemiseen käyttäjältä, johon käytämme Scanner-apuvälinettä. Apuväline tuodaan käyttöön lisäämällä komento import java.util.Scanner;
ennen pääohjelmarungon aloitusta (public class ...
).
import java.util.Scanner; // tuodaan lukemiseen käytetty apuväline Scanner käyttöömme public class Esimerkki { public static void main(String[] args) { Scanner lukija = new Scanner(System.in); // ohjelmakoodi } }
Älä hätäile vaikka pääohjelmarunko saattaa näyttää vaikeaselkoiselta! Jatkamme yhä koodausta kommentilla ohjelmakoodi merkittyyn kohtaan.
Seuraava koodi lukee käyttäjän nimen ja tulostaa tervehdyksen (käyttäjän syöttämä teksti merkitty punaisella):
System.out.print("Mikä on nimesi? "); String nimi = lukija.nextLine(); // Luetaan käyttäjältä rivi tekstiä ja asetetaan se muuttujaan nimi System.out.println("Hei " + nimi);
Mikä on nimesi? Venla
Hei Venla
Seuraavassa on yllä oleva ohjelma pääohjelmarungon kanssa. Ohjelman nimi on Tervehdys.
import java.util.Scanner; public class Tervehdys { public static void main(String[] args) { Scanner lukija = new Scanner(System.in); System.out.print("Kenelle sanotaan hei: "); String nimi = lukija.nextLine(); // Luetaan käyttäjältä rivi tekstiä ja asetetaan sen arvo muuttujaan nimi System.out.println("Hei " + nimi); } }
Kun yllä oleva ohjelma ajetaan, pääset kirjoittamaan syötteen. NetBeansin tulostusvälilehti näyttää ajetun ohjelman jälkeen seuraavalta (käyttäjä syöttää nimen "Venla").
Tee ohjelma joka lukee käyttäjältä merkkijonon ja tulostaa merkkijonon kolmesti peräkkäin.
Mikä tulostetaan? kukka kukkakukkakukka
Esimerkissä punainen väri tarkoittaa käyttäjän kirjoittamaa tekstiä. Tätä käytäntöä noudatetaan jatkossa esimerkeissä.
Scanner-apuvälineemme ei ole hyvä kokonaislukujen lukemiseen, joten käytämme toista apuvälinettä merkkijonon kokonaisluvuksi muuttamisessa. Komento Integer.parseInt
muuttaa sille annetussa tekstimuuttujassa olevan kokonaisluvun kokonaislukumuuttujaksi. Komennolle annetaan tekstimuuttuja sulkuihin, ja se palauttaa kokonaisluvun joka asetetaan kokonaislukumuuttujaan.
Käytännössä kytkemme kaksi komentoa yhteen. Ensin luemme käyttäjältä rivin, jonka annamme heti komennolle Integer.parseInt
.
System.out.print("Anna kokonaisluku: "); int kokonaisluku = Integer.parseInt(lukija.nextLine()); System.out.println("Annoit " + kokonaisluku);
Kysytään seuraavaksi käyttäjältä nimi, ja sen jälkeen ikä. Tällä kertaa esimerkissä on myös ohjelmarunko mukana.
import java.util.Scanner; public class NimiJaIkaTervehdys { public static void main(String[] args) { Scanner lukija = new Scanner(System.in); System.out.print("Nimesi: "); String nimi = lukija.nextLine(); // Luetaan käyttäjältä rivi tekstiä System.out.print("Kuinka vanha olet: "); int ika = Integer.parseInt(lukija.nextLine()); // luetaan käyttäjältä tekstimuuttuja ja muutetaan se kokonaisluvuksi System.out.println("Nimesi on siis " + nimi + " ja ikäsi " + ika + ", hauska tutustua."); } }
Tulostus esimerkiksi:
Nimesi: Nelli Kuinka vanha olet: 4 Nimesi on siis Nelli ja ikäsi 4, hauska tutustua.
Käyttäjän kanssa keskustelevan ohjelman runko:
import java.util.Scanner; public class OhjelmanNimi { public static void main(String[] args) { Scanner lukija = new Scanner(System.in); // koodi tähän } }
Merkkijonon lukeminen:
String merkkijono = lukija.nextLine();
Kokonaisluvun lukeminen:
int kokonaisluku = Integer.parseInt(lukija.nextLine());
Tee ohjelma, joka kysyy käyttäjältä kaksi kokonaislukua ja tulostaa niiden summan.
Anna ensimmäinen luku: 6 Anna toinen luku: 2 Lukujen summa: 8
Esimerkissä punainen väri tarkoittaa käyttäjän kirjoittamaa tekstiä. Tätä käytäntöä noudatetaan jatkossa esimerkeissä.
Tee ohjelma, joka kysyy käyttäjältä kaksi kokonaislukua ja
tulostaa niiden osamäärän. Varmista, että 3 / 2 = 1.5
. Jos desimaaliosa katoaa, lue materiaalin kohdasta Liukuluvut eli desimaaliluvut missä vika on.
Anna ensimmäinen luku: 3 Anna toinen luku: 2 Jakolasku: 3 / 2 = 1.5
Ympyrän kehän pituus lasketaan kaavalla 2 * pii * säde
.
Tee ohjelma, joka kysyy käyttäjältä ympyrän säteen ja laskee sen perusteella ympyrän kehän pituuden.
Javasta löytyy valmis piin arvo, saat sen kirjoittamalla Math.PI
laskutoimitukseen.
Anna ympyrän säde: 20 Ympyrän kehä: 125.66370614359172
Tee ohjelma, joka kysyy kahden käyttäjän nimet ja iät. Tämän jälkeen ohjelma tulostaa henkilöiden ikien summan.
Kerro nimi: Charles Babbage Kerro ikä: 224 Kerro nimi: Ada Lovelace Kerro ikä: 200 Charles Babbage ja Ada Lovelace ovat yhteensä 424 vuotta vanhoja.
Tähän mennessä tekemämme ohjelmat ovat edenneet suoraviivaisesti käskystä toiseen, toimien jokaisella suorituskerralla samalla tavalla. Jotta ohjelman suoritus voisi haarautua erilaisille suorituspoluille esimerkiksi käyttäjän antaman syötteen perusteella, tarvitsemme käyttöömme valintakäskyn.
int luku = 11; if (luku > 10) { System.out.println("Luku oli suurempi kuin 10"); }
Ehto (luku > 10)
on joko totta tai epätotta riippuen muuttujan luku
arvosta. Yllä oleva valintakäsky luetaan "jos muuttujan luku arvo on suurempi kuin 10".
Ehdon jälkeen avaava aaltosulku {
aloittaa lohkon (block), jonka sisältö suoritetaan jos ehto on tosi. Lohko loppuu sulkevaan aaltosulkuun }
. Lohko voi olla kuinka pitkä tahansa.
Huomaa, että if
-lauseen perään ei tule puolipistettä, sillä lause ei lopu ehto-osan jälkeen.
Lohkojen sisällä oleva koodi sisennetään. Esimerkiksi if-komennon jälkeisen lohkon, eli {-merkkiä seuraavien rivien komentoja ei kirjoiteta samalle tasolle (eli yhtä "vasemmalle") kuin komentoa if, vaan ne sisennetään -- neljä välilyöntiä -- oikealle. Neljä merkkiä saa myös tabulaattorimerkillä (q:n vasemmalla puolella oleva näppäin). Kun lohko sulkeutuu, eli tulee }-merkki, sisennys loppuu. }-merkki on samalla tasolla kuin if.
Väärin | Oikein |
---|---|
if (luku > 10) { luku = 9; } |
if (luku > 10) { luku = 9; } |
Tee ohjelma, joka kysyy käyttäjältä kokonaisluvun ja tulostaa merkkijonon "Ylinopeussakko!" jos luku on suurempi kuin 120.
Kerro nopeus: 15
Kerro nopeus: 135 Ylinopeussakko!
Onhan koodisi varmasti sisennetty oikein?
Kertaa materiaalista kohta Koodin sisennys. Kokeile mitä tapahtuu NetBeansissa kun painat yhtä aikaa shift, alt ja f! Sama toiminnallisuus eli automaattinen sisennys saadaan aikaan valitsemalla yläpalkista Source ja sen alta Format.
Vertailuoperaattoreita ovat seuraavat:
>
suurempi kuin>=
suurempi tai yhtäsuuri kuin<
pienempi kuin<=
pienempi tai yhtäsuuri kuin==
yhtäsuuri kuin!=
erisuuri kuinint luku = 55; if (luku != 0) { System.out.println("Luku oli erisuuri kuin 0"); } if (luku >= 1000) { System.out.println("Luku oli vähintään 1000"); }
Tee ohjelma, joka kysyy käyttäjältä kokonaisluvun ja tulostaa merkkijonon "Orwell" jos luku on täsmälleen 1984.
Anna luku: 1983
Anna luku: 1984 Orwell
Jos valinnan ehto on epätotta, voidaan suorittaa vaihtoehtoinen lohko koodia, tämä käy komennon else
avulla. Huomaa lähdekoodin sisennystyyli myös tässä.
int luku = 4; if (luku > 5) { System.out.println("Lukusi on suurempi kuin viisi!"); } else { System.out.println("Lukusi on viisi tai alle!"); }
Lukusi on viisi tai alle!
Huom! Komento else tulee samalle riville loppuvan aaltosulun kanssa. Jos et tee näin, tyylitarkastaja valittaa "Line xx: '}' should be on the same line."
Tee ohjelma, joka kysyy käyttäjältä kokonaisluvun ja kertoo, onko se positiivinen (eli suurempi kuin nolla) vai ei.
Anna luku: 5 Luku on positiivinen.
Anna luku: -2 Luku ei ole positiivinen.
Tee ohjelma, joka kysyy käyttäjän ikää ja kertoo, onko tämä täysi-ikäinen (eli 18-vuotias tai vanhempi).
Kuinka vanha olet? 12 Et ole vielä täysi-ikäinen!
Kuinka vanha olet? 32 Olet jo täysi-ikäinen!
Jos valittavissa olevia vaihtoehtoja on enemmän kuin kaksi kannattaa käyttää else if
-komentoa, joka on kuten else
, mutta lisäehdolla. else if
tulee if
-ehdon jälkeen. else if
ehtoja voi olla useita.
int luku = 3; if (luku == 1) { System.out.println("Luku on yksi"); } else if (luku == 2) { System.out.println("Lukuna on kaksi"); } else if (luku == 3) { System.out.println("Kolme lienee lukuna!"); } else { System.out.println("Jotain muuta!"); }
Kolme lienee lukuna!
Luetaan ylläoleva esimerkki: 'Jos luku on yksi, tulosta "Luku on yksi", muuten jos luku on kaksi, tulosta "Lukuna on kaksi", muuten jos lukuna on kolme, tulosta "Kolme lienee lukuna!". Muulloin, tulosta "Jotain muuta!"'.
Tee ohjelma, joka kysyy käyttäjältä kaksi kokonaislukua ja tulostaa niistä suuremman. Jos luvut ovat yhtä suuret, ohjelma huomaa myös tämän.
Esimerkkitulostuksia:
Anna ensimmäinen luku: 5 Anna toinen luku: 3 Suurempi luku: 5
Anna ensimmäinen luku: 5 Anna toinen luku: 8 Suurempi luku: 8
Anna ensimmäinen luku: 5 Anna toinen luku: 5 Luvut ovat yhtä suuret!
Vertailut suoritetaan järjestyksessä ylhäältä alaspäin. Kun suorituksessa päästään lohkoon, jonka ehto on totta, suoritetaan lohko ja lopetetaan vertailu.
int luku = 5; if (luku == 0) { System.out.println("Luku on nolla."); } else if (luku > 0) { System.out.println("Luku on suurempi kuin nolla."); } else if (luku > 2) { System.out.println("Luku on suurempi kuin kaksi."); } else { System.out.println("Luku on pienempi kuin nolla."); }
Luku on suurempi kuin nolla.
Yllä oleva esimerkki tulostaa merkkijonon "Luku on suurempi kuin nolla." vaikka myös ehto luku > 2
on totta. Vertailu siis lopetetaan ensimmäiseen valintakäskyyn, jonka ehto on totta.
Tee ohjelma, joka ilmoittaa kurssiarvosanan seuraavan taulukon mukaisesti.
pistemäärä | arvosana |
---|---|
< 0 | mahdotonta! |
0–74 | hylätty |
75-89 | hyväksytty |
90–100 | 5 |
> 100 | uskomatonta! |
Esimerkkitulostuksia:
Anna pisteet [0-100]: 37 Arvosana: hylätty
Anna pisteet [0-100]: 76 Arvosana: hyväksytty
Anna pisteet [0-100]: 95 Arvosana: 5
Anna pisteet [0-100]: -3 Arvosana: mahdotonta!
Valinnan ehto voi olla myös monimutkaisempi, yksittäisten loogisten operaatioiden avulla koostettu ehto. Loogisia operaatioita ovat:
ehto1 && ehto2
lausekkeen arvo on tosi molemmat ehdoista ovat tosiaehto1 || ehto2
lausekkeen arvo on tosi jos jompi kumpi tai molemmat ehdoista tosiaSeuraavassa yhdistetään &&
:lla eli ja-operaatiolla kaksi yksittäistä ehtoa. Koodilla tarkistetaan, onko muuttujassa oleva luku suurempi kuin 4 ja pienempi kuin 11, eli siis välillä 5-10:
System.out.println("Onkohan luku väliltä 5-10: "); int luku = 7; if (luku > 4 && luku < 11) { System.out.println("On! :)"); } else { System.out.println("Ei ollut :(") }
Onkohan luku väliltä 5-10: On! :)
Seuraavassa annetaan ||
:n eli tai-operaation avulla kaksi vaihtoehtoa, onko luku pienempi kuin 0 tai suurempi kuin 100. Ehto toteutuu jos luku täyttää jomman kumman ehdon:
System.out.println("Onkohan luku pienempi kuin 0 tai suurempi kuin 100"); int luku = 145; if (luku < 0 || luku > 100) { System.out.println("On! :)"); } else { System.out.println("Ei ollut :(") }
Onkohan luku pienempi kuin 0 tai suurempi kuin 100 On! :)
Tee ohjelma, joka kysyy käyttäjän iän ja tarkistaa, että se on mahdollinen (ainakin 0 ja korkeintaan 120).
Kuinka vanha olet? 10 OK
Kuinka vanha olet? 55 OK
Kuinka vanha olet? -3 Mahdotonta!
Kuinka vanha olet? 150 Mahdotonta!
Kaikki vertailut muuntuvat käytännössä totuusarvomuuttujaksi. Totuusarvomuuttujan tyyppi on boolean
ja arvo true tai false.
boolean onkoTotta = true; System.out.println("Totuusarvomuuttujan arvo on " + onkoTotta);
Totuusarvomuuttujan arvo on true
Vertailuoperaattoreita voi käyttää myös ehtojen ulkopuolella. Tällöin vertailun tuloksena saatu totuusarvo asetetaan talteen totuusarvomuuttujaan myöhempää käyttöä varten.
int eka = 1; int toka = 3; boolean onkoSuurempi = eka > toka;
Yllä olevassa esimerkissä totuusarvomuuttuja onkoSuurempi
sisältää nyt totuusarvon false.
Totuusarvomuuttujaa voidaan käyttää valintakäskyssä ehtona.
int eka = 1; int toka = 3; boolean onkoPienempi = eka < toka; if (onkoPienempi) { System.out.println("1 on pienempi kuin 3!"); }
Yllä olevassa kuvassa ohjelmakoodia on suoritettu niin pitkään, että ohjelman muuttujat on luotu ja niihin on asetettu arvot. Muuttujassa onkoPienempi
on arvona true
. Seuraavana suoritetaan vertailu if (onkoPienempi)
-- muuttujaan onkoPienempi
liittyvä arvo löytyy sen lokerosta, ja lopulta ohjelma tulostaa:
1 on pienempi kuin 3!
Jakojäännös on hieman harvemmin käytetty operaatio, joka on kuitenkin varsin näppärä kun halutaan tarkistaa esimerkiksi luvun jaollisuutta. Jakojäännösoperaation merkki on %
.
int jakojaannos = 7 % 2; System.out.println(jakojaannos); // tulostaa 1 System.out.println(5 % 3); // tulostaa 2 System.out.println(7 % 4); // tulostaa 3 System.out.println(8 % 4); // tulostaa 0 System.out.println(1 % 2); // tulostaa 1
Jos haluamme tietää onko käyttäjän syöttämä luku jaollinen neljälläsadalla, tarkastamme onko syötetyn luvun jakojäännös neljänsadan suhteen nolla.
Scanner lukija = new Scanner(System.in); int luku = Integer.parseInt(lukija.nextLine()); int jakojaannos = luku % 400; if (jakojaannos == 0) { System.out.println("Luku " + luku + " on jaollinen neljälläsadalla."); } else { System.out.println("Luku " + luku + " ei ole jaollinen neljälläsadalla."); }
Koska jakojäännös on samanlainen operaatio kuin muutkin laskut, voi sen asettaa osaksi valintakäskyä.
Scanner lukija = new Scanner(System.in); int luku = Integer.parseInt(lukija.nextLine()); if (luku % 400 == 0) { System.out.println("Luku " + luku + " on jaollinen neljälläsadalla."); } else { System.out.println("Luku " + luku + " ei ole jaollinen neljälläsadalla."); }
Tee ohjelma, joka kysyy käyttäjältä luvun ja ilmoittaa, onko se parillinen vai pariton.
Anna luku: 2 Luku 2 on parillinen.
Anna luku: 7 Luku 7 on pariton.
Vihje: Luvun jakojäännös 2:lla kertoo, onko luku parillinen vai pariton. Jakojäännos taas saadaan %
-operaattorilla, tehtäväpohjassa on lisää ohjeita miten parittomuustarkastus hoituu jakojäännöksen avulla.
Tutustutaan klassiseen ohjelmointiongelmaan:
Ohjelmoija lähtee ratkaisemaan tehtävää lukemalla ongelmakuvauksen, ja luomalla ohjelmakoodia ongelmakuvausta seuraten. Koska ohjelman suoritusehdot esitellään ongelmassa annetussa järjestyksessä, muodostuu ohjelman rakenne järjestyksen perusteella. Ohjelman rakenne muodostuu seuraavien askelten perusteella:
Jos-tyyppiset ehdot on helppo toteuttaa if - else if - else
-valintakäskyjen avulla. Alla oleva koodi on toteutettu ylläolevien askelten perusteella, mutta se ei kuitenkaan toimi oikein. Miksi ei? Kokeile itse!
Scanner lukija = new Scanner(System.in); int luku = Integer.parseInt(lukija.nextLine()); if (luku % 3 == 0) { System.out.println("Fizz"); } else if (luku % 5 == 0) { System.out.println("Buzz"); } else if (luku % 3 == 0 && luku % 5 == 0) { System.out.println("FizzBuzz"); } else { System.out.println(luku); }
Alla kerrotaan syy edellisen ohjelman toimimattomuuteen, spoilerivaroitus!
Edellisessä lähestymistavassa ongelmana on se, että valintakäskyjen läpikäynti lopetetaan ensimmäiseen ehtoon, jonka arvo on totta. Esimerkiksi luvulla 15 tulostetaan merkkijono "Fizz", sillä luku on kolmella jaollinen (15 % 3 == 0).
Yksi lähestymistapa ylläolevan ajatusketjun kehittämiseen on ensin etsiä vaativin ehto ja toteuttaa se. Tämän jälkeen toteutettaisiin muut ehdot. Yllä olevassa esimerkissä ehto "jos luku on jaollinen kolmella ja viidellä" vaatii kahden tapauksen toteutumista. Nyt ajatusketju olisi muotoa.
Nyt ongelmakin tuntuu ratkeavan.
Scanner lukija = new Scanner(System.in); int luku = Integer.parseInt(lukija.nextLine()); if (luku % 3 == 0 && luku % 5 == 0) { System.out.println("FizzBuzz"); } else if (luku % 3 == 0) { System.out.println("Fizz"); } else if (luku % 5 == 0) { System.out.println("Buzz"); } else { System.out.println(luku); }
Monimutkaisempien tarkistusten muodostamisessa voi hyödyntää sulkuja:
int luku = 99; if ((luku > 0 && luku < 10) || luku > 100) { System.out.println("luku oli joko yhden ja yhdeksän väliltä tai yli sata"); } else { System.out.println("luku oli 0 tai pienempi tai väliltä 10-99"); }
luku oli 0 tai pienempi tai väliltä 10-99
Yllä oleva esimerkki toimii käytännössä samoin kuin seuraava esimerkki.
int luku = 99; if (luku > 0 && luku < 10) { System.out.println("luku oli joko yhden ja yhdeksän väliltä tai yli sata"); } else if (luku > 100) { System.out.println("luku oli joko yhden ja yhdeksän väliltä tai yli sata"); } else { System.out.println("luku oli 0 tai pienempi tai väliltä 10-99"); }
Valintakäskyn lohkon sisällä voi olla mitä tahansa koodia, myös toinen valintakäsky.
int x = 45; int luku = 55; if (luku > 0) { System.out.println("Luku on positiivinen"); if (luku > x) { System.out.println(" ja suurempi kuin muuttujan x arvo"); System.out.println("muuttujan x arvohan on " + x); } }
Vuosi on karkausvuosi, jos se on jaollinen 4:llä. Kuitenkin jos vuosi on jaollinen 100:lla, se on karkausvuosi vain silloin, kun se on jaollinen myös 400:lla.
Tee ohjelma, joka lukee käyttäjältä vuosiluvun, ja tarkistaa, onko vuosi karkausvuosi.
Anna vuosi: 2011 Vuosi ei ole karkausvuosi.
Anna vuosi: 2012 Vuosi on karkausvuosi.
Anna vuosi: 1800 Vuosi ei ole karkausvuosi.
Anna vuosi: 2000 Vuosi on karkausvuosi.
Merkkijonoja, eli tekstejä, ei voi vertailla yhtäsuuri kuin (==) operaatiolla. Merkkijonojen vertailuun käytetään erillistä equals
-komentoa, joka liittyy aina verrattavaan merkkijonoon.
String teksti = "kurssi"; if (teksti.equals("marsipaani")) { System.out.println("Teksti-muuttujassa on teksti marsipaani."); } else { System.out.println("Teksti-muuttujassa ei ole tekstiä marsipaani."); }
Komento equals
liitetään aina siihen verrattavaan tekstimuuttujaan, "tekstimuuttuja piste equals teksti". Tekstimuuttujaa voidaan myös verrata toiseen tekstimuuttujaan.
String teksti = "kurssi"; String toinenTeksti = "pursi"; if (teksti.equals(toinenTeksti)) { System.out.println("Samat tekstit!"); } else { System.out.println("Ei samat tekstit!"); }
Merkkijonoja vertailtaessa on syytä varmistaa että verrattavalla tekstimuuttujalla on arvo. Jos muuttujalla ei ole arvoa, ohjelma tuottaa virheen NullPointerException, joka tarkoittaa ettei muuttujan arvoa ole asetettu tai se on tyhjä (null).
Seuraavassa käännetään !
:n eli negaatio-operaation avulla ehdon arvo päinvastaiseksi:
System.out.println("Eihän merkkijono ole 'maito'"); String merkkijono = "piimä"; if (!(merkkijono.equals("maito"))) { // tosi jos ehto merkkijono.equals("maito") on epätosi System.out.println("ei ollut!"); } else { System.out.println("oli"); }
ei ollut!
Negaatio-operaatio, eli !ehto
, kääntää siis totuusarvon ympäri.
int eka = 1; int toka = 3; boolean onkoSuurempi = eka > toka; if (!onkoSuurempi) { System.out.println("1 ei ole suurempi kuin 3"); }
1 ei ole suurempi kuin 3
Tee ohjelma, joka pyytää käyttäjää kirjoittamaan merkkijonon. Jos käyttäjä kirjoittaa merkkijonon "totta", tulostetaan merkkijono "Oikein meni!", muulloin tulostetaan merkkijono "Koitappa uudelleen!".
Kirjoita merkkijono: totta Oikein meni!
Kirjoita merkkijono: tottapa Koitappa uudelleen!
Tee ohjelma, joka tunnistaa seuraavat käyttäjät:
tunnus | salasana |
---|---|
aleksi | tappara |
elina | kissa |
Ohjelma näyttää käyttäjälle henkilökohtaisen viestin tai ilmoittaa, jos tunnus tai salasana on väärin.
Anna tunnus: aleksi Anna salasana: tappara Olet kirjautunut järjestelmään
Anna tunnus: elina Anna salasana: kissa Olet kirjautunut järjestelmään
Anna tunnus: aleksi Anna salasana: jokerit Virheellinen tunnus tai salasana!
HUOM: muista, että merkkijonoja ei voi vertailla ==-operaatiolla!
HUOM: Todellisuudessa kirjautumistoiminnallisuutta ei tule toteuttaa, eikä yleensä toteutetakkaan näin.
Valintakäskyjen avulla saamme ohjelman toimintaan ehdollisuutta, eli esim. jos käyttäjätunnus ja salasana ovat oikein, päästetään käyttäjä kirjautumaan ohjelmaan ja muuten ei.
Ehdollisuuden lisäksi tarvitsemme usein toistoa: käyttäjätunnusta ja salasanaa pitää pystyä kysymään uudelleen niin kauan kunnes oikea käyttäjätunnus/salasana-pari on annettu.
Yksinkertaisin toiston muoto on ikuinen toisto. Seuraava ohjelma tulostaa merkkijonoa osaan ohjelmoida! ikuisesti eli "äärettömän monta kertaa":
while (true) { System.out.println("osaan ohjelmoida!"); }
Komento while (true)
saa sen aikaan, että siihen liittyvää lohkoa, eli {}
:lla ympäröityjä komentoja -- tässä System.out.println("osaan ohjelmoida!");
-- suoritetaan äärettömän monta kertaa.
Ikuinen toisto ei yleensä ole se mitä halutaan. Saat NetBeansista käynnissä olevan ohjelman sammutettua painamalla tulostusikkunan vasemmalla puolella olevaa punaista nappia. Ohjelmakoodissa toistolauseesta poistutaan komennolla break
.
Scanner lukija = new Scanner(System.in); while (true) { System.out.println("osaan ohjelmoida!"); System.out.print("jatketaanko (ei lopettaa)? "); String komento = lukija.nextLine(); if (komento.equals("ei")) { break; } } System.out.println("kiitos ja kuulemiin.");
Kun tietokone suorittaa komennon break
, siirtyy se toistolausetta seuraavan komennon suorittamiseen.
Ylläolevassa esimerkissä toisto etenee siten että ensin tulostuu osaan ohjelmoida! ja tämän jälkeen ohjelma kysyy käyttäjältä jatketaanko vielä. Jos käyttäjä vastaa ei, suoritetaan komento break
. Tällöin suoritus siirtyy toistolausetta seuraavaan komentoon, joka tulostaa merkkijonon kiitos ja kuulemiin.
osaan ohjelmoida! jatketaanko (ei lopettaa)? joo osaan ohjelmoida! jatketaanko (ei lopettaa)? ja osaan ohjelmoida! jatketaanko (ei lopettaa)? ei kiitos ja kuulemiin.
Seuraavassa esimerkissä on toteutettu summa- ja erotustoiminnallisuudet tarjoava laskin. Laskin kysyy käyttäjältä komentoa. Komennolla lopetus suoritetaan break
ja toisto loppuu. Jos komento ei ole lopetus, kysytään kahta lukua. Jos komento oli summa lasketaan lukujen summa ja tulostetaan se. Jos komento oli erotus toimitaan vastaavasti. Muussa tapauksessa ilmoitetaan että komento on tuntematon. Lopulta palataan toistolausekkeen alkuun, ja toistolausekkeessa olevan koodin suoritus alkaa uudelleen.
System.out.println("tervetuloa käyttämään laskinta"); while (true) { System.out.print("anna komento (summa, erotus, lopetus): "); String komento = lukija.nextLine(); if (komento.equals("lopetus")) { break; } System.out.print("anna luvut "); int eka = Integer.parseInt(lukija.nextLine()); int toka = Integer.parseInt(lukija.nextLine()); if (komento.equals("summa")) { int summa = eka + toka; System.out.println("lukujen summa " + summa); } else if (komento.equals("erotus")) { int erotus = eka - toka; System.out.println("lukujen erotus " + erotus); } else { System.out.println("tuntematon komento"); } } System.out.println("kiitos ja kuulemiin.");
Screencast joka näyttää miten ohjelma syntyy:
Tässä tehtävässä luodaan ohjelma joka kyselee käyttäjältä salasanaa. Jos salasana menee oikein, nähdään salainen viesti.
Anna salasana: nauris Väärin! Anna salasana: lanttu Väärin! Anna salasana: porkkana Oikein! Salaisuus on: znvavbfgv grugl!
Toteutetaan ohjelma kolmessa askeleessa.
Testipalvelimelta tulevaan ohjelmarunkoon on määritelty muuttuja String salasana
, jolle on asetettu arvoksi porkkana
-- älä muuta tätä salasanaa. Toteuta lisätoiminnallisuus, jossa ohjelma kysyy käyttäjältä salasanaa ja vertailee sitä muuttujassa salasana
olevaan arvoon. Muista mitä erityistä merkkijonojen vertailussa on!
Anna salasana: nauris Väärin!
Anna salasana: porkkana Oikein!
Anna salasana: bataatti Väärin!
Muokkaa ohjelmaa siten, että se kysyy salasanaa kunnes käyttäjä syöttää oikean salasanan. Toteuta salasanan jatkuva kysyminen while (true) { ... }
-toistolausekkeen avulla. Toistolausekkeesta pääsee pois, jos ja vain jos käyttäjän syöttämä salasana on sama kuin muuttujassa salasana
oleva arvo.
Anna salasana: nauris Väärin! Anna salasana: lanttu Väärin! Anna salasana: porkkana Oikein!
Lisää ohjelmaan oma salainen viestisi joka näytetään kun käyttäjä kirjoittaa salasanan oikein. Se voi olla mitä tahansa!
Anna salasana: nauris Väärin! Anna salasana: lanttu Väärin! Anna salasana: porkkana Oikein! Salaisuus on: znvavbfgv grugl!
Ylläoleva salaisuus on salattu käyttäen Rot13-algoritmia.
Saat tehtäväpohjan mukana komponentin nimeltään Kuvaaja
. Kuvaaja
piirtää sille annetuista luvuista kuvaajan. Lukuja annetaan kuvaajalle näin:
Kuvaaja.lisaaNumero(13.0);
double arvo = 10; Kuvaaja.lisaaNumero(arvo);
Teemme ohjelman, joka piirtää kuvaajan sille annetuista päivittäisistä lämpötiloista.
Tee ohjelma, joka kysyy käyttäjältä liukulukuja (double
) ja lisää ne kuvaajaan. Liukulukuja tulee kysyä kunnes käyttäjä syöttää luvun, joka on pienempi kuin -1000. Tällaista lukua ei tule lisätä kuvaajaan.
Liukulukuja luetaan seuraavasti double luku = Double.parseDouble(lukija.nextLine());
HUOM: Tee kaikki muutokset tiedostoon Lampotiloja.java
. Älä muokkaa tiedostoa Kuvaaja.java
Paranna edellistä ohjelmaasi niin, että lämpötilat jotka ovat alle -30 tai yli 40 jätetään lisäämättä.
Robottimme on kehittynyt, sillä on silmät ja suunta! Huraa!
Tässä tehtävässä ohjaamme robottia, jonka tehtävänä on työntää varastossa oleva laatikko rahtialueelle. Kuvassa robotti on musta neliö jolla on silmät, laatikko harmaa, ja rahtialue turkoosi.
Uusi robottimme ei enää kuuntele käskyjä "ylös", "alas", "vasemmalle" ja "oikealle", vaan se kulkee siihen suuntaan, mihin se osoittaa. Robottia voi kääntää komennoilla Ohjain.vasen();
ja Ohjain.oikea();
, jotka kääntävät robottia vastapäivään ja myötäpäivään. Robotin liikuttaminen tapahtuu komennoilla Ohjain.liiku();
, joka siirtää robottia yhden askeleen robotin osoittamaan suuntaan, ja Ohjain.liikuMonta(int montako);
, joka liikuttaa robottia annetun määrän askelia osoitettuun suuntaan.
Robotin alkutilanteessa se suuntaa katseensa oikealle. Alla olevassa tilanteessa robottia on käännetty vasemmalle, jolloin sen katse suuntaa ylös, ja sitä on komennettu liikkumaan kolme kertaa.
Tehtävä on jaettu useampaan osaan, joissa ensimmäisessä toteutetaan manuaalinen ohjaus robotille, ja seuraavissa kehitämme automaattista ohjausta.
Tässä tehtävässä tavoitteena on rakentaa robotille manuaalinen ohjaus. Rakenna ohjelma samalla tavalla kuin edellä oleva laskin-esimerkki. Ohjelman tulee seurata seuraavia komentoja:
Ohjain.sammuta();
) ja poistuu ohjelmasta.Ohjain.vasen();
).Ohjain.oikea();
).Ohjain.liiku();
).Ohjain.liikuMonta(int montako);
).Huom! Komento Ohjain.sammuta()
sammuttaa vain robottiohjaimen, ei ohjelmaasi jonka kautta robottiohjainta käytetään. Avainsanasta break saattaa olla tässä hyötyä..
Toteuta ohjelma siten, että ohjain suorittaa käyttäjän pyytämät komennot. Alla on esimerkki annetuista komennoista sekä kuva lopputilasta.
komento (sammuta, vasen, oikea, liiku, liikuMonta): liiku komento (sammuta, vasen, oikea, liiku, liikuMonta): vasen komento (sammuta, vasen, oikea, liiku, liikuMonta): liiku komento (sammuta, vasen, oikea, liiku, liikuMonta): liiku komento (sammuta, vasen, oikea, liiku, liikuMonta): oikea komento (sammuta, vasen, oikea, liiku, liikuMonta): liikuMonta Kuinka monta askelta: 3
Huom! Voit palauttaa tehtävän jo tässä välissä vaikka kaikki tehtävän osa-alueet eivät vielä menisikään läpi!
Lisää tekstikäyttöliittymään komento "viereen", joka siirtää robotin laatikon viereen sen vasemmalle puolelle. Ratkaisua ohjelmoidessa voit olettaa, että robotti lähtee liikkeelle aina sen alkusijainnista, se katsoo aluksi aina samaan suuntaan, ja että rahtialue on aina samassa kohdassa.
Ohjaimeen on lisätty seuraavat komennot, joiden avulla saat käyttöösi robotin, laatikon ja rahtialueen sijainnin. Voit käyttää niitä robotin tarvitsemien siirtymien laskemiseen.
// kertoo robotin x- ja y-koordinaatit int robottiX = Ohjain.robottiX(); int robottiY = Ohjain.robottiY(); // kertoo laatikon x- ja y-koordinaatit int laatikkoX = Ohjain.laatikkoX(); int laatikkoY = Ohjain.laatikkoY(); // kertoo rahtialueen x- ja y-koordinaatit int tavoiteX = Ohjain.tavoiteX(); int tavoiteY = Ohjain.tavoiteY();
Yllä komentojen lisäksi käytössä on komento Ohjain.asetaLaatikkoSatunnaisesti();
, joka asettaa laatikon satunnaisesti pelialueelle, kuitenkin siten, että se on aina robotin oikealle yläpuolella, ja rahtialueen vasemmalla yläpuolella. Kutsu sitä ennen käynnistystä seuraavasti:
public class Paaohjelma { public static void main(String[] args) { Scanner lukija = new Scanner(System.in); Ohjain.asetaLaatikkoSatunnaisesti(); Ohjain.kaynnista(); // toteuta ohjelma tänne // oma toteutuksesi, joka saattaa alkaa muodossa while (true) { // ...
komento (sammuta, vasen, oikea, liiku, liikuMonta, viereen): viereen
Vinkki! Kannattanee hahmotella paperilla miten robotin siirtyminen ja liike riippuu laatikon sijainnista.
Lisää vielä käyttöliittymään komento "ratkaise", joka käskee robottia työntämään laatikon rahtialueelle. Kuten edellisessäkin osassa, voit olettaa että laatikko on aina robotin oikealla yläpuolella ja rahtialueen vasemmalla yläpuolella, robotti aloittaa liikkumisen aina samasta ruudusta, katsoo aluksi samaan suuntaan, ja että rahtialue on aina samassa ruudussa. Komennon "ratkaise" tulee toimia myös silloin, kun se annetaan komennon "viereen" jälkeen.
komento (sammuta, vasen, oikea, liiku, liikuMonta, viereen, ratkaise): ratkaise
Komennon "ratkaise" tulee toimia vaikka robotti ei olisi laatikon vieressä.