This shows you the differences between two versions of the page.
| 
    poo-is:laboratoare:10 [2020/10/12 15:14] ruben_gilian.udroiu [3. Stream]  | 
    — (current) | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ======= Laboratorul 10: Biblioteca Standard C++ ======= | ||
| - | In cadrul acestui laborator, vom studia clasa **string** si **fluxurile de intrare/iesire** (**stream**). | ||
| - | Ca referinte externe, recomandam urmatoarele capitole din [[https://discourse-production.oss-cn-shanghai.aliyuncs.com/original/3X/2/3/2380479dcb8e375425884a10da232730bbc7f88d.pdf|Absolute C++]]: | ||
| - | *Capitolul 9 (Chapter 9.3: The Standard Class String, pag 393-413) | ||
| - | *Capitolul 19 (Chapter 19: Standard Template Library, pag 857-915) | ||
| - | ===== 1. Introducere ===== | ||
| - | **Biblioteca Standard C++** (**Standard C++ Library**) cuprinde toate bibliotecile standard C precum si biblioteci dedicate C++. | ||
| - | <note>**Exemple** | ||
| - | *clasa **string** (operatii de procesare text) | ||
| - | *clase pentru procesarea fisierelor de intrare/iesire si operatii consola: **iostream, fstream** etc | ||
| - | ***STL**(**Standard Template Library**) = clase template (containere, iteratori, algoritmi) | ||
| - | </note> | ||
| - | ===== 2. Clasa String ===== | ||
| - | Pentru a accesa tot ce ne este pus la dispozitie de catre **libraria string**, vom apela urmatoarea comanda: | ||
| - | #include <string>  | ||
| - | <note>**Un obiect de tip string** reprezinta **un sir de caractere** (+informatii despre localizarea lui in memorie si dimensiunea sa).</note> | ||
| - | |||
| - | === 2.1. Constructori === | ||
| - | Crearea si initializarea de obiecte de tip string se face folosind **constructorii** pusi la dispozitie de aceasta clasa. | ||
| - | |||
| - | ==Exemple== | ||
| - | | string()  | creaza un obiect string default (lungimea este 0) | | ||
| - | | string(const char *s) | creaza si initializeaza un string folosind un sir de caractere **s** | | ||
| - | | string(size_type n, char c) | creaza un string cu dimensiune **n** si fiecare element este initializat cu **c** | | ||
| - | | string(const string& s) | constructor de copiere  | | ||
| - | | string(string s, int poz_init, int dim) | creaza un string din **s**, incepand cu elementul de pe pozitia **poz_init**, de lungime **dim** (sau pana la finalul lui s) | | ||
| - | <code c++ String> | ||
| - | #include <iostream> | ||
| - | #include <string> | ||
| - | using namespace std; | ||
| - | |||
| - | int main() { | ||
| - | string s1; | ||
| - | cout << "s1: " << s1 << endl;//OUTPUT: s1: | ||
| - |  | ||
| - | string s2("al doilea string"); | ||
| - | cout << "s2: " << s2 << endl;//OUTPUT: s2: al doilea string | ||
| - |  | ||
| - | string s3(s2); | ||
| - | cout << "s3, copia celui de-al doilea string: " << s3 << endl; | ||
| - | //OUTPUT: s3, copia celui de-al doilea string: al doilea string | ||
| - |  | ||
| - | string s4(5, 'o'); | ||
| - | cout << "s4: " << s4;//OUTPUT: s4: ooooo | ||
| - |  | ||
| - | string  s5 = "al 5-lea";//Observam ca operator= este supradefinit pentru tipul de date string | ||
| - | cout << "s5: " << s5 << endl;//OUTPUT: s5: al 5-lea | ||
| - |  | ||
| - | string s6(s5, 3, 5); | ||
| - | cout << "s6: " << s6;//OUTPUT: 5-lea | ||
| - |  | ||
| - | string s7(s5, 3, 10);//se opreste la ultimul caracter din s5 | ||
| - | cout << "s7: " << s7;//OUTPUT: 5-lea | ||
| - |  | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | === 2.2. Operatori supradefiniti=== | ||
| - | Pentru clasa string, urmatorii operatori sunt supradefiniti:  | ||
| - | |||
| - | | operatorul + | string operator+ (const string& lhs, const string& rhs); | | ||
| - | | operatorul += | string& operator+= (const string& str); | | ||
| - | | operatorul = | string& operator= (const string& str); | | ||
| - | | operatorii relationali (==, !=, <, >, <=, >= ) | bool operator== (const string& lhs, const string& rhs); | | ||
| - | | operatorul >>  | istream& operator>> (istream& is, string& str); | | ||
| - | | operatorul <<  | ostream& operator<< (ostream& os, const string& str); | | ||
| - | |||
| - | <note>Exista mai multe definitii pentru unii dintre operatorii de mai sus.</note> | ||
| - | == Exemple == | ||
| - | <code c++ Operatorul+> | ||
| - | #include <iostream> | ||
| - | #include <string> | ||
| - | #include <iomanip> | ||
| - | using namespace std; | ||
| - | |||
| - | int main() { | ||
| - | //operatorul+ | ||
| - | string s1("text"); | ||
| - | string s2("concatenat"); | ||
| - | cout << s1 + " " + s2 << '\n'; // OUTPUT: textconcatenat | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | <code c++ Operatorul=> | ||
| - | #include <iostream> | ||
| - | #include <string> | ||
| - | #include <iomanip> | ||
| - | using namespace std; | ||
| - | |||
| - | int main() { | ||
| - | // operatorul = | ||
| - | s1 = "un string"; | ||
| - | cout << s1 << '\n'; // OUTPUT: un string | ||
| - | s2 = "alt string"; | ||
| - | s1 = s2; | ||
| - | cout << s1 << '\n'; // OUTPUT: alt string | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | <code c++ OperatoriiRelationari> | ||
| - | #include <iostream> | ||
| - | #include <string> | ||
| - | #include <iomanip> | ||
| - | using namespace std; | ||
| - | |||
| - | int main() { | ||
| - | // operatorii relationali : ==, !=, <, >, <=, >= | ||
| - | s1 = "avion"; | ||
| - | s2 = "bivol"; | ||
| - | if(s1 == s2) cout << "cele doua cuvinte sunt egale\n"; | ||
| - | if(s1 < s2) cout << "s1 este lexicografic mai mic decat s2\n"; | ||
| - | if(s1 > s2) cout << "s2 este lexicografic mai mic decat s1\n"; | ||
| - | if(s1 != s2) cout << "cele doua cuvinte difera\n"; | ||
| - | if(s1 <= s2) cout << "s1 este lexicografic mai mic sau egal cu s2\n"; | ||
| - | // OUTPUT: s1 este lexicografic mai mic decat s2 | ||
| - | // cele doua cuvinte difera | ||
| - | // s1 este lexicografic mai mic sau egal cu s2 | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | <code c++ OperatoriCitireAfisare> | ||
| - | #include <iostream> | ||
| - | #include <string> | ||
| - | #include <iomanip> | ||
| - | using namespace std; | ||
| - | |||
| - | int main() { | ||
| - | // operatorii >> si << | ||
| - | string s; | ||
| - | cin >> s; | ||
| - | cout << s << '\n'; | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | |||
| - | === 2.3. Metode utile=== | ||
| - | Dintre metodele clasei string, mentionam: | ||
| - | | length -> s.length()  | (returneaza lungimea string-ului)  | | ||
| - | | empty -> s.empty()  | returneaza daca sirul este gol sau nu | | ||
| - | | substr -> s.substr(a,b)  | returneaza un subsir de b caractere, incepand cu pozitia a; Daca b nu este precizat, se adauga la subsir toate caracterele incepand cu pozitia a | | ||
| - | | replace -> s.replace(a,b,s2)  |(inlocuieste portiunea de sir care incepe pe pozitia a si tine b caractere cu continutul sirului 2) | | ||
| - | | find -> s.find(secv)  |returneaza prima pozitie unde este gasita secventa secv, sau string::npos(constanta a clasei string), in cazul in care secventa nu a fost gasita)  | | ||
| - | |||
| - | Alte metode de cautare in string-uri: | ||
| - | | find_first_of  | returneaza prima pozitie din string unde se gaseste **oricare** dintre caracterele din secventa trimisa ca parametru  | | ||
| - | | find_last_of  | returneaza ultima pozitie din string unde se gaseste **oricare** dintre caracterele din secventa trimisa ca parametru  | | ||
| - | | rfind | cauta de la final spre inceputul stringului si returneaza prima pozitie pe care se gaseste caracterul/secventa sau string::npos  | | ||
| - | |||
| - | <note>Exista mai multe versiuni supradefinite pentru metodele mentionate.</note> | ||
| - | == Exemplu == | ||
| - | <code c++ Exemplu_Metode> | ||
| - | #include <iostream> | ||
| - | #include <string> | ||
| - | #include <iomanip> | ||
| - | using namespace std; | ||
| - | |||
| - | int main() { | ||
| - | // length | ||
| - | string s("bine"); | ||
| - | cout << s.length() << '\n'; // OUTPUT: 4 | ||
| - |  | ||
| - | // empty | ||
| - | if(s.empty()) cout << "s este gol\n"; | ||
| - | if(!s.empty()) cout << "s nu este gol\n"; // OUTPUT: s nu este gol | ||
| - |  | ||
| - | // substr | ||
| - | string s1("calculator"); | ||
| - | string s2 = s1.substr(0, 8); | ||
| - | cout << s2 << '\n'; // OUTPUT: calculat | ||
| - |  | ||
| - | string s3 = s1.substr(3); | ||
| - | cout << s3 << '\n'; // OUTPUT: culator | ||
| - |  | ||
| - | // replace | ||
| - | s1 = "doar"; | ||
| - | s2 = s1.replace(1, 2, "inozau"); | ||
| - | cout << s1 << '\n'; // OUTPUT: dinozaur | ||
| - |  | ||
| - | // find | ||
| - | int pos; | ||
| - | pos = s1.find("ino"); | ||
| - | cout << pos << '\n'; // OUTPUT: 1 | ||
| - |  | ||
| - | if(s1.find('z') == string::npos) cout << "secventa nu a fost gasita"; | ||
| - | //OUTPUT : secventa nu a fost gasita | ||
| - |  | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | <note important>Pentru a transforma o litera dintr-un string in litera mica/mare, putem folosi **tolower()** si **toupper()**, care **nu sunt metode ale clasei string**, ci **functii din biblioteca standard C**.</note> | ||
| - |  | ||
| - | ===== 3. Stream ===== | ||
| - | In C++ exista o ierarhie de clase predefinite, care asigura un suport eficient pentru operatiile de intrare/iesire, atat cu consola cat si cu discul. Conceptul de baza este de dispozitiv logic de intrare/iesire (**flux de intrare/iesire**). | ||
| - | <note>Aceste fluxuri sunt numite **stream**-uri.</note> | ||
| - | <note important>Fisierele care asigura interfata cu clasele predefinite sunt: | ||
| - | -**<iostream> (operatii consola)** | ||
| - | -**<fstream> (operatii fisiere)** | ||
| - | </note> | ||
| - | === 3.1. iostream === | ||
| - | Denumirea de **iostream** provine de la standard input-output stream. | ||
| - | In C++, cele doua metode fundamentale pentru a citi si, respectiv, a scrie, sunt **cin** si **cout**. | ||
| - | <note>**cin**: | ||
| - | |||
| - | Este o instanta a clasei **istream** si se foloseste pentru a citi input-ul de la o sursa (sursa standard este tastatura). Este urmat de operatorul de extractie  (>>), care extrage inputul din obiectul cin, introdus de la tastatura. | ||
| - | </note> | ||
| - | <note>**cout**: | ||
| - | |||
| - | Este o instanta a clasei **ostream** si se foloseste pentru a introduce date in dispozitivul de output (de obicei ecranul). | ||
| - | Utilizand operatorul de insertie (**<<**) datele sunt introduse in stream-ul de output (cout) pentru a aparea pe ecran. | ||
| - | </note> | ||
| - | |||
| - | Operatorii **<<** si **>**> sunt definiti dupa cum urmeaza: | ||
| - | |||
| - | ostream &operator<< (ostream &, consttip_de_baza &); | ||
| - |  | ||
| - | istream &operator>> (istream &, tip_de_baza &); | ||
| - | |||
| - | Acestia pot fi supradefiniti pentru tipuri de date definite de utilizator: | ||
| - | |||
| - | friend ostream& operator<< (ostream&, constTIP &); | ||
| - | friend istream& operator>> (istream&, TIP &); | ||
| - | |||
| - | Pe langa operatorii << si >>, clasele istream si ostream au implementate functiile elementare **get** si **put** | ||
| - | |||
| - | ostream& put (char c); | ||
| - | istream& get (char& c); | ||
| - | |||
| - | == Exemplu == | ||
| - | |||
| - | char ch; | ||
| - | cin.get(ch); | ||
| - | cout.put(ch); | ||
| - | |||
| - | ==Functii de citire/modificare a starii:== | ||
| - | |||
| - | | obool bad();  | arata daca a existat o eroare la efectuarea ultimei operatii  | | ||
| - | | bool good();  | arata daca ultima operatie s-a efectuat cu succes  | | ||
| - | | void clear();  | sterge indicatorii de eroare  | | ||
| - | |||
| - | == Manipulatori == | ||
| - | |||
| - | <note>Manipulatorii reprezinta operatii ce pot fi inserate in secventele de citire/scriere. Acestia fac ca urmatoarele operatii de citire sau scriere sa aiba loc cu un alt tip de conversie. | ||
| - | </note> | ||
| - | |||
| - | Sintaxa: | ||
| - | cout << manipulator << ....; | ||
| - | |||
| - | Exemplu: | ||
| - | cout << hex << 10 << endl << 11;//OUTPUT: a b | ||
| - | cin >> oct >> i; // i va fi citit de la consola in baza 8 | ||
| - | |||
| - | Manipulatorii fara parametri sunt: | ||
| - | |||
| - | -dec (specifica baza10) | ||
| - | -oct (specifica baza8) | ||
| - | -hex (specifica baza16) | ||
| - | -endl (end of line, adica insereaza'\n') | ||
| - | -ws (ignora spatiile goale: space, tab ) | ||
| - | -ends (end of string, adica insereaza '\0') | ||
| - | -flush (goleste bufferul de iesire) | ||
| - | |||
| - | Exemplu:  | ||
| - | int x; | ||
| - | cin >> hex >> x; //F | ||
| - | cout << dec << x;//15 | ||
| - | |||
| - | string s, s1; | ||
| - | cin >> ws >> s; // introducde la tastatura textul: ”xx yy zz” | ||
| - | cout << s; //xx | ||
| - | cin >> s1; //fara sa scriu ceva de la tastatura, in s1 se citeste in continuare yy | ||
| - | cout << s1; //yy | ||
| - | cout << flush; | ||
| - | |||
| - | Manipulatori cu parametri (definiti in **iomanip.h**): | ||
| - | |||
| - | setprecision (int n) - (pentru numerele reale) precizia este setata la n zecimale | ||
| - | setw (int n) - seteaza latimea campului pentru afisare la n | ||
| - | setfill (char ch) - selecteaza caracterul de umplere (completeaza pozitiile libere din camp) | ||
| - | |||
| - | === 3.2. ifstream, ofstream si fstream === | ||
| - | Pentru deschiderea de fisiere putem folosi constructorii cu/fara parametri pusi la dispozitie pentru toate tipurile de fisiere (intrare, iesire si intrare-iesire) | ||
| - | |||
| - | ofstream::ofstream(const char*nume, int mod=ios::out, int acces=0) | ||
| - | nume - numele fisierului | ||
| - | mod - modul de acces | ||
| - | acces - tipul de protectie/acces | ||
| - | |||
| - | Exemplu:  | ||
| - | ofstream ofis("date1.txt",ios::app); | ||
| - | |||
| - | Modurile (preferinite in clasa ios) sunt: | ||
| - | *ios::in - intrare | ||
| - | *ios::out - iesire | ||
| - | *ios::ate - deschidere cu pozitionare la sfarsitul fisierului | ||
| - | *ios::app - append, adaugare la sfarsitul fisierului | ||
| - | *ios::binary - deschidere in mod binar | ||
| - | |||
| - | <note>Modurile pot fi combinate cu SAU logic la nivel de bit (|) | ||
| - | |||
| - | **Acces** | ||
| - | *0 - normal | ||
| - | *1 - read-only | ||
| - | *2 - hidden | ||
| - | *3 - sistem | ||
| - | </note> | ||
| - | |||
| - | Se poate folosi si functia cu efect similar: | ||
| - | void open (const char *nume_fisier, int mod, int acces) | ||
| - | |||
| - | In urma deschiderii, este indicata testarea pentru erori: | ||
| - | if (!numefis) cout << "eroare"; | ||
| - | |||
| - | Pentru inchiderea unui fisier, se foloseste functia "**void close();**", functie ce este apelata de destructorul claselor ce lucreaza cu fisiere, deci fisierul va fi inchis **automat** la finalul duratei de viata a variabilei de tip fisier. | ||
| - | |||
| - | Putem citi o linie dintr-un fisier text (sau cin) cu functia: | ||
| - | getline(unsigned char *buf, int l, char delim); | ||
| - | |||
| - | Functia **getline** citeste in buf cel mult **l-1** caractere, pana la intalnirea caracterului **delim**, care este implicit **'\n'(newline)** si pune **'\0'** la sfarsitul liniei citite. | ||
| - | |||
| - | Exemplu: | ||
| - | ifstream ifis("date2.dat"); | ||
| - | char buf[256]; | ||
| - | while(!ifis.eof()) { | ||
| - | ifis.getline(buf, 256, '\n'); | ||
| - | cout << buf << endl; | ||
| - | } | ||
| - | |||
| - | <note important>A se consulta cursul pentru mai multe exemple!</note> | ||
| - | |||
| - | ==Fisiere binare== | ||
| - | |||
| - | In cazul fisierelor binare, nu se pot folosi functiile obisnuite de citire/scriere deoarece datele nu sunt formatate in vreun fel anume. | ||
| - | |||
| - | Clasele specializate pentru fisiere binare includ doua functii pentru citirea si scrierea secventiala:  | ||
| - | -**write** | ||
| - | -**read** | ||
| - | |||
| - | istream& read(unsigned char *buf, intn); | ||
| - | ostream& write(constunsigned char *buf, intn); | ||
| - | |||
| - | Functiile citesc/scriu din/in fisierul respectiv **n octeti** in/din buf | ||
| - | |||
| - | Pozitionarea absoluta in fisierul binar este realizata de metodele **seekg** (citire din **ifstream**) si **seekp** (scriere in **ofstream**): | ||
| - | |||
| - | ifstream& seekg(long poz, int reper); | ||
| - | ofstream& seekp(long poz, int reper); | ||
| - | poz = pozitia in octeti | ||
| - | Reper poate fi una dintre constantele:  | ||
| - | ios::beg (pozitionare fata de inceput) | ||
| - | ios::cur (fata de pozitia curenta)  | ||
| - | ios::end (fata de sfarsit) | ||