diff --git a/ndl2/CMakeLists.txt b/ndl2/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..80a84408a9796406bc1f92fed6a55c863b571957 --- /dev/null +++ b/ndl2/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.30) +project(ndl2) + +set(CMAKE_CXX_STANDARD 23) + +add_executable(ndl2 main.cpp) diff --git a/ndl2/main.cpp b/ndl2/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..149532c9dcde6fa1716855a201b250c9e214ef20 --- /dev/null +++ b/ndl2/main.cpp @@ -0,0 +1,245 @@ +#include <iostream> +#include <sstream> + +// Proovi lahendada allolevad أ¼lesanded. Lahendusi vaatame pأµgusalt jأ¤rgmises praktikumis ja lahendused panen Git'i +// jأ¤rgmise nأ¤dala alguses. + +// 1. أœlesanne +// Kirjuta funktsioon, mis lأ¼hendab sأµnena antud inimese nime antud nأ¤idete pأµhjal. +// أ„ra kasuta klassi `std::stringstream` +// +// Nأ¤ide: +// lyhenda("Mari-Anne Lill") = "Lill M-A." +// lyhenda("Otto Triin Kaido Maastik") = "Maastik O. T. K." + +// ... + +// 2. أœlesanne +// Kirjuta funktsioon tagurpidi, mis keerab argumendina antud sأµnevektori sأµned tagurpidi. +// Seejأ¤rel keerab funktsioon vektori enda tagurpidi. Tagasta muudetud vektor. +// +// Nأ¤ide: +// tagurpidi({"auto", "koer"}) = {"reok", "otua"} + +// ... + +// 3. أœlesanne +// Kirjuta funktsioon, mis saab argumendiks sأµnedevektori ning kustutab sealt kأµik sأµned, mis sisaldavad +// teises argumendis saadud sأµne. S.t teine argument on kustutatava sأµne alamsأµne. Tagasta muudetud vektor. +// +// Nأ¤ide: +// kustuta({"tere", "auto", "koer"}, "er") = {"auto"} + +// ... + + +// Vأµid allolevad kommentaarid eemaldada, et nأ¤ha, millal mingit puhvrit suuremaks tehakse vأµi uus objekt luuakse +// Reeglina ei ole see hea praktika, aga saame pisut rohkem informatsiooni allokatsioonide kohta. +// Allokatsioone ja vأµtmesأµnu `new` ja `delete` vaatame tulevatel nأ¤dalatel. +// +// void *operator new(size_t size) { +// std::println("new({})", size); +// void *p = malloc(size); +// return p; +// } +// +// void operator delete(void *p) { +// std::println("delete()"); +// free(p); +// } + +// Lahkame seda funktsiooni tulevate nأ¤dalatel +template<typename Container> +void prindi(Container &c) { + std::cout << "["; + for (auto x : c) { + std::cout << x << ' '; + } + std::cout << "]\n"; + + // Kui sul tأ¶أ¶tab std::println, kasuta seda + // std::println("{:}", c); +} + +int main() { + { + // Loob tأ¼hja vektori, kus pole أ¼htegi elementi + // ega ruumi أ¼helegi elemendile + std::vector<int> vec; + + // vec[0] = 1; + // ^ Proovi seda rida jooksutada, see krahhib programmi + } + + { + // Loob tأ¼hja vektori, kus pole أ¼htegi telementi. + // (Liikme)funktsioon reserveerib vektoris ruumi 10 elemendile, kuid ei initsialiseeri أ¼htegi elementi. + std::vector<int> vec; + vec.reserve(10); + + // vec[0] = 1; + // ^ Kas siin on see rida OK? + } + + { + // Loob vektori, kus on ruumi 10 elemendile + // ning initsialiseerib need tavavأ¤أ¤rtusega + + std::vector<int> vec(10); + + // Loob vektori, aga elemendid on vأ¤أ¤rtustatakse vأ¤أ¤rtusega 1 + std::vector<int> vec1(10, 1); + } + + { + std::vector<int> vec(10); + + // Klassikaline for-tsأ¼kkel, kuidas elemente vأ¤أ¤rtustada + for (size_t i = 0; i < vec.size(); i++) { + vec[i] = 1; + } + + // Miks allolev for-of-tsأ¼kkel ei vأ¤أ¤rtusta elemente? + // Mis on tأ¼أ¼pi on muutuja `x`? + for (auto x : vec) { + x = 1; + } + + // Aga miks allolev for-of-tsأ¼kkel tأ¶أ¶tab? + for (auto &x : vec) { + x = 1; + } + } + + { + // Vahel on vektori konstrueerimisel vأµimalik أ¤ra jأ¤tta elementide tأ¼أ¼bid + // See on vأµimalik, kui konstrueerid vektori kohe elementidega + std::vector vec{1, 2, 3}; + + // vأµi kasutad konstruktorit, mis mأ¤أ¤rab algvأ¤أ¤rtuse + std::vector vec1(10, 0); + + // See on vأµimalik tأ¤nu CTAD feature'ile + // Seda vaatame tulevikus pأµhjalikumalt, aga vأµid uurida lأ¤hemalt: + // https://en.cppreference.com/w/cpp/language/class_template_argument_deduction + } + + { + // Miks selline vektori konstrueerimine on ebaefektiivne? + // Mأµtle, kuidas dأ¼naamilist vektorit implementeerida + // Paljud IDE-d peaksid tegema for-tsأ¼kli vأµi seal sees midagi kollaseks ja viitama, et selline + // koodilأµik on ebaefektiivne ja soovitab paremini. Vaata, kas ja kuidas sinu IDE seda teeb. + std::vector<int> vec; + for (int i = 0; i < 10; i++) { + vec.push_back(i); + } + } + + { + // Mأµtle, millal kasutada `std::vector` asemel `std::array` + // Vihje: `std::array` ei saa lisada rohkem elemente, kui esialgselt teise "klassi"-argumendiga defineeritud. + std::array<int, 4> arr{1, 2, 3, 4}; + + // NB! `std::array` suurus peab olema koodis kirjas kompileerimise ajal. + // Nأ¤iteks allolev koodilأµik ei ole korrektne: + // int n = 0; + // std::cin >> n; + // std::array<int, n> arr; + // Kui on vaja kasutaja sisendit kasutada konteineri suurusena, siis peame kasutama dأ¼naamilist konteinerit + } + + { + // Massiivi (`std::array`) saab ka konstrueerida ainult suurusega + // Mis vأ¤أ¤rtusega on antud massiivi elemendid? + std::array<int, 10> arr{}; + } + + { + // Allolev muutuja C-tأ¼أ¼pi sأµne, mis on tأ¼أ¼biga `const char*` + // Selle sأµne kasutamine on limiteeritud, uuri iseseisvalt, mis limitatsioonid sellel on. + // Kas saame sinna karaktereid lisada? + // Kas saame seal karaktereid asendada? + const char *s = "tere maailm!"; + + // C-tأ¼أ¼pi sأµne on sisuliselt karakterite massiiv, mis pannakse reeglina programmi binaari sisse. + // C-tأ¼أ¼pi sأµne peab standardi jأ¤rgi lأµppema karakteriga 0 (NULL-byte, '\0'), mis signaliseerib sأµne lأµpu. + // Funktsioonid, mille signatuuris on `const char*` eeldavad reeglina, et NULL-byte on olemas. + // See tأ¤hendab, et on juhte, et NULL-byte pole vaja. Mأµtle miks see vأµib olla kasulik. + // Erandjuhul + char s1[] = "tere maailm!"; + // on see sأµne pinumأ¤lul, millest rأ¤أ¤gime lأ¤hemalt tulevate nأ¤dalatel. + // Selles sأµnes saame muuta eraldiseisvaid karaktereid, aga ei saa sأµne suurust muuta. + + // Sأµne pikkuse saame funktsiooniga strlen (samuti eeldab sأµne lأµpus NULL-byte'i). Kuidas muidu sأµne lأµppu saada? + } + + { + // C-tأ¼أ¼pi massiivid on sarnased C-tأ¼أ¼pi sأµnedele, ainus erinevus on see, et neid ei panda reeglina* programmi + // binaari ning ei lأµppe NULL-byte'iga. + // Miks ei ole NULL-byte kasutamine vأµimalik massiiviga, aga on vأµimalik C-tأ¼أ¼pi sأµnega? + // Vihje: ASCII tabel + // NULL-byte'i puudumine tأ¤hendab kأ¼ll seda, et alati C-tأ¼أ¼pi massiivi edasi andmisel funktsiooni vmt + // peame kaasa andma ka selle pikkuse. + // Miks see on halb? Kas see vأµib olla ka hea? + + // Konstrueerib massiivi, kus on 3 elementi + int arr[] = {1, 2, 3}; + + // Uuri iseseisvalt, mida teevad jأ¤rgmised konstrueerimised + int arr1[3] = {1, 2, 3}; + int arr2[3] = {}; + int arr3[3] = {0}; + + // Miks see ei kompileeru? + // int arr4[]; + } + + { + // Aga kuidas ma leian sأµnest mingi karakteri vأµi alamsأµne? + + // Kasutame siin `using` konstruktsiooni, siis ei pea kogu aeg + // `std::string` vأ¤lja kirjutama. Pane tأ¤hele, et liigne selle kasutamine + // vأµib teha koodi loetavuse halvemaks. + // Uuri seda konstruktsiooni lأ¤hemalt: https://en.cppreference.com/w/cpp/keyword/using + using Str = std::string; + + Str s = "see on pikk sأµne ja siin on palju sأµnu"; + Str as = "tere"; + // char as = 's'; + if (const auto pos = s.find(as); pos == Str::npos) { + std::println("ei leidnud!"); + } else { + std::println("{} asub positsioonil {}, alles jأ¤أ¤b '{}'", as, pos, s.substr(pos)); + } + } + + { + // Miks on allolev kood reeglina* halb? + // Vihje: vأµib juhtuda, et teeme peaaegu iga += korral sأµnest koopia (Javas samuti) + // Huvi korral uuri konseptsiooni "short string" + std::string result; + for (int i = 0; i < 100; i++) { + result += "a"; + } + + // Jah, saame tegelt luua sama sأµne ka nii + std::string result1(100, 'a'); + // aga sageli أ¼lesanne seda ei vأµimalda + + // Seepأ¤rast on parem tsأ¼klites sأµnesid luues kasutada klassi `std::stringstream` + std::stringstream ss; + for (int i = 0; i < 100; i++) { + ss << "a"; + } + // ja saame konstrueerida sأµne jأ¤rgnevalt: + auto str = ss.str(); + // Jأ¤llegi hea koht, kus kasutada vأµtmesأµna `auto` + + // Klass `stringstream` vأµimaldab veel mitmeid muid asju, uuri iseseisvalt lأ¤hemalt. + if (ss.eof()) { + // ... + } + } + + return 0; +}