Raamatute hinnavaatluse ülesande soovitusi ja nõuandeid: erinevus redaktsioonide vahel

Allikas: Lambda
Mine navigeerimisribale Mine otsikasti
115. rida: 115. rida:




=== Kuidas teha õige suurusega massiiv, kui näiteks failist loed? ===
=== Kuidas teha õige suurusega massiiv, kui näiteks stringist või failist andmeid loed? ===


Failist lugemise kohta vaata kindlasti ka näiteprogrammi [[ioproov.java]]
Failist lugemise kohta vaata kindlasti ka näiteprogrammi [[ioproov.java]]


Probleem selles, et meil on vaja panna failist loetud stringid
Probleem selles, et meil on vaja panna stringist/failist loetud stringijupid
massiivi, aga me ei tea ette, kui suur on fail. Seega, kui
massiivi, aga me ei tea ette, kui palju neid tuleb. Seega, kui
suur massiiv tuleks teha?
suur massiiv tuleks teha?


126. rida: 126. rida:


Hästi lihtne ja ebaefektiivne lahendus on kõigepealt
Hästi lihtne ja ebaefektiivne lahendus on kõigepealt
lugeda fail sisse, aga mitte massiivi panna: selle
lugeda data välja, aga mitte massiivi panna: selle
asemel lugeda kokku ridade arv (ja tulpade arv ka).
asemel lugeda kokku ridade arv.


Siis teeme õige suurusega massiivi ja loeme seejärel
Siis teeme õige suurusega massiivi ja loeme seejärel
failist uuesti kõik read, seekord pannes nad massiivi sisse.
uuesti kõik read, seekord pannes nad massiivi sisse.


Elegantsem lahendus on vältida mitmekordset lugemist. Aga: kui sa
Elegantsem lahendus on vältida mitmekordset lugemist. Aga: kui sa
139. rida: 139. rida:
Teeme esialgse, ajutise massiivi näiteks suurusega
Teeme esialgse, ajutise massiivi näiteks suurusega
100 rida (ja õige arv tulpasid). Hakkame sinna
100 rida (ja õige arv tulpasid). Hakkame sinna
lugema. Kui fail mahtus ära, teeme uue massiivi,
lugema. Kui datal mahtus ära, teeme uue massiivi,
seekord õige (lühema) pikkusega, ja kopeerime esialgse massiivi
seekord õige (lühema) pikkusega, ja kopeerime esialgse massiivi
vajalikud read sinna massiivi. Vana massiiv visatakse
vajalikud read sinna massiivi. Vana massiiv visatakse
mõne aja pärast prahikoristaja poolt automaatselt ära.
mõne aja pärast prahikoristaja poolt automaatselt ära.


Kui fail ei mahtunud esialgsesse massiivi, teeme
Kui data ei mahtunud esialgsesse massiivi, teeme
uue ajutise massiivi, seekord näiteks 2 korda suurema
uue ajutise massiivi, seekord näiteks 2 korda suurema
kui eelmine. Kopeerime vanast ajutisest kõik uude
kui eelmine. Kopeerime vanast ajutisest kõik uude
ajutisse ja jätkame failist uude massiivi lugemist. Võib juhtuda,
ajutisse ja jätkame data uude massiivi lugemist. Võib juhtuda,
et nüüd mahub ära. Siis lõpuks teeme õige pikkusega
et nüüd mahub ära. Siis lõpuks teeme õige pikkusega
(lühema) massiivi.
(lühema) massiivi.


Kui ikka ei mahtunud, kordame protseduuri: teeme
Kui ikka ei mahtunud, kordame protseduuri: teeme
jälle uue, viimasest masiivist jällegi kaks korda
jälle uue, viimasest massiivist jällegi kaks korda
suurema ajutise masssiivi. Jne jne.
suurema ajutise masssiivi. Jne jne.



Redaktsioon: 26. september 2007, kell 13:00

Alltoodud soovitused on esialgsed, oktoobri alguse jooksul nad oluliselt täienevad: loe regulaarselt üle, leiad uusi ideid!

Kuidas andmeid hoida?

Hoia nii google base xml-st saadud olulisi andmeid (pealkiri, hind) kui panga csv-st saadud valuutakursse (valuuta, kurss) kahemõõtmeliste stringimassiividena. Rehkendamise ajal teisenda numbrid jooksvalt stringist numbriks.

