Morjens taas
Harjotuksen vuoksi aattelin tehdä Javalla laskimen, ja ajattelin olevan kaikkein helpoin tapa ottaa käyttäjän syöte stringiin ja muuttaa se laskutoimutukseksi. En ole vaan löytänyt mitään funktiota vielä, joka tekisi tuon muunnoksen.
Koodivinkeissä oli jokin esimerkki tehty PHP:llä säännöllisiä lausekkeita käyttäen, mutta haen jotain toisenlaista toimintoa..
Käyttäjän syöte saa sisältää merkkejä , (desimaalipilkku), + (plus), - (miinus), % (jako) ja x (kerto).
Nyt en oikein ymmärrä kysymystäsi. Ajattelit tehdä laskimen ja kysyt, olisiko Javassa valmista funktiota sen tekemiseen?
Voit lukea syötettä Scanner-luokalla, kuten Javassa yleensä tehdäänkin. (Nyt tiedonhakutaidot käyttöön!) Jos laskutoimitus on yksinkertainen (1 + 2), saat laskettua sen oikein parilla if-lauseella; muuten sinun pitää jäsentää siitä sulut, laskujärjestys ym. hienoudet esimerkiksi shunting yard -algoritmilla. Hyvä harjoitus on myös keksiä tuo jäsennysalgoritmi itse joko puhtaalta pöydältä tai edes lukemalla vain ihan lyhyt kuvaus.
Itse olen joskus tehnyt laskujen lasku -funktion, joka käsittelee laskua tekstijonona. Ensin funktio etsii sulut ja syöttää sulkujen sisällön itselleen ja korvaa sulut funktion palautusarvolla. Sitten funktio katsoo kerto- ja jakolaskun loopissa ja korvaa toimituksen tuloksella ja tekee saman yhteen- ja vähennyslaskulle ja lopulta palauttaa tuloksen käyttäjälle.
Esim.
3*(1,4+2,3)/2 ->1,4+2,3=3,7 3*3,7/2 11,1/2 5,55
(-> = sulkujen lasku)
Tiedän, että tämä ei ole kovinkaan hyvä tapa laskea laskua, mutta toimii ja voi olla aloittelijalle ihan hyvä.
Mulla tuli joku ajatusvirhe, kun kirjoitin "ottaa käyttäjän syöte stringiin". Tarkoitin kyllä jotain muuta, eikä ole tarkoitus ottaa käyttäjältä minkään näköistä tekstiä.
Se mitä tarkoitin tuolla, olisi jotenkin tälläinen. Erona vaan, että lauseketta ei pidä etsiä, vaan se pitää suorittaa stringistä.
Miksi se pitää suorittaa stringistä?
Joka tapauksessa tilanne on sama kuin käyttäjältä luettaessa. Voit edelleen käyttää Scanner-luokkaa syötteen parsimiseen, ja laskeminen tapahtuu edelleen aivan samalla tavalla.
Miten laskeminen tapahtuu edelleen "samalla" tavalla?
Joko ymmärsit mitä tarkoitan, ja en sitten ymmärtänyt tuota Scanner-luokkaa tai et ymmärtänyt. Javascriptissä on täsmälleen sellainen funktio jonka tarvitsen, nimittäin eval (var tulos = eval("1+2/2"), palauttaa 2).
Tutkin tuota Scanner-luokkaa, mutta en keksinyt miten sillä saataisiin tehtyä tuo.
Niin, tuollainen eval-funktio kuuluu tyypillisesti skriptikieliin, joissa on koko ajan alla se tulkki, joka ymmärtää tekstimuotoista syötettä. Java ei ole skriptikieli, joten siinä ei ole tuollaista funktiota; Javan virtuaalikone ei ymmärrä tekstimuotoista lähdekoodia. Sama pätee kaikenlaisiin muihinkin käännettäviin kieliin.
Sinun pitää siis itse ohjelmoimalla purkaa lauseke osiin ("1", "+", "2", "/", "2") ja itse suorittaa oikeat laskut sopivien ehtolauseiden ja apumuuttujien avulla. Mainitsemani shunting yard -algoritmi yhdessä pinolaskimen kanssa on siihen yksi helppo tapa. Hennkan esityskin on oikeastaan vain yksi tapa toteuttaa samainen algoritmi ja pinolaskin yhdistettynä siten, että lauseketta lasketaan jo purkamisen aikana ja "pino" muodostuu funktion rekursiosta.
Niin siis tuo Scanner-luokkahan on tarkoitettu nimenomaan syötteen lukemiseen käyttäjältä ainakin konsolista sekä tiedostosta tai sitten sillä pystyy tutkimaan syötettä jollain tavoin (en aivan kaikkia mahdollisuuksia tunne)...
Tossa on vielä pieni demostraatio scanner käytöstä...
import java.util.Scanner; public class TietojenLukemista { public static Scanner lukija = new Scanner(System.in); public static void main(String[] args) { System.out.println("Kirjoita jotain: "); String syote = lukija.nextLine(); System.out.println("Kirjoitit: " + syote); } }
(Koodia ei ole testattu, mutta tod. näk. toimii)
Scanner-luokalla voi lukea syötettä mm. käyttäjältä, tiedostosta, socketista tai merkkijonosta, ja sillä olisi melko helppo lukea lausekkeesta lukuja ja symboleja parin säännöllisen lausekkeen avulla. Toisaalta yhtä helposti lausekkeen voi jäsentää muuten vain säännöllisillä lausekkeilla, eikä olisi kovin kummoinen vaiva myöskään lukea lauseketta merkki kerrallaan silmukassa. Valinta riippuu lähinnä omista tottumuksista ja taidoista.
Triton, turhaan alustat sen syote-muuttujan.
Metabolix kirjoitti:
Triton, turhaan alustat sen syote-muuttujan.
Joo-o. Noi on jotain jäänteitä yliopiston laskareista... :D
Edit. Onhan tuon Scanner-luokan käyttäminen huomattavasti helpompaa (tai ainakin nopeampaa), kuin lähteä filtteröimään bittivirtaa InputStreamin sekä sun muiden luokkien avulla...
Käyttämällä
http://jeplite.sourceforge.net/faq.html
voi tehdä näin:
Ajon tuloksena on:
1+2*600-100/100 = 1200.0
HYVIN yksin kertainen laskin joka ei osaa laskea muuta: kuin plus miinus jako kerto laskut Voisi näyttää tältä:
import java.util.Scanner; public class laskin { private static Scanner lukija=new Scanner(System.in); public static int Kerro(int luku1,int luku2){ return luku1*luku2; } public static double Jaa(int luku1,int luku2){ return luku1/luku2; } public static int Vahenna(int luku1,int luku2){ return luku1-luku2; } public static int Lisaa(int luku1,int luku2){ return luku1+luku2; } public static void main(String[] args){ System.out.println("Syötä lasku"); String lasku=lukija.nextLine(); if(lasku.indexOf("*")!=-1){ int monesko=lasku.indexOf("*"); String luku1=lasku.substring(0,monesko); String luku2=lasku.substring(monesko+1,lasku.length()); int sluku1=Integer.parseInt(luku1); int sluku2=Integer.parseInt(luku2); int vastaus=Kerro(sluku1,sluku2); System.out.println(sluku1+"*"+sluku2+"="+vastaus); } else if(lasku.indexOf("/")!=-1){ int monesko=lasku.indexOf("/"); String luku1=lasku.substring(0,monesko); String luku2=lasku.substring(monesko+1,lasku.length()); int sluku1=Integer.parseInt(luku1); int sluku2=Integer.parseInt(luku2); double vastaus=Jaa(sluku1,sluku2); System.out.println(sluku1+"/"+sluku2+"="+vastaus); } else if(lasku.indexOf("-")!=-1){ int monesko=lasku.indexOf("-"); String luku1=lasku.substring(0,monesko); String luku2=lasku.substring(monesko+1,lasku.length()); int sluku1=Integer.parseInt(luku1); int sluku2=Integer.parseInt(luku2); int vastaus=Vahenna(sluku1,sluku2); System.out.println(sluku1+"-"+sluku2+"="+vastaus); } else if(lasku.indexOf("+")!=-1){ int monesko=lasku.indexOf("+"); String luku1=lasku.substring(0,monesko); String luku2=lasku.substring(monesko+1,lasku.length()); int sluku1=Integer.parseInt(luku1); int sluku2=Integer.parseInt(luku2); int vastaus=Lisaa(sluku1,sluku2); System.out.println(sluku1+"+"+sluku2+"="+vastaus); } else{ System.out.println("Virheellinen lasku."); } } }
Mod. lisäsi kooditagit.
Aihe on jo aika vanha, joten et voi enää vastata siihen.