Arvutiteaduse instituut
  1. Kursused
  2. 2024/25 kevad
  3. Programmeerimine keeles C++ (LTAT.03.025)
EN
Logi sisse

Programmeerimine keeles C++ 2024/25 kevad

  • Pealeht
  • 1. Muutujad ja andmetüübid
  • 2. Keele põhikonstruktsioonid I
  • 3. Keele põhikonstruktsioonid II
  • 4. Klass, struktuur, mallid
  • 5. Dünaamiline mäluhaldus I
  • 6. Dünaamiline mäluhaldus II
6 Dünaamiline mäluhaldus II
6.1 Kodutöö
6.2 Harjutused
6.3 Videolingid
  • 7. Kontrolltöö 1

Seitsmendal nädalal toimub 1. kontrolltöö

1. kontrolltöö näidis on Moodles

  • 8. Dünaamiline mäluhaldus III
  • 9. STL andmestruktuurid I
  • 10. STL andmestruktuurid II
  • 11. OOP I Klassid
  • 12. OOP II Pärilus ja polümorfism
  • 13. Erindite töötlemine
  • 14. Täiendavad teemad
  • 15. Kontrolltöö 2

Viieteistkümnendal nädalal toimub 2. kontrolltöö

2. kontrolltöö näidis on Moodles

  • 16. Projekti esitlus
  • Mõned viited - vajalikud kaaslased
  • Vanad materjalid
  • Juhendid
  • Viited

Kodused ülesanded

Esitada on vaja failid mvector.h, hadron.h, hadron.cpp, rgb.h, rgb.cpp.

Kodutöö nimede ja funktsioonide valideerimiseks kasuta järgnevat main.cpp faili.

template <typename T>
concept rgbKorrektne = requires(T *rgb_ptr) {
  { new_RGB() } -> std::same_as<T *>;
  { kustuta_RGB(rgb_ptr) };
  { valge_RGB(rgb_ptr) };
};

static_assert(rgbKorrektne<struct RGB>, "RGB funktsioonid katki");

template <typename T>
concept mVectorKorrektne = requires(mVector<T> v) {
  { mVector<T>{} };
  { v.push_back(T{}) };
  { v.size() } -> std::same_as<size_t>;
  { v.capacity() } -> std::same_as<size_t>;
  { v.pop() } -> std::same_as<T>;
  { v.pop(54) } -> std::same_as<T>;
  { v[42] } -> std::same_as<T &>;
  { v.data() } -> std::same_as<T *>;
};

static_assert(mVectorKorrektne<int>, "Vektor katki");

template <typename FilenameT>
concept loeEnergiatPtrKorrektne =
    requires(FilenameT filename, size_t len, double *data) {
      { loe_osakesed(filename, &len) } -> std::same_as<double *>;
      { yle_l2vendi(data, len, 7E12) } -> std::same_as<size_t>;
    };

static_assert(loeEnergiatPtrKorrektne<std::string>,
              "energia lugemine viidaga katki");

template <typename FilenameT, typename T>
concept loeEnergiatVectorKorrektne =
    requires(FilenameT filename, mVector<T> v) {
      { loe_osakesed(filename) } -> std::same_as<mVector<T>>;
      { on_vahemikus(v, 7E12, 10E12) } -> std::same_as<mVector<T>>;
    };

static_assert(loeEnergiatVectorKorrektne<std::string, double>,
              "energia lugemine vektoriga katki");

int main() { return 0; }

1. Omatehtud vektor

Selle ülesande lahendus paiguta faili mvector.h.

Loo enda std::vector analoog. Klassimalli nimeks on mVector. Malliparameetriks on vektoris hoitavate elementide tüüp. Eeskujuna vaata Microsoft STL selgitust. Vektori elemente hoia massiivis, mis asub kuhjamälus. Massiivi suurust tuleb suurendada ja vähendada vastavalt vajadusele (abiks võib võtta teise massiivi). Massiivi suurendamiseks või vähendamiseks on mõistlik teha eraldi funktsioonid. Massiivi elementidele juurdepääsuks kasuta kolme viita (pointer) analoogiliselt Microsoft STL kirjeldusele.

