#include <cstdlib>
#include <iostream>
#include <iomanip>
using namespace std;
class Tim{
char ime[20];
int broj_odigranih, broj_pobjeda, broj_nerijesenih, broj_poraza, broj_datih, broj_primljenih, broj_poena;
public:
Tim(const char ime[]);
void ObradiUtakmicu(int broj_datih, int broj_primljenih);
const char *DajImeTima() const{return ime;}
int DajBrojPoena() const{return broj_poena;}
int DajGolRazliku() const{return broj_datih-broj_primljenih;}
void IspisiPodatke() const;
};
Tim::Tim(const char ime[]): broj_odigranih(0), broj_pobjeda(0), broj_nerijesenih(0),
broj_poraza(0), broj_datih(0), broj_primljenih(0), broj_poena(0) {
// konstruktorska inicijalizacijska lista, dvotacka, inicijalizacija atributa odvojeni zarezom pa tek tijelo komnstruktora
int i(0);
while(*ime!='\0'){
this->ime[i]=*ime;
ime++;
i++;
}
this->ime[i]='\0';
}
void Tim::ObradiUtakmicu (int broj_datih, int broj_primljenih){
if(broj_datih<0||broj_primljenih<0) throw "Unijeli ste neispravne parametre";
if(broj_datih>0) this->broj_datih+=broj_datih;
if(broj_primljenih>0)this->broj_primljenih+=broj_primljenih;
if(broj_datih>broj_primljenih){ this->broj_pobjeda+=1; this->broj_poena+=3;}
if(broj_datih<broj_primljenih) this->broj_poraza+=1;// moglo je i ovako: TIm::broj_poraza+=1;
if(broj_datih==broj_primljenih){ this->broj_nerijesenih+=1; this->broj_poena+=1;}
this->broj_odigranih+=1;
}
void Tim::IspisiPodatke() const{
int br=0; // br je duzina naziva tima
const char *pom=ime;
while(*pom!='\0') { br++; pom++; }
cout <<left << setw(20-br) << ime << right << setw(4) << broj_odigranih << right << setw(4) << broj_pobjeda
<< right << setw(4) << broj_nerijesenih << right << setw(4) << broj_poraza << right << setw(4) << broj_datih <<
right << setw(4) << broj_primljenih << right << setw(4) << broj_poena << endl;
}
class Liga{
int broj_timova;
const int max_br_timova;
Tim **timovi; // dvojni pokazivac
static bool Uporedi (const Tim* t1, const Tim* t2);
Liga(const Liga &);
Liga &operator =(const Liga &);
/* kada zelimo zabraniti kopiranje i medjusobno dodjeljivajne tada konstruktor kopije i operator dodjele samo deklariramo
u privatnom dijelu klase a ne u javnom jer bi tada prijavljivalo gresku , vazno je da ga nigdje ne implemetiramo,*/
public:
explicit Liga(int velicina_lige): broj_timova(0), max_br_timova(velicina_lige),timovi(new Tim* [velicina_lige]){};
// explicit ispred konstruktora zabranjuje da se konstruktor koristi za pretvorbu tipova
~Liga(); // oslobadja svu memoriju koju je zauzela klasa Liga ili bilo koja klasa koja je pozvana iz klase Liga
void DodajNoviTim(const char ime_tima[]);
void RegistrirajUtakmicu(const char tim1[], const char tim2[], int rezultat_1, int rezultat_2);
void IspisiTabelu();
};
Liga::~Liga(){
for(int i=0; i<max_br_timova-1; i++){
delete timovi[i];
}
delete[] timovi;
}
void Liga::DodajNoviTim(const char ime_tima[]){
if(broj_timova==max_br_timova) throw "Nema mjesta u ligi";
Tim *pom=new Tim(ime_tima); // ova naredba poziva konstruktor sa jednim parametrom tj imenom, koji inicijalizia sve objekte primjerka klase
timovi[broj_timova]=pom; // kako su timovi niz pokazivaca, tada timovi[broj_timova] postaje pokazivac primjerak klase Tim sa gore navedenim atributima
broj_timova++;
}
void Liga::RegistrirajUtakmicu (const char tim1[], const char tim2[], int rezultat_1, int rezultat_2){
bool ispit1(true), ispit2(true);
int poz1=-1, poz2=-1;
for(int i=0; i<broj_timova; i++){
const char *pom1=timovi[i]->DajImeTima();// timovi je niz pokazivaca pa koristimo ovaj tip poziva metode,
const char *p1=tim1;// kako je ime tima niz znakova, onda *p pokazuje samo na prvo slovo
if (*pom1==*p1) { // provjerava slovo po slovao, pocevsi od prvog
ispit1=true;
while(*pom1!='\0') {
if (*pom1==*p1) { pom1++; p1++; }// ako su slova ista, prelazimo na sljedeci el niza slova
else {ispit1=false; break; } // ako nisu, zaustavljamo for
// if(*pom!=*p) { ispit1=false; break; }
poz1=i;
}
}
const char *pom2=timovi[i]->DajImeTima();
const char *p2=tim2;
if (*pom2==*p2) {
ispit2=true;
while(*pom2!='\0') {
if (*pom2==*p2) { pom2++; p2++; }
else {ispit2=false; break; }
//if(*pom2!=*p2) { ispit2=false; break; }
poz2=i;// cuva redni tima u ligi
}
}
}
if (poz1==poz2) throw "Nemoze tim igrati sam sa sobom!!!";
if (poz1!=-1&&poz2!=-1) {
timovi[poz1]->ObradiUtakmicu(rezultat_1, rezultat_2); timovi[poz2]->ObradiUtakmicu(rezultat_1, rezultat_2);
}
else throw "Ne postoji u bazi jedan od timova!!!";
}
// funkcije kriterija se izvode kao privatne staticke funkcije, jer su zajednicke za sve primjerke neke klase
// staticke funkcije ne sadrze pokazivac this pa ne znaju na koji su objekat pozvane
bool Liga::Uporedi (const Tim* t1, const Tim* t2){
if(t1->DajBrojPoena()>t2->DajBrojPoena()) return true;
if(t1->DajBrojPoena()==t2->DajBrojPoena()){
if(t1->DajGolRazliku()>t2->DajGolRazliku()) return true;
}
return false;
}
void Liga::IspisiTabelu(){
sort(timovi, timovi+broj_timova, Uporedi);
// timovi je niz pokazivaca pa se funkciji Uporedi mora poslati pokazivac
cout<<"Trenutni poredak lige:"<<endl;
cout <<"---------------------------------------------------------------------"<<endl;
for(int i=0; i<broj_timova; i++){
timovi[i]->IspisiPodatke();
cout<<endl;
}
}
int main(int argc, char *argv[]){
int max;
cout << "Unesite maksimalni broj timova: ";
cin >> max;
Liga L(max);
for(int i=1;;i++){
char ime[20];
cout << "Unesi naziv " << i << " tima: "; cin >> ime;
try { L.DodajNoviTim(ime); }
catch(const char poruka[]) { cout << poruka << endl; i--;}
int choice;
cout << "1 za novi unos ili 2 za izlaz: "; cin >> choice;
if (choice==2) break;
}
cout << "Unos rezultata utakmica: " << endl;
for(;;){
char prvi[20], drugi[20];
int brpr, brdr;
cout << "Unesi naziv prvog tima: "; cin >> prvi;
cout << "Unesi naziv drugog tima: "; cin >> drugi;
cout << "Unesi broj golova prvog tima: "; cin >> brpr;
cout << "Unesi broj golova drugog tima: "; cin >> brdr;
try { L.RegistrirajUtakmicu(prvi, drugi, brpr, brdr); }
catch(const char poruka[]) { cout << poruka << endl; }
int choice;
cout << "1 za novi unos ili 2 za izlaz: "; cin >> choice;
if (choice==2) break;
}
L.IspisiTabelu();
system("PAUSE");
return EXIT_SUCCESS;
}