Kuidas pihta hakata ja mis järjekorras programmeerida?

Põhimõte:

Hakka kirjutama valmis üksikuid juppe, alates lihtsamatest. Kui üks on valmis, testi ta läbi ja mine siis järgmise kallale. Testimiseks kirjuta trükkimisi vahele, hiljem kommenteeri mittevajalikud trükid välja või kustuta ära. Alles lõpuks pane kõik main-i sees kenasti kokku.

Väldi algul mistahes keerukusi ja lisavõimaluste tegemist! Ehita kõik algul valmis nii lihtsalt, kui saad, hiljem saad soovi korral koodi täiustada, kui aega jääb.

Soovitaksin teha tükid valmis näiteks sellises järjekorras:

  • Tõmba endale üks näite-XML failina google basest ja näite-CSV panga valuutakurssidega, ning kasuta progemisel algul sisendina neid faile, mitte aga võrguühendust! See on mugavam ja kiirem. Võrguühenduse pidev kasutamine lisa siis, kui enamus asju failide peal juba funkavad.
  • Programmeeri kõigepealt valmis valuutakursside csv faili massiivi lugemise funktsioon (tingimata tee selleks eraldi funktsioon!), katseta, et käiks ok.
  • Seejärel programmeeri valmis google base XML-st massiivi lugemise funktsioon. Katseta, et käiks ok.
  • Seejärel programmeeri valmis gbase massiivist csv tegemine nii, et hindadega esialgu ei tegelda, küll aga loetakse kokku raamatud. Katseta, et käiks ok.
  • Seejärel lisa hindadega tegelemine.

Mis juhtub, kui sa kõiki asju ei oska või ei jõua teha? Kui mingi mõistlik hulk komponente on tehtud ja töötavad, saad oma ülesande siiski arvestatud, ainult et väiksema arvu punktidega (kui praktikumijuhendaja hindab, et tehtud on pool tööd, siis saadki 5 punkti). Kui praktikumijuhendajale tundub, et tehtud on ikka väga vähe (kolmandik või vähem) siis ta üldjuhul seda ülesannet ei arvesta.

Soovitusi funktsioonide kirjutamisel

uri-ga viidatud teiste failide lugemine

Kui oled esimese faili info sisse lugenud ja massiivi pannud, käi massiiv läbi, ning loe lisaks (samasse tabelisse!) sisse kõik failid, mida uri-tüüpi väärtusega viidatakse. Ära siis juba sisse loetud faili uuesti loe!

Globaalsed muutujad

Päris mõistlik on kasutada mingit hulka globaalseid muutujaid ja massiive, näiteks:

  • readfiles: ühemõõtmeline massiiv, mis sisaldab kõigi sisseloetud failide nimesid
  • rdfdata: kahemõõtmeline massiiv, mis sisaldab kõigi sisseloetud andmefailide infot korraga
  • condname: tingimusvälja nimi
  • condvalue: tingimusvälja väärtus

Funktsioonid võivad vajadusel vabalt otse nende globaalsete muutujatega manipuleerida.


Stringi lõhkumine eraldaja järgi

Sinu programm peab päris mitmes kohas lammutama eraldajaga stringi tükkideks:

  • kettalt loetud csv faili rida, eraldajaks komad
  • käsurealt antud lause

Kuidas seda paremini teha?

Esiteks, iga sellise lammutamise tulemuseks tasub anda stringimassiivi, kus elementideks on järjest vajalikud stringid. Hea on, kui see stringimassiiv teha kohe õige pikkusega, siis saab mh lihtsamalt kontrollida, kui palju elemente temas on (massiiv.length annab massiivi pikkuse).

Teiseks, mõistlik on kirjutada funktsioon, mis võtab ette lammutatava stringijupi, eraldaja-stringi (koma või and vÕi =) ja annab tagasi stringimassiivi.

Stringi lammutamiseks on palju meetodeid, kuid kõige lihtsam on uurida näiteprogrammi splitproov.java ja kasutada seal olevaid ideid. NB! Selleks, et selle programmi lõike kasutada, on vaja, et sa temast aru saaksid. Vaata kindlasti ka massiivide kasutamise näiteprogrammi massiivproov.java

