Rdf-baasi ülesande soovitusi ja nõuandeid

Allikas: Lambda

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:


  • Programmeeri kõigepealt valmis faili massiivi lugemise funktsioon (tingimata tee selleks eraldi funktsioon!), katseta, et käiks ok.
  • Seejärel programmeeri valmis String rdf_omabsumma(String failinimi, String id, String omadus, String vaartus),alustades lihtsamast juhust: tingimusi pole, uri-dega midagi ei viidata jne. Kui see lihtne variant käib, lisa uri-dega tegutsemine ja lõpuks tingimused.
  • Seejärel programmeeri käsurea töötlus, mis lõpuks kutsub välja varem tehtud funktsiooni rdf_omabsumma.
  • Nüüd tee valmis funktsioon String rdf_kesomabmax(String failinimi, String omadus, String vaartus), mis jällegi kasutab varem tehtud funktsiooni rdf_omabsumma.
  • Lõpuks tee valmis käsurea-töötlus kesomabmax jaoks, kasutades vastuse leidmiseks muidugi funktsiooni rdf_kesomabmax


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 failist loed?

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

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

Siin on, nagu alati mitu lahendust.

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

Siis teeme õige suurusega massiivi ja loeme seejärel failist 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 fail 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 fail 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 failist 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 masiivist 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.