Capitolul III
Programarea orientata pe obiecte in C++:clase, obiecte, functii membru, structuri si uniuni in analogie cu clasele, functii speciale

III. 1. Notiuni introductive

Programarea orientatγ pe obiecte este o tehnologie modernγ in domeniul programγrii calculatoarelor, care a rezultat din necesitatea realizγrii de aplicaώii   din ce ξn ce mai complexe. Programarea clasica si structurata avea urmatoarele dezavantaje: control greoi al programelor de dimensiuni mari, dificultati cu privire la reutilizarea codurilor de programe si inflexibiliatea adaptarii si extinderii unor module de program deja realizate. Programarea clasica structurata are la baza celebra ecuatie a lui Nikolaus Wirth:

Program = Structuri de date + Algoritmi

            Programarea Orientata pe Obiecte, POO, se fundamenteaza pe conceptul de obiect, care este definit printr-o multime de date, numite proprietati, si o multime de proceduri sau functii de prelucrare ale acestor date, numite metode. In consecinta, ecuatia POO este:

Obiect = Date + Functii        

sau

Obiect = Date + Functii        

Obiect = Proprietati + Metode        

Diferenta dintre cele doua cai de abordare ale programarii calculatoarelor consta in maniera de abordare a programarii. In timp ce programarea clasica structurata se concentreaza pe prelucrarea datelor, adica pe programe, proceduri si functii, POO se bazeaza pe definirea obiectelor, adica, pe proprietatile acestora, numite date, si pe functiile acestor obiecte, numite metode.

III.2. Clase si  obiecte

            La baza POO stau conceptele de clasa si de obiect.

Definitia 1

            Clasa, intr-un anumit limbaj de programare, reprezinta definirea unui tip de obiecte abstracte sau concrete, adica descrierea proprietatilor, a datelor si a metodelor, a prelucrarilor, posibile asupra datelor. Clasa este, de fapt, o notiune abstracta, care defineste un anumit tip de obiecte, sau, altfel spus, o clasa reprezinta multimea posibila a mai multor obiecte de acelasi tip.

Definitia 2

            Obiect, reprezinta o multime de date care descrie un anumit obiect concret sau abstract, numite si proprietati,  impreuna cu procedurile, functiile, de prelucrare a cestora, numite metode.

            Crearea unui obiect presupune specificarea clasei din care face parte, astfel identificandu-se proprietatile obiectului si modul in care acestea pot fi folosite si prelucrate

Observatie:

Crearea sau declararea unui obiect este similara cu crearea sau declararea unor variabile. Declararea unei variabile se face, dupa cum se stie, prin specificarea identificatorului acesteia, precedat de tipul variabilei iar declararea unui obiect presupune precizarea identificatorului acestuia, precedat de clasa din care face parte, clasa care in mod implicit determina proprietatile si metodele  obiectului definit.

O clasa in limbajul C++ poate fi reprezentata ca o extindere a conceptului de structura, care, ca si o structura, descrie un sablon pentru viitoarele declarari de variabile obiect.

Definirea generala unei clase in C++

class [nume_clasa]

  {

    specificator_acces1;

       date_si_functii1;

    specificator_acces2;

       date_si_functii2;

………………………..

    specificator_accesn;

       date_si_functiin;

}[obiect1] [,obiect2] … [,obiectm];

unde:

            - nume_clasa – optional, este un identificator ales de programator care denumeste clasa definita si prin intermediul caruia se apeleaza aceasta;

- specificator_accesi (i=1,n) – este o eticheta care poate fi unul dintre cuvinele cheie: public, private sau protected.

Spre deosebire de o structura, ai carei membri sunt toti accesibili programului, o clasa poate avea membri pe care programul ii poate accesa  direct (public), utilizand operatorul punct (.) si alti membri, denumiti privati (private), pe care programul nu-i poate accesa direct. Unica accesare a datelor si metodelor private (private) se face numai prin intermediul metodelor publice. Dupa cum se va vedea, o clasa poate deriva dintr-o clasa de baza, anterior definita, concept cunoscut sub numele de mostenire. Un membru protejat (protected) are un statut intermediar intre membri publici si privati. Pentru clasa de baza, obiectele acesteia pot accesa membri protejati, ca si cum ar fi publici, iar obiectele claselor derivate nu pot accesa un membru declarat protected in clasa de baza, decat prin intermediul unor functii de interfata declarate publice.

- date_si_functiii; (i=1,n) – descrie datele, adica proprietatile, si functiile, adica metodele specifice clasei definite care, in functie de specificator_accesi (i=1,n), pot fi public, private sau protected.

- [obiect1] [,obiect2] … [,obiectm] – reprezinta identificatorii obiectelor de tipul clasei la care sunt atasati, adica numele variabilelor obiect respective care vor fi utilizate in programul in care apar.

Observatii:

            - la declararea obiectelor, o data cu definirea clasei asociate,  se poate omite identificatorul de clasa, nume_clasa.

- declararea obiectelor, ulterior definirii clasei asociate, impune obligativitatea identificatorului de clasa, nume_clasa.

Declararea obiectelor, ulterior definirii clase se face astfel:

class nume_clasa [obiect1] [,obiect2] … [,obiectm];

unde, nume_clasa,obiect1,obiect2, … ,obiectm au semnificatiilie mai sus prezentate.

Problema 17

            Sa se citeasca de la tastatura informatiile specifice cartilor dintr-o librarie: denumire carte, autorul principal, al doilea autor, numarul de pagini si pretul. Prin intermediul unei clase, carte, care descrie datele despre o carte, proprietatile (denumire carte, autorul principal, al doilea autor, numarul de pagini si pretul) si metodele de prelucrare (initializarea si afisarea unei carti) sa se afiseze pe ecran informatiile despre orice carte tratata.

// definirea clasei carte

#include<iostream.h>

#include<string.h>

#include<stdio.h>

class carte

{

  public:

    char nume[40];

    char autor1[40];

    char autor2[40];

    int nrpag;

    double pret;

    void citeste_carte(char *numecarte,char *autorcarte1,char *autorcarte2,int *np,double *p);

    void afiseaza_carte();

};

// descrirea functiei de citire carte

void carte::citeste_carte(char *numecarte,char *numeautor1,

                                     char *numeautor2,int *np,double *p)

  {

    strcpy(nume,numecarte);

    strcpy(autor1,numeautor1);

    strcpy(autor2,numeautor2);

    nrpag=*np;

    pret=*p;

  }

void carte::afiseaza_carte()

  {

    cout<<"\n cartea nr."<<i<<":"<<nume<<endl;

    cout<<"\n primul autor:"<<autor1<<endl;

    cout<<"\n al doilea autor:"<<autor2<<endl;

    cout<<"\n nr pagini:"<<nrpag<<endl;

    cout<<"\n pretul:"<<pret<<endl;

  }

int i=0;

void main()

  {

      carte carteacitita;

      char wnume[40],wautor1[40],wautor2[40];

      int wnrpag;

      double wpret;

      char r='d';

      while(r=='d')

        {

           printf("\n denumirea cartii:");

           gets(wnume);

           printf("\n primul autor:");

           gets(wautor1);

           printf("\n al doilea autor:");

           gets(wautor2); 

           cout<<"\n nr. pagini:";

           cin>>wnrpag;

           cout<<"\n pret:";

           cin>>wpret;

           carteacitita.citeste_carte(wnume,wautor1,wautor2,&wnrpag,&wpret);

           carteacitita.afiseaza_carte();

           cout<<"\n continuati?(d/n):";

           cin>>r;

        }

  }

            In urma executarii programului anterior s-au obtinut urmatoarele rezultate, care arata cum se declara o clasa, un obiect al acestei clase si modul in care se apeleaza membrii acestei clase, prin intermediul  unei instante a acestei clase.

 

 denumirea cartii:Trecea o moara pe Siret

 primul autor:Mihail Sadoveanu

 al doilea autor: --

 nr. pagini:200

 pret:30

 

 cartea nr.0:Trecea o moara pe Siret

 primul autor:Mihail Sadoveanu

 al doilea autor:  --

 nr pagini:200

 pretul:30

 continuati?(d/n):d

 

 denumirea cartii:O noapte furtunoasa

 primul autor:Ion Luca Caragiale

 al doilea autor: --

 nr. pagini:50

 pret:25

 continuati?(d/n):n

 

Problema 18

Daca, in programul de mai sus, textul definirii clasei carte impreuna cu textele functiilor precizate in clasa, citeste_carte si afiseaza_carte se salveaza ca un fisier header in directorul include, fie el carti.h, atunci programul de mai sus va arata astfel:

int i;

#include<iostream.h>

#include<string.h>

#include<carti.h>

void main()

{

  carte carteacitita;

  char wnume[40],wautor1[40],wautor2[40];

  int wnrpag;

  double wpret;

  char r='d';

  while(r=='d')

  {

     printf("\n denumirea cartii:");

     gets(wnume);

     printf("\n primul autor:");

     gets(wautor1);

     printf("\n al doilea autor:");

     gets(wautor2); 

     cout<<"\n nr. pagini:";

     cin>>wnrpag;

     cout<<"\n pret:";

     cin>>wpret;

     carteacitita.citeste_carte(wnume,wautor1,wautor2,&wnrpag,&wpret);

     carteacitita.afiseaza_carte();

     cout<<"\n continuati?(d/n):";

     cin>>r;

  }

}

            In urma executarii acestui program, se obtin aceleasi rezultate ca in problema precedenta, cu deosebirea ca referirea clasei carte se face acum din fisierul header, carti.h.

Problema 19 

            Pentru orice sir de caractere, introdus de la tastatura, printr-un meniu adecvat, sa se realizeze, utilizandu-se o clasa clasasir, urmatoarele operatii: conversia sirului la caractere mici, conversia la caractere mari si adaugarea unui subsir la sirul dat.

#include<stdio.h>

#include<conio.h>

#include<string.h>

class clasasir

{

  //definirea clasei sir

  char sir[80]; // variabila sir ca membru privat implicit

  public:

     // declararea functiei de copiere sir

     void copy (char *s) { strcpy(sir,s);}

     // initializarea cu spatii a sirului s

     clasasir(char *s=" ") {copy(s);}

     // declararea functiei de scriere

     void scrie(FILE *fileptr);

     // declararea functiei de citire

     void citeste(FILE *fileptr);

     // declararea functiei de concatenare siruri

     void operator +=(clasasir &s)

      {

        strcat(sir,s.sir); //concatenare siruri

      }

     // declararea functiei friend conversie caractere

     friend void conversie(clasasir &s,char optiune);

}; // sfarsitul declararii clasei

// descrierea functiei de scriere

void clasasir::scrie(FILE *fileptr)

{

 fprintf(fileptr,"\n sirul modificat este:%s",sir);

}

// descrierea functiei de citire

void clasasir::citeste(FILE *fileptr)

{

  // citeste din fisierul *fileptr si depune in sir

 int sizesir; // se memoreaza lungimea sirului citit

 fgets(sir,80,fileptr);

 sizesir=strlen(sir)-1;

 if(sir[sizesir]=='\n') sir[sizesir]=0;

}

// descrierea functiei de conversie sir

void conversie(clasasir &s,char optiune)

{

 clasasir tempsir;

 switch (optiune)

 {

  case '1': strupr(s.sir);//conversie in majuscule

               break;

  case '2': strlwr(s.sir);//conversie in minuscule

               break;

  case '3': printf("\n introduceti un sir (max 80):");

               tempsir.citeste(stdin); //citeste un alt sir

               s+=tempsir; //concateneaza sirurile

               break;

  default:  printf("\n optiune eronata \n");

 }

}

void main()

{

  clasasir clsir; //declararea obiectului clsir

  char alegere='1',r='d';

  while (r=='d')

   {

    printf("\n dati un sir (max=80 caractere):");

    clsir.citeste(stdin);

    do

     {

       // afisarea meniului de comenzi

       printf("\n ==============================");

       printf("\n 1. conversie sir in majuscule");

       printf("\n 2. conversie sir in minuscule");

       printf("\n 3. adaugare subsir la sirul dat");

       printf("\n t. terminare program");

       printf("\n ==============================");

       printf("\n alegeti o optiune:");

       alegere=getchar();getchar();

     }

    while((alegere!='1')&&(alegere!='2')&&

               (alegere!='3')&&(alegere!='t'));

    while(alegere!='t')

      {

        conversie(clsir,alegere);

        clsir.scrie(stdout);

        do

         {

           // reafisarea meniului de comenzi

           printf("\n ==============================");

           printf("\n 1. conversie sir in majuscule");

           printf("\n 2. conversie sir in minuscule");

           printf("\n 3. adaugare subsir la sirul dat");

           printf("\n t. terminare program");

           printf("\n ==============================");

           printf("\n alegeti o optiune:");

          alegere=getchar();getchar();

         }

        while((alegere!='1')&&(alegere!='2')&&

                  (alegere!='3')&&(alegere!='t'));

      }

     printf("\n continuati?(d/n):");

     r=getche();

  }

 printf("\n terminat \n");

}

In urma executarii programului de mai sus, s-au obtinut rezultatele din lista de mai jos,  care pun in evidenta declararea si folosirea membrilor publici si privati, prin intermediul unei instante a clasei declarate.

 

 dati un sir (max=80 caractere):ana are mere

 ==============================

 1. conversie sir in majuscule

 2. conversie sir in minuscule

 3. adaugare subsir la sirul dat

 t. terminare program

 ==============================

 alegeti o optiune:1

 sirul modificat este:ANA ARE MERE

 ==============================

 1. conversie sir in majuscule

 2. conversie sir in minuscule

 3. adaugare subsir la sirul dat

 t. terminare program

 ==============================

 alegeti o optiune:2

 sirul modificat este:ana are mere

 ==============================

 1. conversie sir in majuscule

 2. conversie sir in minuscule

 3. adaugare subsir la sirul dat

 t. terminare program

 ==============================

 alegeti o optiune:3

 introduceti un sir (max 80): frumoase

 sirul modificat este:ana are mere frumoase

 ==============================

 1. conversie sir in majuscule

 2. conversie sir in minuscule

 3. adaugare subsir la sirul dat

 t. terminare program

 ==============================

 alegeti o optiune:1

 sirul modificat este:ANA ARE MERE FRUMOASE

 =====================================

 1. conversie sir in majuscule

 2. conversie sir in minuscule

 3. adaugare subsir la sirul dat

 t. terminare program

 ==============================

 alegeti o optiune:2

 sirul modificat este:ana are mere frumoase

 ==============================

 1. conversie sir in majuscule

 2. conversie sir in minuscule

 3. adaugare subsir la sirul dat

 t. terminare program

 ==============================

 alegeti o optiune:3

 introduceti un sir (max 80): si mari

 sirul modificat este:ana are mere frumoase si mari

 ====================================

 1. conversie sir in majuscule

 2. conversie sir in minuscule

 3. adaugare subsir la sirul dat

 t. terminare program

 ==============================

 alegeti o optiune:1

 sirul modificat este:ANA ARE MERE FRUMOASE SI MARI

 =============================================

 1. conversie sir in majuscule

 2. conversie sir in minuscule

 3. adaugare subsir la sirul dat

 t. terminare program

 ==============================

 alegeti o optiune:2

 sirul modificat este:ana are mere frumoase si mari

 ===================================

 1. conversie sir in majuscule

 2. conversie sir in minuscule

 3. adaugare subsir la sirul dat

 t. terminare program

 ==============================

 alegeti o optiune:t

 ==============================

 terminat

 continuati?(d/n):n

 

