Curs C++ | Sectiunea 6 – Input & Output

 

💡 Facem o pauza de la expresiile conditionate si discutam despre modul in care comunicam cu lumea exterioara. Trimiterea de date de la utilizator (user) catre program este numita input. Procesul invers, de la program catre utilizator se numeste output.

Nu este prima data cand lucram cu acest concept. Inca de la inceput am folosit stream-ul de date cout impreuna cu operatorul << . Acest operator se mai poate numi uneori si operator de insertie, intrucat insereaza un sir (string) de caractere in consola. Mai mult, cout poate scrie orice tip de date.

 

Output

int x = 10;
cout << x;

Operatorul << si stream-ul de date cout se ocupa de urmatoarele actiuni:

  • conversia (converting) reprezentarii interne a valorii intregi intr-o forma recunoscuta de oameni
  • transferarea (transferring) formei converitite catre output (consola)

Avem posibilitatea sa folosim de mai multe ori operatorul << intr-o singura expresie, indiferent de tipul elementelor afisate. Putem chiar sa facem si operatii, acestea fiind valide pentru afisare.

int x = 10;
cout<<"Valoarea lui x = " << x;
cout << x * 10; // 100

 

Manipulator

💡 In cazul in care dorim sa modificam reprezentarea unei valori, spre exemplu din int in hexazecimal, avem nevoie de un manipulator. Acesta este o entitate speciala ce ii spune stream-ului de date ca reprezentarea trebuie modificata.

❗ Teoretic, un manipulator este o functie ce modifica una din proprietatile output-ului unui stream de date, numita basefield. Aceasta proprietate este folosita pentru a determina ce numar sa fie folosit ca baza in timpul conversiei unei valori int intr-un text citibil.

Un manipulator ce modifica reprezentarea unui stream in hexazecimal se numeste hex.

int number = 255;
cout << "Numarul in hex: " << hex << number; // Numarul in hex: ff

Trebuiesc mentionate 2 lucruri:

  • orice manipulator modifica stream-ul din momentul primei aparitii si continua chiar si dupa finalul instructiunii cout; poate fi oprit numai prin apelarea altui manipulator ce va anula modificarile celui anterior
  • numele unui manipulator poate fi in conflict cu numele unei entitati declarate de programator (ex: putem avea o variabila numita hex ); acest lucru se poate rezolva prin folosirea unui namespace

Sa aruncam o privire pe urmatorul exemplu si sa analizam output-ul:

int byte = 255; 
cout << hex << byte <<"\n"; //ff
cout << byte << " " << dec << byte; //ff 255
cout << oct << byte; //377
  1. FF ca reprezentare hexazecimala a lui 255 (manipulatorul hex)
  2. FF din nou (datorita manipulatorului hex ce inca este activ)
  3. 255 ca rezultat al manipulatorului dec
  4. 377 ca rezultat al manipulatorului oct (reprezentare octala)

Observatie: manipulatorul dec modifica stream-ul in forma decimala. Acesta este forma default in cele mai multe cazuri.

 

Setbase

Alta metoda prin care putem obtine aceleasi rezultate este prin manipulatorul setbase. Acesta atentioneaza in mod direct stream-ul in legatura cu baza in care sa se realizeze conversiile.

#include <iostream>
#include <iomanip>

using namespace std;
int main()
{
int number = 255;
cout << setbase(16) << number; //ff
return 0;
}

Valorile acceptate de acest manipulator sunt 8, 10 si 16 (corespunzatoare celor 3 reprezentari).

Observatie: este necesar un nou header numit iomanip (pentru manipulatorii anteriori nu este nevoie, aflandu-se in iostream).

O lista completa a tuturor manipulatorilor din C++ o puteti gasi aici.

 

(newtype)expr

char var_char = 'X';
int var_int = var_char ;
cout << var_char << " " << (int)var_char << " " << endl << var_int << " " << (char)var_int ;

/*Output
x 88
88 x
*/

💡 Conversia folosita modifica tipul de date al unei expresii intr-un nou tip de date. In cazul nostru, prin conversia tipului char la tipul int, si invers, putem vedea corespondenta dintre codul ASCII si caracterul corepunzator. Vom discuta ulterior mai in amanunt despre aceste conversii.

❗ Se mai poate observa si comanda endl. Acesta este tot un manipulator ce marcheaza sfarsitul liniei (end line), astfel trecand pe urmatoarea linie. Noi am mai realizat acest rezulat si prin caracterul de control newline, adica \n. Ambele indeplinesc aceeasi functie.

 

endl vs \n

💡 Singura diferenta semnificativa este ca manipulatorul endl vine la pachet si cu o comanda flush (flush the output buffer). Sa explicam putin acel output buffer inainte.

❗ Ne putem imagina un exemplu practic. Vrem sa scriem o propozitie intr-un fisier text. Daca scriem fiecare caracter/byte pe rand, acest proces ne va costa foarte multe resurse astfel ca o metoda simpla ar fi sa stocam toate acele caractere intr-un buffer temporar, numit output buffer. Doar cand acest buffer este ocupat suficient va scrie datele in fisier. Prin aceasta metoda, putem creste performanta unui program, amanand procesul de scriere.

Avand acest exemplu in minte, procesul de flush produce aceasta scriere din acel buffer in output-ul nostru de fiecare data. Astfel, comanda endl ar arata astfel:

std::cout << std::endl;
//echivalent cu
std::cout << '\n' << std::flush;

❗ Caracterul de control \n realizeaza acest flush o singura data, la finalul programului. In final, depinde de programul nostru si cazurile noastre individuale ce este mai indicat sa folosim.

 

Input

Bineinteles, la fel de importante sunt si datele de input (data input). Daca ne dorim totusi sa nu avem input de la utilizator, desi rar, avem urmatoarele cazuri:

  • suprascrisem toate informatiile de input direct in codul sursa (hard coding)
  • rulam programul cu aceleasi date de input dar modificam functionalitatea interna

Trecand mai departe, cea mai simpla metoda de a prelua date de input este prin:

  • folosim stream-ul cin in loc de cout
  • folosim operatorul >> (extraction operator) in loc de <<

Stream-ul cin impreuna cu operatorul de extractie are urmatoarele responsabiliati:

  • transfera forma citibila din consola
  • conversteste datele intr-o reprezentare interna

 

Acum sa aruncam o privire pe un exemplu pentru a ingloba tot ce am discutat in aceasta sectiune.

#include <iostream>

using namespace std;

int main()
{
int valoare;

cout << "Introduceti numarul dorit \n";
cin >> valoare;
cout << "Patratul valorii este " << valoare * valoare << endl;

return 0;
}

Nu cred ca mai este nevoie de o explicatie a codului. Este destul de simplu si folosim tot ce am discutat mai sus 🙂 .

Astfel, aici se termina si sectiunea si Modulul 1. Daca aveti nevoie de intrebari ma puteti gasi oricand folosind informatiile de aici.

➡ Sectiunea anterioara: Curs C++ | Sectiunea 5 – Flow Control

➡ Sectiunea urmatoare:Curs C++ | Sectiunea 7 – If-Else

You may also like...