Gleeshoux

zadatak

Sep 18th, 2025
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.26 KB | None | 0 0
  1. // INDEKS IME PREZIME
  2. /**
  3.  * Napisati konkurentni C++ program koji iz ulazne datoteke "ulaz.txt" cita red po red, obradjuje ih po navedenim komandama i potom rezultat smesta u izlazne datoteke "ponovo3.txt" i "ostali.txt".
  4.  *
  5.  * U svakoj ulaznoj datoteci su podaci podeljeni delimiterom ',', i prate
  6.  * sledeci format:
  7.  *     1. broj: ID, unsigned int
  8.  *     2. broj: komanda, unsigned char, odreduje sta treba raditi sa brojevima
  9.  *                koji slede, pritom obratiti paznju da je komanda takodje BROJ
  10.  *     3+. brojevi: brojevi, double, koje treba obraditi po definiciji komande
  11.  *
  12.  * Ulazna datoteka je "ulaz.txt".
  13.  *
  14.  *
  15.  * Komande koje postoje su:
  16.  *     1) Pocevsi od nule svaki prvi razlomljeni broj dodati rezultatu a svaki drugi oduzeti
  17.  *     2) Naci minimum razlomljenih brojeva
  18.  *     3) Podrazumevati da su navedeni razlomljeni brojevi redom brojevi a,b,c,d; izracunati e gde je e = (a+2b+3b+4c) / 10
  19.  *     4) odbaciti brojeve deljive sa 7
  20.  *     5) sortirati uzlazno razlomljene brojeve
  21.  *
  22.  * U svakoj izlaznoj datoteci su podaci nakon transformacije upisani u jedan
  23.  * red, podeljeni delimiterom ',', i prate sledeci format:
  24.  *     1. broj: ID, neoznacen ceo broj
  25.  *     2+. brojevi: razlomljeni broj/evi dobijen/i transformacijom na osnovu
  26.  *                    komande
  27.  *
  28.  * Izlazni podaci se rasporedjuju u izlazne datoteke i to:
  29.  *     "ponovo3.txt" - rezultaati za unose sa neparnim dvocifrenim ID-om
  30.  *     "ostali.txt" - za sve ostale rezultate
  31.  *
  32.  * Treba napraviti jednu citac nit koja ce samo citati redove iz ulaznih
  33.  * datoteka, jednu stampac nit koja ce samo pisati izlazne podatke u izlazne
  34.  * datoteke i 9 niti radnika koji ce transformisati ulazne podatke u izlazne.
  35.  *
  36.  * NAPOMENE:
  37.  * Komanda 0 nikada nece postojati u ulaznim datotekama.
  38.  * Redove sa nepostojecim komandama napisati u datoteku "kanta.txt" tako da budu
  39.  * ispisani id, komanda i potom polazni brojevi podeljeni delimiterom ','.
  40. */
  41. #include <iostream>
  42. #include <thread>
  43. #include <mutex>
  44. #include <condition_variable>
  45. #include <vector>
  46. #include <queue>
  47. #include <fstream>
  48. #include <sstream>
  49. #include <cmath>
  50. #include <sstream>
  51.  
  52.  
  53. #define BROJ_RADNIKA 9
  54. using namespace std;
  55.  
  56. typedef struct izlazni_podaci {
  57.     // TODO
  58.     unsigned int id;
  59.     unsigned char komanda;
  60.     vector<double> NizBrojeva;
  61.     int KojiFajl;  // 0-Kanta 1- ponovo 2-ostali
  62. }iPodaci;
  63.  
  64. /** Klasa koja modeluje "postansko sanduce" izmedju citaca i radnika.
  65. */
  66. template<typename T>
  67. class UlazniPodaci {
  68. private:
  69.     // TODO dodati polja ako je potrebno
  70.     mutex podaci_mx;                      
  71.     queue<T> redovi;
  72.     condition_variable podaci_spremni;
  73.     bool kraj;
  74. public:
  75.     UlazniPodaci(): kraj(false){}
  76.  
  77.     void dodaj(T neobradjeni_podaci) {
  78.         // TODO
  79.     unique_lock<mutex> propusnica(podaci_mx);
  80.         redovi.push(neobradjeni_podaci);
  81.     }
  82.  
  83.     bool preuzmi(T &neobradjeni_podaci) {
  84.         // TODO
  85.     unique_lock<mutex> propusnica(podaci_mx);
  86.         while (daLiCekamPodatke()) {
  87.             podaci_spremni.wait(propusnica);
  88.         }
  89.  
  90.         if (jeLiKraj()) {
  91.             return false;  
  92.         }
  93.  
  94.         neobradjeni_podaci = redovi.front();
  95.         redovi.pop();
  96.         return true;
  97.     }
  98.        void objaviKraj() {
  99.         unique_lock<mutex> propusnica(podaci_mx);
  100.         kraj = true;
  101.         podaci_spremni.notify_all();
  102.     }
  103. private:
  104.     bool daLiCekamPodatke() {
  105.         return redovi.empty() && !kraj;
  106.     }
  107.  
  108.    
  109.     bool jeLiKraj() {
  110.         return redovi.empty() && kraj;
  111.     }
  112.     // TODO dodati jos neku metodu ako je potrebno
  113. };
  114.  
  115.  
  116. /** Klasa koja modeluje "postansko sanduce" izmedju radnika i pisaca.
  117. */
  118. template<typename T>
  119. class IzlazniPodaci {
  120. private:
  121.     mutex podaci_mx;                      
  122.     queue<T> IzlazniRed;
  123.     condition_variable podaci_spremni;
  124.     bool kraj;
  125.     int br_stvaralaca_podataka;
  126.    
  127. public:
  128.     IzlazniPodaci(): kraj(false), br_stvaralaca_podataka(0){}
  129.  
  130.     void dodaj(T obradjeni_podaci) {
  131.        
  132.         unique_lock<mutex> propusnica(podaci_mx);
  133.         IzlazniRed.push(obradjeni_podaci);
  134.     }
  135.  
  136.     bool preuzmi(T &obradjeni_podaci) {
  137.         // TODO
  138.         unique_lock<mutex> propusnica(podaci_mx);
  139.         while (daLiCekamPodatke()) {
  140.             podaci_spremni.wait(propusnica);
  141.         }
  142.  
  143.         if (jeLiKraj()) {
  144.             return false;
  145.         }
  146.  
  147.         obradjeni_podaci= IzlazniRed.front();
  148.         IzlazniRed.pop();
  149.         return true;
  150.     }
  151.  void prijavaStvaraocaPodataka() {
  152.         unique_lock<mutex> propusnica(podaci_mx);
  153.         br_stvaralaca_podataka++;
  154.     }
  155.  
  156.  
  157.     void odjavaStvaraocaPodataka() {
  158.         unique_lock<mutex> propusnica(podaci_mx);
  159.         br_stvaralaca_podataka--;
  160.         if (!br_stvaralaca_podataka) {  
  161.             kraj = true;
  162.             podaci_spremni.notify_one();  
  163.         }
  164.     }
  165.  
  166. private:
  167.    
  168.     bool daLiCekamPodatke() {
  169.         return IzlazniRed.empty() && !kraj;
  170.     }
  171.  
  172.    
  173.     bool jeLiKraj() {
  174.         return IzlazniRed.empty() && kraj;
  175.     }
  176.     // TODO dodati jos neku metodu ako je potrebno
  177. };
  178.  
  179.  
  180. /**
  181.  * Parsiranje reda iz ulazne datoteke
  182.  *   parametri:
  183.  *     - red_datoteke, sadrzaj jednog reda ulazne datoteke
  184.  *     - id, adresa gde ce biti upisan id procitan iz reda
  185.  *     - komanda, adresa gde ce biti upisan id komande procitan iz reda
  186.  *   vraca: kolekciju brojeva koje radnik treba da transformise po komandi
  187. */
  188.  
  189. vector<double> izdvoj_brojeve(const string red_datoteke, unsigned &id, unsigned char &komanda) {
  190.     istringstream red_datoteke_tok(red_datoteke);
  191.     vector<double> brojevi;
  192.     string broj;
  193.  
  194.     if (getline(red_datoteke_tok, broj, ','))
  195.         id = stoul(broj);
  196.  
  197.     if (getline(red_datoteke_tok, broj, ','))
  198.         komanda = stoul(broj);
  199.  
  200.     while (getline(red_datoteke_tok, broj, ','))
  201.         brojevi.push_back(stod(broj));
  202.  
  203.     return brojevi;
  204. }
  205.  
  206. /**
  207.  * Logika radnika - niti koje vrse transformaciju ulaznih podataka u izlazne
  208.  * podatke spremne za ispis.
  209. */
  210. void radnik_nit(UlazniPodaci<string> &ulaz, IzlazniPodaci<struct izlazni_podaci> &izlaz) {
  211.     // TODO
  212.     izlaz.prijavaStvaraocaPodataka();  //
  213.  
  214.     string red;
  215.     while (ulaz.preuzmi(red)) {
  216.        iPodaci Podatak;
  217.        Podatak.NizBrojeva=izdvoj_brojeve(red,Podatak.id,Podatak.komanda);
  218.        if(Podatak.id%2==1 && Podatak.id>=10)
  219.         Podatak.KojiFajl=1;
  220.        else if(Podatak.id%2==0)
  221.         Podatak.KojiFajl=2;
  222.        
  223.        
  224.        switch(Podatak.komanda){
  225.        
  226.           case 1:
  227.           {
  228.             double rezultat=0;
  229.             for(int i=0;i<Podatak.NizBrojeva.size();i++){
  230.                 if(i%2==0)
  231.                     rezultat += Podatak.NizBrojeva[i];
  232.                 else
  233.                     rezultat -= Podatak.NizBrojeva[i];
  234.                    
  235.             }
  236.             Podatak.NizBrojeva.clear();
  237.             Podatak.NizBrojeva.push_back(rezultat);
  238.         break;
  239.         }
  240.           case 2:
  241.           {
  242.             double min=Podatak.NizBrojeva[0];
  243.             for(int i=1;i<Podatak.NizBrojeva.size();i++){
  244.                 if(Podatak.NizBrojeva[i] < min ){
  245.                     min=Podatak.NizBrojeva[i];
  246.                 }
  247.             }
  248.         Podatak.NizBrojeva.clear();
  249.             Podatak.NizBrojeva.push_back(min);
  250.             break;
  251.         }
  252.          case 3:
  253.             {
  254.             double e;
  255.            
  256.         e = ( Podatak.NizBrojeva[0] + 2 * Podatak.NizBrojeva[1] + 3 * Podatak.NizBrojeva[1] + 4 * Podatak.NizBrojeva[2] ) / 10 ; //ne koristi se nigde d, verovatno greska u postavci
  257.             Podatak.NizBrojeva.clear();
  258.             Podatak.NizBrojeva.push_back(e);
  259.            
  260.         break;
  261.         }
  262.          case 4:{
  263.         vector<double>noviNiz;
  264.         string num;
  265.         for(int i=0;i<Podatak.NizBrojeva.size();i++){
  266.             if( (int)Podatak.NizBrojeva[i] % 7 == 0)
  267.                 noviNiz.push_back(Podatak.NizBrojeva[i]);
  268.        
  269.         }
  270.         Podatak.NizBrojeva.clear();
  271.         for(int i=0;i<noviNiz.size();i++)
  272.             Podatak.NizBrojeva.push_back(noviNiz[i]);
  273.        
  274.         break;
  275.         }
  276.          case 5:
  277.          {
  278.             double temp;
  279.         //bubble sort
  280.         for(int i=0;i<Podatak.NizBrojeva.size()-1;i++){
  281.             for(int j=i+1; j<Podatak.NizBrojeva.size();i++)
  282.                 if(Podatak.NizBrojeva[j]<Podatak.NizBrojeva[i]){
  283.                     temp = Podatak.NizBrojeva[j];
  284.                     Podatak.NizBrojeva[j]=Podatak.NizBrojeva[i];
  285.                     Podatak.NizBrojeva[i]=temp;
  286.                 }
  287.                
  288.         }
  289.          }
  290.      default:
  291.      {
  292.          Podatak.KojiFajl=0;
  293.          break;      
  294.          }
  295.        
  296.        }
  297.        
  298.        
  299.         izlaz.dodaj(Podatak);
  300.     }
  301.  
  302.     izlaz.odjavaStvaraocaPodataka();  
  303.    
  304.    
  305. }
  306.  
  307. /**
  308.  * Logika citaca - nit koja radi citanje iz ulazne datoteke i salje u ulaznu
  309.  * kolekciju za radnike
  310. */
  311. void citac_nit(UlazniPodaci<string> &ulaz) {
  312.     // TODO
  313.         string ime_ulazne_dat="ulaz.txt";
  314.         ifstream ulazna_dat(ime_ulazne_dat);
  315.         cout << "CITAC: Obradjujem datoteku. . . \"" << ime_ulazne_dat << "\"." << endl;
  316.         if(ulazna_dat.is_open()) {
  317.             string red_datoteke;
  318.             while(getline(ulazna_dat, red_datoteke)) {  // citanje datoteke red po red
  319.                 ulaz.dodaj(red_datoteke);
  320.             }
  321.  
  322.             ulazna_dat.close();
  323.         } else
  324.             cerr << "CITAC: Nisam mogao da otvorim datoteku \"" << ime_ulazne_dat << "\" za citanje!\n";
  325.    
  326.  
  327.     ulaz.objaviKraj();
  328. }
  329.  
  330. //serijalizacija
  331. string ToString(iPodaci podatak){
  332.   string result = to_string(podatak.id)+",";
  333.   string str;
  334.   if(podatak.KojiFajl==0)
  335.     result +=to_string(podatak.komanda)+",";
  336.  
  337.     if(podatak.NizBrojeva.size()){
  338.     str=podatak.NizBrojeva[0];
  339.     if(str!="0\0"){
  340.         str.erase ( str.find_last_not_of('0') + 1, std::string::npos );
  341.     str.erase ( str.find_last_not_of('.') + 1, std::string::npos );
  342.     }
  343.         result += str;
  344.         }
  345.     for (int i = 1; i < podatak.NizBrojeva.size(); ++i) {
  346.         str=podatak.NizBrojeva[i];
  347.         str.erase ( str.find_last_not_of('0') + 1, std::string::npos );
  348.     str.erase ( str.find_last_not_of('.') + 1, std::string::npos );
  349.         result += "," + str;
  350.     }
  351.     result+='\n';
  352.  return result;
  353.  
  354.     }
  355. /**
  356.  * Logika stampaca - nit koja radi pisanje u izlaznu datoteku podataka dobijenih
  357.  * od radnika
  358. */
  359.  
  360. void stampac_nit(IzlazniPodaci<struct izlazni_podaci> &izlaz) {
  361.     // TODO
  362.     ofstream parni_dat("parni.txt");
  363.     ofstream neparni_dat("neparni.txt");
  364.     ofstream kanta_dat("kanta.txt");
  365.     if(parni_dat.is_open()&&neparni_dat.is_open()&&kanta_dat.is_open()){
  366.     iPodaci podatak;
  367.         while (izlaz.preuzmi(podatak)) {
  368.            if(podatak.KojiFajl==2)
  369.             parni_dat<<ToString(podatak);
  370.            else if (podatak.KojiFajl==1)
  371.             neparni_dat<<ToString(podatak);
  372.            else
  373.             kanta_dat<<ToString(podatak);
  374.         }
  375.  
  376.         parni_dat.close();
  377.         neparni_dat.close();
  378.         kanta_dat.close();
  379.     } else
  380.         cerr << "Greska prilikom otvaranja datoteke \n";
  381. }
  382.  
  383.  
  384.  
  385.  
  386. int main() {
  387.     // TODO
  388.     UlazniPodaci<string> Redovi;
  389.     IzlazniPodaci<iPodaci> PripremljeniPodaci;
  390.     thread th_reader(citac_nit, ref(Redovi));
  391.     thread th_writer(stampac_nit, ref(PripremljeniPodaci));
  392.     thread th_workers[BROJ_RADNIKA];
  393.  
  394.     for(auto &th: th_workers){
  395.         th = thread(radnik_nit, ref(Redovi), ref(PripremljeniPodaci));
  396.     }
  397.  
  398.     th_reader.join();
  399.     for(auto &th: th_workers) {
  400.         th.join();
  401.     }
  402.     th_writer.join();
  403.     exit(0);
  404. }
Advertisement
Add Comment
Please, Sign In to add comment