In programul de mai sus s-a  declarat o clasa numita clasasir, utilizata pentru declararea obiectelor specifice acesteia (exemplu clasasir tempsir) si are ca membri date si functii. Se constata ca unii membri sunt publici, marcati cu eticheta public: functiile copy, scrie, citeste, operator si conversie iar altii sunt privati, nemarcati cu nici o eticheta sau marcati cu eticheta private: variabila (data) sir de exemplu. Se observa, de asemenea, ca unele functii sunt descrise in corpul clasei clasasir: copy si operator iar altele sunt descrise in afara clasei: citeste, scrie si conversie. Membri publici ai unei clase, date sau functii publice, pot fi accesati din interiorul si exteriorul clasei. De exemplu, functiile citeste si scrie au fost accesate direct din functia main prin intermediul obiectului clsir al clasei clasasir : clsir.citeste si respectiv clsir.scrie. Membri privati ai unei clase nu pot fi accesati decat din interiorul clasei. Membrul privat sir a fost accesat numai din interiorul clasei de catre functiile membre: copy, citeste si scrie indiferent daca sunt descrise in interiorul sau in exteriorul clasei.

III. 3. Functii membru ale unei clase

            Functiile membru ale unei clase sunt functiile descrise sau declarate in interiorul unei clase. Deci, descrierea efectiva a functiilor membru ale unei clase se poate face, fie in interiorul clasei, fie in afara clasei, daca in interiorul clasei s-au declarat ca prototipuri. Ele pot fi accesate din interiorul clasei si din afara clasei, prin intermediul obiectelor declarate, daca au fost  declarate publice, sau numai direct din interiorul clasei de catre alte functii membru ale aceleiasi clase, daca au fost declarate private.

III. 3. 1. Apelarea unei functii membru al unei clase

            Apelarea unei functii membru, din interiorul unei clase, se face precizandu-se numele acesteia si parametrii efectivi:

            nume_functie_membru(parametri_efectivi_de_apel)

ca in problema de mai sus:  clasasir(char *s=" ") {copy(s);}

            Apelarea unei functii membru, din exteriorul unei clase, se face precizandu-se obiectul declarat, numele acesteia si parametri efectivi:

            nume_obiect.nume_functie_membru(parametri_efectivi_de_apel)

asa cum s-a precizat mai sus:   clsir.citeste, clsir.scrie.

III. 3. 2. Functii friend

Functiile friend sunt functii obisnuite declarate intr-o clasa, precedate de calificativul friend.

            friend nume_functie_membru(parametri_formali)

Acest calificativ le permite sa acceseze membrii privati ai unei clase, din exteriorul acesteia, asa cum este cazul functiei conversie din problema precedenta:

            friend void conversie(clasasir &s,char optiune);

Apelarea unei functii friend se face asemanator cu apelarea oricarei functii din C++, ca de exemplu, in functia main() a programului de mai sus: conversie(clsir,alegere);

Variabile de tip referinta

            O variabila de tip referinta, in definirea unei functii, este precedata de operatorul adresa &, iar in corpul functiei variabila este referita normal, ca o variabila de tip structura. De fapt, o variabila de tip referinta este un alias, un pseudonim, pentru alta variabila, in esenta, un pointer cu urmatoarele precizari:

-          odata initializata valoarea sa nu se mai poate modifica

-          eliberarea, anularea referirii, se face in mod automat

Variabila referinta se utilizeaza, in corpul functiei, ca o structura (exemplu, in programul de mai sus: s.sir)  si nu ca un pointer la o structura, asa cum eram obisnuiti la structuri (s->sir)

Variabilele referinta, dupa cum se stie, permit transmiterea parametrilor la functia apelata, prin adrese si nu prin valoare, eliminand, astfel, pierderile de timp cu copierea parametrilor efectivi in memoria stiva  Apelarea unei functii membru cu parametri de tip referinta se face fara a preceda parametri respectivi de operatorul adresa & (exemplu, in functia main()de mai sus:conversie(clsir,alegere))

III. 4. Membri statici ai unei calase

            Oricare obiect declarat intr-un program, in mod normal, primeste o copie a membrilor clasei la care este asociat. Uneori, este nevoie sa se defineasca unii membrii care sunt folositi in comun de catre toate obiectele clasei. Astfel de membri se numesc membri statici care au proprietati diferite de ceilalti membri nestatici.

Declararea unui membru static presupune precedarea acestuia de cuvantul cheie static:

            static tip_membru nume_membru_static;

iar referirea unui membru static se face astfel:                                       

            nume_clasa::nume_membru_static;

unde, nume_membru_static poate fi o data sau o functie membru statica

Referirea unui membru static se poate face chiar si inaintea declararii de obiecte ale clasei, in care a fost declarat membru static respectiv, iar initializarea sa se poate face numai in domeniul sau de vizibilitate.

Problema 20

            Se considera o clasa de puncte din spatiu in care se descrie un punct de coordonate fixe M0(x0,y0,z0), reprezentand centrul unei sfere, raza fixa a unei sferei ro si un  punct oarecare din spatiu M(x,y,z) si functiile:distanta(M0,M) care determina distanta dintre punctele M0 si M, pozitia_fata_de_centru(M), care determina  coordonatele punctului M in raport cu centrul sferei si pozitia(M) care precizeaza pozitia punctului M fata de sfera.  Sa se scrie un program care sa sa calculeze distanta dintre punctele M0 si M, coordonatele punctului M fata de centrul sferei si sa determine pozitia punctului M fata de sfera utilizandu-se obiecte din clasa declarata.

#include<iostream.h>

#include<conio.h>

#include<math.h>

// definirea clasei clspunct

class clspunct

{

 public:

   static int x0,y0,z0,raza;

   int x,y,z;

   double distanta(void)

   {

     return(sqrt((x-x0)*(x-x0)+(y-y0)*

                       (y-y0)+(z-z0)*(z-z0)));  

   }

   int poz_x_fata_m0(void)

   {

     return(x-x0);

   }

   int poz_y_fata_m0(void)

   {

     return(y-y0);

   }  

   int poz_z_fata_m0(void)

   {

     return(z-z0);

   }

   double poz_m_fata_sfera(void)

   {

     return(distanta()-raza);

   }

};

// initializare datelor statice inainte de

// declararea obiectelor clasei

int clspunct::x0=10; 

int clspunct::y0=10; 

int clspunct::z0=10; 

int clspunct::raza=10; 

void main(void)

{

 // declararea obiectelor ob1 si ob2

 clspunct a;

 char r='d';

 while(r=='d')

 {

  cout<<"\n sfera are la inceput raza "

         <<a.raza<<" si centrul in M0("

         <<a.x0<<','<<a.y0<<','<<a.z0<<")";

  cout<<"\n coordonatele unui pct (int x,y,z):";

  cin>>a.x>>a.y>>a.z;

  cout<<"\n distanta(M0("<<a.x0<<','<<a.y0<<','

         <<a.z0<<"),M1("<<a.x<<','<<a.y<<','

         <<a.z<<"))="<<a.distanta();

  cout<<"\n coordonatel lui M fata de centru("

         <<a.poz_x_fata_m0()<<','<<a.poz_y_fata_m0()

         <<','<<a.poz_z_fata_m0()<<")";

  if(a.poz_m_fata_sfera()>0)

    cout<<"\n punctul M("<<a.x<<','<<a.y<<','

           <<a.z<<") este exterior sferei";

  if(a.poz_m_fata_sfera()<0)

    cout<<"\n punctul M("<<a.x<<','<<a.y<<','

           <<a.z<<") este interior sferei";

  if(a.poz_m_fata_sfera()==0)

    cout<<"\n punctul M("<<a.x<<','<<a.y<<','

            <<a.z<<") este pe sfera";

  // se modifica datele statice

  a.x0=1;a.y0=1;a.z0=1;a.raza=10;

  cout<<"\n sfera modificata are raza "<<a.raza

         <<" si centrul in M0("<<a.x0<<','<<a.y0

         <<','<<a.z0<<")";

  cout<<"\n distanta(M0("<<a.x0<<','<<a.y0<<','

         <<a.z0<<"),M1("<<a.x<<','<<a.y<<','

         <<a.z<<"))="<<a.distanta();

  cout<<"\n coordonatel lui M fata de centru("

         <<a.poz_x_fata_m0()<<','<<a.poz_y_fata_m0()

         <<','<<a.poz_z_fata_m0()<<")";

  if(a.poz_m_fata_sfera()>0)

    cout<<"\n punctul M("<<a.x<<','<<a.y<<','

           <<a.z<<") este exterior sferei";

  if(a.poz_m_fata_sfera()<0)

    cout<<"\n punctul M("<<a.x<<','<<a.y<<','

           <<a.z<<") este interior sferei";

  if(a.poz_m_fata_sfera()==0)

    cout<<"\n punctul M("<<a.x<<','<<a.y<<','

           <<a.z<<") este pe sfera";

  cout<<"\n continuati?(d/n):";

  cin>>r;

 }

}

            In urma executarii programului de mai sus, s-au obtinut rezultatele din lista de mai jos, evidentiindu-se declararea si modul de utilizare a membrilor statici precizati in clasa definita.

 

 sfera are la inceput raza 10 si centrul in M0(10,10,10)

 coordonatele unui pct (int x,y,z):20 30 40

 

 distanta(M0(10,10,10),M1(20,30,40))=37.4166

 coordonatel lui M fata de centru(10,20,30)

 punctul M(20,30,40) este exterior sferei

 sfera modificata are raza 10 si centrul in M0(1,1,1)

 distanta(M0(1,1,1),M1(20,30,40))=52.1824

 coordonatel lui M fata de centru(19,29,39)

 punctul M(20,30,40) este exterior sferei

 continuati?(d/n):d

 

 sfera are la inceput raza 10 si centrul in M0(1,1,1)

 coordonatele unui pct (int x,y,z):1 2 3

 distanta(M0(1,1,1),M1(1,2,3))=2.23607

 coordonatel lui M fata de centru(0,1,2)

 punctul M(1,2,3) este interior sferei

 sfera modificata are raza 10 si centrul in M0(1,1,1)

 distanta(M0(1,1,1),M1(1,2,3))=2.23607

 coordonatel lui M fata de centru(0,1,2)

 punctul M(1,2,3) este interior sferei

 

 continuati?(d/n):d

 sfera are la inceput raza 10 si centrul in M0(1,1,1)

 coordonatele unui pct (int x,y,z):-10 -20 20

 distanta(M0(1,1,1),M1(-10,-20,20))=30.3809

 coordonatel lui M fata de centru(-11,-21,19)

 punctul M(-10,-20,20) este exterior sferei

 sfera modificata are raza 10 si centrul in M0(1,1,1)

 distanta(M0(1,1,1),M1(-10,-20,20))=30.3809

 coordonatel lui M fata de centru(-11,-21,19)

 punctul M(-10,-20,20) este exterior sferei

 continuati?(d/n):n

 

Spre deosebire de o functie membru nestatica, o functie membru statica poate fi apelata cu sau fara sintaxa specifica unei functii membru:

Exemplu:

……………………….

class clsx

{

   int b;

   public:

      ……………………

      static void nume_functie(int a, clsx *ptr);

     ……………………..

};

…………….

void main(void)

{

  int i=1;

  clsx obiect;

  // apelari corecte numai pentru functii statice

  clsx::nume_functie1(i,&obiect); 

  obiect.functie(i,&obiect);

  // apelare eronata

  functie(i.obiect);

  ………………..

}

            Functiile statice nu sunt aplicate unui obiect anume si din acest motiv ele nu accepta ca parametru implicit pointerul this. Si ca atare, din corpul unei functii statice nu se pot accesa membrii obiectelor decat prin calificare explicita, utilizand sageata dreapta (->) sau punctul (.). Pentru declaratia din exemplul de mai sus descrierea functiei statice se face astfel:

Exemplu:

void clsx::functie(int i,clsx *ptr)

{

  …………………..

  ptr->b=i;  // se atribuie datei b din obiectul ptr al ckasei clsx

  b=i;  // atribuire incorecta

  ………………………

}

Observatie:

            Utilizarea principala a membrilor statici este determinata de necesitatea memorarii datelor comune tuturor obiectelor create, de aceeasi clasa, cum ar fi:

- pastrarea unor informatii comune tuturor obiectelor unei clase: semafoare, comutatori.

- inregistrarea numarului obiectelor create asociate aceleiasi clase

- reducerea numarului declaratiilor globale

- validarea accesului la denumirea campurilor de date

 

III. 5. Pointerul this din C++

Apelarea unei functii membru pozitioneaza un pointer la obiectul de tipul clasei asociate. In momentul apelului, acest pointer apare ca un argument suplimentar nevizibil. El poate fi referit, totusi, cu ajutorul cuvantului cheie this (aici). Utilizarea de baza a cuvantului cheie this este legata de descrierea functiilor membru care manipuleaza pointeri. Deoarece this este un cuvant cheie in C++, el nu poate fi declarat explicit iar, in orice functie membru nestatica a unei clase, pointerul this este declarat implicit ca nume_clasa *this si initializat sa adreseze spre obiectul pentru care este apelata functia membru. Utilizarea pointerului this poate fi pusa in evidenta in functia care insereaza o componenta intr-o lista dublu inlantuita.

Exemplu:

            ………………….

class clsinsert

{

  clsinsert *anterior;

  clsinsert *urmator;

  public:

            void finsert(clsinsert *);

            ……………………….

};

void clsinsert::finsert(clsinsert *ptr)

{

   //utilizare implicita, ptr->urmator=this->urmator;

   ptr->urmator=urmator;

   //utilizare explicita a lui this

   ptr->anterior=this;

   //utilizare implicita, this->urmator->anterior=ptr;

   urmator->anterior=ptr; 

   //utilizare implicita, this->urmator=ptr;

   urmator=ptr; 

}

III. 6.  Structuri si uniuni, analogii cu clasele din C++

Limajul C++, dupa cum am mai precizat, reprezinta o extensie a limajului C. Toate facilitatile limbajului C se regasesc in limbajul C++. In continuare, se va pune accentul pe deosebirile dintre cele doua limbaje si, cu precadere, pe extensiile aduse de C++ la C.

In C++ clasele nu sunt, altceva, decat extensii ale structurilor din limbajul C. Mai mult, structurile in C++, sunt constructii mult mai puternice decat in C. Structurile, ca si clasele, pe langa date, pot contine descrieri si/sau declarari de functii prototip, inclusiv functii constructor,  care sunt de fapt metode publice ce au acelasi nume cu clasa si care se executa automat ori de cate ori se creeaza o instanta, un obiect, al unei clase, si functii destructor, care sunt tot metode publice ce au acelasi nume cu clasa si care se executa, de obicei, la terminarea programului pentru distrugerea instantei unui clase, cu scopul eliberarii memoriei alocate, anterior, instantei.

III. 6. 1. Structuri in limbajul C++

            In C++, o structura este, de fapt,  o clasa ai carei membri sunt declarati, in mod implicit, public. In consecinta in C++, la declararea unei variabile de tip structura nu mai este obligatorie precizarea cuvantului cheie struct.

Exemplu:

a)      descrierea unei structuri in C      b) descrierea unei structuri in C++

typedef struct                                      struct tip_student

  {                                                          {

     int matricola;                                       int matricola;

     char nume[20];                                    char nume[20];

     int nr_note;                                          int nr_note;

     double nota[15];                                 double nota[15];

     double media;                                    double media;

  }tip_student;                                       }

Iar declararea de variabile de tipul structurii de mai sus, in C si in C++ se face astfel:

a) struct tip_student s1,s2,student;   b)    tip_student s1,s2, student;

Problema 21 

            Sa se creeze un tablou de structuri de tip student (cod matricol, un numar in intervalul 1..999; nume student, un sir de 20 caractere; numar de note, un numar in intervalul 1..15, notele: nota(1), nota(2) … si media calculata) pentru maximum nmax (20) studenti si apoi sa se afiseze un tabel cu mediile studentilor, utilizandu-se declararea unei structuri specifice limbajului C++ care sa includa descrierea structurii, functia de citire si cea de afisare a informatiilor unui student.

#include<stdio.h>

#include<iostream.h>

#include<iomanip.h>

#include<conio.h>

#include<string.h>

#define nmax 20

struct tip_student

{

 int cm;

 char nume[20];

 int nrn;

 double nota[15];

 double media;

 void citeste_student(int wcm,char wnume[20],int wnrn,

               double wnota[15],double wmedia)