Failide sisselugemine ja komade järgi splittimine

Sellest on veidi kirjas siinse jutu lõpuosas. Kindlasti tee funktsioon, mis saab ette failinime ja annab tagasi kahemõõtmelise massiivi temast leitud stringidest. Siis on lihtne seda funktsiooni tsüklis välja kutsuda, üle kõigi sisseloetavate failide.

Muid soovitusi

Stringide võrdlemine

NB! Kui x ja y on stringid, siis võrdlemine

 x==y

ei anna oodatud tulemust! See võrdlus ainult kontrollib, kas x ja y on võrdsed pointerid, st viitavad samale stringile mälus. Aga, kui teeme nii:

 String x="ab";
 String y="ab";
 if (x==y) ...

siis x ja y on erinevad pointerid (kuigi stringide sisud on samad!) ja neid ei peeta võrdseks.

Selleks, et kontrollida, kas stringide sisud on samad, on vaja kasutada sellist spetsiaalset stringivõrdlust:

 x.equals(y)

(selle funktsiooni ja muud head stringifunktsioonid leiab nii Ecki õpikust kui ametliku manuaali lingilt http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html)

Võrdlemaks, kas string x on suurem kui string y (vajalik sorteerimisel), kasuta järgmist funktsiooni:

 x.compareTo(y)

Lisainfot (mitte väga olulist) leiad eelnevalt viidatud linkidest.

Mida compareTo välja annab? int-i. Mida see int näitab? Katseta ise: võrdle paari stringi (pane katse main funktsiooni) ja trüki tulemus-int välja.


Kuidas teha õige suurusega massiiv, kui näiteks stringist või failist andmeid loed?

Failist lugemise kohta vaata kindlasti ka näiteprogrammi ioproov.java

Probleem selles, et meil on vaja panna stringist/failist loetud stringijupid massiivi, aga me ei tea ette, kui palju neid tuleb. Seega, kui suur massiiv tuleks teha?

Siin on, nagu alati mitu lahendust.

Hästi lihtne ja ebaefektiivne lahendus on kõigepealt lugeda data välja, aga mitte massiivi panna: selle asemel lugeda kokku ridade arv.

Siis teeme õige suurusega massiivi ja loeme seejärel uuesti kõik read, seekord pannes nad massiivi sisse.

Elegantsem lahendus on vältida mitmekordset lugemist. Aga: kui sa endas väga kindel ei ole, soovitan algul realiseerida lihtsama lahenduse, mida äsja kirjeldasin.

Elegantsema lahenduse saab kirjutada näiteks nii:

Teeme esialgse, ajutise massiivi näiteks suurusega 100 rida (ja õige arv tulpasid). Hakkame sinna lugema. Kui datal mahtus ära, teeme uue massiivi, seekord õige (lühema) pikkusega, ja kopeerime esialgse massiivi vajalikud read sinna massiivi. Vana massiiv visatakse mõne aja pärast prahikoristaja poolt automaatselt ära.

Kui data ei mahtunud esialgsesse massiivi, teeme uue ajutise massiivi, seekord näiteks 2 korda suurema kui eelmine. Kopeerime vanast ajutisest kõik uude ajutisse ja jätkame data uude massiivi lugemist. Võib juhtuda, et nüüd mahub ära. Siis lõpuks teeme õige pikkusega (lühema) massiivi.

Kui ikka ei mahtunud, kordame protseduuri: teeme jälle uue, viimasest massiivist jällegi kaks korda suurema ajutise masssiivi. Jne jne.

NB! Selliselt ajutisi massiive tehes pane tähele, et kuna tulpade arv on neis alati õige, ei ole tegelikult vaja kopeerida vanast massiivist uude üksikute stringide kaupa (st topelttsükliga). Kahemõõtmeline massiiv on ju massiiv mitmest ühemõõtmelisest! Kopeerimise käigus saame kopeerida korraga terve rea (käsitledes massiive kui ühemõõtmelisi) ja see on palju kiirem meetod. Siin on veel võimalik teha mitu täiendavat optimeeringut, aga liiale ei ole optimeerimis-pingutustega ka mõtet minna.