Simpatie.ro - matrimoniale
alqabomb
Numele forumului cat si aceasta descriere pot fi modificate accesind meniul ADMIN -> OPTIUNI
Nou pe simpatie:
dannutzza din Mehedinti
Femeie
25 ani
Mehedinti
cauta Barbat
25 - 52 ani
alqabombInregistrareLoginPozeNu sunteti logat. Lista Forumurilor Pe Tematici
alqabomb / HacK School /

CURS I - PROGRAMARE C++ vol II

Pagini: 1  
#1
JaGuaruL
Administrator
Postari: 19
Cap. 5. Stream-uri

Cap. 5.1. Introducere

    Stream-urile au in principal rolul de a abstractiza operatiile de intrare- iesire. Ele ofera metode de scriere si citire a datelor independente de dispozitivul I/O si chiar independente de platforma. Stream-urile incapsuleaza (ascund) problemele specifice dispozitivului cu care se lucreaza, sub libraria standard iostream.
    Alt avantaj al folosirii stream-urilor se datoreaza implementarii librariei iostream, care utilizeaza un sistem de buffer-e. Se stie ca in general operatiile de intrare/iesire cu dispozitivele periferice sunt relativ mari consumatoare de timp, astfel incat aplicatiile sunt uneori nevoite sa astepte terminarea acestor operatiuni. Informatiile trimise catre un stream nu sunt scrise imediat in dispozitivul in cauza, ci sunt transferate intr-o zona de memorie tampon, din care sunt descarcate catre dispozitiv abia in momentul umplerii acestei zone de memorie.
    In C++ stream-urile au fost implementate utilizand clase, dupa cum urmeaza:
  # clasa streambuf gestioneaza buffer-ele.
  # clasa ios este clasa de baza pentru clasele de stream-uri de intrare si de iesire. Clasa ios are ca variabila membru un obiect de tip streambuf.
  # clasele istream si ostream sunt derivate din ios.
  # clasa iostream este derivata din istream si ostream si ofera metode pentru lucrul cu terminalul.
  # clasa fstream ofera metode pentru operatii cu fisiere.


    Cap. 5.2. Obiecte standard

    Cand un program C++ care include iostream.h este lansat in executie, sunt create si initializate automat patru obiecte:

  # cin gestioneaza intrarea de la intrarea standard (tastatura).
  # cout gestioneaza iesirea catre iesirea standard (ecranul).
  # cerr gestioneaza iesirea catre dispozitivul standard de eroare (ecranul), neutilizand buffer-e.
  # clog gestioneaza iesirea catre dispozitivul standard de eroare (ecranul), utilizand buffer-e.


    Cap. 5.3. Redirectari

    Dispozitivele standard de intrare, iesire si eroare pot fi redirectate catre alte dispozitive. Erorile sunt de obicei redirectate catre fisiere, iar intrarea si iesirea pot fi conduse ("piped" catre fisiere utilizand comenzi ale sistemului de operare (utilizarea iesirii unui program ca intrare pentru altul).

    Sintaxa pentru operatii de iesire, cout:

    cout << InformatieDeTrimisLaIesire;


    respectiv pentru intrare, cin:

    cin >> NumeVariabila;


    De fapt, cin si cout sunt niste obiecte definite global, care au supraincarcat operatorul >> respectiv << de mai multe ori, pentru fiecare tip de parametru in parte (int, char *, etc.):

    istream &operator >> (TipParametru &


    De exemplu:

    #include <iostream.h>

    void main()
    {
    int IntegerNumber;

    cout << "IntegerNumber = ";
    cin >> IntegerNumber;
    cout << "nWhat you entered = " << IntegerNumber << endl;
    }

    Acest scurt program citeste de la intrarea standard o valoare intreaga, pe care o trimite apoi catre iesirea standard. Se observa posibilitatea de a utiliza simbolurile 'n', 't', s.a.m.d (ca la printf, scanf, etc.). Utilizarea simbolului endl va forta golirea zonei tampon, adica trimiterea datelor imediat catre iesire.
    Atat operatorul >> cat si << returneaza o referinta catre un obiect al clasei istream. Deoarece cin respectiv cout este si el un obiect istream, valoarea returnata de o operatie de citire/scriere din/in stream poate fi utilizata ca intrare/iesire pentru urmatoarea operatie de acelasi fel.


    Cap. 5.4. cin

  # Functia cin.get()

    Functia membra get() poate fi utilizata pentru a obtine un singur caracter din intrare, apeland-o fara nici un parametru, caz in care returneaza valoarea utilizata, sau ca referinta la un caracter.

    get() fara parametri
    In aceasta forma, functia intoarce valoarea caracterului gasit. De remarcat este faptul ca, spre deosebire de operatorul >>, nu poate fi utilizata pentru a citi mai multe intrari, deoarece valoarea returnata este de tip intreg, nu un obiect istream. Mai jos, un exemplu de utilizare:

    #include <iostream.h>

    void main()
    {
    char c;

    while((c = cin.get()) != EOF)
    {
    cout << "c = " << c << endl;
    }
    }

    Citirea de siruri de caractere utilizand get()
    Operatorul >> nu poate fi utilizat pentru a citi corect siruri de caractere de la intrare deoarece spatiile sunt interpretate ca separator intre diverse valori de intrare. In astfel de cazuri trebuie folosita functia get(). Sintaxa de utilizare a functiei get in acest caz este urmatoarea:

    cin.get(char *PointerLaSirulDeCaractere, int LungimeMaxima, char Sfarsit);


    Primul parametru este un pointer la zona de memorie in care va fi depus sirul de caractere. Al doilea parametru reprezinta numarul maxim de caractere ce poate fi citit plus unu. Cel de-al treilea parametru este caracterul de incheiere a citirii, care este optional (implicit considerat 'n').
    In cazul in care caracterul de incheiere este intalnit inainte de a fi citit numarul maxim de caractere, acest caracter nu va fi extras din stream. Exista o functie similara functiei get(), cu aceeasi sintaxa, numita getline(). Functionarea sa este identica cu get(), cu exceptia faptului ca acel ultim caracter mentionat mai sus este si el extras din stream.

  # Functia cin.ignore()

    Aceasta functie se utilizeaza pentru a trece peste un numar de caractere pana la intalnirea unui anume caracter. Sintaxa sa este:

    cin.ignore(int NumarMaximDeCaractere, char Sfarsit);


    Primul parametru reprezinta numarul maxim de caractere ce vor fi ignorate iar al doilea parametru caracterul care trebuie gasit.

  # Functia cin.peek()

    Aceasta functie returneaza urmatorul caracter din stream, fara insa a-l extrage.

  # Functia cin.putback()

    Aceasta functie insereaza in stream un caracter.


    Cap. 5.5. cout

    Cap. 5.5.1. Functii membre ale cout
  # Functia cout.flush()

    Functia cout.flush() determina trimiterii catre iesire a tuturor informatiilor aflate in zona de memorie tampon. Aceasta functie poate fi apelata si in forma cout << flush.

  # Functia cout.put()

    Functia cout.put() scrie un caracter catre iesire. Sintaxa sa este urmatoarea:

    cout.put(char Caracter);


    Deoarece aceasta functie returneaza o referinta de tip ostream, pot fi utilizate apeluri succesive ale acesteia, ca in exemplul de mai jos:

    #include <iostream.h>

    void main()
    {
    cout.put('H').put('i').put('!').put('n');
    }

  # Functia cout.write()

    Aceasta functie are acelasi rol ca si operatorul <<, cu exceptia faptului ca se poate specifica numarul maxim de caractere ce se doresc scrise. Sintaxa functiei cout.write() este:

    cout.write(char *SirDeCaractere, int CaractereDeScris);



    Cap. 5.5.2. Formatarea iesirii

  # Functia cout.width()

    Aceasta functie permite modificarea dimensiunii valorii trimise spre iesire, care implicit este considerata exact marimea campului in cauza. Ea modifica dimensiunea numai pentru urmatoarea operatie de iesire. Sintaxa este:

    cout.width(int Dimensiune);


  # Functia cout.fill()

    Functia cout.fill() permite modificarea caracterului utilizat pentru umplerea eventualului spatiu liber creat prin utilizarea unui dimensiuni mai mari decat cea necesara iesirii, cu functia cout.width(). Sintaxa acesteia este:

    cout.fill(char Caracter);



    Cap. 5.5.3. Optiuni de formatare a iesirii

    Pentru formatarea iesirii sunt definite doua functii membre ale cout, si anume:

  # Functia cout.setf()

    Aceasta functie activeaza o optiune de formatare a iesirii, primita ca parametru:

    cout.setf(ios::Optiune);


    Unde Optiune poate fi:

  # showpos determina adaugarea semnului plus (+) in fata valorilor numerice pozitive;
  # left, right, internal schimba alinierea iesirii;
  # dec, oct, hex schimba baza de numeratie pentru valori numerice;
  # showbase determina adaugarea identificatorului bazei de numeratie in fata valorilor numerice.

  # Functia cout.setw()

    Aceasta functie modifica dimensiunea iesirii, fiind similara functiei cout.width(). Sintaxa sa este:

    cout.setw(int Dimensiune);


    In continuare vom exemplifica utilizarea functiilor pentru formatarea iesirii:

    #include <iostream.h>
    #include <iomanip.h>

    void main()
    {
    int number = 783;

    cout << "number = " << number;
    cout.setf(ios::showbase);
    cout << "number in hexa = " << hex << number;
    cout.setf(ios::left);
    cout << "number in octal, aligned to the left = " << oct << number;
    }



    Cap. 5.6. Operatii de intrare/iesire cu fisiere

    Lucrul cu fisiere se face prin intermediul clasei ifstream pentru citire respectiv ofstream pentru scriere. Pentru a le utiliza, aplicatiile trebuie sa includa fstream.h. Clasele ofstream si ifstream sunt derivate din clasa iostream, ca urmare toti operatorii si toate functiile descrise mai sus sunt mostenite si de aceasta clasa.
    Sintaxele pentru constructorii acestor doua clase sunt:

    ofstream Variabila(char *NumeFisier, ios::Mod);

    ifstream Variabila(char *NumeFisier);


    Acesti constructori au rolul de a deschide fisierul specificat ca parametru. Cel de-al doilea parametru al constructorului ofstream este optional si specifica modul de deschidere a fisierului:

  # ios::append - adauga la sfarsitul fisierului;
  # ios::atend - pozitioneaza pointer-ul la sfarsitul fisierului, insa informatiile pot fi scrise oriunde in cadrul fisierului;
  # ios::truncate - este modul de deschide implicit: vechiul continut al fisierului este pierdut;
  # ios::nocreate - daca fisierul nu exista, atunci operatia esueaza;
  # ios::noreplace - daca fisierul deja exista, atunci operatia esueaza.
    Pot fi utilizate prescurtarile: app pentru append, ate pentru atend, si trunc pentru truncate.

    Pentru a inchide aceste fisiere trebuie apelata functia membra close().
    Rezultatul operatiilor de intrare/iesire poate fi testat prin intermediul a patru functii membre:

  # eof() verifica daca s-a ajuns la sfarsitul fisierului;
  # bad() verifica daca s-a executat o operatie invalida;
  # fail() verifica daca ultima operatie a esuat;
  # good() verifica daca toate cele trei rezultate precedente sunt false.

    In urmatorul capitol veti afla despre mecanismul de tratare a exceptiilor oferit de C++.


 
   
#2
JaGuaruL
Administrator
Postari: 19
Cap. 6. Tratarea exceptiilor

    Este un fenomen "natural" ca in programe sa se strecoare erori, de diverse naturi. Activitatea de programare implica si actiuni mai putini placute, adica testarea, depanarea si corectarea erorilor. Costurile de indepartare a erorilor creste de obicei direct proportional cu intarzierea din cadrul procesului de dezvoltare cand sunt descoperite.
    Trebuie insa inteleasa diferenta dintre erori (bug-uri) si exceptii. Exceptiile sunt situatiile neasteptate aparute in cadrul sistemului care ruleaza un program. Programele trebuie sa fie pregatite pentru a trata aceste situatii exceptionale.
    In C++ s-a realizat un mecanism facil de tratare a exceptiilor. Astfel, o exceptie este un obiect a carui adresa este trimisa dinspre zona de cod unde a aparut problema catre o zona de cod care trebuie sa o rezolve.
    Pasii care trebuiesc in general urmati in vederea tratarii exceptiilor in cadrul programelor C++ sunt:
    1. se identifica acele zone din program in care se efectueaza o operatie despre care se cunoaste ca ar putea genera o exceptie, si se marcheaza in cadrul unui bloc de tip try. In cadrul acestui bloc, se testeaza conditia de aparitie a exceptiei, si in caz pozitiv se semnaleaza aparitia exceptiei prin intermediul cuvantului cheie throw;
    2. se realizeaza blocuri de tip catch pentru a capta exceptiile atunci cand acestea sunt intalnite.
    Blocurile catch urmeaza un bloc try, in cadrul carora sunt tratate exceptiile.
    Sintaxa pentru try:

    try
    {
    // cod
    throw TipExceptie;
    }

    Sintaxa pentru throw:

    throw TipExceptie;

    Sintaxa pentru catch:

    catch(TipExceptie)
    {
    // cod tratare exceptie
    }

    Daca TipExceptie este "...", este captata orice exceptie aparuta.

    Dupa un bloc try, pot urma unul sau mai multe blocuri catch. Daca exceptia corespunde cu una din declaratiile de tratare a exceptiilor, aceasta este apelata. Daca nu exista definita nici o rutina de tratare a exceptiei, este apelata rutina predefinita, care incheie executia programului in curs. Dupa ce rutina este executata, programul continua cu instructiunea imediat urmatoare blocului try.
    TipExceptie nu este altceva decat instantierea unei clase vide (care determina tipul exceptiei), putand fi declarat ca:

    class TipExceptie {};

    In continuare prezentam un exemplu de program care utilizeaza tratarea exceptiilor.

    #include <iostream.h>

    #define MAXX    80
    #define MAXY    25

    class Point
    {
     public:

      class xZero {};
      class xOutOfScreenBounds {};

      Point(unsigned __x, unsigned __y)
        {
        x = __x;
        y = __y;
        }

      unsigned GetX()
        {
        return x;
        }

      unsigned GetY()
        {
        return y;
        }

      void SetX(unsigned __x)
        {
        if(__x > 0)
          if(__x < = MAXX)
            x = __x;
           else
            throw xOutOfScreenBounds();
         else
          throw xZero();
        }

      void SetY(unsigned __y)
        {
        if(__y > 0)
          if(__y < = MAXY)
            y = __y;
           else
            throw xOutOfScreenBounds();
         else
          throw xZero();
        }

     protected:
      int x, y;
    };

    main()
    {
      Point p(1, 1);
      try
        {
        p.SetX(5);
        cout << "p.x successfully set to " << p.GetX() << "." << endl;
        p.SetX(100);
        }
      catch(Point:Zero)
        {
        cout << "Zero value!n";
        }
      catch(Point:OutOfScreenBounds)
        {
        cout << "Out of screen bounds!n";
        }
      catch(...)
        {
        cout << Unknown exception!n";
        }
    }


    Datorita faptului ca exceptia este instantierea unei clase, prin derivare pot fi realizate adevarate ierarhii de tratare a exceptiilor. Trebuie avuta insa in vedere posibilitatea de aparitie a unor exceptii chiar in cadrul codului de tratare a unei exceptii, situatii care trebuie evitate.

    In urmatorul capitol va fi prezentata notiunea de template.


 
   
#3
JaGuaruL
Administrator
Postari: 19
Cap. 7. Template-uri

    Template-ul implementeaza asa-zisul concept de "tip parametrizat" ("parametrized type". Un template reprezinta o familie de tipuri sau functii, cu alte cuvinte, un sablon sau model. Acest concept a fost introdus in primul rand pentru a creste gradul de reutilizabilitate a codului. De exemplu, pentru a implementa o lista de numere intregi este necesara in mod normal realizarea unei clase speciale (sa spunem ListOfIntegers), iar pentru o lista de siruri alta clasa (sa spunem ListOfStrings). Conceptul de template permite realizarea unei clase generale (sa spunem List), care sa accepte orice tip de element, inclusiv tipuri necunoscute la momentul implementarii acesteia. Tipul template-ului este stabilit in momentul instantierii sale. Template-urile sunt foarte utile pentru realizarea de biblioteci care trebuie sa ofere metode generice de prelucrare a datelor.
    Sintaxa generala de declarare a unui template este urmatoarea:

    template < ListaDeParametri > Declaratie


    unde Declaratie reprezinta declararea sau definirea unei clase sau functii, definirea unui membru static al unei clase template, definirea unei clase sau functii membre al unei clase template, sau definirea unui membru template al unei clase.
    Clasele parametrizate (sau clasele template) se declara astfel:

    template <class NumeParametru>
    class NumeClasa {
    // ...
    // definirea clasei
    }


    Particularizarea (= stabilirea tipului) clasei template se face prin intermediul unei constructii de genul:

    NumeClasa <NumeParametru>

    unde NumeParametru reprezinta tipul obiectului.

    Functiile template se declara astfel:

    template <class NumeParametru>
    // ...
    // declaratia functiei


    Sa consideram in continuare ca exemplu implementarea unei stive generice folosind template-uri.

    #include <iostream.h>

    template <class T> class StackItem {
    public:

          StackItem *Next;
          T *Data;
          StackItem(T __Data, StackItem <T> *__Next)
          {
                Data = new T(__Data);
                Next = __Next;
          }

    };

    template <class T> class Stack {
    public:

          T pop()
          {
                T result = *(Data->Data);
                StackItem <T> *temp = Data;
                Data = Data->Next;
                delete temp;
                return result;
          }
          T top()
          {
                return *(Data->Data);
          }
          void push(T __Data)
          {
                Data = new StackItem <T>(__Data, Data);
          }
          int isEmpty()
          {
                return Data == 0;
          }
          Stack()
          {
                Data = 0;
          }

    private:

          StackItem <T> *Data;

    };

    main()
    {

          Stack <int> anIntegerStack;
          anIntegerStack.push(5);
          anIntegerStack.push(7);
          if(anIntegerStack.isEmpty())
              cout << "Stiva goala" << endl;
              else
              cout << anIntegerStack.pop() << endl;
              cout << anIntegerStack.top() << endl;

    }

    In exemplul urmator a fost implementata o lista generica (List). Ca elemente a listei s-au folosit obiecte de tip Point (clasa definita in Cap. 4). Pentru parcurgerea usoara a listei a fost implementata o clasa de tip "iterator", care poate fi considerata ca fiind un "cursor" care strabate lista. Functia List.begin() returneaza un iterator pozitionat pe primul element al listei, List.end() pe ultimul element al listei. Saltul la urmatorul element al listei se face cu ajutorul operatorului ++ din clasa Iterator.

    #include <iostream.h>

    class Point
    {
    friend ostream& operator << (ostream& output, Point p);
    protected:

          unsigned x, y;

    public:

          Point()
          {
                x = 0;
                y = 0;
          }
          Point(unsigned X, unsigned Y)
          {
                x = X;
                y = Y;
          }
          ~Point() {}
          unsigned GetX()
          {
                return x;
          }
          unsigned GetY()
          {
                return y;
          }
          void SetX(unsigned X)
          {
                x = X;
          }
          void SetY(unsigned Y)
          {
                y = Y;
          }

    };

    ostream& operator << (ostream& output, Point p)
    {

          output << "(" << p.x << ", " << p.y << "";
          return output;

    }

    template <class T> class Item {
    public:

          Item *Next;
          T *Data;
          Item(T __Data, Item <T> *__Next)
          {
                Data = new T(__Data);
                Next = __Next;
          }

    };

    template <class T> class List {
    public:

          T pop_front()
          {
                T result = *(Data->Data);
                Item <T> *temp = Data;
                Data = Data->Next;
                delete temp;
                return result;
          }
          T front()
          {
                return *(Data->Data);
          }
          void push_front(T __Data)
          {
                Data = new Item <T>(__Data, Data);
          }
          int empty()
          {
                return Data == 0;
          }
          List()
          {
                Data = 0;
          }

    class Iterator {
    friend class List <T>;
    protected:

          Item <T> *Current;
          Iterator(Item <T> *x)
          {
                Current = x;
          }

    public:

          Iterator() {}
          int operator == (Iterator& x)
          {
                return Current == x.Current;
          }
          int operator != (Iterator& x)
          {
                return Current != x.Current;
          }
          T operator *()
          {
                return *(Current->Data);
          }
          Iterator& operator ++(int)
          {
                Current = Current->Next;
                return *this;
          }

    };
    Iterator begin()
    {

          return Iterator(Data);

    }
    Iterator end()
    {

          Item <T> *temp;
          for(temp = Data; temp; temp = temp->Next);
          return Iterator(temp);

    }
    private:

          Item <T> *Data;

    };

    main()
    {

          List <Point> anPointList;
          List <Point>::Iterator index, end;
          anPointList.push_front(Point(1, 1));
          anPointList.push_front(Point(3, 14));
          index = anPointList.begin();
          end = anPointList.end();
          if(anPointList.empty())
                cout << "Lista vida" << endl;
          else
                for(; index != end; index++)
                      cout << *index << " ";
          cout << endl;

    }

  # Clasele template pot avea trei tipuri de prieteni (friends): o clasa sau functie care nu este de tip template;
  # o clasa sau functie template;
  # o clasa sau functie template avand tipul specificat.
    Daca este necesara particularizarea unei functii template sau a unei functii membre a unei clase template pentru un anumit tip, functia respectiva poate fi supraincarcata pentru tipul dorit.
    Trebuie remarcat de asemenea ca in cazul in care o clasa template contine membri statici, fiecare instanta a template-ului in cauza va contine propriile date statice.

    In capitolul ce urmeaza vor fi prezentate diverse particularitati legate de programarea in C++ pe sisteme UNIX.


 
   
Pagini: 1  
Mergi la