#include <iostream>
#include<string>
#include<vector>
#include<algorithm>


using namespace std;

class ApstraktniStudent{

    string ime, prezime;
    int indeks;
    int polozeni;
    double prosjek;

    public:
    ApstraktniStudent(string ime, string prezime, int indeks) : 
    ime(ime), prezime(prezime), indeks(indeks), polozeni(0), prosjek(5){}
    virtual ~ApstraktniStudent() = default;
    string DajIme() const{
        return ime;
    }
    string DajPrezime () const{
        return prezime;
    }
    int DajBrojIndeksa() const {
        return indeks;
    }
    int DajBrojPolozenih() const {

        return polozeni;
        
    }
    double DajProsjek() const { return prosjek; }

    void RegistrirajIspit(int ocjena) {
        if(ocjena < 5 || ocjena > 10) throw domain_error("Neispravna ocjena");
        if (ocjena == 5) return;
        double prosjek1 = prosjek;
        prosjek1 *=polozeni;
        polozeni++;
        prosjek = (prosjek1 + ocjena) / polozeni;
        
    }

    void PonistiOcjene() {
        prosjek=5;
        polozeni = 0;
    }
    virtual void IspisiPodatke() const = 0; 
    virtual ApstraktniStudent *DajKopiju() const = 0;
       
};

class StudentBachelor : public ApstraktniStudent {

    public: 
    StudentBachelor(string ime, string prezime, int indeks) :
                    ApstraktniStudent(ime, prezime, indeks){}

    void IspisiPodatke() const override{
        cout << "Student bachelor studija " << DajIme() << " " << DajPrezime() 
     << ", sa brojem indeksa " << DajBrojIndeksa() << "," << endl 
   << "ima prosjek " << DajProsjek() << "." <<endl;
    }

     ApstraktniStudent *DajKopiju() const override { return new StudentBachelor(*this); } 

    
};

class StudentMaster : public ApstraktniStudent { 
  int godina_diplomiranja; 
public: 
  StudentMaster(string ime,  string prezime, int indeks, int god_dipl) : 
    ApstraktniStudent(ime, prezime, indeks), godina_diplomiranja(god_dipl) {} 
  void IspisiPodatke() const override { 
    cout << "Student master studija " << DajIme() << " " << DajPrezime() 
     << ", sa brojem indeksa " << DajBrojIndeksa() << "," <<  endl 
     << "zavrsio bachelor studij godine " << godina_diplomiranja << ", " 
   << "ima prosjek " << DajProsjek() << "." <<  endl; 
  } 
  ApstraktniStudent *DajKopiju() const override { return new StudentMaster(*this); } 
 };

class Fakultet {

    vector<ApstraktniStudent*> studenti;

    

    public:
    Fakultet() = default;
    ~Fakultet();
    Fakultet(const Fakultet &f);
    Fakultet (Fakultet &&f) = default;
    Fakultet &operator =(Fakultet f) {swap(studenti, f.studenti); return *this;}
    void UpisiStudenta(string ime, string prezime, int indeks);
    void UpisiStudenta(string ime, string prezime, int indeks, int godina_diplomiranja);
    void ObrisiStudenta(int indeks);
    ApstraktniStudent &operator[](int indeks);
    const ApstraktniStudent &operator[](int indeks) const;
    void IspisiSveStudente() const;
    
    
    
};

Fakultet::~Fakultet(){
    for(ApstraktniStudent *s : studenti){
        delete s;
    }
}

Fakultet::Fakultet(const Fakultet &f) : studenti(f.studenti.size()){

    try {
        for(int i = 0; i < studenti.size(); i++){
            studenti[i] = f.studenti[i]->DajKopiju();
        }
    } catch (...) {
        for(ApstraktniStudent *s : studenti) delete s;
    }
    
}

