konyvek202505dk_C++.cpp


  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 adatai
113      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 adatai
118      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 elemre
124      {
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ük
129          }
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 adatoknak
152  
153      set<string> leirasok;   // Ebbe a halmazba kerül az a leí­rás, amit már néztünk
154  
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ásra
158          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 db
161              int peldanyszam = k[i].peldany;     // aktuális példányszám, ehhez viszonyí­tjuk a későbbi kiadásokat
162              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-t
165                  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  }