190 likes | 280 Views
12. Näppäimistöltä lukeminen. Sisällys. Arvojen lukeminen näppäimistöltä yleisesti. Arvojen lukeminen näppäimistöltä Java-kielessä. In -luokka. Luetun arvon tarkistaminen. Tietovirrat ja ohjausmerkit. Scanner -luokka. Yleistä.
E N D
Sisällys • Arvojen lukeminen näppäimistöltä yleisesti. • Arvojen lukeminen näppäimistöltä Java-kielessä. • In-luokka. • Luetun arvon tarkistaminen. • Tietovirrat ja ohjausmerkit. • Scanner-luokka.
Yleistä • Näppäimistöltä annettujen arvojen (syötteiden) lukeminen on periaatteessa helppoa: • Lukuoperaation kohdatessaan ohjelman jää odottamaan käyttäjän syötettä. • Näppäimistöltä annettu syöte lähetetään ohjelmalle Enter-näppäintä painamalla. • Ohjelman suoritus jatkuu syötteen lähetyksen jälkeen. • Ongelma: lukuoperaatio odottaa saavansa tietyn tyyppisen arvon, mutta ohjelman käyttäjä voi antaa syötteeksi jotain muuta tyyppiä olevan arvon.
Yleistä • Esim. Ollaan lukemassa kokonaislukua ja käyttäjä syöttää syystä tai toisesta ohjelmalle liukuluvun. • Jos lukuoperaatio ei pysty muuttamaan syötettä halutun tyyppiseksi, tapahtuu usein ajonaikainen virhe (runtime error). • Ajonaikainen virhe pysäyttää ohjelman suorituksen, ellei siihen ole varauduttu lukuoperaation yhteydessä.
Javassa • Lisävaikeuksia aiheuttaa itse Java-kieli, jossa tietojen lukeminen näppäimistöltä on vaikeaa. • Uusimmissa Java-versioissa (≥ 1.5.0) lukeminen on helpompaa, mutta Scanner-luokan operaatiot ovat virheenkäsittelyn osalta valitettavan yksinkertaisia. • Koska ajonaikaisista virheistä selviäminen vaatii edistyneempiä Java-taitoja, Laki-kurssilla lukemiseen käytetään pääasiassa omatekoista In-luokkaa, jonka operaatioihin virheidenkäsittely on koodattu valmiiksi.
In-luokka • Luokka sisältää operaatiot: • readInt() int-tyyppisen kokonaisluvun lukemiseen • readDouble() double-tyyppisen liukuluvun lukemiseen • readString() merkkijonon (String) lukemiseen ja • readChar() merkin (char) lukemiseen. • Nämä operaatiot eivät luovuta helpolla: lukemista jatketaan kunnes on saatu kelvollinen syöte. • Luokka löytyy kurssin kotisivuilta Harjoitustyö-kohdasta.
In-luokka • Operaatioita kutsutaan pistenotaatiolla, joka on tuttu jo tulostamisen yhteydessä: In.operaatio • Esim. double d = In.readDouble(); if (In.readChar() == 'k') { ... } • Lukuoperaation palauttama arvo sijoitetaan usein muuttujaan, jonka on oltava luonnollisesti sopivaa tyyppiä. • Paluuarvoa voidaan myös käyttää myös suoraan lauseen osana.
… int n = In.readInt(); System.out.println(n); … 10 10 In-luokka • Näppäimistöltä annettu syöte saadaan ohjelmaan lukuoperaation paluuarvona. • Ohjelmassa tulostusoperaation parametriksi annettu arvo tulostetaan näytölle.
In-luokka • In-luokka on käännettävä yhdessä oman ohjelman (luokan) kanssa. Tämä on tehtävissä eri tavoin. • Luokan voi kopioida samaan hakemistoon kuin oman ohjelman, jolloin ohjelmaa käännettäessä myös In-luokka kääntyy. Esimerkki: javac Tehtavat.java • Nyt ohjelma on ajettavissa tutulla komennolla: java Tehtavat
In-luokka • In-luokan voi sisällyttää käännökseen myös jostakin muusta hakemistosta joko polkumäärittelyllä tai javac-ohjelman sourcepath-parametrillä. • Esim. Oletetaan, että In-luokan lähdekoodi löytyy Windows-käyttöjärjestelmässä työhakemiston ylihakemistosta. Tällöin Tehtavat-ohjelma voidaan kääntää vaihtoehtoisesti komennoilla: javac Tehtavat.java ..\In.java (UNIX: javac Tehtavat.java ../In.java) tai javac -sourcepath .. Tehtavat.java
In-luokka • Muussa kuin nykyisessä hakemistossa sijaitseva In-luokan tavukoodi sisällytetään ohjelman suoritukseen classpath-parametrillä. • Esim. Oletetaan, että In-luokan tavukoodi löytyy Windowsissa työhakemiston ylihakemistosta. Tällöin ohjelma suoritetaan komennolla: java -classpath .;.. Tehtavat (Linux: java -classpath .:.. Tehtavat)
Syötteen tarkistaminen • Vaikka syöte olisi oikeaa tyyppiä, se ei ole välttämättä oikeellinen: Usein on tarpeen lukea arvo tietyltä arvoalueella. • Esim. Jos käsitellään henkilön pituutta ja painoa, syötearvojen tulisi olla positiivisia. • Usein ohjelma yrittää “pakottaa” käyttäjänsä antamaan oikeellisen arvon silmukan avulla. • do-while-rakenne on tässä tehtävässä erityisen hyödyllinen.
Syötteen tarkistaminen • Idea pseudokoodina: do { Lue syöte; Jos syöte virheellinen, niin ilmoita käyttäjälle. } while (syöte virheellinen); • Syötteen oikeellisuus voidaan ilmaista joko loogisella lausekkeella tai lippumuuttujalla, joka on usein boolean-tyyppinen. • Lippumuuttujan käsite on venyvä. Lippuarvo määritellään usein ohjelmalle tuntemattomaksi arvoksi, jolla lopetetaan silmukan suoritus.
Tietovirrat • Usein ajatellaan abstraktisti, että ohjelma kommunikoi ympäristönsä kanssa tietovirtojen (data stream) avulla. • Tyypillisesti käytettävissä ovat standarditulos-, standardisyöte- ja -standardivirhevirrat. • Tulos- ja virhevirrat liittyvät oletusarvoisesti näyttöön ja syötevirta näppäimistöön. • Javassa standardivirtojen tunnukset ovat System.out, System.in ja System.err.
… int n = In.readInt(); System.out.println(n); … System.in System.out In Tietovirrat • System.out-virta tuttu tulostamisoperaatioiden yhteydestä. • In-luokan operaatiot liittyvät System.in-virtaan.
Ohjausmerkit • Komentoikkunassa standardisyöte- ja standarditulostevirrat voidaan liittää väliaikaisesti tiedostoihin ohjausmerkeillä. • Uudelleenohjaus toimii Windows- ja UNIX-komentoikkunoissa. • Pienempi kuin -merkillä (<) ohjelma lukee syötteet tiedostosta näppäimistön asemasta. • Esim. java OmaOhjelma < syote.txt • Syötetiedostossa kukin syöte on omalla rivillään.
Ohjausmerkit • Suurempi kuin -merkillä (>) ohjelma tulostaa tiedostoon näytön asemasta. • Esim. java OmaOhjelma > tulos.txt • Kannattaa tarkastaa, että tiedostossa ei ole mitään tärkeää, koska tiedoston vanha sisältö menetetään! • Ohjausmerkkejä voidaan myös käyttää yhdessä, jolloin syötteet tulevat tiedostosta ja tulosteet menevät tiedostoon. • Esim. java OmaOhjelma < syote.txt > tulos.txt
Scanner-luokka • Sisältää yksinkertaisia metodeja (esim. nextInt(), nextDouble(), nextLine(), nextBoolean()) näppäimistöltä tai tiedostosta lukemiseen. • char-tyypille ei ole omaa lukumetodia: Scanner sc = new Scanner(System.in); char merkki = sc.nextLine().charAt(0); • Löytyy Javan uusimmissa versioissa (≥ 1.5.0) java.util-pakkauksesta: import java.util.*; • Virheenkäsittely hoidettava try-catch-lauseilla.
Scanner-luokka import java.util.*; // Otetaan Scanner-luokka käyttöön import-lauseella. public class ScannerDemo { public static void main(String[] args) { Scanner sc = new Scanner(System.in); // Liitetään oletussyötevirtaan. try { // Yritetään lukea kokonaisluku. System.out.print("Anna luku: "); int luku = sc.nextInt(); } catch (Exception e) { // Jos tapahtui virhe, niin se "siepataan" tänne. System.out.println("Tapahtui virhe: " + e); } // Suljetaan. sc.close(); } }