 {

   int i; 

   this->cm=wcm;

   strcpy(this->nume,wnume);

   this->nrn=wnrn;

   this->media=0;

   for(i=0;i<wnrn;i++)

   {

     this->media=this->media+wnota[i];

   }

   this->media=this->media/this->nrn;

   wmedia=this->media;

 }

 void afisaza_student()

 {

  printf("\n %5d %-22s %6.2lf",this->cm,this->nume,this->media);

 }

};

void main(void)

{

  tip_student student[nmax]; char r='d';

  int wcm,wnrn;char wnume[20];double wnota[15];

  int k,i=0;

  while((r=='d')&&(i<nmax))

  {

   do

   {

     printf("\n cod student (1..999):");

     scanf("%d",&wcm);

   }

   while((wcm<1)||(wcm>999));

   printf("\n nume student:");

   cin.getline(wnume,20,'\n');

   do

   {

     printf("\n nr note(1..15):");

     scanf("%d",&wnrn);

   }

   while((wnrn<1)||(wnrn>15));

   for(k=0;k<wnrn;k++)

   {

    do

     {

       printf("\n nota(%d)=",k);

       scanf("%lf",&wnota[k]);

     }

    while((wnota[k]<1)||(wnota[k]>10));

   }

   student[i].citeste_student(wcm,wnume,wnrn,wnota,0);

   i++;

   printf("\n continuati?(d/n):");

   r=getche();

  }

  printf("\n        mediile studentilor ");

  printf("\n =====================================");

  printf("\n  cod    nume si prenume        media ");

  printf("\n =====================================");

  for(k=0;k<i;k++) student[k].afisaza_student();

  printf("\n =====================================\n");

}

 

            Rezultatele executiei programului, de mai sus, sunt prezentate in continuare, putandu-se urmari cum se declara si se utilizeaza o structura care, pe langa campurile componente,  contine si doua functii membre, cu care se prelucreaza datele unei structuri date

 

 cod student (1..999):100

 nume student:popescu ilie

 nr note(1..15):3

 nota(0)=2.55

 nota(1)=8.45

 nota(2)=9.50

 

 continuati?(d/n):d

 cod student (1..999):200

 nume student:ionescu stefan

 nr note(1..15):4

 nota(0)=9.25

 nota(1)=7.50

 nota(2)=4.95

 nota(3)=8.30

 

 continuati?(d/n):d

 cod student (1..999):150

 nume student:tomescu stan

 nr note(1..15):2

 nota(0)=8.21

 nota(1)=6.13

 continuati?(d/n):n

 

        mediile studentilor

 ==========================

  cod  nume si prenume          media

 ==========================

   100 popescu ilie                   6.83

   200 ionescu stefan                7.50

   150 tomescu stan                  7.17

 ==========================

 

In problema de mai sus, citirea efectiva a campurilor unei componente a tabloui student poate fi inclusa chiar in definirea structurii tip_student, ca in problema de mai jos:

Problema 22 

Aceeasi problema ca cea de mai sus, cu deosebirea ca citire efectiva a campurilor unei componente a tabloului student se face in functia citeste_student(), membru al structurii tip_student.

#include<stdio.h>

#include<iostream.h>

#include<iomanip.h>

#include<conio.h>

#include<string.h>

#define nmax 20

struct tip_student

{

 int cm;

 char nume[20];

 int nrn;

 double nota[15];

 double media;

 void citeste_student()

 {

  int k; 

  int wcm,wnrn;char wnume[20];

  double wnota[15],wmedia;   

  do

   {

     printf("\n cod student (1..999):");

     scanf("%d",&wcm);

   }

  while((wcm<1)||(wcm>999));

  printf("\n nume student:");

  cin.getline(wnume,20,'\n');

  do

   {

     printf("\n nr note(1..15):");

     scanf("%d",&wnrn);

   }

  while((wnrn<1)||(wnrn>15));

  for(k=0;k<wnrn;k++)

  {

   do

    {

      printf("\n nota(%d)=",k);

      scanf("%lf",&wnota[k]);

    }

   while((wnota[k]<1)||(wnota[k]>10));

  }

  this->cm=wcm;

  strcpy(this->nume,wnume);

  this->nrn=wnrn;

  this->media=0;

  for(k=0;k<wnrn;k++)

  {

   this->media=this->media+wnota[k];

  }

  this->media=this->media/this->nrn;

  wmedia=this->media;

 }

 void afisaza_student()

 {

  printf("\n %5d %-22s %6.2lf",this->cm,this->nume,this->media);

 }

}; // sfarsitul definirii structurii tip_student

void main(void)

{

  tip_student student[nmax]; char r='d';

  int i=0,k;

  while((r=='d')&&(i<nmax))

  {

   student[i].citeste_student();

   i++;

   printf("\n continuati?(d/n):");

   r=getche();

  }

  printf("\n        mediile studentilor ");

  printf("\n =====================================");

  printf("\n  cod    nume si prenume        media ");

  printf("\n =====================================");

  for(k=0;k<i;k++) student[k].afisaza_student();

  printf("\n =====================================\n");

}

 

III. 6. 2. Uniuni in limbajul C++

            In limbajul C++, tipul uniune de date, precizat prin cuvantul cheie union, se defineste in mod similar cu definirea unei structuri, adica, tot ca si o clasa ai carei membri sunt considerati in mod implicit public, pana la prima declaratie private explicita. Ca si la declararea variabilelor de tip structura, in C++, la declararea unei variabile de tip union nu mai este obligatorie precizarea cuvantului cheie union. Dupa cum se stie, fata de o structura, tipul union declara date de acelasi tip sau de tipuri diferite care utilizeaza in comun aceeasi zona de memorie, dar la momente diferite de timp. Partajarea aceleasi zone de memorie de catre doua sau mai multe variabile nu se poate realiza cu o structura sau o clasa obisnuita. Tipul union de date are si cateva restrictii importante cum ar fi:

- nu poate include obiecte care sa contina functii constructor si destructor, fara a se intelege ca tipul union nu poate avea definite functii constructor si destructor proprii.

- nu poate include membri statici: date si functii statice

- nu poate fi mostenirea altei clase si nu poate servi, ca baza, pentru definirea, derivarea, altei clase.

Problema 23

            Se introduc, pe rand, de la tastatura oricare n (1<=n<=nmax) numere reale (float) si 2*n numere intregi (int) si  care vor folosi in comun aceasi zona de memorie. Sa se afiseze, pe rand, numerele introduse, cele reale si cele integi, impreuna cu mediile lor aritmetice, utilzandu-se un tip union adecvat care sa contina datele care utilizeaza in comun aceeasi zona de memorie precum si functiile membru de citire, calcul medii si de afisare a datelor si rezultatelor.

#include <stdio.h>

#include <conio.h>

#include<malloc.h>

const int nmax=20;

union tipnumere

{

 long int x[nmax];

 double y[nmax/2];

 void citeste_intregi(long int n)

  {

    int k;

    printf("\n introduceti cele %d de nr. intregi in uniunea u:",n);

    for (k=0;k<n;k++)

    {

      printf("\n x(%d)=",k);

      scanf("%d",&this->x[k]);

    }

  }

 void citeste_reale(long int n)

  {

    int k;

    printf("\n introduceti cele %d de numere reale din uniunea u:",n/2);

    for (k=0;k<(n/2);k++)

     {

       printf("\n y(%d)=",k);

       scanf("%lf",&this->y[k]);

     }

  }

 void calcul_medie_intregi(int n)

  {

    int k;

    double mint=0;

    printf("\n nr intregi si calculul medie in uniune:\n");

    /* insumarea numerelor intregi */

    for(k=0;k<n;k++)

     {

       printf("%ld ",this->x[k]);

       mint=mint+this->x[k];

     }

    printf("\n media arit. a celor %d nr. intregi=%1.2lf",n,mint/n);

  }

 void calcul_medie_reale(int n)

  {

    int k;

    double mfloat=0;

    printf("\n nr reale si calculul medie in uniune:\n");

    /* insumarea numerelor intregi */

    for(k=0;k<(n/2);k++)

     {

       printf("%1.2lf ",this->y[k]);

       mfloat=mfloat+this->y[k];

     }

    printf("\n media arit. a celor %d nr.reale=%1.2lf",n/2,2*mfloat/n);

  }

}; // sfarsitul descrierii uniunii

void main(void)

{

  tipnumere u,v1,v2,*pv1,*pv2;int k,n;

  double mint,mfloat; char r='d';

while(r=='d')

  {

   mint=0,mfloat=0;

   do

    {

      printf("\n nr par de numere intregi (1<=n<=%d):",nmax);

      scanf("%d",&n);

    }

   while((n<1)||(n>nmax)||(n%2));

   // apelarea functiei membru ptr citirea a n nr intregi

   u.citeste_intregi(n); 

   v1=u; /* atribuire de variabila de tip uniune cu numere intregi*/

   // apelarea functiei membru ptr citirea a n/2 nr reale  

   u.citeste_reale(n);

   v2=u; /* atribuire de variabila de tip uniune cu numere reale*/

   pv1=&v1; /* adresa variabilei uniune v1 in pointerul pv1 */

   pv2=&v2; /* adresa variabilei uniune v2 in pointerul pv2 */

   /* afisarea numerelor intregi si calcularea mediei aritmetice a acestora */

   // apelarea functiei membru ptr calculul mediei nr intregi

   v1.calcul_medie_intregi(n);

   printf("\n nr intregi si media calculate in main:\n");

   /* insumarea numerelor intregi */

   for(k=0;k<n;k++)

    {

      printf("%ld ",pv1->x[k]);

      mint=mint+pv1->x[k];

    }

   printf("\n media celor %d nr. intregi=%1.2lf",n,mint/n);

   /* afisarea numerelor reale si calcularea mediei aritmetice a acestora */

   // apelarea functiei membru ptr calculul mediei nr reale

   v2.calcul_medie_reale(n);

   printf("\n nr reale si media calculate in main:\n");

   /* insumarea numerelor reale */

   for(k=0;k<(n/2);k++)

    {

      printf("%1.2lf ",pv2->y[k]);

      mfloat=mfloat+pv2->y[k];

    }

   printf("\n media celor %d nr. reale=%1.2lf",n/2,2*mfloat/n);

   printf("\n continuati?(d/n):");

   r=getche();

  }

}

            Rezultatele executiei programului, de mai sus, sunt prezentate in continuare, putandu-se urmari cum se declara si se utilizeaza o uniune de date care, pe langa campurile componente,  contine si functii membre, cu care se prelucreaza datele uniunii ce folosesc aceeasi zona de memorie in comun

 

 nr par de numere intregi (1<=n<=20):4

 introduceti cele 4 de nr. intregi in uniunea u:

 x(0)=25

 x(1)=45

 x(2)=65

 x(3)=35

 introduceti cele 2 de numere reale din uniunea u:

 y(0)=67.77

 y(1)=99.12

 nr intregi si calculul medie in uniune:

 25 45 65 35

 media arit. a celor 4 nr. intregi=42.50

 nr intregi si media calculate in main:

 25 45 65 35

 media celor 4 nr. intregi=42.50

 nr reale si calculul medie in uniune:

 67.77 99.12

 media arit. a celor 2 nr.reale=83.44

 nr reale si media calculate in main:

 67.77 99.12

 media celor 2 nr. reale=83.44

 

 continuati?(d/n):d

 nr par de numere intregi (1<=n<=20):6

 introduceti cele 6 de nr. intregi in uniunea u:

 x(0)=10

 x(1)=20

 x(2)=30

 x(3)=40

 x(4)=50

 x(5)=60

 introduceti cele 3 de numere reale din uniunea u:

 y(0)=23.45

 y(1)=67.97

 y(2)=-34.56

 nr intregi si calculul medie in uniune:

 10 20 30 40 50 60

 media arit. a celor 6 nr. intregi=35.00

 nr intregi si media calculate in main:

 10 20 30 40 50 60

 media celor 6 nr. intregi=35.00

 nr reale si calculul medie in uniune:

 23.45 67.97 -34.56

 media arit. a celor 3 nr.reale=18.95

 nr reale si media calculate in main:

 23.45 67.97 -34.56

 media celor 3 nr. reale=18.95

 continuati?(d/n):n

 

Observatie:  

Limbajul C++ accepta uniunile anonime, fara specificarea numelui uniunii, ca in programul de mai jos:

Problema 24

Se considera o uniune anonima, fara nume, de trei date: intreaga, reala si caracter. Sa se afiseze pe rand toate datele intregi, reale si caracter tastate.

#include<iostream.h>void main(void)

{

 union

 {

   int x;

   double y;

   char z;

 };

 char r='d';

 while(r=='d')

 {

   cout<<"\n dati un nr intreg, x=";

   cin>>x;

   cout<<"\n ati tastat nr intreg "<<x;

   cout<<"\n dati un nr real, y=";

   cin>>y;

   cout<<"\n ati tastat nr real "<<y;

   cout<<"\n dati un caracter, z=";

   cin>>z;

   cout<<"\n ati tastat caracterul "<<z;

   cout<<"\n continuati?(d/n):";

   cin>>r;

 }

}

Problema 25

            Se considera trei siruri: primul de numere intregi, al doilea  de caractere si al treilea de numere reale, care utilizeaza in comun aceeasi zona de memorie. Cu ajutorul unei uniuni a celor trei tipuri de data, sa se citeasca, pe rand, elementele sirurilor, cu ajutorul unei functii membru (citeste_sir), sa se ordoneze crescator fiecare sir cu o alta functie membru (ordoneaza_sir) si apoi sa se afiseze sirurile astfel ordonate cu alta functie membru (afisaza_sir)

#include<iostream.h>

#define nmax1 20

#define nmax2 15

#define nmax3 10

int i;

union tip_siruri

 {

  int sint[nmax1];

  char scar[nmax2];

  double sreal[nmax3];

  void citeste_sir(int n,char tsir) //functia membru de citire

  {

   for(i=0;i<n;i++)

   {

    if(tsir=='i')

    {

     cout<<"\n sint("<<i<<")=";

     cin>>sint[i];

    }

    if(tsir=='c')

    {

     cout<<"\n scar("<<i<<")=";

     cin>>scar[i];

    }

    if(tsir=='r')

    {

     cout<<"\n sreal("<<i<<")=";

     cin>>sreal[i];

    }

   }

  }

  void afisaza_sir(int n,char tsir) //functia membru de afisare

  {

   for(i=0;i<n;i++)

   {

    if(tsir=='i') cout<<sint[i]<<' ';

    if(tsir=='c') cout<<scar[i]<<' ';

    if(tsir=='r') cout<<sreal[i]<<' ';

   }

  }

  void ordonare_sir(int n,char tsir) //functia membru de ordonare

  {

   int ok,i,auxi; char auxc;double auxr;

   ok=1;

   while(ok)

   {

    ok=0;

    for(i=0;i<n-1;i++)

    {

      if(tsir=='i')

       {

         if(sint[i]>sint[i+1])

         {

          auxi=sint[i];sint[i]=sint[i+1];

          sint[i+1]=auxi;ok=1;

         }

        }

       if(tsir=='c')

        {

         if(scar[i]>scar[i+1])

          {

           auxc=scar[i];scar[i]=scar[i+1];

           scar[i+1]=auxc;ok=1;

          }

        }

       if(tsir=='r')

        {

         if(sreal[i]>sreal[i+1])

          {

           auxr=sreal[i];sreal[i]=sreal[i+1];

           sreal[i+1]=auxr;ok=1;

          }

         }

     }

   }

  }

 };

void main(void)