Klassimallis peavad olema järgmised komponendid:

  • mVector()
    • Vaikekonstruktor. Algväärtustab kõik muutujad (kõik viidad nullptr).
  • void push_back(T el)
    • Lisab parameetrina antud elemendi vektori lõppu. Kui massiiv on tühi, luuakse kuhjamällu üheelemendiline massiiv ja element paigutatakse sinna. Kui massiivis on juba elemente, kuid massiiv on täis, siis kahekordistatakse massiivile eraldatud ruumi (elementide arvu). Mõistlik on ruumi suurendamiseks luua eraldi funktsioon.
  • size_t size()
    • Tagastab vektoris olevate elementide arvu.
  • size_t capacity()
    • Tagastab massiivi jaoks hõivatud mälu suuruse elementide arvuna.
  • T pop()
    • Tagastab ja eemaldab vektori viimase elemendi.
  • T pop(size_t i)
    • Tagastab ja eemaldab kohal i oleva elemendi. Järgmised elemendid nihutatakse ühe koha võrra tagasi.
    • Mõlema pop funktsiooni korral: kui massiivis on elemente vähem kui veerand mahutavusest, vabastatakse mälu poole massiivi mahutavuse ulatuses. Mõistlik on ruumi vähendamiseks luua eraldi funktsioon.
  • T& operator[]
    • Tagastab viite (reference) antud indeksil olevale elemendile.
  • T* data()
    • Tagastab viida (pointer) vektori esimesele elemendile.
  • void reserve(size_t)
    • Ruumi reserveerimine size_t ulatuses. See võib tähendada ka ruumi vähendamist.
  • void clear()
    • vektori tühjendamine (ja viidad nullptr-ks)

Näiteks, testkoodi

cout << format("Lisan 10 miljonit täisarvu.\n");
mVector<int> a;
for (int i{0}; i < 10000000; i++) {
    a.push_back(i);
}
cout << format("capacity: {}; size: {}\n", a.capacity(), a.size());
cout << format("Eemaldan (pop) 10 miljonit täisarvu.\n");
for (int i{0}; i < 10000000; i++) {
    a.pop();
}
cout << format("capacity: {}; size: {}", a.capacity(), a.size());

tulemusel kuvatakse ekraanile

Lisan 10 miljonit täisarvu.
capacity: 16777216; size: 10000000
Eemaldan (pop) 10 miljonit täisarvu.
capacity: 0; size: 0

2. RGB

Selle ülesande lahendus paiguta failidesse rgb.h ja rgb.cpp.

Juku renoveerib kodus oma tuba ja tahab kõik tuled muuta kaugjuhitavaks. Sel eesmärgil kavatseb ta ise valmis kirjutada serveri, mis tulesid juhib. Renoveerimine on veel pooleli ja Juku pole kindel, mis värvi tuled täpsemalt tulevad.

Loo struktuur RGB kolme täisarvu (lõigus 0-255) esitamiseks. Iga arv esitab ühte värvi. Värvide jaoks vali sobiv andmetüüp.

Lisaks struktuurile loo kolm funktsiooni:

  • RGB* new_RGB()
    • Loob uue RGB struktuuri koos algväärtustamisega kuhjamällu ja tagastab selle viida.
  • void kustuta_RGB()
    • Nullib RGB värvid ja ei tagasta midagi.
  • void valge_RGB()
    • Seab kõik värvid maksimumi ja ei tagasta midagi.

Näiteks, testkoodi (siin värvide nimed on r, g ja b)

RGB *ptr = new_RGB();
cout << format("r: {} g: {} b: {}\n", ptr->r, ptr->g, ptr->b);
valge_RGB(ptr);
cout << format("r: {} g: {} b: {}\n", ptr->r, ptr->g, ptr->b);
kustuta_RGB(ptr);
cout << format("r: {} g: {} b: {}\n", ptr->r, ptr->g, ptr->b);
delete ptr;

tulemusel kuvatakse ekraanile

r: 0 g: 0 b: 0
r: 255 g: 255 b: 255
r: 0 g: 0 b: 0

3. Suur Hadroni Põrguti

Selle ülesande lahendus paiguta failidesse hadron.h ja hadron.cpp.

