(H) Liikennevaloissa

Tavoite: Opin dynaamista muistinhallintaa ja osoittimien käsittelemistä.

Ohjeita: Hae ohjelmakoodipohja: templates/08/traffic/ -> student/08/traffic/.

Liikennevaloissa seisovat ajoneuvot voidaan esittää jonona, josta ensiksi tullut ajoneuvo poistuu ensimmäisenä ja jossa jonoon tulevat asettuvat viimeisen ajoneuvon perään. Jono on siis tietorakenne, jossa alkioita voidaan lisätä loppuun ja poistaa alusta. Usein näiden operaatioiden nimet ovat enqueue ja dequeue.

Koska harjoittelemme dynaamista muistinhallintaa, tehtävänäsi on toteuttaa tarvittava luokka ilman, että käytät STL:n säiliöitä tai C++:n taulukkoa.

Tarvittavat osatoiminnot

Toteutettavan ohjelman liikennevalot toimivat seuraavasti. Luokalla on kokonaislukuattribuutti cycle_, joka kertoo, kuinka monta ajoneuvoa enintään pääsee samoilla vihreillä läpi. Tämän attribuutin arvo annetaan rakentajalle parametrina, mutta sitä voi myöhemmin muuttaa.

Jos liikennevalo näyttää punaista, jonon perään voidaan lisätä uusia ajoneuvoja odottamaan. Jos liikennevalo näyttää vihreää, uudet ajoneuvot eivät jää odottamaan, vaan pääsevät suoraan valoista läpi. Niitä ei siis lisätä jonoon lainkaan.

Jonosta voi poistaa ajoneuvoja vain silloin, kun liikennevalo näyttää vihreää. Jos poistamista yritetään punaisten valojen aikana, ei tapahdu mitään.

Liikennevalojen väriä voi vaihtaa punaisesta vihreäksi ja päinvastoin. (Keltaista ei ole, sillä siitä ei aiheutuisi mitään toimintoja.) Jos liikennevalojen uusi väri on vihreä (eli väri vaihtui punaisesta vihreäksi), päästetään enintään attribuutin cycle_ verran ajoneuvoja menemään. (Jos jonossa oli vähemmän ajoneuvoja kuin cycle_, päästetään vain nämä.) Lisäksi tulostetaan niiden ajoneuvojen rekisterinumerot, jotka pääsivät samoilla vihreillä eteenpäin. Kun riittävä määrä ajoneuvoja on mennyt, valo vaihtuu takaisin punaiseksi (itsestään eli ilman, että käyttäjä vaihtaisi sen).

Jos liikennevalojen uusi väri on punainen, jonossa ei tapahdu muutoksia. Tällöin tulostetaan vain liikennevalojen tilanne. Samoin käy, jos jono oli alun perin tyhjä, tällöinkin tulostetaan vain tilanne.

Liikennevalojen tilanne voidaan tulostaa seuraavasti. Ensin tulostetaan, palaako vihreä vai punainen valoa, ja sen jälkeen kaksoispiste. Lopuksi tulostetaan niiden ajoneuvojen rekisterinumerot, jotka odottavat jonossa. Jos jono on tyhjä, tulostetaan tieto siitä.

Ohjelma kokonaisuudessaan

Liikennevalojen ajoneuvojonoja kuvaavalla luokalla on julkiset metodit enqueue, switch_light, reset_cycle ja print, joiden toiminta käy ilmi alla olevasta esimerkistä. Pääohjelmassa pyörii ikuinen silmukka, jossa käyttäjä voi antaa komentoja, joiden vaikutus näkyy myös alla olevassa esimerkissä:

Current cycle is 3, i.e. at most 3 vehicles can pass during the same green period
(a)dd, (p)rint, (s)witch light, (r)eset cycle, (q)uit: a
  Input a register number: IV-10

(a)dd, (p)rint, (s)witch light, (r)eset cycle, (q)uit: a
  Input a register number: IIT-896

(a)dd, (p)rint, (s)witch light, (r)eset cycle, (q)uit: a
  Input a register number: 313

(a)dd, (p)rint, (s)witch light, (r)eset cycle, (q)uit: a
  Input a register number: ABC-111

(a)dd, (p)rint, (s)witch light, (r)eset cycle, (q)uit: p
RED: Vehicle(s) IV-10 IIT-896 313 ABC-111 waiting in traffic lights

(a)dd, (p)rint, (s)witch light, (r)eset cycle, (q)uit: s
GREEN: Vehicle(s) IV-10 IIT-896 313 can go on

