Laske tekstitiedostossa olevat luvut siten, että erottelet luvun tyypin (int, float). Luvut voi olla eroteltu pilkulla, välilyönneillä, puolipisteeellä, tabulaattorilla tai rivinvaihdolla. Jos syötteessä on virhe niin ohjelman pitää osata tarkalleen kertoa rivi ja sarake missä virhe on tapahtunut. Luvuissa pitää olla E-notaatio tuettuna myös.
Alla oma toteutukseni 8th-ohjelmointikielellä:
\ \ scanner.8th \ needs file/getc ns? ns: scanner -1 constant EOF 10 constant LF 32 constant SPACE 0 constant ,SYM 1 constant ;SYM 2 constant INTSYM 3 constant FLOATSYM [] constant special-chars : scanner:__init__ "file" rot m:! "column" 0 m:! "line" 1 m:! "char" SPACE m:! "number" 0 m:! "word" "" m:! drop ; : scanner:__deinit__ ; : new \ file -- scanner ns:scanner G:new ; : >char \ n -- char "" swap s:+ ; : line@ \ scanner -- scanner line "line" m:@ ; : column@ \ scanner -- scanner column "column" m:@ ; : char@ \ scanner -- scanner char "char" m:@ ; : number@ \ scanner -- scanner string "number" m:@ ; : word@ \ scanner -- scanner string "word" m:@ ; : file@ \ scanner -- scanner file "file" m:@ ; : line! \ scanner n -- scanner "line" swap m:! ; : column! \ scanner n -- scanner "column" swap m:! ; : char! \ scanner char -- scanner "char" swap m:! ; : number! \ scanner n -- scanner "number" swap m:! ; : word! \ scanner s -- scanner "word" swap m:! ; : accept \ n a -- n T ( over n:= ) a:map ' or false a:reduce ; : digit? \ n -- bool '0 '9 n:between ; : alpha? \ n -- bool dup >r 'a 'z n:between r@ 'A 'Z n:between or r> special-chars accept nip or ; : read-char \ scanner -- scanner char@ LF n:= if line@ n:1+ line! 0 column! then file@ f:getc swap -rot char! swap f:eof? nip if EOF char! then char@ EOF n:= not if column@ n:1+ column! then ; \ Status 0 constant EMPTY 1 constant PARTIAL-FAIL 2 constant PARTIAL-OK 3 constant OK 4 constant ERROR \ State 0 constant S0 1 constant IPART 2 constant FPART 3 constant ESIGN 4 constant EPART : make-dword \ lword hword -- dword 0xffff n:band 16 n:shl swap 0xffff n:band n:bor ; : s2 OK IPART 2 a:close extra! ; : s3 PARTIAL-FAIL FPART 2 a:close extra! ; : s4 PARTIAL-OK ESIGN 2 a:close extra! ; : s5 extra@ 0 OK a:! drop ; : s6 PARTIAL-FAIL FPART 2 a:close extra! ; : s7 PARTIAL-OK ESIGN 2 a:close extra! ; : s8 extra@ 0 OK a:! drop ; : s9 PARTIAL-OK ESIGN 2 a:close extra! ; : s10 PARTIAL-FAIL EPART 2 a:close extra! ; : s11 extra@ 1 EPART a:! drop ; : s12 extra@ 0 OK a:! drop ; hex \ hi-word valid character, low-word state [ 20,9,30,31,32,33,34,35,36,37,38,39,2e,65,45,10030,10031,10032,10033,10034, 10035,10036,10037,10038,10039,1002e,10065,10045,20030,20031,20032,20033, 20034,20035,20036,20037,20038,20039,20065,20045,3002b,3002d,30030,30031, 30032,30033,30034,30035,30036,30037,30038,30039,40030,40031,40032,40033, 40034,40035,40036,40037,40038,40039] constant state-table decimal : actions: a:new '; parse /\s+/ s:/ ( s:len nip ) a:filter a:len if ( w:find a:push ) a:each! drop else drop then ; actions: noop noop s2 s2 s2 s2 s2 s2 s2 s2 s2 s2 s3 s4 s4 s5 s5 s5 s5 s5 s5 s5 s5 s5 s5 s6 s7 s7 s8 s8 s8 s8 s8 s8 s8 s8 s8 s8 s9 s9 s10 s10 s11 s11 s11 s11 s11 s11 s11 s11 s11 s11 s12 s12 s12 s12 s12 s12 s12 s12 s12 s12 ; constant action-table : read-number \ scanner -- scanner type "" word! repeat char@ swap word@ rot s:+ word! read-char char@ dup >r digit? r@ '. n:= or r@ [69, 101, 43, 45, 46] accept nip or not r> EOF n:= or if word@ >n number! break else char@ over extra@ nip 1 a:@ nip make-dword state-table swap ' n:= a:indexof nip null? if drop extra@ 0 ERROR a:! drop else action-table case then extra@ 0 a:@ nip ERROR n:= if column@ swap line@ nip "Line:%d Column:%d, Not a valid number" s:strfmt throw then then again extra@ a:open make-dword [0x10003, 0x20003, 0x20002, 0x30002, 0x40003, 0x40002] swap ' n:= a:indexof nip null? if drop column@ swap line@ nip "Line:%d Column:%d, Not a valid number" s:strfmt throw else [ @INTSYM, @FLOATSYM, @FLOATSYM, @FLOATSYM, @FLOATSYM, @FLOATSYM ] caseof then ; : partial-fail \ state -- PARTIAL-FAIL swap 2 a:close extra! ; [ ( char@ digit? ), ( OK IPART 2 a:close extra! read-number ), ( char@ '+ n:= ), ( IPART partial-fail read-number ), ( char@ '- n:= ), ( IPART partial-fail read-number ), ( char@ '. n:= ), ( FPART partial-fail read-number ), ( char@ ', n:= ), ( read-char ,SYM ), ( char@ '; n:= ), ( read-char ;SYM ), ( char@ EOF n:= ), ( EOF ), ( char@ >char swap column@ swap line@ nip "Line:%d Column:%d, Illegal character: %s" s:strfmt throw ) ] var, symbols : get-token \ scanner -- scanner token \ skip white space repeat char@ EOF n:= not swap char@ SPACE n:> not rot and if read-char else break then again symbols @ a:when ; ns
\ \ nc.8th \ "scanner.8th" f:include var ints var floats [ ' noop , \ ,SYM ' noop , \ ;SYM ( 1 ints n:+! ) , \ INTSYM ( 1 floats n:+! ) \ FLOATSYM ] var, possible-tokens : app:main 0 args "numbers.txt" ?: f:open-ro scanner:new repeat scanner:get-token dup scanner:EOF n:= if 2drop break else possible-tokens @ case then again floats @ ints @ "Number of ints: %d\nNumber of floats: %d\n" s:strfmt . bye ;
Ohjelmoin aluksi tuollaisen lukugeneraattorin Javalla, kun ajattelin Javalla ohjelmoida tämän jalskin esittämän haasteen, vaikka varmaan se kovinkaan tehokas ole välttämättä olioperusteisena suoritusajaltaan, mutta pitää demoaineisto olla ensin koottuna.
Tämä nyt tulostaa satunnaisen käyttäjän määrittelemän kokoisen tiedostoon tallennettavan demoaineiston niillä kriteereillä, joita jalski on antanut, luotavan demo-populaation koko on suhteutettu koko aineiston määrään, ja tiedoston "sample.txt" -alkioiden lukumäärän saa itse määritellä, olen kommentoinut koodin kohtiin, samaten mitä virhesyotteiden määrän voi määritellä, jos tykkää käyttää sitten siinä varsinaisessa ohjelmassa ohjelmoidessaan sen virheen sijainnin tallentamisen johonkin muuttujaan, ja jos niitä on useampia, jos asettaa 0 ERRORS -vakiomuuttujan arvoksi, niin sittenhän tiedostoon ei tulosteta, kuin läpimeneviä arvoja.
Koodini, olkaa hyvä, saa käyttää vapaasti oman demopopulaation generointiin ja helpottaa huomattavasti, jos ohjelmoitte tätä jalskin haastetta.
EDIT: Muokkasin koodiani modulaarisempaan suuntaan, niin nyt kokonaislukuja ja erikokoisia liukulukuja on satunnaisesti voi olla sekaisin samaten, kuten erotinmerkkejä, mitä jalski antoi ehdoiksi.
Lopullinen koodini, käyttäkää tätä, kun ohjelmoitte itse haasteen tiedostonlukuohjelmaa, demopopulaation voi kätevästi "sample.txt" -tiedostoon luoda ajamalla tämä:
import java.util.Random; import java.util.ArrayList; import java.io.*; public class Lukugeneraattori { private ArrayList<String> lista; private Random r; private File tiedosto; private FileWriter fw; private BufferedWriter bwriter; private final String[] DE = {",",";","\t","\n"}; //Muokkaa näitä tietoja vaikuttaaksesi demoaineiston kokoon, joka tallennetaan tiedostoon. private final int SIZE = 100; private final int ERRORS = 0; ///////////////////////////////////////////////////////////////////////////////////////// public Lukugeneraattori() { r = new Random(); this.lista = new ArrayList<String>(); try { fw = new FileWriter(tiedosto=new File("sample.txt")); bwriter = new BufferedWriter(fw); } catch (IOException e) { System.out.println("An error occurred."); e.printStackTrace(); } generoi(SIZE); tallenna(); } public void generoi(int size) { String temp; for (int y=0;y<SIZE;y++) { switch(r.nextInt(2)) { case 0: { temp = generoiFloat(); } break; case 1: { temp = generoiInt(); } break; default: { temp =""; } } lista.add(temp); } char[] errors = generoiVirheet(); for (int z=0;z<errors.length;z++) { lista.add(r.nextInt(lista.size()-1), String.valueOf(errors[r.nextInt(errors.length)])); } } public String generoiFloat() { float leftLimit = 1F,rightLimit = 10F,tempF; tempF = leftLimit + r.nextFloat() * (rightLimit - leftLimit); String temp = String.valueOf(tempF) + DE[r.nextInt(DE.length)]; return temp; } public String generoiInt() { return String.valueOf(r.nextInt(SIZE*2)+ DE[r.nextInt(DE.length)]); } public void tallenna() { for (int x=0;x<lista.size();x++) { try { bwriter.write((String) lista.get(x)); bwriter.flush(); } catch (Exception e) { } } System.out.println("Tiedosto kirjoitettu!"); } public char[] generoiVirheet() { char[] temp = new char[ERRORS]; char err ='X'; for (int x=0;x<temp.length;x++) { temp[x] = err; } return temp; } public void tulosta() { for (int x=0;x<lista.size();x++) { System.out.print(lista.get(x)); } } public static void main(String[] args) { new Lukugeneraattori().tulosta(); } }
Selkeytin vähän koodia ja lisäsin jokusen kommentin. Oman versioni pitäsi nyt toimia oikein joka tilanteessa ja olla kohtuulisen nopea.
Jere, pistätkö jonnekin saataville kohtuullisen kokoisen generoimasi syötetiedoston ilman virheitä (minimissään vaikka joku 100000 lukua sisältävä)? Itsellä Raspberry PI 4B koneessa niin pieni sd-kortti, että en saa Javaa asennettua.
Tottahan toki pistän!
Uploadasin Dropboxiin 200 000 alkion sisältävän syötetiedoston, ja pistin tuon ERRORS -arvoksi 0, joten siinä ole virheitä.
Suora linkki, josta voit ladata itsellesi testiaineiston, on
Tietynlaiseen täsmällisen insinöörimäiseen käsittelyyn tilakone on ihan kätevä vaihtoehto. Tosin jalskin toteutus näyttää vaikeasti ylläpidettävältä, kun ilmeisesti tilasiirtymiä on laitettu koodiin taikalukuina. Tässä on tilakoneen toteutus PHP:llä, tilat ja siirtymät ovat yksinkertaisesti tekstinä.
<?php function count_numbers($s) { $ends = ",; \t\n"; $dfs = [ "" => ["+-" => "sign", "0123456789" => "int", "." => "empty_float", " \t\n" => ""], "sign" => ["0123456789" => "int", "." => "empty_float"], "int" => ["0123456789" => "int", "." => "float", "e" => "e_empty", $ends => "int_done"], "empty_float" => ["0123456789" => "float"], "float" => ["0123456789" => "float", "e" => "e_empty", $ends => "float_done"], "e_empty" => ["+-" => "e_sign", "0123456789" => "e"], "e_sign" => ["0123456789" => "e"], "e" => ["0123456789" => "e", $ends => "float_done"], ]; // Ylläpidon helpottamiseksi yllä on esim. "+-" => "sign", ja tämä // muutetaan nyt koneellisesti muotoon "+" => "sign", "-" => "sign". foreach ($dfs as $i => $arr) { $dfs[$i] = []; foreach ($arr as $chars => $next) { foreach (str_split($chars) as $c) { $dfs[$i][$c] = $next; } } } $ints = $floats = 0; $line = $column = 0; $state = ""; for ($i = 0; $i <= strlen($s); ++$i) { $c = $i < strlen($s) ? $s[$i] : "\n"; if (!isset($dfs[$state][$c])) { $c_json = json_encode($c); $ok_json = json_encode(implode("", array_keys($dfs[$state]))); return "error at $line:$column, found $c_json, expected one of $ok_json"; } $column += 1; if ($c == "\n") { $line += 1; $column = 0; } $state = $dfs[$state][$c]; if ($state == "float_done") { $floats += 1; $state = ""; } if ($state == "int_done") { $ints += 1; $state = ""; } } return "floats $floats, ints $ints"; }
Testikoodi yllä olevan käyttöön:
<?php echo "data.txt: ", count_numbers(file_get_contents("data.txt")), "\n"; echo "syötä rivejä testattavaksi:\n"; while ($s = fgets(STDIN)) { echo count_numbers(trim($s)), "\n"; }
Tässä on vielä JS-koodi, jolla saa tehtyä deterministisen datatiedoston suoraan selaimella (F12:lla konsoli auki ja copy-paste sinne), ainoana satunnaistekijänä mahdolliset selainten JS-toteutusten laskutarkkuuden erot. Koodin lopussa oleva luku 1000000 on generoitavien lukuarvojen määrä.
(n => { let m = n / 10 |0; let signs = ["+", "-", ""], sign_i = 0; let ends = [" ", ",", ";", "\t", "\n"], end_i = 0; let data = Array(m).fill(0) .map((x,i) => 0.999834792348697614689 * i / m) .flatMap(x => [x, x/10, x/1000, 10*x, 10000*x, 1000000000 * x |0, 1e300 * x, 1e-300 * x, Math.pow(1e300, x), Math.pow(1e-300, x)]) .map(x => signs[sign_i++ % signs.length] + x + ends[end_i++ % ends.length]) .join(""); let link = document.createElement("a"); link.textContent = "data.txt @ " + new Date().toLocaleString(); link.href = URL.createObjectURL(new File([data], "data.txt", {type: "text/plain"})); link.download = "data.txt"; document.body.appendChild(link); link.click(); })(1000000);
Edellä oleva optimoimaton PHP-koodi käsittelee nämä miljoona lukua (20 megaa dataa) parissa sekunnissa omalla koneellani.
Generoidussa testidatassa ei ole virheitä, koska niiden laittaminen testidatan sekaan ei ole jalskin antamilla spekseillä järkevää, kun ilmeisesti käsittely loppuu ensimmäiseen virheeseen. Erilaiset virheet kannattaa laatia ja testata erikseen, järkevä testi ei ole vain selvästi väärän merkin heittäminen sekaan, vaan virhetyyppejä ovat esimerkiksi oikeiden merkkien sijainti väärässä kohti kuten "1+1", "+1.e1.2" jne.
jalskin speksit eivät ole aivan yksiselitteiset (eikä niitä jalskin koodistakaan helposti näe; jos tuo on selvää koodia, en palkkaa jalskia töihin). Esimerkiksi saako lukujen välillä olla useampi välilyönti (tai pilkku) ja miten sallivasti piste tulisi käsitellä (".1", "1.", "1.e+2"), ja mikä on kokonaisluvun määritelmä eli onko tällä jokin rajoitettu lukualue ja saako kokonaisluvun esittää e-notaatiolla (ja onko tällöin myös 1.3e1 kelvollinen kokonaisluku, sehän on sama kuin 13).
Lisäksi kun tehtävä lähti toisen keskustelun kysymyksestä, miten käyttäjän lukusyöte luetaan, niin tämähän on siihen liittymätön tehtävä, kun insinöörin suunnittelemat formaatit on kovakoodattu tilakoneeseen, lukuihin kelpaavat vain ASCII-merkit ja esimerkiksi pilkku on koodattu erottamaan lukuja, vaikka suomen kielessä pitäisi käyttää nimenomaan desimaalipilkkua. Mutta ei siitä enempää tässä keskustelussa.
Huomasin muuten vasta nyt tänään iltapäivemmällä, kun aamulla jaoin tuon Dropbox-jaon tänne, että tuosta alkuperäisestä lähdekoodistani puuttuu noista erotinmerkeistä välilyönti. No, sama kai se, ei sen puuttuminen nyt mikään suuri synti ole, jos joku tykkää generoida itse käyttäen tuota koodia, niin helposti voinee lisätä tuon välilyönti-merrkijonon alkion tuohon DE-taulukkoon, eikä koodissa tarvitse muutta muutoin mitään, niin sitten osa noista alkioiden erotinerkeistä on pelkkä välilyönti, kun ajaa ohjelman.
Tässä on nyt tuo tilakone kahdella kielellä esiteltynä tyylikkäästi, ja tuo tilakone itselleni vähän vieraampi, tiedä oikein pitäisi saada jotain lähdemateriaalivinkkiä, ja jotain täkyä sen suuntaan, miten sitä asiaa kannattaisia lähteä lähestymään, kun kiinnostus ottaa selvää on tilakoneesta.
Tämä loppuiltapäivä itselläni aika seesteinen, eikä mitään erityistä menoa tai ohjelmaa ole suunniteltuna, niin ajan kuluksi voisi Javalla olioperusteisen sellaisen tiedostoluku-ohjelman kirjoittaa, joka lukee tavu kerrallaan tai rivi kerrallaan tuota syötetiedostoa, ja summaa luvut ja antaa floattina lopputuloksen. En tiedä, ei se varmaankaan noopeudessa pärjää teidän noille esityksille, mutta voihan sen ihan ajan kuluksi ohjelmoida, vaikka varmaan mitään merkittävää hyötyä siinä nyt ei saavuta ketään.
Kävi ensin mielessä siitä tiedostonlukijasta Javalla, vaikka tosiaan en tiedä, saako millään nykyisellä korkean tason kielellä mitään aikaetua, ei varmaan saa millään ratkaisulla, mutta kun nuo erotinmerkit ovat määritelty ja tiedossa ennallaan, niin siinä voisi jotain metodin ylikuormitusta harkita ja sitten haarautuminen oikean metodin kutsuun kone osaisi päättää itse, mutta eihän se toimikaan, kun kaikki nuo ovat String-tyyppisiä, niin valintarakenteen kautta sitten StringTokenizer -ilmentymän mukan varmaan järkevintä se lukujen erottelu.
Kyllä varmaan nopeampi ohjelma tulee, kun lukee ensin rivi kerrallaan, kun taas jos lukisi merkki kerrallaan, niin sitten kuluisi aikaa siihen tiedon yhteenliittämiseen esim. StringBufferilla. Tietty molemmat voisi ohjelmoida, ja joku voi sitten mitata aikaa kukin tahollaan, kumpi suoriutuu nopeammin tehtävästä.
Varmaan nopeiten jollain kehittyneemmällä assemblerilla konekielisenä saa nopeimman ratkaisun aikaan, mutta katsellaan illan päälle, jos julkaisen Java-koodia lisää.
Tällaisen ohjelmoin, mutta jostain syystä ohjelma tulostaa aina summaksi 0.0 ikäänkuin se ei laskisi mitään. Tuossa Float.parseFloat(Object) -rivissä voi olla mätää, tai sitten pitäisi silmukan ulkopuolella enimmäinen StringTokenizer elementti laskea, nyt tässä on vikaa jotenkin todella paljon, kun ei summaa millään yhtään mitään.
import java.util.ArrayList; import java.util.StringTokenizer; import java.io.*; public class Lukunopeus { private File tiedosto; private FileReader fr; private BufferedReader bwReader; private ArrayList<String> lista; private float summa; private final String DE = new String(", ,;,\t\n"); public Lukunopeus() { try { tiedosto = new File("./Sample.txt"); bwReader = new BufferedReader(new FileReader(tiedosto)); } catch (Exception e) { System.out.println("An error occurred."); e.printStackTrace(); } this.summa = 0; this.lista = new ArrayList<String>(); this.lista = listaa(); this.handleLista(); } public ArrayList<String> listaa() { String temp =""; ArrayList<String> tempLista = new ArrayList<String>(); try { while (fr.read() !=-1) { temp = (String) bwReader.readLine(); tempLista.add(temp); } } catch (Exception e) { } return tempLista; } public void handleLista() { for (int x=0;x<lista.size()-1;x++) { this.summa+=handleMjono(lista.get(x)); } } public float handleMjono(String mjono) { float summa = 0; StringTokenizer[] erottajat = new StringTokenizer[DE.length()]; for (int x=0;x<DE.length();x++) { erottajat[x] = new StringTokenizer(mjono, String.valueOf(DE.charAt(x))); } StringTokenizer temp = null; for (int y=0;y<erottajat.length;y++) { temp = erottajat[y]; while (temp.hasMoreElements()) { summa+=(float)Float.parseFloat((String)temp.nextElement()); } } return summa; } public float getSumma() { return summa; } public void setSumma(float summa) { this.summa = summa; } public static void main(String[] args) { System.out.println("" +new Lukunopeus().getSumma()); } }
Metabolix kirjoitti:
Tosin jalskin toteutus näyttää vaikeasti ylläpidettävältä, kun ilmeisesti tilasiirtymiä on laitettu koodiin taikalukuina.
jalskin speksit eivät ole aivan yksiselitteiset (eikä niitä jalskin koodistakaan helposti näe; jos tuo on selvää koodia, en palkkaa jalskia töihin). Esimerkiksi saako lukujen välillä olla useampi välilyönti (tai pilkku) ja miten sallivasti piste tulisi käsitellä (".1", "1.", "1.e+2"), ja mikä on kokonaisluvun määritelmä eli onko tällä jokin rajoitettu lukualue ja saako kokonaisluvun esittää e-notaatiolla (ja onko tällöin myös 1.3e1 kelvollinen kokonaisluku, sehän on sama kuin 13).
Muutan nuo taulukot heksa muotoon, niin ajatus tulee selvemmin esille.
Ohjelmani skanneri ei välitä erotin merkeistä ollenkaan ( koodissa näkyy taulukossa pilkun ja puolipisteen käsittelyyn ' noop sana, eli "no operation" ). Skanneri myöskin skippaa "whitespace merkit".
Käytin numerosyötteen hyväksyntään kriteerinä sitä, että 8th pystyy muuntamaan siitä numeron. Nuo "ei valmiit" muodot mitkä hyväksytään on käsitelty lopuksi kun on päätellään luvun tyyppi. E-notaatiota käytettäessä luvusta tulee aina float-tyyppinen.
Jos joku osaisi auttaa tässä Java-koodissa, kun poistin tuon StringTokenizer -taulukon tuosta "Lukunopeus" -luokasta, jonka aiemmin esiin, ja yksinkertaistin Demo-luokkaan poistaen tuon tiedostosta luvun vielä tässä vaiheessa, ja yritän saada pelkästään tuota lukujen erottamista ja summaamista yhdestä listan alkiosta ulos. Tämä seuraava koodi jostain syystä ilmoittaa virheherjaa "String is empty", ajettaessa ohjelmaa, vaikka tarkistin Oraclen manuaaleista, että tyhjä merkkijono vastaa "" -eli nollaa pituutta ja on eri asia mitä null. Tuossa listan ensimmäisessä alkiossa on merkkijono "5;\t3.14", jonka lisään populoi-metodissa. Voiko joku selventää tämän, mahdollisesti auttaa korjaamaan lähdekoodissa olevan virheen, että saisi summattua nuo listan alkioiden luvut.
import java.util.ArrayList; import java.util.StringTokenizer; public class Demo { private float summa; private ArrayList<String> lista; public Demo() { this.summa = 0; this.lista = new ArrayList<String>(); this.lista = this.populoi(); this.handleLista(); } public ArrayList<String> populoi() { ArrayList<String> tempLista = new ArrayList<String>(); tempLista.add("5;\t3.14"); tempLista.add("3.14,5"); return tempLista; } public void handleLista() { for (int x=0;x<lista.size()-1;x++) { this.summa+=handleMjono(lista.get(x)); } } public float handleMjono(String mjono) { StringBuffer sb = new StringBuffer(""); float summa = 0; float value = 0; int start = 0; for (int y = start;y<mjono.length();y++) { sb.delete(0, sb.toString().length()); if (mjono.charAt(y) == ',' || mjono.charAt(y) == ' ' || mjono.charAt(y) == ';' || mjono.charAt(y) == '\t' && mjono.length() != 0) { sb.append(mjono.substring(start, y-1)); value = Float.valueOf(sb.toString()); summa+=value; } continue; } return summa; } public float getSumma() { return summa; } public void setSumma(float summa) { this.summa = summa; } public static void main(String[] args) { Demo demo = new Demo(); System.out.println(demo.getSumma()); } }
Tässä Konsolin virheilmoitus, kun yrittää ajaa ohjelmaa:
Exception in thread "main" java.lang.NumberFormatException: empty String at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1842) at java.base/jdk.internal.math.FloatingDecimal.parseFloat(FloatingDecimal.java:122) at java.base/java.lang.Float.parseFloat(Float.java:461) at java.base/java.lang.Float.valueOf(Float.java:425) at Demo.handleMjono(Demo.java:45) at Demo.handleLista(Demo.java:29) at Demo.<init>(Demo.java:14) at Demo.main(Demo.java:64)
Tuo lienee lähempänä oikeaa tapaa erotella luvut tuo ehtolohkossa tarkistamisen jälkeen jokainen OR -operaattorilla noista erotinmerkeistä, koska ne voi olla sekaisin mikä tahansa voi esiintyä samalla rivillä. Tuota ihmettelen, kun AND -operaattorilla vielä toinen ehto, jonka JA tulisi täyttyä on tuo, että merkkijono ei ole 0 -merkkiä pitkä, eli empty string. Silti tulee tuo virheherja, että merkkijono on tyhjä.
*Ohjelmointihaaste
mpni kirjoitti:
*Ohjelmointihaaste
Jos tuntuu liian helpolta, niin voit vaikka kirjoitella tavukoodia käyttävän yksinkertaisen ohjelmointikielen tulkin Pascal tyyppiselle ohjelmointikielelle. Pitäisi onnistua muutamassa illassa...
Aihe on jo aika vanha, joten et voi enää vastata siihen.