Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Java: Tyyppimuunnos String --> int [java]

Sivun loppuun

Tommittaja [07.01.2009 18:45:48]

#

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.

Metabolix [07.01.2009 18:57:35]

#

Käytä funktiota Integer.parseInt(str).

Tommittaja [07.01.2009 19:02:03]

#

voitko antaa esimerkin?

Sami [07.01.2009 19:26:11]

#

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.

Tommittaja [07.01.2009 19:28:16]

#

mutta haluaisin että sen voi lukea myös string muodossa

Sami [07.01.2009 19:30:23]

#

Täh? Sehän on String ennen muunnosta... Ja se sama merkkijono säilyy siinä sen muunnoksen jälkeenkin.

Teuro [07.01.2009 19:31:21]

#

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.

Metabolix [07.01.2009 19:32:00]

#

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());
		}
	}
}

Tommittaja [07.01.2009 19:33:05]

#

aa.. joo katoin vaan että

Sami kirjoitti:

(esim. sisältää kirjaimia), niin metodi heittää NumberFormatExceptionin.

Sami [07.01.2009 19:37:00]

#

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);
  // ...
}

Metabolix [07.01.2009 19:38:19]

#

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);
			}
		}
	}
}

Tommittaja [10.01.2009 17:47:54]

#

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...

Blaze [10.01.2009 23:47:17]

#

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.

Tommittaja [11.01.2009 13:24:15]

#

miten tuo sitten tehdään? voitko kirjoittaa vastaavan esimerkin?

Blaze [11.01.2009 14:05:24]

#

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");
}

Päärynämies [11.01.2009 17:29:22]

#

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.

Grez [11.01.2009 17:36:19]

#

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.

Metabolix [11.01.2009 18:12:38]

#

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.

Päärynämies [11.01.2009 18:27:05]

#

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/langspec-3.0.pdf. Sieltä erityisesti kohta 4.12.5. Toivottavasti tuijottelin oikeasta paikasta.

Tommittaja [11.01.2009 18:35:46]

#

eli toimisi, jos teen tuon samanlailla kuin Blaze teki, mutta alustan b:n nollaksi?

Grez [11.01.2009 18:38:06]

#

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.

Tommittaja [11.01.2009 18:45:21]

#

ok, yritän tehdä siis tuolla tavalla.. +b = 0;
PS: mikä toi NumberFormatException ex on? yleensähän se on vain e?

Grez [11.01.2009 18:55:55]

#

NumberFormatException on luokan nimi eli luokkamuuttujan tyyppi ja ex on muuttujan nimi. Nimet on melko pitkälti koodaajan vapaasti valittavissa.

Tommittaja [11.01.2009 18:57:23]

#

eli voin laittaa vaikka NumberFormatException lafhoawnfo jos haluan?

Grez [11.01.2009 18:58:39]

#

Kyllä.

Tommittaja [11.01.2009 19:02:02]

#

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..

Tommittaja [12.01.2009 18:06:57]

#

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...

Päärynämies [12.01.2009 19:20:25]

#

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.

Tommittaja [12.01.2009 20:02:07]

#

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?

Metabolix [12.01.2009 20:28:16]

#

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ä.

Tommittaja [12.01.2009 21:10:32]

#

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.

Metabolix [12.01.2009 23:18:29]

#

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.

Tommittaja [13.01.2009 16:59:16]

#

eli sen voi vain poistaa sieltä? sen if- lauseen siis


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta