Rubriigiarhiiv: pr2_et

PR2ET1: Viidad

Praktikumi materjal

Meeldetuletuseks koodimisstiilist

  • Koodimisstiil peab olema ühtne kõigis koodifailides
  • Kood peaks olema lihtsasti loetav ja hallatav
  • Väldi põhjendamatult keeruka koodi kirjutamist
  • Tükelda oma kood funktsioonideks
    • Funktsioonid peaksid olema lihtsad, lühikesed ja tegema vaid ühte asja ning tegema seda hästi.
    • Hoia arvutamine ja väljastus erinevates funktsioonides. Tulemusi leidvad funktsioonid peaksid olema eelistatult kõrvalmõjudeta.
    • Funktsioonid peaksid olema kergelt korduvkasutatavad (sh tulevikus kontrolltöös, eksamil)
    • main() funktsioon on kõige esimene funktsioon failis. Enda loodud funktsioonid paiknevad pärast main funktsiooni.
  • Kasuta kiireid algoritme ja andmestruktuure (minimaalselt seni õpitute hulgast)
  • Väldi globaalmuutujaid (selles aines näeme ka olukordi kus globaalmuutujad on OK)

Ülesanded

Selles praktikumis on kaks ülesannet. Teine ülesanne on tükeldatud kahte ossa. Lisaülesanne on ehitatud teise ülesande põhjal.

Ülesanne 1 [W01-1]: Viidad ja muutujad

Tegu on klassikalise muutuja väärtuse vahetamise ülesandega. Proovi lahendada ülesanne ilma igasuguse kolmanda abi ega materjalita!

Lae alla ülesande aluskood: https://blue.pri.ee/ttu/files/iax0584/aluskoodid/t1_swap_template.c

Teooriakild: stderr standardvoog

Sellest semestrist hakkame veaväljundeid regulaarselt stderr standardvoogu väljastama. Tegu on standardlähenemisega enamikes programmeerimiskeeltes, sealhulgas C keeles. See võimaldab ühtlasi ka näiteks vigu programmi väljundist hõlpsalt välja filtreerida – uuri “redirect stderr to file“.

Vanaviisi: prindime veateated stdout  standardvoogu: printf("Error! ....");

Sellest semestrist: trükime veateated stderr  standardvoogu: fprintf(stderr, "Error! ...");

Teooriakild: Aluskoodis uued makrod

Lugedes aluskoodi märkad, et selles on kasutusel __FUNCTION__  nimeline sõne. Selle sisu lahendatakse ära kompileerimise käigus – ära seda ise käsitsi ümber kirjuta! Alates C99 standardist võib selle asemel kirjutada ka __func__ .

Täiendavalt kasutatakse sageli veel kahte makrot:

  • __LINE__ väljastab koodirea numbri, millel makro asub
  • __FILE__  väljastab koodifaili nime, milles makro asub

Tegu on levinud võtetega koodi silumiseks. Näiteks saame kirjutada:

Nii on lihtne jälgida mis failis, mis funktsioonis ja millisel real tekkis viga.

Nõuded
  • Ehita oma lahendus aluskoodile
  • Aluskoodis on koodilõigud, mille lõpetamine on jäetud sinu ülesandeks. Need on märgitud koodis kommentaariga TODO .
  • Loo kaks funktsiooni vastavalt aluskoodis olevatele kommentaaridele. Ühes neist tuleb väärtused kasutajalt küsida ja salvestada ning teises funktsioonis tuleb need väärtused omavahel vahetada. Mõlemad funktsioonid toetuvad viitade kasutamisele.
  • Trüki välja muutujate mäluaadressid kolmes erinevas kohas
    1. main()  funktsioonis – näita kus muutujate väärtused hoiustatud on
    2. Lugemise funktsioonis – näita kuhu kohta loetavad väärtused salvestatakse
    3. Vahetamise funktsioonis – näita kus asuvad need väärtused mida parasjagu vahetad.
  • Kaitsmisel selgita mis on kuvatud väärtuste puhul oluline!
Testimine

Ülesanne 2 osa 1 [W01-2]: Viidad ja massiivid

