Yksinkertaisiksi lauseiksi kutsutaan sellaisia ohjelmointikielen lauseita, jotka tekevät "yhden asian yhden kerran". Esimerkiksi muuttujan määrittely, arvon sijoittaminen muuttujaan ja tulostus ovat tällaisia yksinkertaisia lauseita.
int x; x = 10; System.out.println(x);
Lauseet suoritetaan järjestyksessä yksi kerrallaan. Tätä kutsutaan peräkkäisrakenteeksi ja sen voidaan ajatella olevan ensimmäinen ohjausrakenne.
Yksinkertaisilla lauseilla on mahdollista tehdä toimivia ohjelmia. Ohjelmat jäävät kuitenkin välttämättä varsin yksinkertaisiksi, koska melkein kaikissa algoritmeissa tarvitaan ehdollisuutta ja toistoa.
Esimerkiksi kymmenen arvon järjestämisessä tarvitaan (käytettäessä kuplalajittelua) 9 + 8 + ... + 1 vertailua, jotka pitäisi peräkkäisrakenteena toteutettuna todella kirjoittaa näkyville. Kymmenelle arvolle tehty ohjelma ei myöskään toimisi esimerkiksi 11 arvolle. Toistorakenteen avulla lajittelu voidaan toteuttaa kahdella sisäkkäisellä toistolla ja se toimii kaikille arvojen lukumäärille.
Java-kielessä ehdollisuus toteutetaan if-lauseella eli
ehtolauseella. Toisto toteutetaan while-lauseella
tai for-lauseella eli toistolauseilla.
Ehdollisuus voidaan usein kuvata sanoilla:
jos ehto pitää paikkansa, niin tehdään toiminto
Toisto voidaan kuvata sanoilla:
niin kauan kuin ehto pitää paikkansa, tehdään toiminto uudestaan
Kummassakin edellisessä esiintyy ehto, joka lopulta ratkaisee toiminnon suorittamisen.
Ohjelmoinnissa ehto on lauseke, jonka arvona on totuusarvo (tosi tai
epätosi). Javassa tosuuarvo esitetään boolean-tietotyypin
avullaja on joko true tai false.
Tavallisimpia totuusarvoisia lausekkeita ovat vertailulausekkeet. Niissä verrataan kahta arvoa toisiinsa vertailuoperaattorin avulla. Vertailuoperaattoreita ovat
| Lauseke | Merkitys |
|---|---|
a == b |
a on yhtäsuuri kuin b |
a != b | a on erisuuri kuin b |
a < b | a on pienempi kuin b |
a > b | a on suurempi kuin b |
a <= b |
a on pienempi tai yhtäsuuri kuin b |
a >= b |
a on suurempi tai yhtäsuuri kuin b |
Yhtäsuuruusvertailun == sekoittaa helposti sijoitukseen
=. Ne ovat aivan eri asia!
Vertailuoperaattoreita voi käyttää mihin tahansa perustietotyyppeihin. Merkkijonojen vertailussa pitää käyttää erilaista tapaa
a.equals(b) |
a on sama merkkijono kuin b |
!a.equals(b) |
a on eri merkkijono kuin b |
a.compareTo(b) < 0 |
a on aakkosjärjestyksessä edellä merkkijonoa b |
a.compareTo(b) > 0 |
a on aakkosjärjestyksessä jäljessä merkkijonoa b |
Vertailulausekkeita (ja muita totuusarvoisia lausekkeita) voi edelleen käyttää loogisten operaattorien kanssa.
Operaattori ! (looginen ei)
vaihtaa lausekkeen totuusarvon. Esimerkiksi a <= b voidaan kirjoittaa
myös !(a > b). Katso myös merkkijonojen erisuuruuden tutkiminen
yllä.
Operaattori && (looginen ja) yhdistää kaksi totuusarvoa
siten, että koko lauseke on tosi vain jos kumpikin yhdistetty lauseke on tosi.
Esimerkiksi matemaattinen ilmaus 0 < x < 10 kirjoitetaan
Java-kielellä 0 < x && x < 10 (edellyttäen, että
muuttuja x on määritelty kokonaisluvuksi).
Operaattori || (looginen tai) yhdistää kaksi tosuuarvoa siten,
että koko lauseke on tosi jos jompikumpi yhdistetyistä on tosi tai kumpikin
yhdistetyistä on tosi.
Esimerkiksi, jos halutaan osoittaa, että muuttujan x arvo ei
ole välillä 0 - 10, kirjoitetaan x < 0 || x > 10.
Ehtolause on muotoa
if (ehto) {
lauseet
}
ja merkitys on "jos ehto on tosi, niin lauseet suoritetaan".
Sulut {} voi jättää pois, jos lauseita on vain yksi.
Esimerkkiohjelma laskee annetut kaksi lukua yhteen, jos ne todella on annettu.
1:class Summa2 2:{ 3: public static void main(String[] args) 4: { 5: if (args.length == 2) { 6: int a = Integer.parseInt(args[0]); 7: int b = Integer.parseInt(args[1]); 8: int summa = a + b; 9: System.out.println(" " + a + " + " + b + " = " + summa); 10: } 11: } 12:}
Annettujen komentoriviparametrien määrä saadaan selville
lausekkeella args.length
(lisätietoja).
Vertaa ohjelmaa aikaisemmin esitettyyn esimerkkiin, jossa lukujen puuttuminen aiheutti ruman virheilmoituksen.
C:\java> java Jarjesta3 51 23 40 23 40 51 C:\java>
else-osa
Edellinen esimerkki on hieman tylysti toteutettu,
koska se ei kerro miksi mitään ei
tapahdu ilman annettuja lukuja. Tämä voidaan korjata käyttämällä
if-lauseen laajennettua muotoa
if (ehto) {
lauseet
} else {
vaihtoehtoiset lauseet
}
jonka merkitys on "jos ehto on tosi, niin suoritetaan lauseet, muutoin suoritetaan vaihtoehtoiset lauseet".
Nyt esimerkkiin voidaan lisätä virheilmoitus:
1:class Summa2 2:{ 3: public static void main(String[] args) 4: { 5: if (args.length == 2) { 6: int a = Integer.parseInt(args[0]); 7: int b = Integer.parseInt(args[1]); 8: int summa = a + b; 9: System.out.println(" " + a + " + " + b + " = " + summa); 10: } else { 11: System.out.println(" Tarvitaan kaksi lukua!"); 12: } 13: } 14:}
else if -osatEhtolauseita voi ketjuttaa peräkkäin, jolloin lauseen muoto on
if (ehto1) {
lauseet1
} else if (ehto2) {
lauseet2
} else if (ehto3) {
lauseet3
}
...
} else {
vaihtoehtoiset lauseet
}
ja merkitys on "jos ehto1 on tosi, niin suoritetaan lauseet1, muutoin jos ehto2 on tosi, niin suoritetaan lauseet2, muutoin jos ehto3 on tosi, niin suoritetaan lauseet3, muutoin suoritetaan vaihtoehtoiset lauseet".
Tehtävä D2: Tee ohjelma, jolle annetaan kaksi, kolme tai neljä kokonaislukua. Ohjelma tulostaa lukujen summan tai virheilmoituksen, jos lukuja on jokin muu määrä.
Toistolauseita esitellään tässä kaksi kappaletta:
while-lause ja for-lause.
Kaikki alhoritmeissa esiintyvät toistot voidaan toteuttaa toisella
käyttämällä vain toista näistä lausetyypeistä. Lauseen valinnassa onkin
kysymys lähinnä sopivuudesta ja myös makuasioista.
while-lauseYksinkertaisemman toistolauseen muoto on
while (ehto) {
lauseet;
}
ja merkitys on "niin kauan kuin ehto pitää paikkansa, tehdään lauseet uudestaan. Ehto tutkitaan aina ennen lauseita eli järjestys on
Toistolauseen sisällä olevien lauseiden pitäisi jollakin tavalla muuttaa ehdossa käytettävien muutujien arvoja. Muussa tapauksessa voi syntyä päättymätön silmukka (ehto on aina tosi).
Ensimmäinen esimerkki tulostaa yksinkertaisesti parametrina annetun määrän rivejä. Koodi on tiedostossa "Rivit.java".
1:class Rivit { 2: 3: public static void main (String[] args) { 4: // luetaan rivien lukumäärä komentoriviltä 5: int lkm = Integer.parseInt(args[0]); 6: // tulostetaan rivit 7: int i = 0; 8: while (i < lkm) { 9: System.out.println("Rivi " + i); 10: i++; 11: } 12: } 13:}
Huomaa apumuuttujan i käyttö toisto toteutuksessa.
Sen arvoa muutetaan toistolauseen sisällä (i++).
Toistolauseen ehto tulee näin väkisin epätodeksi, kun haluttu määrä
kierroksia on saatu täyteen.
Esimerkki ohjelman käytöstä (käännös on tässä tehty aiemmin) on alla.
C:\java> java Rivit 5 Rivi 0 Rivi 1 Rivi 2 Rivi 3 Rivi 4 C:\java>
Toinen esimerkki on sovelma, joka piirtää toistuvan kuvion. Aluksi koodi tiedostossa "PalloSovelma.java".
1:import java.awt.*; 2:import java.applet.*; 3: 4:public class PalloSovelma extends Applet { 5: 6: public void paint(Graphics g) { 7: // piirretään kymmenen palloa kasvavalla koolla 8: int i = 0; 9: int paikka = 10; 10: int koko = 10; 11: while (i < 10) { 12: g.fillOval(paikka, paikka, koko, koko); 13: paikka += 20; 14: koko += 10; 15: i++; 16: } 17: } 18:}
Kerrataan tarvittava koodi sovelman lisäämiseksi sivulle. Sovelma on alihakemistossa "java". Katso ohjeet sovelman kääntämisestä aiemmasta materiaalista.
<applet codebase="java" code="PalloSovelma.class" width="300" height="300"> Sovelmat eivät toimi tässä selaimessa. </applet>
Aiemmin havaittujen WebCT/Applet -ongelmien vuoksi näytetään tässä vain kuva sovelmasta. Kuva on otettu IE 6.0 -selaimesta.
![]() |
Kuva sovelmasta, ei itse sovelma. |
for-lauseHuomattava osa toistolauseista on muotoa
alustus;
while (ehto) {
lauseet;
muutos;
}
jossa alustus antaa toistossa käytettäville (apu)muuttujille alkuarvot ja muutos muuttaa em. muuttujien arvoja.
Tällaiselle toistolauseelle on olemassa tiiviimpi muoto:
for (alustus; ehto; muutos) {
lauseet;
}
Esimerkiksi yllä annetussa rivejä tulostavassa sovelluksessa käytetty
while-lause voidaan kirjoittaa muotoon:
for (int i = 0; i < lkm; i++) {
System.out.println("Rivi" + i);
}
Toistolauseilla ei ole mitään merkittävää toiminnallista eroa. Monien mielestä
for-lause soveltuu parhaiten taulukoiden läpikäyntiin.
for (int i = 0; i < args.length; i++) {
// nyt parametrin saa kokonaislukuna lausekkeella
int luku = Integer.parseInt(args[i]);
}for (int rivi = 0; rivi < 8; rivi++) {
for (int sarake = 0; sarake < 8; sarake++) {
// piirrä yksi ruutu tässä
// kuinka selvität mustat ja valkoiset?
}
}Toistolauseen käyttö on välttämätöntä useimmissa taulukoita käyttävissä sovelluksissa. Tässä esitettävissä esimerkeissä käsitellään kokonaislukuja sisältäviä taulukoita, joihin sisältö saadaan komentoriviltä. Aluksi yksinkertainen ohjelma, joka kopioi komentorivin kokonaislukutaulukkoon ja tulostaa sen näkyville. Tiedostossa "Luvut.java":
1:class Luvut { 2: 3: public static void main (String[] args) { 4: // luodaan ensin sopivan kokoinen taulukko 5: // args.length on komentorivin parametrien lukumäärä 6: int[] luvut = new int[args.length]; 7: // kopioidaan taulukosta toiseen ja muutetaan kokonaisluvuiksi 8: for (int i = 0; i < args.length; i++) { 9: // kopioidaan kohdasta i kohtaan i 10: luvut[i] = Integer.parseInt(args[i]); 11: } 12: // tulostetaan jokainen luku omalle rivilleen indeksin kanssa 13: for (int i = 0; i < luvut.length; i++) { 14: System.out.println(i + ": " + luvut[i]); 15: } 16: } 17:}
Esimerkki ohjelman käytöstä:
C:\java> java Luvut 45 12 32 7 123 0: 45 1: 12 2: 32 3: 7 4: 123 C:\java>
Etsintä taulukosta voidaan toteuttaa samankaltaiselle algoritmilla. Seuraava esimerkki tulostaa komentoriviparametreista pienimmän. Tiedostossa "Pienin.java":
1:class Pienin { 2: 3: public static void main (String[] args) { 4: int[] luvut = new int[args.length]; 5: for (int i = 0; i < args.length; i++) { 6: luvut[i] = Integer.parseInt(args[i]); 7: } 8: // etsitään pienin 9: // oletetaan, että se on ensimmäinen 10: int pienin = luvut[0]; 11: // tutkitaan lopputaulukko toisesta alkiosta eteenpäin 12: for (int i = 1; i < luvut.length; i++) { 13: // jos löydetty pienempi kuin aiemmat 14: if (luvut[i] < pienin) { 15: pienin = luvut[i]; 16: } 17: } 18: // tulostetaan pienin 19: System.out.println("Pienin on " + pienin); 20: } 21:}
Esimerkki ohjelman käytöstä seuraa:
C:\java> java Pienin 56 12 34 9 12 78 Pienin on 9 C:\java>
Lopuksi vielä lukujen järjestäminen valintalajittelua käyttämällä. Siinä etsitään aina lopputaulukosta pienin ja laitetaan se oikealle paikalleen. Tiedostossa "Jarjesta.java":
1:class Jarjesta { 2: 3: public static void main (String[] args) { 4: int[] luvut = new int[args.length]; 5: for (int i = 0; i < args.length; i++) { 6: luvut[i] = Integer.parseInt(args[i]); 7: } 8: 9: // järjestetään luvut 10: // jokaisella kierroksella laitetaan yksi alkio paikalle p 11: for (int p = 0; p < luvut.length-1; p++) { 12: // oletetaan, että pienin on paikassa p 13: int pienin = p; 14: // tutkitaan loput taulukon alkiot 15: for (int i = p+1; i < luvut.length; i++) { 16: // jos pienempi löytyy, laitetaan paikka talteen 17: if (luvut[i] < luvut[pienin]) { 18: pienin = i; 19: } 20: } 21: // vaihdetaan pienin alkuun ellei jo ole 22: if (pienin != p) { 23: // vaihto apumuuttujan avulla 24: int apu = luvut[p]; 25: luvut[p] = luvut[pienin]; 26: luvut[pienin] = apu; 27: } 28: } 29: 30: // tulostetaan järjestettynä 31: for (int i = 0; i < luvut.length; i++) { 32: System.out.println(i + ": " + luvut[i]); 33: } 34: } 35:}
Esimerkki ohjelman käytöstä:
C:\java> java Jarjesta 23 1 67 34 2 89 24 3 2 50 0: 1 1: 2 2: 2 3: 3 4: 23 5: 24 6: 34 7: 50 8: 67 9: 89 C:\java>
Edellinen lajittelualgoritmi on kuvattu korttiprosessorilla.
Tehtävä D5: Tee sovellus "Tilastot", joka laskee komentoriviltä saamistaan luvuista keskiarvon (summa/lkm), suurimman luvun, pienimmän luvun ja mediaanin (järjestyksessä keskimmäinen tai kahden keskimmäisen keskiarvo). Sovellus tulostaa tiedot siistissä muodossa.