{

 tip_siruri u; 

 int n;char r='d';

 while(r=='d')

  {

   do

    {

      cout<<"\n dati nr de intregi de citit(n<"<<nmax1<<")=";

      cin>>n;

    }

   while((n<1)||(n>nmax1));

   cout<<"\n se citesc "<<n<<" intregi:\n";

   cout<<"===============================";

   u.citeste_sir(n,'i');

   u.ordonare_sir(n,'i');

   cout<<"\n=============================";

   cout<<"\n sirul de intregi ordonat:";

   u.afisaza_sir(n,'i');

   cout<<"\n=============================";

   do

    {

      cout<<"\n dati nr de caractere de citit(n<"<<nmax2<<")=";

      cin>>n;

    }

   while((n<1)||(n>nmax2));

   cout<<"\n se citesc "<<n<<" caractere:";

   cout<<"\n=============================";

   u.citeste_sir(n,'c');

   u.ordonare_sir(n,'c');

   cout<<"\n=============================";

   cout<<"\n sirul de caractere ordonat:";

   u.afisaza_sir(n,'c');

   cout<<"\n=============================";

   do

    {

      cout<<"\n dati nr de reali de citit(n<"<<nmax3<<")=";

      cin>>n;

    }

   while((n<1)||(n>nmax3));

   cout<<"\n se citesc "<<n<<" reali:\n";

   cout<<"\n=============================";

   u.citeste_sir(n,'r');

   u.ordonare_sir(n,'r');

   cout<<"\n=============================";

   cout<<"\n sirul de reali ordonat:";

   u.afisaza_sir(n,'r');

   cout<<"\n=============================";

   cout<<"\n continuati?(d/n):";

   cin>>r;

  }

}.

            Rezultatele executiei programului, sunt prezentate in continuare, putandu-se urmari cum se declara si se utilizeaza o uniune de siruri de date care, pe langa aceste siruri,  contine si functii membre (citeste_sir(), afisaza_sir() si ordonare_sir()), cu care se prelucreaza datele uniunii, de tip siruri de date, ce folosesc aceeasi zona de memorie in comun

 

 dati nr de intregi de citit(n<20)=4

 se citesc 4 intregi:

===============================

 sint(0)=45

 sint(1)=-34

 sint(2)=78

 sint(3)=-90

=============================

 sirul de intregi ordonat:-90 -34 45 78

=============================

 dati nr de caractere de citit(n<15)=5

 se citesc 5 caractere:

=============================

 scar(0)=i

 scar(1)=y

 scar(2)=3

 scar(3)=a

 scar(4)=f

=============================

 sirul de caractere ordonat:3 a f i y

=============================

 dati nr de reali de citit(n<10)=4

 se citesc 4 reali:

=============================

 sreal(0)=32.45

 sreal(1)=89.45

 sreal(2)=-67.99

 sreal(3)=-23.33

=============================

 sirul de reali ordonat:-67.99 -23.33 32.45 89.45

=============================

 continuati?(d/n):d

 dati nr de intregi de citit(n<20)=3

 se citesc 3 intregi:

===============================

 sint(0)=45

 sint(1)=-34

 sint(2)=18

=============================

 sirul de intregi ordonat:-34 18 45

=============================

 dati nr de caractere de citit(n<15)=4

 se citesc 4 caractere:

=============================

 scar(0)=k

 scar(1)=a

 scar(2)=w

 scar(3)=h

=============================

 sirul de caractere ordonat:a h k w

=============================

 dati nr de reali de citit(n<10)=3

 se citesc 3 reali:

=============================

 sreal(0)=-34.78

 sreal(1)=67.33

 sreal(2)=-97.5

=============================

 sirul de reali ordonat:-97.5 -34.78 67.33

=============================

 continuati?(d/n):n

 

 

 

 

 

 

 

III. 7. Declararea si utilizarea functiilor de clasa speciale

III. 7. 1. Functiile constructor

            In mod uzual, cand intr-un program se creeaza o instanta obiect a unei clase, atunci se vor atribui valori initiale datelor membru ale acelui obiect. Pentru simplificarea procesului de initializare a membrilor obiectelor declarate, limbajul C++ accepta declararea si utilizarea unei functii speciale, numita functie constructor, care se executa automat la creearea unei instante a  clasei din care face parte functia.

            Structura generala a unei clase cu functie constructor este data mai jos:

class nume_clasa

 {

    public:

      // declararea si/sau descrierea functiei constructor

      nume_clasa (parametri_formali)

        {

            //descrierea algoritmului functiei constructor

        }

      // declararea datelor publice

      // declararea si sau descrierea functiilor publice

    private:      

      // declararea datelor private

      // declararea si/sau descrierea functiilor private

    protected:  

      // declararea datelor protejate

      // declararea si/sau descrierea functiilor protejate

  }

Observatii:

-          numele functiei constructor trebuie sa fie acelasi cu numele clasei la care este atasata

-    descrierea efectiva a functiei constructor se poate face in corpul clasei respective sau, ulterior, in afara clasei, declararea prototipului sau fiind obligatorie in interiorul clasei, ca mai jos:

nume_clasa:: nume_clasa (parametri_formali)

  {

    // descrierea algoritmului functiei constructor

  }

-   transmiterea parametrilor efectivi, la apelarea unei functii constructor, se face in partea executabila a programului astfel:

nume_clasa  nume_functie(parametri_efectivi);

-   parametrii efectivi transmisi pot fi utilizati pentru initializarea unui obiect creat in partea executabila a programului sau pentru initializarea  membrilor clasei respective.

-   functia constructor se executa automat cand, in program, se creeaza o instanta a clasei respective

-  prin definitie, functia constructor nu returneaza nici o valoare, deci numele sau nu poate fi precedat de nici un tip

-   la compilare se va apela functia constructor numai atunci cand in program se declara un obiect al clasei corespunzatoare. Momentul real, in care compilatorul apeleaza codul functiei constructor, este dictat de tipul clasei si de locul din cadrul programului. Cand in program se creaza mai multe obiecte in aceeasi instructiune, apelarea si executarea functiilor constructor se va face in ordinea declararii acestora, adica de la stanga la dreapta. De asemenea, functia constructor a unei instante locale se va executa cand, in partea executabila a programului, se va intalni instructiunea de declarare a unui obiect al clasei respective. 

-   cand exista ambiguitati intre datele clasei si parametrii functiei constructor, cum ar fi utilizarea acelorasi identificatori,  se procedeaza la calificarea datelor clasei cu ajutorul operatorului de rezolutie ::, ca mai jos:

nume_clasa::nume_data;

            -   functiile constructor admit si valori implicite ale parametrilor formali, care, in lipsa transmiterii de parametri efectivi de catre o instanta a clasei respective, sunt utilizate pentru initializarea datelor clasei.

Problema 26

            Se considera  fisele de materiale dintr-un depozit cu materiale de constructii cu informatiile: cod material, un intreg cuprins intre 10000 si 99999; denumire material, un sir de 20 caractere maxim; unitatea de masura in multimea (bc, kg, ml, mp, mc, l, hl); pretul, un numar real si pozitiv; cantitatea din stoc, un numar real si pozitiv si valoarea, calculata ca produs intre cantitate si pret. Prin intermediul unei clase, in care s-a declarat o functie constructor, sa se initializeze datele referitoare la fiecare material din magazie: codul, denumirea si unitatea de masura de tip public, iar pretul, cantitatea si valoarea de tip privat. Prin intermediul unei functii membru te tip public sa se afiseeze datele publice: codul, denumirea si unitatea de masura iar prin intermediul unei functii private sa se afiseze si celelalte date private.

// definirea clasei material

#include<iostream.h>

#include<string.h>

class material

 {

   public:

     material(int codmat, char *denum, char *umas, double pret, double cant, double val)

       {

            material::cod_material=codmat;

            strcpy(material ::denumire, denum); 

            strcpy(material ::unitate_masura, umas); 

            material::pret_material=pret;

            material::cantitate_stoc=cant;

            material::valoare_stoc=cant*pret;

       };

     int cod_material;

     char denumire[20];

     char unitate_masura[2];

     void afiseaza_fisa(void)

       {

          afiseaza_date_publice();

          afiseaza_date_private();

        };

      void afiseaza_date_publice()

        {

            cout<<"\n   Informatii de nomenclator ale materialului:"<<endl;

            cout<<"\n ===================================="<<endl;

            cout <<"\n codul materialui: "<<cod_material;  

            cout <<"\n denumirea materialului: "<<denumire;  

            cout <<"\n unitatea de masura: "<<unitate_masura;  

            cout<<"\n ===================================="<<endl;

        }; 

   private:

       double pret_material;

       double cantitate_stoc;

       double valoare_stoc;     

       void afiseaza_date_private()

         {

            cout<<"\n  Informatii specifice materialului:"<<endl;

            cout<<"\n ===================================="<<endl;

            cout<<"\n pretul materialului:"<<material::pret_material;

            cout<<"\n cantitatea din stoc:"<<material::cantitate_stoc;

            cout<<"\n valoarea stocului:"<<material::valoare_stoc;

            cout<<"\n ===================================="<<endl;

         }; 

  };

void main()

  {

      int wcod; char wdenum[20],wumas[2];

      double wpret, wcant, wval=0;

      char r='d';

      while(r=='d')

        {

           cout<<"\n codul materialului:";

           cin>>wcod;

           cout<<"\n denumirea materialului:";

           cin>>wdenum;

           cout<<"\n unitatea de masura:";

           cin>>wumas;

           cout<<"\n pretul materialului:";

           cin>>wpret;

           cout<<"\n cantitatea din stoc:";

           cin>>wcant;

           material fisa(wcod,wdenum,wumas,wpret,wcant,wval);

           fisa.afiseaza_fisa();

           cout<<"\n continuati?(d/n):";

           cin>>r;

        }

  }

            Rezultatele executiei acestui program, mai jos afisate, arata cum se transmit parametri efectivi functiei constructor material, cum se initializeaza datele publice si private si cum se apeleaza, pentru afisarea datelor initializate, functiile publice si private definite in clasa material.

 

 codul materialului:20000

 denumirea materialului:fier*beton*fi16

 unitatea de masura:kg

 pretul materialului:22.55

 cantitatea din stoc:200

 

   Informatii de nomenclator de materiale:

 =========================================

 codul materialui: 20000

 denumirea materialului: fier*beton*fi16

 unitatea de masura: kg

 ====================================

  Informatii specifice materialului:

 ====================================

 pretul materialului:22.55

 cantitatea din stoc:200

 valoarea stocului:4510

 ====================================

 continuati?(d/n):d

 codul materialului:30000

 denumirea materialului:ciment*alb

 unitatea de masura:bc

 pretul materialului:16

 cantitatea din stoc:150

  

 Informatii de nomenclator de materiale:

 ====================================

 codul materialui: 30000

 denumirea materialului: ciment*alb

 unitatea de masura: bc

 ====================================

 Informatii specifice materialului:

 ====================================

 pretul materialului:16

 cantitatea din stoc:150

 valoarea stocului:2400

 ====================================

 continuati?(d/n):n

            Deoarece, identificarorii datelor, declarate in interiorul clasei, sunt diferiti de identificatorii parametrilor formali ai functiei constructor, nu exista ambiguitati in folosirea acestora, fara calificarea lor cu ajutorul operatorului de rezolutie ::. In functia afiseaza_date_publice() nu s-a folosit calificarea datelor membre (cod_material, denumire, unitate_masura), in schimb, in functia afiseaza_date_private() s-a folosit calificarea cu ajutorul operatorului de rezolutie ::, desi nu era necesara, neexistand ambiguitati de calificare a datelor  (material::pret_material, material::cantitate_stoc, material::valoare_stoc).

 

Problema 27

            Se considera o suma s0=100000 depusa initial la o banca, cu dobanda 10% pe o perioada de 10 ani. Sa se determine, dupa fiecare  an suma cumulata si dobanda cumulata, utilizandu-se o clasa cu functie constructor corespunzatoare avand parametri impliciti dati (s0=100000, p=10% si n=10 ani), care sa permita, totodata, obtinerea rezultatelor pentru orice suma s0 (100000<=s0<=1000000), orice dobanda p (10<<p<=100) si pentru orice perioada n (5<=n<=20).

#include<iostream.h>

#include<iomanip.h>

// definirea clasei dobanda

class dobanda

{

 public:

   // prototipul functiei constructor dobanda()

   dobanda(double s0=100000, double p=10, int n=10);

   // declararea datelor membru publice

   double s0;

   double p;

   int n;

   // prototipul functiei afiseaza_linie,ce lanseaza

   // functiile:calcul_dobanda() si afisare_rezultat()

   void afiseaza_linie(int m);   

 private:

   // declararea datelor membru private

   double suma_cumulata;

   double dobanda_cumulata;

   // prototipul functiei de calcul a sumei si dobanzii cumulate

   void calcul_dobanda(int k);

   // prototipul functiei afiseaza_rezultat()

   // ce afiseaza rezultatele dupa un anumit an

   void afiseaza_rezultat(int k);

};

// descrierea functiei constructor in afara clasei

dobanda::dobanda(double s0, double p, int n)

{

 int i;

 dobanda::s0=s0;

 dobanda::p=p;

 dobanda::n=n;

 cout<<"\n suma depusa="<<s0<<" dobanda=";

 cout<<p<<"%"<<" perioada="<<n<<" ani";

 cout<<"\n   =====================================";

 cout<<"\n   anul suma cumulata dobanda cumulata";

 cout<<"\n   =====================================";

 for(i=1;i<=n;i++) afiseaza_linie(i);

 cout<<"\n   =====================================";

}

// descrierea functiei calcul_dobanda in afara clasei

void dobanda::calcul_dobanda(int k)

{

 int j;

 suma_cumulata=dobanda::s0;

 for (j=1;j<=k;j++)

 {

  suma_cumulata=suma_cumulata+suma_cumulata*dobanda::p/100;

  dobanda_cumulata=suma_cumulata-dobanda::s0;

 }

};

// descrierea functiei afiseaza_rezultat in afara clasei

void dobanda::afiseaza_rezultat(int k)

{

 cout<<"\n "<<setw(4)<<k<<" ";

 cout<<"  "<<setw(13)<<setiosflags(ios::fixed);

 cout<<setprecision(2)<<dobanda::suma_cumulata;

 cout<<"  "<<setw(13)<<setiosflags(ios::fixed);

 cout<<setprecision(2)<<dobanda::dobanda_cumulata;

}; 

// descrierea functiei afiseaza_linie in afara clasei

void dobanda::afiseaza_linie(int m)

{

 calcul_dobanda(m);

 afiseaza_rezultat(m);

}

// descrierea functiei principale main

void main()