void Fakultet::UpisiStudenta(string ime, string prezime, int indeks){
    for(int i=0; i < studenti.size(); i++){
        if(studenti[i]->DajBrojIndeksa() == indeks) throw logic_error("Student sa adanim brojem indeksa vec postoji");
    }
    studenti.push_back(new StudentBachelor(ime, prezime, indeks));
    
}
void Fakultet::UpisiStudenta(string ime, string prezime, int indeks, int godina_diplomiranja){
    for(int i=0; i < studenti.size(); i++){
        if(studenti[i]->DajBrojIndeksa() == indeks) throw logic_error("Student sa adanim brojem indeksa vec postoji");
    }
    studenti.push_back(new StudentMaster(ime, prezime, indeks, godina_diplomiranja));
    
}
void Fakultet::ObrisiStudenta(int indeks){
    int i;
    for(i = 0; i < studenti.size(); i++){
        if(studenti[i]->DajBrojIndeksa() == indeks) break;
    }
    if(i == studenti.size()) throw logic_error("...");
    delete studenti[i];
    studenti.erase(studenti.begin() + i);
}

    ApstraktniStudent &Fakultet::operator[](int indeks){
        int i;
    for(i = 0; i < studenti.size(); i++){
        if(studenti[i]->DajBrojIndeksa() == indeks) break;
    }
    if(i == studenti.size()) throw logic_error("...");
        return *studenti[i];
    }

    const ApstraktniStudent &Fakultet::operator[](int indeks) const{
        int i;
    for(i = 0; i < studenti.size(); i++){
        if(studenti[i]->DajBrojIndeksa() == indeks) break;
    }
    if(i == studenti.size()) throw logic_error("...");
        return *studenti[i];
    }


void Fakultet::IspisiSveStudente() const {
    auto studenti_kopija = studenti;
    sort(studenti_kopija.begin(), studenti_kopija.end(),
         [](ApstraktniStudent *s1, ApstraktniStudent *s2){
             if(s1->DajProsjek() != s2->DajProsjek()) return s1->DajProsjek() > s2->DajProsjek();
            return s1->DajBrojIndeksa() < s2->DajBrojIndeksa();
         });
    for(ApstraktniStudent *s : studenti_kopija) s->IspisiPodatke();
}







template <typename TipIzuzetka, typename FunkcijskiTip> 
  void TestirajIzuzetak(FunkcijskiTip akcija) { 
    try { akcija(); } 
    catch(TipIzuzetka &e) { std::cout << e.what() << std::endl; } 
  }








int main() {
  Fakultet f1; 
  f1.UpisiStudenta("Meho", "Mehic", 3412);  
  f1.UpisiStudenta("Ibro", "Ibric", 3124, 2015); 
  f1.UpisiStudenta("Pero", "Peric", 1243); 
  f1.IspisiSveStudente(); 
  TestirajIzuzetak<std::logic_error>([&]() { f1.UpisiStudenta("Drugi", "Drugic", 3412); }); 
  f1[3412].RegistrirajIspit(7); f1[3412].RegistrirajIspit(9); 
  f1[3124].RegistrirajIspit(9); f1[3124].RegistrirajIspit(10); 
  f1[1243].RegistrirajIspit(8); 
  f1.IspisiSveStudente(); 
  TestirajIzuzetak<std::logic_error>([&]() { f1[9876].IspisiPodatke(); }); 
  f1.ObrisiStudenta(3412);  
  f1.IspisiSveStudente(); 
  TestirajIzuzetak<std::logic_error>([&]() { f1.ObrisiStudenta(6789); }); 
  Fakultet f2 = f1; 
  f2.IspisiSveStudente(); 
  Fakultet f3 = std::move(f1); 
  f3.IspisiSveStudente(); 
  f3.UpisiStudenta("Ivan", "Ivanic", 4312, 2016); 
  f2 = f3; 
  f2.IspisiSveStudente(); 
  f3.ObrisiStudenta(4312); 
  f2 = f3;  
  f2.IspisiSveStudente(); 
  f2 = std::move(f3); 
  f2.IspisiSveStudente(); 
  const Fakultet f4 = f2; 
  f4.IspisiSveStudente(); 
  f4[3124].IspisiPodatke(); 
    return 0;
}

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: