1 #include <iostream> // cin, cout 2 #include <fstream> // fájlkezelés 3 #include <string> // string (szövegek) 4 #include <vector> // vector adattípus 5 #include <algorithm> // max_element, sort 6 #include <iomanip> // setw, setprecision 7 #include <sstream> // stringstream 8 #include <utility> // pair 9 #include <map> // szótár (dict) adattípus 10 #include <set> // halmaz (set) adattípus 11 using namespace std; 12 13 struct kiadas 14 { 15 int ev, nev; 16 string eredet, leiras; 17 int peldany; 18 19 }; 20 21 vector<kiadas> F1_beolvas(string fajl) 22 { 23 cout << "--------------------------------------------------------------------------" << endl; 24 cout << "1. feladat - adatok beolvasása" << endl; 25 vector<kiadas> konyvek; 26 string sor; 27 ifstream fbe(fajl); // fbe.open(fajl); 28 while(getline(fbe, sor)) 29 { 30 stringstream ss(sor); // Olyan, mintha egy szöveges fájllal dolgoznánk, aminek a "sor" egy sora 31 string temp; // Ebbe kerülnek a "sor" egyes "mezői", amiket most pontosvessző választ el 32 kiadas k; // Lásd 13. sora a programnak. Ez egy struktúra, ami összefogja a mezőket 33 // Év (ev) 34 getline(ss, temp, ';'); // Egy mező beolvasása ss-ből (kvázi fájlból) 35 k.ev = stoi(temp); // Beolvasott mező elhelyezése a struktúrába. És ezt csináljuk 5-ször, mert öt mező van (lesz) 36 // Negyedév (nev) 37 getline(ss, temp, ';'); 38 k.nev = stoi(temp); // Ahol kell adatkonverziót végzünk. string --> int 39 // Eredet (eredet) 40 getline(ss, temp, ';'); 41 k.eredet = temp; 42 // Leírás (leiras) 43 getline(ss, temp, ';'); 44 k.leiras = temp; 45 // Példányszám (peldany) 46 getline(ss, temp, ';'); 47 k.peldany = stoi(temp); 48 49 konyvek.push_back(k); // A kész, feltöltött struktúra megy a vektorba 50 } 51 52 fbe.close(); 53 return konyvek; // A kész vektort adja vissza ez a függvény (F1_beolvasas) 54 } 55 56 void F2(vector<kiadas> k) 57 { 58 cout << "--------------------------------------------------------------------------" << endl; 59 cout << "2. feladat - Szerző" << endl << endl; 60 string szerzo; 61 cout << "Szerző: "; 62 int poz, db = 0; 63 getline(cin, szerzo); // getline használatára van szükség, mert szóköz is lehet a bemenetben 64 for(auto adatok: k) // Vektor bejárása struktútáról struktúrára 65 { 66 poz = adatok.leiras.find(szerzo); // find metódussal keressük a szerzőt a vektor aktuális struktúra-elemének "leiras" mezőjében 67 if(poz > -1) db++; // -1 értéket ad a find, ha nem találja, egyébként a találat helyét megadó karakterpozíciót 68 } 69 if(db > 0) // Ha volt találat a szerzőre, akkor... 70 cout << db << " könyvkiadás" << endl; 71 else 72 cout << "Nem adtak ki" << endl; 73 } 74 75 void F3(vector<kiadas> k) 76 { 77 cout << "--------------------------------------------------------------------------" << endl; 78 cout << "3. feladat - Legnagyobb példányszám" << endl << endl; 79 vector<kiadas> temp = k; // Az eredeti vektort meghagyjuk, egy átmeneti vektort (temp) rendezünk 80 // Struktúra-vektor rendezése PÉLDÁNYSZÁM szerint csökkenőbe... 81 sort(temp.begin(), temp.end(), [](const kiadas a, const kiadas b) {return a.peldany > b.peldany;}); // RENDEZÉS! Elsőre bonyolultnak látszik, de csak szokás kérdése... :) 82 int maxpeldany = temp[0].peldany; // a rendezés után a legelső vektor-elemben lesz a legnagyobb példányszám 83 cout << "Legnagyobb példányszám: " << maxpeldany; 84 int i = 0; 85 while(temp[i].peldany == maxpeldany) // Index (i) alapján addig "megyünk" a rendezett vektorban, amíg maximális példányszámok vannak... 86 i++; // Léptetjük a ciklusmagban az indexet... 87 cout << ", előfordult " << i << " alkalommal" << endl; // Ameddig léptünk, annyi maximális példányszámú kiadásunk van. 88 89 } 90 91 void F4(vector<kiadas> k) 92 { 93 cout << "--------------------------------------------------------------------------" << endl; 94 cout << "4. feladat - Első külföldi legalább 40000 példányszámmal" << endl << endl; 95 // Első külföldi legalább 40000 példány 96 // Év és azon belül negyedév szerint rendezettek az adatok 97 int i = 0; 98 while(!(k[i].eredet == "kf" && k[i].peldany >= 40000)) // "Sima" kiválasztás, mert biztosan van ilyen (Idézet a feladatleírásból: "Tudjuk, hogy volt ilyen könyv")! 99 i++;100 cout << k[i].ev << "/" << k[i].nev << ". " << k[i].leiras << endl;101 102 }103 104 void F5(vector<kiadas> k)105 {106 cout << "--------------------------------------------------------------------------" << endl;107 cout << "5. feladat - Statisztika" << endl << endl;108 // Két szótárat (map) hozunk létre. Egyet a magyar (ma), egyet a külföldi (kf) eredetű kiadásoknak.109 // A szótár deklarációja (map) a kulcs típusát és a kulcshoz tartozó elem típusát adja meg:110 // Így most a kulcs egy egész (az évszám, 2020-2023 között), az elemek pedig egész típusú adatpárok (pair) lesznek, darabszám és összes példányszám.111 // A pair-ben különböző típusú adatok is lehetnek, és az első adatra "first", a másodikra "second" néven hivatkozhatunk. Lásd lejjebb...112 map<int, pair<int, int>> stat_ma; // magyar kiadások statisztikai adatai113 stat_ma[2020] = {0, 0};114 stat_ma[2021] = {0, 0};115 stat_ma[2022] = {0, 0};116 stat_ma[2023] = {0, 0};117 map<int, pair<int, int>> stat_kf; // külföldi kiadások statisztikai adatai118 stat_kf[2020] = {0, 0};119 stat_kf[2021] = {0, 0};120 stat_kf[2022] = {0, 0};121 stat_kf[2023] = {0, 0};122 cout << "Ãv" << "\t" << "Magyar kiadás" << "\t" << "Magyar példányszám" << "\t" << "Külföldi kiadás" << "\t" << "Külföldi példányszám" << endl;123 for(auto sor: k) // Struktúra-vektor bejárása elemről elemre124 {125 if(sor.eredet == "ma") // Ha magyar eredtű kiadásról van szó, akkor...126 {127 stat_ma[sor.ev].first++; // A vektor aktuális elemében szereplő évszám lesz a szótár kulcsa, és az első (first) adatot növeljük (kiadás darabszáma),128 stat_ma[sor.ev].second += sor.peldany; // itt pedig a példányszámot (second) összegezzük129 }130 else // "kf" eredet esetén hasonlóan...131 {132 stat_kf[sor.ev].first++;133 stat_kf[sor.ev].second += sor.peldany;134 }135 136 }137 for(int i = 2020; i < 2024; i++) // A két szótár bejárása párhuzamosan kulcs segítségével. A kulcsok 2020 és 2023 között vannak...138 {139 cout << i << "\t\t" << stat_ma[i].first << "\t\t" << stat_ma[i].second << "\t\t";140 cout << stat_kf[i].first << "\t\t" << stat_kf[i].second << endl;141 }142 // HTML témától most eltekintenék, egy csomó cout...143 144 }145 146 void F6(vector<kiadas> k)147 {148 cout << "--------------------------------------------------------------------------" << endl;149 cout << "6. feladat - Újrakiadások (2, 40000)" << endl << endl;150 // Nagyon sokféle megoldás lehet. Nézzük a legegyszerűbb(?) megközelítést... --->151 // Az alap rendezettségét kihasználjuk az adatoknak152 153 set<string> leirasok; // Ebbe a halmazba kerül az a leírás, amit már néztünk154 155 for(int i = 0; i < k.size() - 1; i++) // Végig megyünk az adatsorokon (utolsó előttivel bezárólag...)156 {157 auto it = leirasok.find(k[i].leiras); // Rákeresünk a halmazban a leírásra158 if (it == leirasok.end()) // Ha még nincs a halmazban, akkor még nem néztük, tehát nézzük meg...159 {160 int db = 0; // Meglesz-e a legalább 2 db161 int peldanyszam = k[i].peldany; // aktuális példányszám, ehhez viszonyítjuk a későbbi kiadásokat162 for(int j = i + 1; j < k.size(); j++) // Ezzel a ciklussal az aktuális adatsort követő adatsorokon fogunk végigmenni...163 {164 // ha passzol a leírás és nagyobb a példányszám, akkor számoljuk a db-t165 if(k[j].leiras == k[i].leiras && k[j].peldany > peldanyszam) db++;166 }167 leirasok.insert(k[i].leiras); // Az aktuális leírás a halmazba kerül és így nem fogunk már foglalkozni vele.168 if(db >= 2) // Ha megvolt a legalább 2 darab nagyobb példányszám, akkor kiírjuk az eredeti leírást.169 {170 cout << k[i].leiras << endl;171 }172 }173 }174 }175 176 int main()177 {178 setlocale(LC_ALL, "hun");179 vector<kiadas> konyvek = F1_beolvas("kiadas2.txt"); // Célszerű az ékezetmentes forrást használni, ha nem akarunk egyéb problémákkal bajlódni...180 181 F2(konyvek);182 F3(konyvek);183 F4(konyvek);184 F5(konyvek);185 F6(konyvek);186 return 0;187 }