Haluaisin laittaa ohjelmaan lopetuskomennon(String) ja esim. rahan(int) ja molemmilla on syötteestä asetetettavat arvot, mutta en halua, että ohjelma kysyy aina kahta syötettä, vaan että esim. 'q' lopettaa ja rahan voi asettaa 0-99999999... ja kumminkin pyytää vain yhden syötteen
voitte myös näyttää, miten muunnetaan int --> char yms.
Käytä funktiota Integer.parseInt(str).
voitko antaa esimerkin?
Kannattaa opetella lukemaan niitä javadoceja. Siinä lukee aivan selvästi, että se ottaa sisään merkkijonon (10-kantajärjestelmässä), jossa on numeroita ja mahdollisesti miinusmerkki edessä ja sen paluuarvo on int-tyyppiä. Lisäksi jos annettu merkkijono ei satu olemaan kelvollinen luku (esim. sisältää kirjaimia), niin metodi heittää NumberFormatExceptionin.
mutta haluaisin että sen voi lukea myös string muodossa
Täh? Sehän on String ennen muunnosta... Ja se sama merkkijono säilyy siinä sen muunnoksen jälkeenkin.
Käsittelet virheen normaalilla exeption menetelmällä, koska annettu syöte ei ole normaali tuolle muuttujalle. Muuta järjellistä ratkaisua ei ole mielekästä lähteä rakentamaan. Tai rakenna try - catch rakenne, jossa yrität lukua, mutta jos ei onnistu yritetään merkkijonoa. Tuosta tulee helpolla vaan aika sekava.
class Tommittaja_Integer_parseInt { public static void main(String [] args) { String s = "123"; Integer i; try { i = Integer.parseInt(s); System.out.println("Luku oli " + i); } catch (NumberFormatException e) { System.out.println("Eipä ollut luku: " + e.getMessage()); } } }
aa.. joo katoin vaan että
Sami kirjoitti:
(esim. sisältää kirjaimia), niin metodi heittää NumberFormatExceptionin.
Ja kukaan ei tietysti estä tarkistamasta joitain tiettyjä merkkijonoja ensin, esim.
if (str.equals("Moro!") { System.out.println("Älä nyt mitään moroja anna, vaan lukuja!"); } else { int luku = Integer.parseInt(str); // ... }
Voit tietysti myös käyttää Scanner-luokkaa:
import java.util.Scanner; class Tommittaja_Scanner { public static void main(String [] args) { Scanner input = new Scanner(System.in); while (input.hasNext()) { if (input.hasNextInt()) { Integer i = input.nextInt(); System.out.println("Tuli luku: " + i); } else { String s = input.next(); if (s.equals("quit")) { System.out.println("Tuli " + s + ", lopetetaan."); break; } System.out.println("Tuli muu sana: " + s); } } } }
toimiiko tuo parseint siis näin:
String sana = Lue.rivi(); // käytän tätä Lue.rivi:ä koska se on yksinkertaisempi if (sana.equals("Q")) { System.out.println("Jotakin random txt"); } else { int b = Integer.parseInt(sana) } if (b == 0) { System.out.println("jotain random num"); } // ja niinpoispäin...
Määrittelet muuttujan b tuolla else-lohkon sisällä, josta se ei näy tuolle ifille kyseisen lohkon ulkopuolella.
Lisäksi parseInt heittää poikkeuksen, jos tuossa muunnettavassa merkkijonossa ei sattunukaan olemaan mitään luvuksi tulkittavaa. Se varmaan kannattaa ottaa kiinni.
miten tuo sitten tehdään? voitko kirjoittaa vastaavan esimerkin?
String sana = Lue.rivi(); int b; if (sana.equals("Q")) { System.out.println("Jotakin random txt"); } else { try { b = Integer.parseInt(sana); } catch(NumberFormatException ex) { System.out.println("No ei se ollu numerokaan"); } } if (b == 0) { System.out.println("jotain random num"); }
Blazen antamassa esimerkissähän tuo muuttuja b tulisi myös alustaa jossain vaiheessa, koska esim. jos muuttuja sana sisältää merkkijonon "a", niin myöhemmin aiheutuu vertailu tuon alustamattoman b:n ja 0:n kesken.
Päärynämies kirjoitti:
Blazen antamassa esimerkissähän tuo muuttuja b tulisi myös alustaa jossain vaiheessa, koska esim. jos muuttuja sana sisältää merkkijonon "a", niin myöhemmin aiheutuu vertailu tuon alustamattoman b:n ja 0:n kesken.
No käytännössähän se b on nolla (tämä on siis Java ja int primitiivityyppi, ei esim. C), mutta toki on huono ohjelmointitapa olla alustamatta se.
Grez kirjoitti:
No käytännössähän se b on nolla
Siksi tuo koodi toimiikin väärin ja voi tulostaa peräkkäin "Jotakin random txt" ja "jotain random num", vaikka pitäisi tulostaa vain jompikumpi. Lopun if-lause pitäisi siis esimerkiksi siirtää try-blokkiin, jottei sitä suoriteta, jos kyseessä ei ollut luku.
Itse kokeilin tehdä luokan, joka käyttää tuota koodia. Tällainen syntyi:
class Alustus { public static void main(String args[]){ String sana = "a"; int b; if (sana.equals("Q")) { System.out.println("Jotakin random txt"); } else { try { b = Integer.parseInt(sana); } catch(NumberFormatException ex) { System.out.println("No ei se ollu numerokaan"); } } if (b == 0) { System.out.println("jotain random num"); } } }
Koodi on oleellisesti sama. Tuo ei mene kääntäjästä läpi vaan kääntäjä herjaa, että "The local variable b may not have been initialized". Koitin jonkilaista Javan spesifikaatiota myös katsella ja siellä luki, mikäli oikein ymmärsin, että lokaaleille muuttujille tulee antaa jokin arvo ennen niiden käyttämistä. Asia on eri sitten luokan jäsenmuuttujien kohdalla, jotka int -tyypin kohdalla alustetaan nollaan.
Tässä vielä linkkiä käyttämääni lähteeseen (The Java Language Spesification, Third Edition): http://java.sun.com/docs/books/jls/download/
eli toimisi, jos teen tuon samanlailla kuin Blaze teki, mutta alustan b:n nollaksi?
Joo, olet oikeassa. Oletin että tuo alkuperäinen koodi olisi kääntynyt (koska muuten ei mielestäni voida puhua siitä mitä tapahtuu jossain vaiheessa ohjelman suoritusta jos se ei edes käänny)
Javassahan koodin kääntyminen tarkoittaa käytännössä sitä, että alustamattomat primäärityypit on alustettu 0:lla, kun taas C:ssä ne yleensä saavat sisällökseen satunnaista roskaa.
ok, yritän tehdä siis tuolla tavalla.. +b = 0;
PS: mikä toi NumberFormatException ex on? yleensähän se on vain e?
NumberFormatException on luokan nimi eli luokkamuuttujan tyyppi ja ex on muuttujan nimi. Nimet on melko pitkälti koodaajan vapaasti valittavissa.
eli voin laittaa vaikka NumberFormatException lafhoawnfo jos haluan?
Kyllä.
ok, sitten vain parantelemaan ohjelmia.
Tein juuri eilen ohjelman, jossa on 6 sec aikaa laskea laskutoimitus(paransin myöhemmin sitä) niin jouduin laittamaan lopetus komennoksi 999..
tein nyt tämmösen yksikertasen ohjelman, testatakseni tota parseint metodia.
public class KArvo { public static void main(String[] args) { System.out.println("\n****Keskiarvon laskenta**** tyhjä syöte lopettaa"); int jatka = 0; int lkm = 0; double summa = 0.0; double Karvo = 0.0; while ( jatka == 0 ) { double i = 0.0; String sana = Lue.rivi(); if (sana.equals("")) { System.out.println("Lopetit laskemisen"); jatka = 1; } else { i = Double.parseDouble(sana); try { if (i >= 0 || i <= 0) { lkm += 1; summa += i; } } catch (NumberFormatException e) { } } } Karvo = summa/lkm; System.out.println("Lukujen keskiarvo on: "+Karvo); } }
Edit: Hyvä kun ton jdk docs saa ladattuu niin tietää löysin tohon ohjelmaan parseDouble:nkin...
Minun silmiini tuossa koodissa on muutama outous. Kyllähän tuo kääntyy noinkin, mutta tuskin toimii halutulla tavalla. Nythän tuon parseDouble -metodin aiheuttamaa poikkeusta ei napata. Tuo parseDouble -metodi tulisi kirjoittaa tuonne try -lohkon sisälle, että se toimisi kuten koodin kirjoittaja on varmaankin ajatellut sen toimivan.
Lisäksi tuo rivi
if (i >= 0 || i <= 0) {
näyttää hieman hassulta. Muuttuja i kyllä ilmeisesti voi saada arvon(NaN), joka ei täytä tuota ehtoa, mutta sen testaamiseen on ihan oma metodinsa.
pitäisikö sitten tuohon
if (i >= 0 || i <= 0) {
laittaa
if ( i = Lue.dluku()) // lukee syötteen double muodossa
vai? ja toimii kyllä täysin halutulla tavalla, paitsi että NumberFormatException lopettaa ohjelman ja toi NaN on siitä ihan ok, että jos ei syötä mitään numeroa, eihän se olekaan numero (NaN =Not a Number)
Edit: toi if (i >= 0 || i <= 0) pätkä oli ihan heitto vaan(eka mikä tuli mieleen)
Edit: mitä eroa tossa olisi jos sen parseDoublen laittaa tonne try:n sisään?
NaNin voi tietääkseni testata mm. tarkistamalla, onko luku yhtäsuuri itsensä kanssa. :) Nyt onkin kyse lähinnä koodin selkeydestä: Kaikille ei ole selvää, että tuossa vertailussa on järkeä. Sen sijaan kaikille on selvää, että luku.isNaN() tarkistaa asian.
Koodissasi parseDouble on juuri se ainokainen asia, joka kuuluu laittaa try-blokkiin, koska se on ainoa asia, joka voi mennä pieleen. Tarkoituksena on siis, että jos syöte ei ole kelvollinen luku, lennetään suoraan catch-blokkiin. Tällöin ohjelma ei lopu virheeseen, vaan voit käsitellä sen itse ja vaikkapa pyytää uudestaan lukua käyttäjältä.
ok, kokeilen sitä sitten, mutta kannattaisiko laittaa ton if (i >= 0 || i <= 0) { tilalle if (i = Lue.dluku()) ?
Edit: tein siitä koodista nyt tämmöisen:
public class KArvo { public static void main(String[] args) { System.out.println("\n****Keskiarvon laskenta**** tyhjä syöte lopettaa"); int jatka = 0; int lkm = 0; double summa = 0.0; double Karvo = 0.0; while ( jatka == 0 ) { double i = 0.0; String sana = Lue.rivi(); if (sana.equals("")) { System.out.println("Lopetit laskemisen"); jatka = 1; } else { try { i = Double.parseDouble(sana); if (i <= 0 ^ i >= 0) { lkm += 1; summa += i; } } catch (NumberFormatException e) { } } } Karvo = summa/lkm; System.out.println("Lukujen keskiarvo on: "+Karvo); } }
toi if lause ei kylläkään periaatteessa muuttunut mitenkään, mutta en keksinyt mitään hienoa tapaa kirjoittaa että jos on numero
Hmm.. mistäköhän yhtäkkiä keksin laittaa tuon parseint:in tryn ulkopuolelle kun mulla oli esimerkit copy/pastetettu täältä??
Edit: toi ei näköjään toiminut toi parseintin jälkeen toi if i = Lue.dluku() ei yhteensopiva tyyppi, sanoi.
Et tarvitse mitään if-tarkistusta, koska jos parseDouble ei saa luettua lukua, hypätään automaattisesti catch-osioon, jolloin if-lause jää suorittamatta, ja jos taas luku saadaan luettua, if-lauseesikin ehto on tietenkin tosi.
eli sen voi vain poistaa sieltä? sen if- lauseen siis
Aihe on jo aika vanha, joten et voi enää vastata siihen.