(a)dd, (p)rint, (s)witch light, (r)eset cycle, (q)uit: p
RED: Vehicle(s) ABC-111 waiting in traffic lights

(a)dd, (p)rint, (s)witch light, (r)eset cycle, (q)uit: s
GREEN: Vehicle(s) ABC-111 can go on

(a)dd, (p)rint, (s)witch light, (r)eset cycle, (q)uit: p
RED: No vehicles waiting in traffic lights

(a)dd, (p)rint, (s)witch light, (r)eset cycle, (q)uit: s
GREEN: No vehicles waiting in traffic lights

(a)dd, (p)rint, (s)witch light, (r)eset cycle, (q)uit: s
RED: No vehicles waiting in traffic lights

(a)dd, (p)rint, (s)witch light, (r)eset cycle, (q)uit: s
GREEN: No vehicles waiting in traffic lights

(a)dd, (p)rint, (s)witch light, (r)eset cycle, (q)uit: a
  Input a register number: 313
GREEN: The vehicle 313 need not stop to wait

(a)dd, (p)rint, (s)witch light, (r)eset cycle, (q)uit: p
GREEN: No vehicles waiting in traffic lights

(a)dd, (p)rint, (s)witch light, (r)eset cycle, (q)uit: r
  Input a new amount for cycle: 2

(a)dd, (p)rint, (s)witch light, (r)eset cycle, (q)uit: q

Yllä olevan esimerkkiajon vaiheet on kuvattu alla olevassa kuvasarjassa. Aloitetaan siitä tilanteesta, kun käyttäjä on lisännyt neljä ajoneuvoa.

Neljä auto pysähtyneenä liikennevaloihin

Seuraavaksi käyttäjä vaihtaa valot vihreiksi,

Valot vaihdettu vihreiksi, mutta autot eivät ole vielä ehtineet liikkua

mikä tarkoittaa, että kolme ensimmäistä ajoneuvoa pääsee jatkamaan matkaansa. Tämän jälkeen valot vaihtuvat punaisiksi automaattisesti (ilman että käyttäjä antaa siitä komennon).

Valot vaihtuneet punaisiksi automaattisesti

Sitten käyttäjä antaa komennon valojen vaihtumisesta, jolloin väri vaihtuu punaisesta vihreäksi.

Valot vaihdettu vihreiksi, mutta auto ei ole vielä ehtinyt lähteä liikkeelle

Tämä tarkoittaa, että ainoa valoissa oleva ajoneuvo pääsee jatkamaan matkamaan matkaansa, minkä jälkeen väri vaihtuu automaattisesti punaiseksi.

Valot vaihtuneet punaisiksi, mutta autoja ei ole tullut lisää

Tämän jälkeen esimerkkisuorituksessa valojen väriä vaihdellaan, mutta tilanne ei muuten muutu, koska valoissa ei ole enää ajoneuvoja. Lopulta kun valot näyttävät vihreää, käyttäjä lisää yhden ajoneuvon (rekisterinumeroltaan 313), mutta sitä ei lisätä jonoon, vaan se jatkaa suoraan matkaansa.

Automaattitarkastus testaa toteuttamasi luokan toimintaa ilman pääohjelmaa, eli tarkastin ei välitä siitä, mitä omassa pääohjelmassasi tehdään. Kannattaa kuitenkin ehkä pitää osa alkuperäisistä testeistä tallella, että voit vertailla niidenkin tulosteita yllä olevaan mallitulosteeseen.

Vinkkejä tehtävän tekemiseen:

  • Kannattaa toteuttaa myös (yksityinen) metodi dequeue, joka poistaa jonosta yhden ajoneuvon mikäli mahdollista (eli jos valo on vihreänä). Metodi switch_light voi sitten kutsua dequeue-metodia sopivan määrän kertoja.
  • Toteuta aluksi vain kaksi välttämättömintä metodia (enqueue ja print) ja kommentoi pääohjelmasta pois kaikkien muiden metodien kutsut. Tässä tarkoituksessa useamman rivin kommentti /* tämä osa on kommentoitu pois */ on kätevä.
  • Muista jokaista operaatiota toteuttaessasi miettiä, mitä kaikkia tapauksia linkitetyn tietorakenteen käsittelemisessä pitää ottaa huomioon (edellisen materiaaliosion yhteenveto).
  • Automaattitestit testaavat myös dynaamisen muistinhallinnan käyttöä, ohjelma ei siis saa esimerkiksi jättää varattua muistia vapauttamatta. Tämän testaamisessa käytetetään valgrind-työkalua, josta kerrotaan seuraavalla kierroksella.

A+ esittää tässä kohdassa tehtävän palautuslomakkeen.