{

 int wn; double wp, ws0;

 char r='d',tip_depozit;

 while(r=='d')

 {

  cout<<"\n tip depozit implicit(s0=100000,p=10%,n=10 ani)?(d/n):";

  cin>>tip_depozit;

  if (tip_depozit=='d')

  {

   cout<<"\n tip depozit implicit(s0=100000,p=10%,n=10 ani)";     

   //apelarea functiei constructor cu parametri impliciti

   dobanda implicit;

  }

  else

  {

   // citirea parametrilor efectivi expliciti

   cout<<"\n tip depozit explicit(s0<>100000,p<>10%,n<>10 ani)";

   do

   {

    cout<<"\n suma initiala depusa (100000<=s0<=1000000):";

    cin>>ws0;

   }

   while((ws0<100000)||(ws0>1000000));

   do

   {

    cout<<"\n dobanda anuala % (10<=p<=100):";

    cin>>wp;

   }

   while((wp<10)||(wp>100));

   do

   {

    cout<<"\n perioada depozitului (5<=n<=20):";

    cin>>wn;

   }

   while((wn<5)||(wn>20));

   //apelarea functiei constructor cu parametri expliciti

   dobanda explicita(ws0,wp,wn);

  }

  cout<<"\n continuati?(d/n):";

  cin>>r;

 }

}

            In urma executarii acestui program, s-au obtinut urmatoarele rezultate, care scot in evidenta: declararea prototipurilor tuturor functiilor, in corpul clasei, inclusiv a functiei constructor cu parametri formali impliciti, descriera tuturor functiilor in afara clasei, apelarea functiei constructor cu si fara  parametri efectivi expliciti.

 

 tip depozit implicit(s0=100000,p=10%,n=10 ani)?(d/n):d

 tip depozit implicit(s0=100000,p=10%,n=10 ani)

 suma depusa=100000 dobanda=10% perioada=10 ani

   =====================================

   anul suma cumulata dobanda cumulata

   =====================================

    1       110000.00         10000.00

    2       121000.00         21000.00

    3       133100.00         33100.00

    4       146410.00         46410.00

    5       161051.00         61051.00

    6       177156.10         77156.10

    7       194871.71         94871.71

    8       214358.88       114358.88

    9       235794.77       135794.77

   10      259374.25       159374.25

   =====================================

 continuati?(d/n):d

 tip depozit implicit(s0=100000,p=10%,n=10 ani)?(d/n):n

 tip depozit explicit(s0<>100000,p<>10%,n<>10 ani)

 suma initiala depusa (100000<=s0<=1000000):1000000

 dobanda anuala % (10<=p<=100):100

 perioada depozitului (5<=n<=20):8

 suma depusa=1000000.00 dobanda=100.00% perioada=8 ani

   =====================================

   anul suma cumulata dobanda cumulata

   =====================================

    1        2000000.00          1000000.00

    2        4000000.00          3000000.00

    3        8000000.00          7000000.00

    4      16000000.00        15000000.00

    5      32000000.00        31000000.00

    6      64000000.00        63000000.00

    7    128000000.00      127000000.00

    8    256000000.00      255000000.00

   =====================================

 continuati?(d/n):d

 tip depozit implicit(s0=100000,p=10%,n=10 ani)?(d/n):d

 tip depozit implicit(s0=100000,p=10%,n=10 ani)

 suma depusa=100000.00 dobanda=10.00% perioada=10 ani

   =====================================

   anul suma cumulata dobanda cumulata

   =====================================

    1         110000.00        10000.00

    2         121000.00        21000.00

    3         133100.00        33100.00

    4         146410.00        46410.00

    5         161051.00        61051.00

    6         177156.10        77156.10

    7         194871.71        94871.71

    8         214358.88      114358.88

    9         235794.77      135794.77

   10        259374.25      159374.25

   =====================================

 continuati?(d/n):n

III. 7. 2. Alocarea memoriei prin functiile constructor. Controlul alocarii memoriei.

Dupa cum s-a precizat, functiile constructor permit intializare datelor membre, inclusiv a datelor de tip tablouri, matrici. In cazul initializarii tablourilor, functiile constructor pot aloca memoria necesara tablourilor, putand controla modul in care s-a realizat alocarea de memorie ceruta. Alocarea memoriei necesare pentru tablouri de caractere se poate face simultan cu testarea modului in care s-a realizat efectiv alocarea, printr-o constructie de forma:

if (nume_functie_constructor::nume_tablou = new char[numar_octeti] == 0)

  {

    cerr<<”\n eroare de alocare a memoriei pentru tabloul nume_tablou”;

    exit(0);

  }

Constructia de mai sus, poate fi folosita pentru alocarea si verificarea alocarii pentru mai multe variabile de tip tablou, de tip caracter, in acelasi timp, ca mai jos:

…………………………………………………………………………….

nume_functie_constructor::nume_tablou1 = new char[numar_octeti1];

nume_functie_constructor::nume_tablou12= new char[numar_octeti2];

……………………………………………………………………………….

nume_functie_constructor::nume_tabloun = new char[numar_octetin];