Teise ülesande eesmärgiks on tutvuda viitade ja massiivide koos kasutamisega. Lisaks harjutame ka viidaaritmeetikat ja meenutame eelmisel semestril õpitud failide ning käsureaargumentide kasutamist.

Programm vajab kasutamiseks andmefaili, mis sisaldab täisarve. Andmefail loo ise! Arvud võivad olla eraldatud kas tühikute või reavahetustega.

Nõuded

Loo programm, mis

  • Loeb failist 10 täisarvu ja salvestab need massiivi
  • Faili nimi loetakse käsureaargumendina
  • Kuvab massiivi mäluaadress main() funktsioonis
  • Väljastab loetud arvud ning nende mäluaadressid
  • Leiab minimaalse ja maksimaalse arvu massiivist

Kehtivad kitsendused

  • Ülesande vältel ei tohi massiivi indekseerimiseks kasutada kantsulge []  (massiivi deklareerimisel see piirang ei kehti). Rakenda kõigis funktsioonides indekseerimiseks viida-aritmeetikat.
  • Programmi töö katkestatakse juhul, kui faili ei eksisteeri või failist ei õnnestunud täisarve lugeda – nt failis oli midagi muud.
  • Sulle on ette antud loetelu funktsioonidest, mis tuleb realiseerida
  • Kõik ülesannete nõuetes olevad funktsioonid tuleb välja kutsuda main()  funktsioonis
  • Ülesande tulemusena leitavad minimaalne ja maksimaalne väärtus väljastatakse main()  funktsioonis.
  • Kõik veateated tuleb kirjutada stderr  voogu.

Loo järgnevad funktsioonid

  • Funktsioon, mis loeb failist 10 arvu ning salvestab need massiivi
    • Valikuline: Soovi korral võid lisada massiivi liikmete mäluaadresside väljatrüki siia funktsiooni, et võrrelda neid aadressidega teistes funktsioonides.
    • Parameetriteks: massiiv, massiivi lubatud suurus, faili nimi
    • Tagastus: mitu arvu failist loeti
    • Funktsiooni käigus on oluline vältida rohkemate numbrite lugemist, kui massiivi mahub.
    • Järgnevalt on sulle antud ka funktsiooni osaline lahendus, täida puuduvad osad ise.
    • Vihje: Funktsiooni väljakutse loetavuse huvides on soovitatav käsureaargument eraldi viita salvestada, näiteks järgnevalt
  • Funktsioon, mis väljastab kõik loetud arvud ning nende asukoha mälus.
    • Parameetriteks massiivi nimi ja massiivi suurus!
  • Funktsioon, mis leiab korraga nii minimaalse kui maksimaalse arvu massiivist
    • Seda funktsiooni tohid välja kutsuda vaid ühe korra, mõlemad tulemused tuleb leida korraga
    • Funktsioon ei tohi tagastada midagi (st tagastuse tüüp on  void ).
    • Võid eeldada, et eksisteerib vaid üks vähim ja üks suurim arv.
    • Kasuta eelnevas ülesandes tutvutud viitade omadustega minimaalse ja maksimaalse väärtuse main()  funkitsiooni saamiseks. Funktsioon ei tohi ise tulemusi väljastada!
Testimine

Baasülesande testimisel on neli võimalikku tulemust

  1. Käsureaargumendid puuduvad, programm annab veateate ja sulgub
  2. Fail ei avane, programm annab veateate ja sulgub
  3. Failis ei ole ühtegi täisarvu, programm annab veateate ja sulgub
  4. Failis on vähemalt mingi kogus täisarve, maksimaalselt 10 tükki loetakse ja väljastatakse koos leitud minimaalse ja maksimaalse väärtusega.

Ülesanne 2 osa 2 [W01-3]: Massiivi tõlgendamine

Selle ülesande eesmärk on veenduda, et mõistad korrektselt ideed “massiiv on käsitletav kui viit esimesele massiivi liikmele”.

Nõuded
  • Loo (või korduvkasuta 😉 ) funktsioon, mis suudaks massiivist välja trükkida n numbrit ja mäluaadressi.
  • Funktsioonil tohib olla vaid 2 parameetrit.
  • Funktsioon peab olema ehitatud sedasi, et see suudaks väljastada ükskõik millise etteantud massiivi
  • Näitamaks, et su funktsioon on tehtud õigesti (ning veelgi enam, tõestamaks, et mõistsid teemat õigesti), kutsu loodavat funktsiooni välja 3 korda sedasi, et
    • esimene kord trükitakse välja kogu massiiv
    • teine kord trükitakse välja vaid elemendid 0 – 4
    • kolmas kord trükitakse välja elemendid 3 – 7
    • Elementide vahemike määramisel võid kasutada maagilisi arve selles ülesandes
  • NB! Mis juhtub, kui failist loeti väiksem kogus arve?

Vihje: Mõtle enne hoolikalt kui hakkad funktsiooni koostama! Ülesande eesmärk on veenduda, et saad massiivi ja viida omavahelisest seosest õigesti aru.  Ülesande eesmärk ei ole luua ülimalt keerulist või kavalat lahendust!

Testimine

Selle ülesande puhul on kaks võimalikku tulemust

  1. Massiiv on piisavalt pikk, programm väljastab soovitud tulemuse.
  2. Massiivis ei ole piisavalt liikmeid, programm annab veateate.

Järgnevas näites on ootuspärane väljund, kui massiiv on piisavalt pikk

Lisaülesanne [W01-4]: MinMax koos aadressidega

Selles ülesandes taasloome teise ülesande esimeses osas loodud ekstreemväärtuste leidmise funktsiooni. Teeme muudatuse mis lubab meil lisaks väärtusele saada ka asukoha, jällegi kasutades viitade omadusi

Nõuded
  • Loo uus funktsioon või muuda olemasolevat sedasi, et leida minimaalse ja maksimaalse arvu asukoht. Funktsioon peab leidma mõlema asukoha ühe käivitusega.
  • Funktsioon ei tohi tagastada midagi (st tagastuse tüüp on  void ).
  • Funktsioonil tohib olla täpselt 4 parameetrit
    • Massiiv arvudega
    • Massiivi pikkus
    • 2 viita või topeltviita – mõtle välja mis nendes hoida sobiks!
  • Trüki välja järgnevad tulemused main funktsioonis
    • Minimaalne ja maksimaalne arv
    • Minimaalse ja maksimaalse arvu aadressid massiivis
    • Minimaalse ja maksimaalse arvu indeksid massiivis
    • NB! Aadressi ja indeksi leidmiseks ei tohi sa täiendavalt massiivi uuesti läbi käia! Tulemuste saamiseks tuleb kasutada viitade omadusi ja arvutada vastused funktsioonist saadavate tulemuste põhjal!
Testimine

Lisaülesande lahendusena oodatav väljund

Pärast seda tundi peaksid

  • mõistma aine nõudeid, sh kuidas hinne kujuneb
  • teadma, mis on viit
  • oskama mõista mäluaadressi iseloomu
  • tegema vahet virtuaalsel ja füüsilisel aadressil
  • teadma, mis mõjutab mäluaadressi suurust
  • teadma täiendavast mäluvajadusest ja keerukusest mis tuleb viitade otsese kasutamisega
  • oskama viitmuutujat deklareerida
  • teadma, kuidas viitadega koodi kirjutada lähtuvalt koodimisstiilist
  • teadma, mis tähtsus on viida andmetüübil
  • teadma, mis on  NULL-viit ja kus seda kasutatakse
  • teadma mõningaid valdkondi, kus viitasid kasutatakse
  • teadma ja oskama kasutada viida-aritmeetikat
  • mõistma scanf argumente ja kuidas viidad ning aadressid siin mängu tulevad
  • mõistma, miks me eelmine semester ütlesime, et massiivi edastamisel manipuleerime originaalandmeid ning muutujate puhul mitte
  • osksama muutujate mäluaadresse funktsioonidesse edastada
  • oskama mitme muutuja väärtust ühe funktsiooni sees manipuleerida kasutades viitasid
  • mõistma topeltviida ideed
  • oskama kasutada tingimuslausete koostamiseks kolmikoperaatorit
  • oskama kasutada GCC makrosid faili ja funktsiooni nime ning rea numbri leidmiseks
  • teadma millal ja kuidas kasutada stderr standardvoogu

Täiendavat materjali