Suur Hadronite Põrguti on Šveitsis asuv osakestekiirendi. Osakestele antakse suur energia ja siis need põrgatatakse omavahel kokku. Kokkupõrgete tagajärgi uurivad teadlased. Osakeste energiad on failis osakesed.txt. Faili esimesel real on osakeste arv. Igal järgneval real on ühe osakese energia elektronvoltides ujukomaarvuna. Fail on kättesaadav allpool. Faili suurus on umbes 20 MB. Reaalselt genereeris Suur Hadroni Põrguti testide jooksul 600 petabaiti infot.

Loo funktsioonid, et analüüsida kokkupõrgete tagajärjel saadud osakeste energiaid.

  • double* loe_osakesed(string failinimi, size_t* pikkus)
    • Funktsiooni parameetriteks on faili nimi ja viit elementide arvule (pöördumisel 0). Funktsioon loeb sellesse osakeste arvu faili esimesest reast. Funktsioon loob kuhjamällu ujukomaarvude massiivi, loeb failist energiad loodud massiivi ja tagastab viida massiivile. Kui faili ei eksisteeri, tagastab funktsioon nullptr.
  • size_t yle_l2vendi(double* andmed, size_t pikkus, double l2vend)
    • Funktsioon tagastab nende osakeste arvu, mille energia ületab etteantud lävendit.

Näiteks, testkoodi

size_t len{};
double *data = loe_osakesed("osakesed.txt", &len);
cout << format("Osakeste arv: {}\n", len);
for (int i{}; i < 5; i++) {
    cout << format("Osake nr {}: {}\n", i, data[i]);
}
int yle_avg = yle_l2vendi(data, len, 7);
int yle_max = yle_l2vendi(data, len, 10);
cout << format("Üle 7 TeV: {}\n", yle_avg);
cout << format("Üle 10 TeV: {}\n", yle_max);
cout << format("Kustutan andmed");
delete[] data;

tulemusel kuvatakse ekraanile

Osakeste arv: 2204598
Osake nr 0: 11.727679
Osake nr 1: 0.481038
Osake nr 2: 6.05704
Osake nr 3: 8.604874
Osake nr 4: 6.862579
Üle 7 TeV: 1110607
Üle 10 TeV: 634209
Kustutan andmed

osakesed.txt

4. Suur Hadroni Põrguti vektoriga

Selle ülesande lahendus paiguta samuti failidesse hadron.h ja hadron.cpp.

Loo Suure Hadroni Põrguti ülesande versioon, mis kasutab esimeses ülesandes loodud vektorit mVector.

Loo järgmised funktsioonid:

  • mVector<double> loe_osakesed(string file_name)
    • Failis esimesel real on osakeste arv. Funktsioon loeb failist alates teisest reast osakeste energiad vektorisse. Kuna osakeste arv on ette teada, siis on mõistlik teha klassimalli mVector juurde funktsioon mälu hõivamiseks etteantud arvu elementide jaoks.
  • mVector<double> on_vahemikus( mVector<double>& v, double min, double max)
    • Funktsioon tagastab vektori nende energiatega, mis jäävad etteantud vahemikku (otspunktid ei ole kaasa arvatud).

Näiteks, testkoodi

mVector<double> v{loe_osakesed("osakesed.txt")};
cout << format("capacity: {}; size: {}\n", v.capacity(), v.size());
mVector<double> avg{on_vahemikus(v, 7, 10)};
mVector<double> min{on_vahemikus(v, 0, 7)};
cout << format("7-10 : {}; 0-7 : {}\n", avg.size(), min.size());

tulemusel kuvatakse ekraanile

capacity: 2204598; size: 2204598
7-10 : 476398; 0-7 : 1093991
  • Arvutiteaduse instituut
  • Loodus- ja täppisteaduste valdkond
  • Tartu Ülikool
Tehniliste probleemide või küsimuste korral kirjuta:

Kursuse sisu ja korralduslike küsimustega pöörduge kursuse korraldajate poole.
Õppematerjalide varalised autoriõigused kuuluvad Tartu Ülikoolile. Õppematerjalide kasutamine on lubatud autoriõiguse seaduses ettenähtud teose vaba kasutamise eesmärkidel ja tingimustel. Õppematerjalide kasutamisel on kasutaja kohustatud viitama õppematerjalide autorile.
Õppematerjalide kasutamine muudel eesmärkidel on lubatud ainult Tartu Ülikooli eelneval kirjalikul nõusolekul.
Courses’i keskkonna kasutustingimused