if ((nume_functie_constructor::nume_tablou1  &&

     (nume_functie_constructor::nume_tablou2  &&

     …………………………………………………….

     (nume_functie_constructor::nume_tabloun ) == 0)

  {

    cerr<<”\n eroare de alocare a memoriei pentru toate tablourile specificate”;

    exit(0);

  }

Pentru alocarea memoriei, pentru oricare tipuri de tablouri, prin intermediul pointerilor la tablouri, se poate folosi functia de alocare dinamica malloc.

nume_functie_constructor::pointer_tablou1 = (tip_componenta1*)malloc(n*sizeof(tip_componenta1));

nume_functie_constructor::pointer_tablou2 = (tip_componenta2*)malloc(n*sizeof(tip_componenta2));

……………………………………………………………………

nume_functie_constructor::pointer_tabloun = (tip_componentan*)malloc(n*sizeof(tip_componentan));

iar verificarea alocarii necesarului de memorie se poate face asemanator ca la tablourile de siruri, prezentata mai sus.

if((!nume_functie_constructor::pointer_tablou1) ||

    (!nume_functie_constructor::pointer_tablou2) ||

     …………………………………………………

    (!nume_functie_constructor::pointer_tabloun)  == 0)

    {

      cout<<"\n alocarea dinamica a tablourilor, nereusita in functia constructor";

      exit(1);

    }

    

Problema 28

            Se da o matrice  dreptunghiulara de n linii si m coloane, unde m reprezinta numarul de tipuri de produse fabricate intr-o uzina, iar n numarul de tipuri de materiale folosite la fabricarea acestora. Un element al matricei a[i,j] reprezinta cantitatea, in aceeasi unitate de masura, din materialul i consumat pentru produsul j. Un vector de m componente contine numarul de produse fabricate din fiecare tip. Se cere sa se determine un vector de n componente care sa contina cantitatile totale, din fiecare tip de material, consumate pentru realizarea fabricatiei celor m tipuri de produse. Cunoscandu-se, apoi, intr-un vector, costurile unitare de materiale pe fiecare tip de material, sa se calculuze valoarea  fiecarui tip de material consumat si valoarea totala a tuturor materialelor consumate. Pentru rezolvarea acestei aplicatii se va folosi o clasa adecvat definita care contine o functie constructor ce va initializa datele membre de tip pointeri la tablouri si va calcula si afisa cele cerute in problema. Se vor folosi parametri formali si efectivi de tip pointer, pentru transmiterea lor intre functia principala si functia constructor, utilizanduse, din acest motiv, alocarea dinamica de memorie si verificarea alocarii memoriei dinamice necesara tablourilor.

 

#include<iostream.h>

#include<iomanip.h>

#include<malloc.h>

#include<stdlib.h>

#define nmax 20

#define mmax 20

int i,j;

// definirea clasei consunuri

class consumuri

{

 public:

   consumuri::consumuri(int n, int m, double *pc, double *pp, double *pv);

   // declararea datelor membru publice

   int n;

   int m;

   double *pc; //pointer la matricea consumurilor specifice

   double *pp; //pointer la vectorul produselor fabricate

   double *pv; //pointer la vectorul costurilor unitare ale materialelor

 private:

   double *pmateriale; //pointer la vectorul materialelor consumate

   double *pcosturi; //pointer la vectorul costurilor materialelor

   double costotal;

   //declararea prototipurilor functiilor membru private

   // prototipul functiei de afisare a consumurilor

   //specifice de materiale pe produse

   void afiseaza_matrice_consumuri(int n, int m);      

   // prototipul functiei de calcul a consumurilor de materiale

   void calcul_consumuri(int n, int m);

   // prototipul functiei de calcul ale costurilor de materiale

   void calcul_costuri_materiale(int n);

   // prototipul functiei de afiseare vector produse

   void afiseaza_vector_produse(int m);

   // prototipul functiei de afiseare vector consumuri de materiale

   void afiseaza_vector_consumuri(int n);

   // prototipul functiei de afiseare vector consturi unitare pe materiale

   void afiseaza_vector_costuri_unitare(int n);

   // prototipul functiei de afiseare vector consturi totale pe materiale

   void afiseaza_vector_costuri_materiale(int n);

};

// descrierea functiei constructor consumuri in afara clasei

consumuri::consumuri(int n, int m, double *pc, double *pp, double *pv)

{

 cout<<"\n functia constructor consumuri";

 // alocarea dinamica de memorie pentru tablourile aplicatiei

 consumuri::pc=(double*)malloc(nmax*mmax);

 consumuri::pp=(double*)malloc(mmax);

 consumuri::pv=(double*)malloc(nmax);

 consumuri::pmateriale=(double*)malloc(nmax);

 consumuri::pcosturi=(double*)malloc(mmax);

 //verificarea necesarului de memorie

if((!consumuri::pc) ||(!consumuri::pp) || (!consumuri::pc)  ||

    (!consumuri::pmateriale) || (!consumuri::pcosturi))

 {

   cout<<"\n alocarea dinamica a tablourilor, nereusita in functia constructor";

   exit(1);

 }

 consumuri::n=n;

 consumuri::m=m;

 // initializarea matricei consumurilor specifice

 for(i=0;i<n;i++)

    for(j=0;j<m;j++) consumuri::pc[i*m+j]=pc[i*m+j];

 // initializarea vectorului produselor fabricate

 for(i=0;i<m;i++) consumuri::pp[i]=pp[i];

 // initializarea vectorului costurilor unitare ale materialelor folosite

 for(i=0;i<n;i++) consumuri::pv[i]=pv[i];

 cout<<"\n matricea consumurilor de materiale pe produse";

 cout<<"\n================================\n";

 afiseaza_matrice_consumuri(n,m);

 cout<<"\n=================================";

 cout<<"\n      vectorul produselor fabricate";

 cout<<"\n ================================\n";

 afiseaza_vector_produse(m);

 cout<<"\n ================================\n";

 cout<<"\n   vectorul costurilor unitare pe materiale\n";

 cout<<"\n =================================";

 afiseaza_vector_costuri_unitare(n);

 cout<<"\n =================================";

 calcul_consumuri(n,m);

 cout<<"\n      vectorul materialelor consumate";

 cout<<"\n ================================\n";

 afiseaza_vector_consumuri(n);

 cout<<"\n =================================";

 calcul_costuri_materiale(n);

 cout<<"\n      vectorul costurilor totale pe materiale";

 cout<<"\n =================================";

 afiseaza_vector_costuri_materiale(n);

 cout<<"\n =================================";

};

// descrierea functiei calcul_consumuri

// in afara clasei cu ajutorul pointerilor

void consumuri::calcul_consumuri(int n,int m)

{

  for (i=0;i<n;i++)

   {

     consumuri::pmateriale[i]=0;

     for (j=0;j<m;j++)

      {

        consumuri::pmateriale[i]=consumuri::pmateriale[i]+

        consumuri::pc[i*m+j] * consumuri::pp[j];

      }

   }

}

// descrierea functiei calcul_costuri_materiale

//in afara clasei cu ajutorul pointerilor

void consumuri::calcul_costuri_materiale(int n)

{

 consumuri::costotal=0;

 for (i=0;i<n;i++)

 {

   consumuri::pcosturi[i]=consumuri::pmateriale[i] * consumuri::pv[i];

   consumuri::costotal= consumuri::costotal + consumuri::pcosturi[i];

 }

}

// descrierea functiei afiseaza_matrice_consumuri

//in afara clasei cu ajutorul pointerilor

void consumuri::afiseaza_matrice_consumuri(int n, int m)

{

 for(i=0;i<n;i++)

 {

   for(j=0;j<m;j++)

   {

     cout<<" "<<setw(7)<<setiosflags(ios::fixed);

     cout<<setprecision(3)<<consumuri::pc[i*m+j];

   }

   cout<<"\n";

 }

} 

// descrierea functiei afiseaza_vector_produse

// in afara clasei cu ajutorul pointerilor

void consumuri::afiseaza_vector_produse(int m)

{

 cout<<"\n";

 for(i=0;i<m;i++)

 {

   cout<<" "<<setw(7)<<setiosflags(ios::fixed);

   cout<<setprecision(2)<<consumuri::pp[i];

 }

} 

// descrierea functiei afiseaza_vector_consumuri

// in afara clasei cu ajutorul pointerilor

void consumuri::afiseaza_vector_consumuri(int n)

{

 cout<<"\n";

 for(i=0;i<n;i++)

 {

   cout<<" "<<setw(7)<<setiosflags(ios::fixed);

   cout<<setprecision(2)<<consumuri::pmateriale[i];

 }

} 

// descrierea functiei afiseaza_vector_consturi_unitare

// in afara clasei cu ajutorul pointerilor

void consumuri::afiseaza_vector_costuri_unitare(int n)

{

 cout<<"\n";

 for(i=0;i<n;i++)

 {

   cout<<" "<<setw(7)<<setiosflags(ios::fixed);

   cout<<setprecision(2)<<consumuri::pv[i];

 }

} 

// descrierea functiei afiseaza_vector_costuri_materiale

// in afara clasei cu ajutorul pointerilor

void consumuri::afiseaza_vector_costuri_materiale(int n)

{

 cout<<"\n";

 for(i=0;i<n;i++)

 {

   cout<<" "<<setw(7)<<setiosflags(ios::fixed);

   cout<<setprecision(2)<<consumuri::pcosturi[i];

 }

 cout<<"\n valoare totala costuri materiale="<<consumuri::costotal;

} 

// descrierea functiei principale main()

void main()

{

 int n,m;

 // declararea pointerilor la tablourile aplivatiei

 double *ptrc,*ptrp,*ptrv;

 char r='d';

 // alocarea memoriei pentru tablourile date in aplicatie

 ptrc=(double*)malloc(nmax*mmax);

 ptrp=(double*)malloc(mmax);

 ptrv=(double*)malloc(nmax);

 // verificarea alocarii memoriei pentru tablurile date in aplicatie

 if((!ptrc)||(!ptrp)||(!ptrv))

 {

   cout<<"\n alocarea tablourilor nereusita in functia principala";

   exit(1);

 }

 while(r=='d')

 {

   do

    {

      cout<<"\n numarul de produse fabricate,m(1<=m<=20):";

      cin>>m;

    }

   while((m<1)||(m>20));

   do

    {

      cout<<"\n numarul de materiale folosite,n(1<=n<=20):";

      cin>>n;

    }

   while((n<1)||(n>20));

   //citirea matricii consumurilor specifice de materiale pe produs

   for(i=0;i<n;i++)

     for(j=0;j<m;j++)

      {

        cout<<"\n materialul "<<i<<" din produsul "<<j<<" =";

        cin>>ptrc[i*m+j];

      }

   cout<<"\n matricea consumurilor:\n";

   for(i=0;i<n;i++)

    {

      for(j=0;j<m;j++)

       {  

          cout<<ptrc[i*m+j]<<" ";

       }

      cout<<"\n";

  }

  for(i=0;i<m;i++)

  {

    cout<<"\n numarul de bucati fabricate din produsul "<<i<<" =";

    cin>>ptrp[i];

  }

  for(i=0;i<n;i++)

  {

    cout<<"\n costul unitar al materialului "<<i<<" =";

    cin>>ptrv[i];

  } 

  //apelarea functiei constructor, consumuri, cu parametri expliciti

  consumuri functie_consumuri(n,m,ptrc,ptrp,ptrv);

  cout<<"\n continuati?(d/n):";

  cin>>r;

 }

}

            Rezultatele executiei programului sunt afisate in continuare, putandu-se usor observa, modul in care, unei functii constructor, i se transmit parametri efectivi de tip pointeri la tablouri, alocarea dinamica de memorie pentru tablourile pointate ale functiei principale main, cat si pentru datele membre, de tip pointeri la tablouri, ale clasei corespunzatoare si verificarea alocarii memoriei pentru tablourile aplicatiei.

 

 numarul de produse fabricate,m(1<=m<=20):3

 numarul de materiale folosite,n(1<=n<=20):2

 materialul 0 din produsul 0 =1

 materialul 0 din produsul 1 =2

 materialul 0 din produsul 2 =3

 materialul 1 din produsul 0 =4

 materialul 1 din produsul 1 =5

 materialul 1 din produsul 2 =6

 matricea consumurilor:

 1 2 3

 4 5 6

 numarul de bucati fabricate din produsul 0 =1

 numarul de bucati fabricate din produsul 1 =2

 numarul de bucati fabricate din produsul 2 =3

 costul unitar al materialului 0 =1

 costul unitar al materialului 1 =2

 functia constructor consumuri

 matricea consumurilor de materiale pe produse

 =============================================

   1.000   2.000   3.000

   4.000   5.000   6.000

 ==============================================

      vectorul produselor fabricate

 =============================================

    1.00    2.00    3.00

 =============================================

   vectorul costurilor unitare pe material

 =============================================

    1.00    2.00

 ==============================================

      vectorul materialelor consumate

 =============================================

   14.00   32.00

 ==============================================

    vectorul costurilor totale pe materiale

 =============================================

   14.00   64.00

 valoare totala costuri materiale=78.00

 ==============================================

 continuati?(d/n):d

 numarul de produse fabricate,m(1<=m<=20):2

 numarul de materiale folosite,n(1<=n<=20):3

 materialul 0 din produsul 0 =6

 materialul 0 din produsul 1 =5

 materialul 1 din produsul 0 =4

 materialul 1 din produsul 1 =3

 materialul 2 din produsul 0 =2

 materialul 2 din produsul 1 =1

 matricea consumurilor:

 6.00 5.00

 4.00 3.00

 2.00 1.00

 numarul de bucati fabricate din produsul 0 =1

 numarul de bucati fabricate din produsul 1 =2

 costul unitar al materialului 0 =1

 costul unitar al materialului 1 =2

 costul unitar al materialului 2 =3

 functia constructor consumuri

 matricea consumurilor de materiale pe produse

 =============================================

   6.000   5.000

   4.000   3.000

   2.000   1.000

 ==============================================

      vectorul produselor fabricate

 =============================================

    1.00    2.00

 =============================================

   vectorul costurilor unitare pe materiale

 =============================================

    1.00    2.00    3.00

 ==============================================

      vectorul materialelor consumate

 =============================================

   16.00   10.00    4.00

 ==============================================

      vectorul costurilor totale pe materiale

 =============================================

   16.00   20.00   12.00

 valoare totala costuri materiale=48.00

 ==============================================

 continuati?(d/n):n

III. 7. 3. Supraincarcarea functiilor constructor si a functiilor membre

            Dupa cum s-a invatat, functia constructor este o metoda speciala a claselor care se executa automat cand se creeaza diverse instante ale unui obiect. Supraincarcarea  functiilor presupune declararea si definirea unor functii cu acelasi nume, astfel incat, in functie de parametrii transmisi, la compilare, sa se poata decida care dintre functiile cu acelasi nume sa fie adresata. Ca orice functie in C++ si functiile constructor pot fi supraincarcate si adresate. Daca o functie constructor este supraincarcata, atunci, la creearea unei instante a unui obiect, se va executa totdeauna prima functie constructor, cea de-a doua executandu-se cand prima nu poate fi executata din diferite motive, ca de exemplu, transmiterea eronata a parametrilor.

Problema 29

            Se considera un vector care contine numarul variabil de perechi de pantaloni (p[20]), care se pot produce intr-o fabrica de confectii, costurile fixe necesare producerii acestor produse (cf), costul de productie variabil pe unitatea de produs (cp) si pretul de vanzare pe piata a acestui produs (pv). Se cere, utilizandu-se o functie constructor intr-o clasa adecvat definita, vectorul costurilor totale (ct), vectorul veniturilor obtinute prin vanzarea produselor (vt), vectorul profiturilor realizate si determinarea punctului critic care desparte zona pierderilor de zona de zona profitului. Se va utiliza supraincarcarea functiei constructor cu o a doua functie care sa afiseze un mesaj de eroare in cazul in care, functiei constructor principale, nu i se transmit toti parametrii necesari rezolvarii aplicatiei. De asemenea, se va utiliza tehnica pointerilor pentru vectorii utilizati, alocarea dinamica a memoriei necesare si verificarea alocarii corecte a volumului de memorie necesar.

#include<iostream.h>

#include<iomanip.h>

#include<malloc.h>

#include<stdlib.h>

#define nmax 20 //nr maxim de variante de productie

int i,j;

// definirea clasei cost_venit

class cost_venit

{

 public:

   // declararea primei functii constructor, de baza

   cost_venit (int n, int *p, double cf, double cp, double pv);

   // supraincarcarea functiei constructor prin declararea

   // celei de-a doua functie constructor

   cost_venit(void);

   // declararea datelor membru publice

   int n; // numarul de componente ale vectorului produse

   int *p; // pointer la vectorul cu cantitatile de produse de fabricat

   double cf; // cheltuielile fixe de fabricatie a produselor

   double cp; // cheltuielile variabile de fabricatie pe produs

   double pv; // pretul unitar de vanzare a produsului private:

 private: 

   // pointer la vectorul costurilor totale

   // pe cantitati variabile de productie

   double *ct;

   //pointer la vectorul veniturilor pe cantitati variabile de produse

   double *vt;

   int produs_critic;

   int maxim_produse; // numarul maxim de produse propuse ptr fabricare

   double cost_critic; // costul total critic

   double venit_critic;// venitul total critic

   // declararea prototipurilor functiilor membru private

   // prototipul functiei de ordonare vector produse

   void ordonare_vector_produse(int n);

   void determinare_max_produse(int n);

   // prototipul functiei de afisare a cantitatilor

   // produselor de fabricat

   void afiseaza_vector_produse(int n);          

   // prototipul functiei de afisare a datelor: cf,cp,pv

   // ale produselor de fabricat

   void afiseaza_date_produse(void); 

   // prototipul functiei de calcul al costurilor totale

   void calcul_costuri_produse(int n);

   // prototipul functiei de calcul ale veniturilor din vanzari

   void calcul_venituri_produse(int n);

   // prototipul functiei de afiseare vector costuri

   void afiseaza_vector_costuri(int n);

   // prototipul functiei de afiseare vector venituri

   void afiseaza_vector_venituri(int n);

   // prototipul functiei de afiseare vector profit

   void afiseaza_vector_profit(int n);

   // prototipul functiei de calcul al punctului critic

   void calcul_punct_critic(int n);

   // prototipul functiei de afiseare a punctului critic

   void afiseaza_punct_critic();

};

// descrierea primei functii constructor, de baza.

// cost_venit in afara clasei

cost_venit::cost_venit (int n, int *p, double cf, double cp, double pv)

{

 cout<<"\n functia constructor cost_venit";

 // alocarea dinamica de memorie pentru tablourile aplicatiei

 cost_venit::p=(int*)malloc(nmax);

 cost_venit::ct=(double*)malloc(nmax);

 cost_venit::vt=(double*)malloc(nmax);

 //verificarea necesarului de memorie

 if((!cost_venit::p) ||(!cost_venit::ct) || (!cost_venit::vt))

 {

   cout<<"\n alocarea dinamica a tablourilor, nereusita in functia constructor";

   exit(1);

 }

 // initializarea numarului cu variantele cantitatilor de fabricat

 cost_venit::n=n;

 // initializarea datei cu costurile fixe

 cost_venit::cf=cf;

 // initializarea datei cu costurile unitare pe produs

 cost_venit::cp=cp;

 // initializarea datei cu preturile unitare pe produs

 cost_venit::pv=pv;

 // initializarea vectorului cu cantitatile de fabricat

 for(i=0;i<n;i++) cost_venit::p[i]=p[i];

 cout<<"\n=================================";

 // lansarea functiei de ordonare vector de produse

 ordonare_vector_produse(n);

 cout<<"\n   vectorul produselor fabricate";

 cout<<"\n ================================\n";

 afiseaza_vector_produse(n);

 cout<<"\n ================================\n";

 cout<<"\n     datele produselor cf,cp,pv   ";

 cout<<"\n ================================\n";

 afiseaza_date_produse();

 cout<<"\n ================================\n";

 calcul_costuri_produse(n);

 cout<<"\n vectorul costurilor totale pe produse";

 cout<<"\n =======================================\n";

 afiseaza_vector_costuri(n);

 cout<<"\n =================================";

 calcul_venituri_produse(n);

 cout<<"\n vectorul veniturilor totale pe produse";

 cout<<"\n =======================================\n";

 afiseaza_vector_venituri(n);

 cout<<"\n =================================";

 cout<<"\n vectorul profitului total pe nr de produse";

 cout<<"\n =======================================\n";

 afiseaza_vector_profit(n);

 cout<<"\n =================================";

 determinare_max_produse(n);

 calcul_punct_critic(n);

}

// supraincarcarea functiei constructor prin declararea

// celei de-a doua functie constructor in afara clasei

cost_venit::cost_venit(void)

{

  cerr<<"\n lista parametrilor efectivi eronata";

  //exit(1);

}

// descrierea functiei calcul_costuri_produse

//in afara clasei cu ajutorul pointerilor

void cost_venit::ordonare_vector_produse(int n)

{

 int ok,paux;

 ok=1;

 while(ok)

 {

  ok=0;

  for(i=0;i<n-1;i++)

  {

   if(p[i]>p[i+1])

   {

            paux=cost_venit::p[i]; cost_venit::p[i]=p[i+1];

            cost_venit::p[i+1]=paux; ok=1;

   }

  }

 }

}

void cost_venit::determinare_max_produse(int n)

{

  cost_venit::maxim_produse=cost_venit::p[0];

  for(i=0;i<n;i++)

  if(cost_venit::p[i]>cost_venit::maxim_produse)

            cost_venit::maxim_produse=cost_venit::p[i];

  cout<<"\n nr maxim de produse de fabricat:";

  cout<<cost_venit::maxim_produse;

}

void cost_venit::calcul_costuri_produse(int n)

{

  for (i=0;i<n;i++)

  cost_venit::ct[i]=cost_venit::cf+cost_venit::cp * cost_venit::p[i];

}

// descrierea functiei calcul_venituri_produse

//in afara clasei cu ajutorul pointerilor

void cost_venit::calcul_venituri_produse(int n)

{

 for (i=0;i<n;i++)

 cost_venit::vt[i]=cost_venit::pv*cost_venit::p[i];

}

// descrierea functiei afiseaza_vector_produse

// in afara clasei cu ajutorul pointerilor

void cost_venit::afiseaza_vector_produse(int n)

{

 cout<<"\n";

 for(i=0;i<n;i++)

 {

  cout<<" "<<setw(7)<<setiosflags(ios::fixed);

  cout<<setprecision(2)<<cost_venit::p[i];

 }

} 

// descrierea functiei afiseaza_vector_costuri

//in afara clasei cu ajutorul pointerilor

void cost_venit::afiseaza_vector_costuri(int n)

{

 for(i=0;i<n;i++)

 {

  cout<<" "<<setw(7)<<setiosflags(ios::fixed);

  cout<<setprecision(3)<<cost_venit::ct[i];

 }

} 

// descrierea functiei afiseaza_vector_profit

//in afara clasei cu ajutorul pointerilor

void cost_venit::afiseaza_vector_profit(int n)

{

 for(i=0;i<n;i++)

 {

  cout<<" "<<setw(7)<<setiosflags(ios::fixed);

  cout<<setprecision(3)<<cost_venit::vt[i]-cost_venit::ct[i]<<" ";

 }

} 

// descrierea functiei afiseaza_vector_venituri

//in afara clasei cu ajutorul pointerilor

void cost_venit::afiseaza_vector_venituri(int n)

{

 for(i=0;i<n;i++)

 {

  cout<<" "<<setw(7)<<setiosflags(ios::fixed);

  cout<<setprecision(3)<<cost_venit::vt[i];

 }

} 

// descrierea functiei calcul_punct_critic

//in afara clasei cu ajutorul pointerilor

void cost_venit::calcul_punct_critic(int n)

{

 int ok=0;double ct,vt;

 for(i=0;i<cost_venit::maxim_produse;i++)

 {

  ct=cost_venit::cf+cost_venit::cp * i;

  vt=cost_venit::pv * i;

  if (vt<ct)

    continue;

  else

  {

   ok=1;

   cost_venit::cost_critic=ct;

   cost_venit::venit_critic=vt;

   cost_venit::produs_critic=i;

   break;

  }

 }

  if(!ok)

  {

    cout<<"\n nu exista punct critic";

    cout<<"\n la structura aleasa fabrica inregistreaza pierderi";

  }

  else

  {

   cout<<"\n afisarea punctului critic ";

   cout<<"\n =================================\n";

   afiseaza_punct_critic();

   cout<<"\n =================================\n";

  }

} 

// descrierea functiei afiseaza_punct_critic

//in afara clasei cu ajutorul pointerilor

void cost_venit::afiseaza_punct_critic()

{

  cout<<"\n punctul critic este atunci cand:\n";

  cout<<"\n nr produse ="<<cost_venit::produs_critic;

  cout<<"\n costurile totale ="<<cost_venit::cost_critic;

  cout<<"\n veniturile totale ="<<cost_venit::venit_critic;

} 

void cost_venit::afiseaza_date_produse()

{

 cout<<"\n cheltuielile fixe ale fabricii:"<<cost_venit::cf;

 cout<<"\n costul de productie pe produs :"<<cost_venit::cp;

 cout<<"\n pretul de vanzare al produsului:"<<cost_venit::pv;

} 

void main()

{

 int n;

 // declararea pointerului la vectorul produse al aplicatiei,

 // a cheltuielilor fixe, variabile pe produs si a pretului de vanzare

 int *ptrp; double cf,cp,pv;

 char r='d';

 // alocarea memoriei pentru tabloul produse

 ptrp=(int*)malloc(nmax);

 // verificarea alocarii memoriei pentru tablul de produse

 if(!ptrp)

 {

   cout<<"\n alocarea vectorului de produse nereusita in functia principala";

   exit(1);

 }

 while(r=='d')

 {

  do

  {

   cout<<"\n numarul de variante de  fabricate,n(1<=n<=20):";

   cin>>n;

  }

  while((n<1)||(n>20));

  do

  {

    cout<<"\n cheltuielile fixe ale fabricii(10000<<cf<<1000000):";

    cin>>cf;

  }

  while((cf<10000)||(cf>1000000));

  do

  {

    cout<<"\n costurile unitare de productie (10<<cp<<100):";

    cin>>cp;

  }

  while((cp<10)||(cp>100));

  do

  {

   cout<<"\n preturile unitare de vanzare (100<<cp<<300):";

   cin>>pv;

  }

  while((pv<100)||(pv>300));

  //citirea vectorului cu cantitatile posibile de fabricat

  for(i=0;i<n;i++)

  {

   cout<<"\n cantitatea de fabricat din varianta "<<i<<" =";

   cin>>ptrp[i];

  }

  cout<<"\n variantele cantitatile de fabricat:\n";

  for(i=0;i<n;i++) cout<<ptrp[i]<<" ";

  //apelarea functiei constructor, consumuri, cu parametri expliciti

  cost_venit f_cost_venit(n,ptrp,cf,cp,pv);

  // apelarea fara parametri a functiei constructor supraincarcata

  cost_venit f_cost_venit_vida;

  cout<<"\n continuati?(d/n):";

  cin>>r;

 }

}

            In urma executarii acestui program se obtin rezultatele afisate mai jos, care ilustreaza modul in care se realizeaza supraincarcarea functiei constructor, alocarea dinamica de memorie pentru vectorii folositi precum si verificarea alocarii memoriei necesare acestora. Apelarea functiei constructor cu parametri efectivi valizi, determina initializarea datelor membre, obtinerea si afisarea rezultatelor, iar apelarea eronata a functiei constructor, in cazul de fata fara specificarea parametrilor efectivi, antreneaza executarea celei de-a doua functii constructor, care va afisa mesajul de eroare corespunzator "lista parametrilor efectivi eronata".

 

 numarul de variante de  fabricate,n(1<=n<=20):4

 cheltuielile fixe ale fabricii(10000<<cf<<1000000):20000

 costurile unitare de productie (10<<cp<<100):40

 preturile unitare de vanzare (100<<cp<<300):200

 cantitatea de fabricat din varianta 0 =200

 cantitatea de fabricat din varianta 1 =50

 cantitatea de fabricat din varianta 2 =150

 cantitatea de fabricat din varianta 3 =100

 variantele cantitatile de fabricat:

 200 50 150 100

  functia constructor cost_venit

 =================================

   vectorul produselor fabricate

 ================================

      50     100     150     200

 ================================

     datele produselor cf,cp,pv   

 =======================================

 cheltuielile fixe ale fabricii:20000.00

 costul de productie pe produs :40.00

 pretul de vanzare al produsului:200.00

 =======================================

 vectorul costurilor totale pe produse

 =======================================

 22000.000 24000.000 26000.000 28000.000

 =======================================

 vectorul veniturilor totale pe produse

 =======================================

 10000.000 20000.000 30000.000 40000.000

 =======================================

 vectorul profitului total pe nr de produse

 ==========================================

 -12000.000  -4000.000  4000.000  12000.000

 ==========================================

 nr maxim de produse de fabricat:200

 afisarea punctului critic

 =================================

 punctul critic este atunci cand:

 nr produse =125

 costurile totale =25000.000

 veniturile totale =25000.000

 =================================

 lista parametrilor efectivi eronata

 continuati?(d/n):d

 numarul de variante de  fabricate,n(1<=n<=20):5

 cheltuielile fixe ale fabricii(10000<<cf<<1000000):50000

 costurile unitare de productie (10<<cp<<100):50

 preturile unitare de vanzare (100<<cp<<300):100

 cantitatea de fabricat din varianta 0 =150

 cantitatea de fabricat din varianta 1 =200

 cantitatea de fabricat din varianta 2 =50

 cantitatea de fabricat din varianta 3 =100

 cantitatea de fabricat din varianta 4 =250

 variantele cantitatile de fabricat:

 150 200 50 100 250

  functia constructor cost_venit

 =================================

   vectorul produselor fabricate

 =======================================

      50     100     150     200     250

 =======================================

     datele produselor cf,cp,pv  

 ================================

 cheltuielile fixe ale fabricii:50000.00

 costul de productie pe produs :50.00

 pretul de vanzare al produsului:100.00

 ================================

 vectorul costurilor totale pe produse

 =================================================

 52500.000 55000.000 57500.000 60000.000 62500.000

 =================================================

 vectorul veniturilor totale pe produse

 =================================================

 5000.000 10000.000 15000.000 20000.000 25000.000

 =================================================

 vectorul profitului total pe nr de produse

 ==========================================================

 -47500.000  -45000.000  -42500.000  -40000.000  -37500.000

 ==========================================================

 nr maxim de produse de fabricat:250

 nu exista punct critic

 la structura aleasa fabrica inregistreaza pierderi

 lista parametrilor efectivi eronata

  continuati?(d/n):n

            In limbajul C++, exista posibilitatea supraincarcarii functiilor membre, prin folosirea acelorasi identificatori pentru mai multe functii, care urmeaza sa fie apelate si executate, la un anumit  moment de timp. Inlaturarea ambiguitatilor legate de apelarea functiilor supraincarcate se poate face prin diferentierea parametrilor efectivi cum ar fi: numar diferit de parametri, tipuri diferite de parametri, etc..

Problema 30

Se considera o factura care contine mai multe materiale: cod material, un numar natural cuprins intre 1000 si 9999, denumirea materialului, un sir alfanumeric de carcatere, unitatea de masura in multimea (bc,kg,ml,mp,mc,etc), cantitatea si pretul. Prin intermediul unei clase, in care sunt definite doua functii cu acelasi nume sa se ordoneze elementele facturii dupa cod si sa se calculeze factura, adica sa se determine valoarea fiecarui material si TVA aferent precum si valoarea totala fara TVA si TVA total. Pentru inlaturarea ambiguitatii cu privire la functia apelata se va folosi un pointer declarat la functii care trebuie sa difere prin parametri.

#include<iostream.h>

#include<iomanip.h>

int i;

struct tipfact

{         

  unsigned int cod;

  char denumire[20];

  char umas[2];

  double pret;

  double cant;

  double valoare;

  double tva;

};

class facturare

{

public:

// void factura_citita (struct tipfact f,int i)

 void f_factura (struct tipfact f,int i)

 {

  facturare::factura[i]=f;

 }

 struct tipfact factura[20];

 //void factura_ordonare (int n)

 void f_factura (int n) //a doua functie cu acelasi nume

 {

  int ok; struct tipfact aux;

  ok=1;

  while (ok)

  {

   ok=0;

   for(i=0;i<n-1;i++)

    if(facturare::factura[i].cod>facturare::factura[i+1].cod)

    {

      aux=facturare::factura[i];

      facturare::factura[i]=facturare::factura[i+1];

      facturare::factura[i+1]=aux;

      ok=1;

    }

  }

 }

 void calculeaza_factura(int n)

 {

  for(i=0;i<n;i++)

  {

   facturare::factura[i].valoare=facturare::factura[i].pret*facturare::factura[i].cant;

   facturare::factura[i].tva=0.19*facturare::factura[i].valoare;

  }

 }

 void afiseaza_factura(int n)

 {

   for(i=0;i<n;i++)

   {

     cout<<"\n";

     cout<<setw(5)<<setiosflags(ios::right)<<facturare::factura[i].cod;

     cout<<setw(12)<<setiosflags(ios::left)<<facturare::factura[i].denumire;

     cout<<setw(3)<<setiosflags(ios::right)<<facturare::factura[i].umas;

     cout<<setw(10)<<setprecision(2)<<setiosflags(ios::fixed);

     cout<<setiosflags(ios::right)<<facturare::factura[i].pret;

     cout<<setw(10)<<setprecision(2)<<setiosflags(ios::fixed);

     cout<<setiosflags(ios::right)<<facturare::factura[i].cant;

     cout<<setw(10)<<setprecision(2)<<setiosflags(ios::fixed);

     cout<<setiosflags(ios::right)<<facturare::factura[i].valoare;

     cout<<setw(10)<<setprecision(2)<<setiosflags(ios::fixed);

     cout<<setiosflags(ios::right)<<facturare::factura[i].tva;

   }

 }

};

void main(void)

{

 int n; struct tipfact f;char r='d';

 while(r=='d')

 {

   facturare obfactura;

   do

   {

     cout<<"\n numarul de pozitii din factura (1<=n<=20):";

     cin>>n;

   }

   while((n<1)||(n>20));

   for(i=0;i<n;i++)

   {

    do

     {

      cout<<"\n cod material "<<i<<" (1000-9999):";

      cin>>f.cod;

     }

    while((f.cod<1000)||(f.cod>9999));

    cout<<"\n denumire material "<<i<<":";

    cin>>f.denumire;

    cout<<"\n unitate de  masura (bc,kg,mp,ml,mc) "<<i<<":";

    cin>>f.umas;

    cout<<"\n cod pret "<<i<<":";

    cin>>f.pret;

    cout<<"\n cantitate material "<<i<<":";

    cin>>f.cant;

    //obfactura.factura_citita(f,i);

    // se aleleaza functia pentru inregistrarea unui rand al facturii

    obfactura.f_factura(f,i);

   }

  //   obfactura.factura_ordonare(n);

  // se aleleaza functia pentru ordonarea dupa coduri a produselor facturii

  obfactura.f_factura(n);

  cout<<"\n                     factura furnizor                ";

  cout<<"\n ==========================================";

  cout<<"\n  cod denumire umas    pret     cant   valoare   tva ";

  cout<<"\n =========================================\n";

  // se apeleaza functia de calcul a facturii

  obfactura.calculeaza_factura(n);

  // se apeleaza functia de afisare a facturii

  obfactura.afiseaza_factura(n);

  cout<<"\n ==========================================";

  cout<<"\n continuati facturarea?(d/n):";

  cin>>r;

 }

}

            In urma executarii acestui program sau obtinut rezultatele afisate mai jos, care pun in evidenta elementele de calcul ale unei facturi, cat, mai ales, modul de supraincarcare si utilizare a unor functii membre, inlaturandu-se ambiguitatile legate de folosirea acelorasi identificatori, prin utilizarea de parametri efectivi de apel diferiti ca numar sau ca tip.

 

 numarul de pozitii din factura (1<=n<=20):2

 cod material 0 (1000-9999):500

 denumire material 0:var

 unitate de  masura (bc,kg,mp,ml,mc) 0:kg

 pret art 0:0.85

 cantitate material 0:255.00

 cod material 1 (1000-9999):300

 denumire material 1:ciment

 unitate de  masura (bc,kg,mp,ml,mc) 1:kg

 pret art 1:0.55

 cantitate material 1:375.85

                     factura furnizor               

 ====================================================

  cod denumire umas    pret     cant   valoare   tva

 ====================================

  300 ciment    kg     0.85    255.00   216.75  41.18    

  500 var          kg     0.55    375.85   206.72  39.28    

 ====================================

 continuati facturarea?(d/n):d

 numarul de pozitii din factura (1<=n<=20):

 cod material 0 (1000-9999):

 denumire material 0:

 unitate de  masura (bc,kg,mp,ml,mc) 0:

 cod pret 0:

 cantitate material 0:

 cod material 1 (1000-9999):

 denumire material 1:

 unitate de  masura (bc,kg,mp,ml,mc) 1:

 cod pret 1:

 cantitate material 1:

 cod material 2 (1000-9999):

 denumire material 2:

 unitate de  masura (bc,kg,mp,ml,mc) 2:

 cod pret 2:

 cantitate material 2:

                     factura furnizor               

 =======================================

  cod denumire umas    pret     cant     valoare    tva

 =======================================

  100 lapte        hl      255.56    45.26  11566.65  2197.66  

  300 unt           bc         2.50    35.00        87.50    16.63    

  700 mere        kg         2.55    34.75        88.61    16.84    

 ========================================

 continuati facturarea?(d/n):n

III. 8. Functiile destructor

            Dupa cum s-a precizat, daca intr-o clasa se declara si se descrie o functie constructor, atunci cand se ceeaza o instanta obiect a acelei clase, functia constructor se executa automat determinand initializarea diversilor membri ai clasei respective. De asemenea, la declararea unei instante obiect se aloca memoria necesara acesteia. In mod asemanator, limbajul C++ permite definirea unei functii destructor care se va executa automat cand se distrugea instanta obiect a unei clase. In mod uzual, functia destructor se executa automat in urmatoarele doua situatii: in cazul in care in program se intalneste operatorul delete in vederea eliberarii memoriei anterior alocata instantei obiect sau in cazul terminarii efective a programului. Mai jos, sunt date prototipurile generale ale unei functii constructor si functiei destructor asociata.

 

 // declararea prototipului functiei constructor

nume_functie_constructor (parametrii_formali_ai_functiei_constructor);

// declararea prototipului functiei destructor

~nume_functie_constructor (void);

Observatii:

            - functia destructor trebuie sa aiba acelasi nume ca functia constructor asociata, preccedat in mod definitoriu de caracterul tilda(~);

- functia destructor nu accepta parametri formali si, ca si functia constructor, nu poate returna  nicio valoare;

- utilitatea evidenta a functiilor destructor se face imperios simtita, mai ales, atunci cand clasele aloca memorie dinamica unor date membre, cum ar fi matricele, structurile si alte tipuri complexe de date. Prin functiile destructor se poate elibera memoria alocata pe parcursul executarii programului, unor date membre;

- prin functiile destructor se pot efectua multe din operatiile specifice listelor simplu si dublu inlantuite, cum arfi: stergerea sau adaugarea, unuor elemente in lizta;

- functiile destructor nu trebuie apelate si executate inaintea incheierii ciclului de existenta a instantei obiect respective, ci numai cand se asigura faptul ca instanta obiect urmeaza efectiv sa fie distrusa.

Problema 31

   Se considera o echpa de muncitori (max=20) cu structura: cod matricol (intre 1000 si 9999), nume, prenume, salariu brut, somaj, CAS (Contributia pentru Asigurari Sociale), CASS  (Contributia pentru Asigurari Sociale de Sanatate), baza de impozitare, impozitul pe salariu, retineri si rest de plata. Prin intermediul unei clase, in care a fost definita o functie constructor careia i se transmit parametri efectivi: cod matricol, nume, prenume, salariu brut si retinerile, sa se calculeze: contributia de somaj, CAS, CASS, baza de impozitare, impozitul, si restul de plata pentru toti muncitorii din echipa, condusi de seful de achipa aflat in capul listei, pentru seful de sectie si inginerul sef. Concomitent cu functia constructor adecvata, se va defini si functia destructor asociata, care, la terminarea programului, sa afiseze mesajele cu privire la distrugerea instantelor declarate in functia principala main().

#include<iostream.h>

#include<iomanip.h>

#define nmax 20

int i;

// declararea structurii unui angajat

struct tipangajat

{         

  unsigned int matricol;

  char nume[10];

  char prenume[10];

  double brut;

  double somaj;

  double cas;

  double cass;

  double bazaimpozit;

  double impozit;

  double retineri;

  double restplata;

};

// declararea procentelor de somaj, CAS si CASS

double psomaj=1;

double pcas=9.5;

double pcass=6.5;

// declararea clasei salarii

class salarii

{

public:

 // descrierea functiei constructor de initializare

 // a vectorului cu articolele de salarii

 salarii (struct tipangajat a[nmax],int n,char tm)

 {

  for(i=0;i<n;i++) salarii::statplata[i]=a[i];

  salarii::tm=tm;

 };

 // descrierea functiei destructor

 ~salarii (void)

 {

  if(tm=='m')

  {

   cout<<"\n s-a distrus instanta muncitorilor cu seful de achipa ";

   cout<<statplata[0].nume<<" "<<statplata[0].prenume<<"\n";

  }

  if(tm=='a')

  {

   cout<<"\n s-a distrus instanta sefului de sectie ";

   cout<<statplata[0].nume<<" "<<statplata[0].prenume;

  }

  if(tm=='s')

  {

   cout<<"\n s-a distrus instanta inginerului sef ";

   cout<<statplata[0].nume<<" "<<statplata[0].prenume;

  }

 };

 // declararea vectorului cu structurile angajatilor

 struct tipangajat statplata[nmax];

 char tm;

 // descrierea functiei de calcul al salariilor

 void calculeaza_statplata(int n)

 {

  for(i=0;i<n;i++)

  {

    salarii::statplata[i].somaj=salarii::statplata[i].brut*psomaj/100;

    salarii::statplata[i].cas=salarii::statplata[i].brut*pcas/100;

    salarii::statplata[i].cass=salarii::statplata[i].brut*pcass/100;

    salarii::statplata[i].bazaimpozit=salarii::statplata[i].brut -

    salarii::statplata[i].somaj-salarii::statplata[i].cas-salarii::statplata[i].cass;

    salarii::statplata[i].impozit=salarii::statplata[i].bazaimpozit*0.16;

    salarii::statplata[i].restplata=salarii::statplata[i].bazaimpozit -

    salarii::statplata[i].impozit-salarii::statplata[i].retineri;

  }

 };

 // descrierea functiei de afisare stat de plata

 void afiseaza_statplata(int n)

 {

  for(i=0;i<n;i++)

   {        

    cout<<"\n"; 

    cout<<"\n matricol:"<<salarii::statplata[i].matricol;

    cout<<"\n nume:"<<salarii::statplata[i].nume;

    cout<<"\n prenume:"<<salarii::statplata[i].prenume;

    cout<<"\n salariu brut:"<<setprecision(2)<<setiosflags(ios::fixed);

    cout<<salarii::statplata[i].brut;

    cout<<"\n somaj:"<<setprecision(2)<<setiosflags(ios::fixed);

    cout<<salarii::statplata[i].somaj;

    cout<<"\n CAS:"<<setprecision(2)<<setiosflags(ios::fixed);

    cout<<salarii::statplata[i].cas;

    cout<<"\n CASS:"<<setprecision(2)<<setiosflags(ios::fixed);

    cout<<salarii::statplata[i].cass;

    cout<<"\n impozit:"<<setprecision(2)<<setiosflags(ios::fixed);

    cout<<salarii::statplata[i].impozit;

    cout<<"\n retineri:"<<setprecision(2)<<setiosflags(ios::fixed);

    cout<<salarii::statplata[i].retineri;

    cout<<"\n rest plata:"<<setprecision(2)<<setiosflags(ios::fixed);

    cout<<salarii::statplata[i].restplata;

  }

 };

};

void main(void)

{

 // declararea vectorilor de structuri pentru

 // angajati, sef de sectie si inginer sef

 struct tipangajat p[nmax],psefsectie[1],pingsef[1];

 char r='d';int n;

 while(r=='d')

 {

  do

  {

   cout<<"\n numarul de angajati (1<=n<="<<nmax<<"):";

   cin>>n;

  }

  while ((n<1)||(n>nmax));

  // citirea datelor unui angajat

  for(i=0;i<n;i++)

  {

    cout<<"\n cod matricol "<<i<<" (1000-9999):";

    cin>>p[i].matricol;

    cout<<"\n nume :";

    cin>>p[i].nume;

    cout<<"\n prenume :";

    cin>>p[i].prenume;

    cout<<"\n salariu brut :";

    cin>>p[i].brut;

    cout<<"\n retineri :";

    cin>>p[i].retineri;

  }

  cout<<"\n==================================";

  // creearea instantei angajat a clasei salarii

  salarii angajat(p,n,'m');

  cout<<"\n stat de plata muncitori";

  cout<<"\n==================================";

  // apelarea functiei ptr calcularea salariilor angajatilor

  angajat.calculeaza_statplata(n);

  // afisarea salariilor angajatilor

  angajat.afiseaza_statplata(n);

  cout<<"\n ==================================";

  cout<<"\n cod matricol sef sectie (1000-9999):";

  cin>>psefsectie[0].matricol;

  cout<<"\n nume sef sectie:";

  cin>>psefsectie[0].nume;

  cout<<"\n prenume sef sectie:";

  cin>>psefsectie[0].prenume;

  cout<<"\n salariu brut sef sectie :";

  cin>>psefsectie[0].brut;

  cout<<"\n retineri sef sectie:";

  cin>>psefsectie[0].retineri;

  cout<<"\n ===================================";

  // creearea instantei sefsectie a clasei salarii

  salarii sefsectie(psefsectie,1,'a');

  cout<<"\n stat de plata sef de sectie ";

  cout<<"\n==================================";

  // apelarea functiei ptr calcularea salariului sefului de sectie

  sefsectie.calculeaza_statplata(1);

  // afisarea salariului sefului de sectie

  sefsectie.afiseaza_statplata(1);

  cout<<"\n ===================================";

  cout<<"\n cod matricol ing. sef (1000-9999):";

  cin>>pingsef[0].matricol;

  cout<<"\n nume ing. sef:";

  cin>>pingsef[0].nume;

  cout<<"\n prenume ing. sef:";

  cin>>pingsef[0].prenume;

  cout<<"\n salariu brut ing. sef :";

  cin>>pingsef[0].brut;

  cout<<"\n retineri ing. sef:";

  cin>>pingsef[0].retineri;

  cout<<"\n ===================================";

  // creearea instantei ingsef a clasei salarii

  salarii ingsef(pingsef,1,'s');

  cout<<"\n stat de plata inginer sef ";

  cout<<"\n==================================";

  // apelarea functiei ptr calcularea salariului ing sef

  ingsef.calculeaza_statplata(1);

  // afisarea salariului ing sef

  ingsef.afiseaza_statplata(1);

  cout<<"\n ===================================";

  cout<<"\n continuati salarizarea?(d/n):";

  cin>>r;

  // la terminarea programului, prin functia destructor definita

  // se distrug instantele creeate cu mesajele predeclarate

 }

}

            In urma executarii programului de mai sus, s-au obtinut rezultatele urmatoare, punandu-se in evidenta declararea, descrierea si utilizarea functiei destructor pentru distrugerea instantelor create in functia main(), cu afisarea mesajelor de rigoare, transmiterea si utilizarea structurilor, ca parametri formali in functia constructor.

 numarul de angajati (1<=n<=20):2

 cod matricol 0 (1000-9999):100

 nume :pop

 prenume :ion

 salariu brut :3000

 retineri :1000

 cod matricol 1 (1000-9999):200

 nume :stanescu

 prenume :stefan

 salariu brut :2000

 retineri :850

 ====================================================

 stat de plata muncitori

 ====================================================

 matricol:100

 nume:pop

 prenume:ion

 salariu brut:3000.00

 somaj:30.00

 CAS:285.00

 CASS:195.00

 impozit:398.40

 retineri:1000.00

 rest plata:1091.60

 

 matricol:200

 nume:stanescu

 prenume:stefan

 salariu brut:2000.00

 somaj:20.00

 CAS:190.00

 CASS:130.00

 impozit:265.60

 retineri:850.00

 rest plata:544.40

 ====================================================

 cod matricol sef sectie (1000-9999):300

 nume sef sectie:popescu

 prenume sef sectie:sandu

 salariu brut sef sectie :4000

 retineri sef sectie:1200

 ====================================================

 stat de plata sef de sectie

 ====================================================

 matricol:300

 nume:popescu

 prenume:sandu

 salariu brut:4000.00

 somaj:40.00

 CAS:380.00

 CASS:260.00

 impozit:531.20

 retineri:1200.00

 rest plata:1588.80

 ========================================

 cod matricol ing. sef (1000-9999):500

 nume ing. sef:stabu

 prenume ing. sef:spiridon

 salariu brut ing. sef :5000

 retineri ing. sef:2000

 ========================================

 stat de plata inginer sef

 ========================================

 matricol:500

 nume:stabu

 prenume:spiridon

 salariu brut:5000.00

 somaj:50.00

 CAS:475.00

 CASS:325.00

 impozit:664.00

 retineri:2000.00

 rest plata:1486.00

 ========================================

 continuati salarizarea?(d/n):n

 s-a distrus instanta inginerului sef stabu spiridon

 s-a distrus instanta sefului de sectie popescu sandu

 s-a distrus instanta muncitorilor cu seful de achipa pop ion

            Functiile destructor sunt utilizate si pentru distrugerea instantelor obiectelor care gestioneaza diverse stive de date, ocazie cu care se si elibereaza memoria alocata unei stive, prin functia constructor.

Problema 32

Se considera o stiva de containere cu caracteristicile:cod container, un numar cuprins intre 1 si 99,  continut, un camp alfanumeric de 20 caractere, data ambalarii (zi, luna si an) si greutatea in kg. Sa se simuleze activitatile de stivuire si de incarcare intr-un mijloc de transport a containerelor din stiva prin intermediul unei clase stivuire_incarcare, care contine: o functie constructor utilizata pentru initializarea stivei (alocarea spatiului de memorie adecvat), o functie destructor necesata distrugerii instantelor obiectelor folosite, o functie de depunere container in stiva si o functie de extragere container din stiva.

#include<iostream.h>

#include<string.h>

#include<malloc.h>

#include<stdlib.h>

#define nmax 6

int nrob=2;

struct tipdata

{

 int zi;

 int luna;

 int an;

};

struct tipstiva

{

 int cc;

 char continut[20];

 struct tipdata data;

 int greutate;

};

class stivuire_incarcare

{

  public:

    // declararea functiei constructor

    stivuire_incarcare (void);

    // declararea functiei destructor

    ~stivuire_incarcare (void);

    // declararea functiei de depunere in stiva

    int depune_in_stiva(struct tipstiva *ptrstructura);

    // declararea functiei de extragere din stiva

    int extrage_din_stiva(struct tipstiva *ptrstructura);

    struct tipstiva *varfstiva;

};

// descrierea functiei constructor care  aloca spatiul pentru stiva

stivuire_incarcare::stivuire_incarcare(void)

{

  cout<<"\n initializarea stivei de containere ";

  stivuire_incarcare::varfstiva=

  (struct tipstiva*)malloc(nmax*sizeof(struct tipstiva));

  if(stivuire_incarcare::varfstiva==NULL)

  {

    cout<<"\n memorie insuficienta ptr memoria stivei  ";

    exit(1);

  }

}

// descrierea functie destructor

stivuire_incarcare::~stivuire_incarcare (void)

{

  cout<<"\n s-a distrus instanta obiect"<<nrob;

  nrob--;

}

// descrierea functiei depune_in_stiva()

int stivuire_incarcare::depune_in_stiva(struct tipstiva *ptrstructura)

{

 struct tipstiva *ptrcontainer;

 ptrcontainer=(struct tipstiva*)malloc(sizeof(struct tipstiva));

 if(ptrcontainer==NULL)

 {

  cout<<"\n memorie insuficienta ptr un container ";

  return 0;

 }

 *ptrcontainer=*ptrstructura;

 *stivuire_incarcare::varfstiva=*ptrcontainer;

 cout<<"\n varf stiva ="<<stivuire_incarcare::varfstiva;

 cout<<"\n cod container ="<<stivuire_incarcare::varfstiva->cc;

 stivuire_incarcare::varfstiva++;;

 return 1;

}

/* descrierea functiei de extragere din stiva */

int stivuire_incarcare::extrage_din_stiva(struct tipstiva *ptrstructura)

{

 if(!stivuire_incarcare::varfstiva)

 {

  cout<<"\n stiva goala "<<endl;

  return 0;

 }

 stivuire_incarcare::varfstiva--;

 *ptrstructura=*stivuire_incarcare::varfstiva;

 ptrstructura=stivuire_incarcare::varfstiva;

 return 1;

}

void main(void)

{

 int k,n;

 struct tipstiva *ptrcontainera,*ptrcontainers,container,containers;

 stivuire_incarcare obiect1,obiect2;

 char rasp;k=0;

 int terminat=0;

 ptrcontainera=(struct tipstiva*)malloc(sizeof(struct tipstiva));

 if(ptrcontainera==NULL)

 {

  cout<<"\n memorie insuficienta un container ";

  exit(1);

 }

 do

 {

  cout<<"\n numarul maxim de containere, n(1<=n<="<<nmax<<")=";

  cin>>n;

 }

 while((n<1)||(n>nmax));

 while(!terminat)

 {

  cout<<"\n a - asezare container in stiva";

  cout<<"\n s - scoatere container din stiva";

  cout<<"\n t - terminare program";

  cout<<"\n Alegeti operatia dorita:";

  cin>>rasp;

  switch (rasp)

  {

   case 'a':

    if(k<n)

     {

       k++;

       cout<<"\n cod container:";

       cin>>container.cc;

       cout<<"\n continut container:";

       cin>>container.continut;

       cout<<"\n ziua ambalarii:";

       cin>>container.data.zi;

       cout<<"\n luna ambalarii:";

       cin>>container.data.luna;

       cout<<"\n anul ambalarii:";

       cin>>container.data.an;

       cout<<"\n greutate container:";

       cin>>container.greutate;

       ptrcontainera=&container;

       if(k%2)

         obiect1.depune_in_stiva(ptrcontainera);

       else

         obiect2.depune_in_stiva(ptrcontainera);

      }

    else

      cout<<"\n depasirea capacitatii de depozitare";               

      break;

   case 's':

     if(k>=1)

      {

        ptrcontainers=(struct tipstiva*)malloc(sizeof(struct tipstiva));

        if(ptrcontainers==NULL)

         {

           cout<<"\n memorie insuficienta ptr un container ";

           exit(1);

         }

        if(k%2)

         {

            obiect1.extrage_din_stiva(ptrcontainers);

            containers=*ptrcontainers;

            cout<<"\n s-a extras containerul obiectului 1:";

            cout<<"\n =======================================:";

            cout<<"\n cod container :"<<containers.cc;

            cout<<"\n continut container :"<<containers.continut;

            cout<<"\n data containerului :"<<containers.data.zi;

            cout<<"/"<<containers.data.zi<<"/"<<containers.data.an;

            cout<<"\n greutate container :"<<containers.greutate;

         }

        else

         {

            obiect2.extrage_din_stiva(ptrcontainers);

            containers=*ptrcontainers;

            cout<<"\n s-a extras containerul obiectului 2:";

            cout<<"\n ===================================:";

            cout<<"\n cod container :"<<containers.cc;

            cout<<"\n continut container :"<<containers.continut;

            cout<<"\n data containerului :"<<containers.data.zi;

            cout<<"/"<<containers.data.zi<<"/"<<containers.data.an;

            cout<<"\n greutate container :"<<containers.greutate;

         }

        k--;

      }

     else

       cout<<"\n nu mai sunt containere depozitate";

       break;

   case 't':

       terminat=1;

       break;

   default: 

       cout<<"\n operatie gresit selectata";

  }

 }

}

            Rezultatele executiei programului de mai sus, sunt afisate in continuare, punandu-se in evidenta urmatoarele: initializarea si alocarea memoriei pentru o stiva de structuri, depunerea adreselor structurilor intr-o stiva si a structurilor aferente la adresle specificate in stiva, extragerea adreselor structurilor din stiva si a structurilor corespunzatoare de la aceste adrese precum si distrugerea instantelor celor doua obiecte create in program dupa terminarea folosirii acestora.

 initializarea stivei de containere

 initializarea stivei de containere

 numarul maxim de containere, n(1<=n<=6)=4

 a - asezare container in stiva

 s - scoatere container din stiva

 t - terminare program

 Alegeti operatia dorita:a

 cod container:100

 continut container:ciment

 ziua ambalarii:11

 luna ambalarii:11

 anul ambalarii:2005

 greutate container:150

 varf stiva =0x00790610

 cod container =100

 a - asezare container in stiva

 s - scoatere container din stiva

 t - terminare program

 Alegeti operatia dorita:a

 cod container:200

 continut container:var

 ziua ambalarii:21

 luna ambalarii:11

 anul ambalarii:2005

 greutate container:400

 varf stiva =0x007904F0

 cod container =200

 a - asezare container in stiva

 s - scoatere container din stiva

 t - terminare program

 Alegeti operatia dorita:a

 cod container:300

 continut container:suruburi

 ziua ambalarii:11

 luna ambalarii:10

 anul ambalarii:2005

 greutate container:125

 varf stiva =0x00790638

 cod container =300

 a - asezare container in stiva

 s - scoatere container din stiva

 t - terminare program

 Alegeti operatia dorita:a

 cod container:400

 continut container:saibe

 ziua ambalarii:07

 luna ambalarii:09

 anul ambalarii:2005

 greutate container:175

 varf stiva =0x00790518

 cod container =400

 a - asezare container in stiva

 s - scoatere container din stiva

 t - terminare program

 Alegeti operatia dorita:r

 operatie gresit selectata

 a - asezare container in stiva

 s - scoatere container din stiva

 t - terminare program

 Alegeti operatia dorita:d

 operatie gresit selectata

 a - asezare container in stiva

 s - scoatere container din stiva

 t - terminare program

 Alegeti operatia dorita:a

 depasirea capacitatii de depozitare

 a - asezare container in stiva

 s - scoatere container din stiva

 t - terminare program

 Alegeti operatia dorita:s

 s-a extras containerul obiectului 2:

 ===================================:

 cod container :400

 continut container :saibe

 data containerului :07/09/2005

 greutate container :175

 a - asezare container in stiva

 s - scoatere container din stiva

 t - terminare program

 Alegeti operatia dorita:s

 s-a extras containerul obiectului 1:

 =======================================:

 cod container :300

 continut container :suruburi

 data containerului :11/10/2005

 greutate container :125

 a - asezare container in stiva

 s - scoatere container din stiva

 t - terminare program

 Alegeti operatia dorita:s

 s-a extras containerul obiectului 2:

 ===================================:

 cod container :200

 continut container :var

 data containerului :21/i1/2005

 greutate container :400

 a - asezare container in stiva

 s - scoatere container din stiva

 t - terminare program

 Alegeti operatia dorita:s

 s-a extras containerul obiectului 1:

 =======================================:

 cod container :100

 continut container :ciment

 data containerului :11/11/2005

 greutate container :150

 a - asezare container in stiva

 s - scoatere container din stiva

 t - terminare program

 Alegeti operatia dorita:s

 nu mai sunt containere depozitate

 a - asezare container in stiva

 s - scoatere container din stiva

 t - terminare program

 s-a distrus instanta obiect2

 s-a distrus instanta obiect1