Intrări/Ieșiri de bază

Programele date ca exemplu în secțiunile anterioare au conținut prea puțină interacțiune cu utilizatorul, dacă nu chiar deloc. Ele pur și simplu afișau valori pe ecran, dar biblioteca standard furnizează multe alte modalități de interacțiune cu utilizatorul prin facilitățile de intrare/ieșire. Această secțiune va prezenta o scurtă introducere în câteva dintre cele mai utile.

C++ folosește o noțiune potrivită numită stream-uri pentru a efectua operații secvențiale de intrare/ieșire la/de la monitor, tastatură sau fișiere. Un stream este o entitate în care un program poate insera sau din care poate extrage caractere. Nu este necesar să cunoaștem amănunte despre locațiile asociate acestui stream sau detalii interne ale sale. Tot ceea ce trebuie să știm este faptul că stream-ul reprezintă sursa /destinația caracterelor și faptul că aceste caractere sunt transmise/preluate secvențial (adică unul după altul).

Biblioteca standard definește un tip comod de lucru cu obiecte stream care pot fi folosite pentru accesarea a ceea ce se consideră surse și destinații standard de caractere pentru mediul în care rulează programele:

StreamDescriere
cinStream standard de intrare
coutStream standard de ieșire
cerrStream standard de afișare a erorilor
clogStream standard de afișare a logărilor

Noi vom da mai multe detalii numai despre cout și cin (stream-urile standard pentru ieșire, respectiv intrare); cerr și clog reprezintă tot stream-uri de ieșire, deci ele lucrează, în esență,ca și cout, cu singura diferență că identifică stream-uri cu un anumit scop: mesajele de eroare și logările; iar, de cele mai multe ori, în cele mai multe setări de mediu, ele fac exact același lucru: afișează pe ecran, deși se poate face redirecționarea lor.

Ieșire standard (cout)

În cele mai multe medii de programare, ieșirea standard implicită este ecranul monitorului, iar obiectul stream C++ definit pentru accesarea lui este cout.

Pentru operații de ieșire formatată, cout se folosește împreună cu operatorul de inserare, care se scrie cu simbolul << (adică două semne ”mai mic decât”).

1
2
3
cout << "Instructiune de iesire"; // afiseaza pe ecran Instructiune de iesire
cout << 120;               // afiseaza pe ecran numarul 120
cout << x;                 // afiseaza pe ecran valoarea lui x  

Operatorul << inserează datele care urmează în stream-ul care îl precede. În exemplele de mai sus, inserează string-ul de caractere Instructiune de iesire, numărul 120 și valoarea variabilei x în stream-ul standard de ieșire cout. Să observăm că mesajul din prima instrucțiune este cuprins între ghilimele (") deoarece este un string (șir de caractere), în timp ce în ultima x nu este. Ghilimelele sunt cele care fac diferența între un text (cel care este cuprins între ele) care va fi afișat pe ecran exact așa cum este și identificatorii de variabile (care nu sunt cuprinși între ghilimele) ce se interpretează, afișându-se pe ecran valorile lor. De exemplu, aceste două instrucțiuni au rezultate foarte diferite:

1
2
cout << "Hello";  // afiseaza pe ecran Hello
cout << Hello;    // afiseaza pe ecran continutul variabilei Hello 

Într-o singură instrucțiune pot fi incluse mai multe operații de inserare (<<):

1
cout << "Aceasta " << " este o " << "singura instructiune C++";

Ultima instrucțiune ar trebui să afișeze pe ecran Aceasta este o singura instructiune C++. Înlănțuirea de inserții este foarte utilă în afișarea mixtă de mesaje și variabile cu o singură instrucțiune:

1
cout << "Eu am " << varsta << " ani si codul meu postal este " << cod;

Presupunând că variabila varsta conține valoarea 24 și că variabila cod conține 90064, ieșirea instrucțiunii anterioare este:

Eu am 24 ani si codul meu postal este 90064
cout nu adaugă automat sfârșit de linie, dacă nu i se precizează să facă asta. De exemplu, să luăm următoarele două instrucțiuni de inserare în cout:
cout << "Aceasta este o propozitie.";
cout << "Aceasta este o alta propozitie.";

Afișarea se face pe o singură linie, fără trecere la rând nou. Cam așa:

Aceasta este o propozitie.Aceasta este o alta propozitie.
Pentru a insera un rând nou, ar trebui să inserăm caracterul new-line exact în poziția în care ar trebui să apară întreruperea rândului. În C++, un caracter new-line poate fi precizat cu \n (adică un caracter backslash urmat de litera mică n). De exemplu:

1
2
cout << "Prima propozitie.\n";
cout << "A doua propozitie.\nA treia propozitie.";

Acestea produc următoarea ieșire:

Prima propozitie.
A doua propozitie.
A treia propozitie.

Alternativ, manipulatorul endl poate fi folosit pentru a întrerupe liniile. De exemplu:

1
2
cout << "Prima propozitie." << endl;
cout << "A doua propozitie." << endl;

Aceasta ar afișa:

Prima propozitie.
A doua propozitie.

Manipulatorul endl produce un caracter newline, exact ca și inserarea cu '\n'; dar are, totuși un comportament diferit: buffer-ul de stream (dacă există) este curățat, ceea ce înseamnă că ieșirea necesită scrierea fizică la dispozitiv, dacă nu s-a făcut deja. Aceasta afectează, în principal, stream-urile cu buffer plin și cout nu este (în general) un stream cu buffer plin. Este o idee bună să folosim endl numai când curățarea stream-ului ar fi un lucru pe care nu îl poate face '\n'. Să reținem că operația de curățare aduce o suprasolicitare și unele dispozitive pot fi mai încete, producând întârzieri.

Intrare standard (cin)

În cele mai multe medii de programare, intrarea standard setată implicit este tastatura, iar obiectul stream C++ definit pentru a o accesa este cin.

Pentru operații de intrare cu formatare cin se folosește împreună cu operatorul de extragere, pentru care folosim simbolul >> (adică două semne "mai mare decât"). Acest operator este urmat de variabila în care va fi depusă informația extrasă. De exemplu:

1
2
int varsta;
cin >> varsta;

Prima instrucțiune declară o varibilă de tip int denumită varsta, iar a doua extrage din cin o valoare ce va fi memorată în ea. Această operație face ca programul să aștepte o intrare de la cin; în general, aceasta înseamnă că programul va aștepta după utilizator să introducă o secvență de la tastatură. În acest caz, rețineți că toate caracterele tastate sunt transmise programului numai câdn este apăsată tasta ENTER (sau RETURN). Când se ajunge la instrucțiunea cu operația de extragere din cin, programul va aștepta atât cât este necesar până când sunt introduse date.

Operația de extragere din cin folosește tipul variabilei de după operatorul >> pentru a determina cum să interpreteze caracterele citite de la intrare; dacă este un întreg, formatul așteptat este o serie de cifre, dacă este un string se așteaptă o secvență de caractere, etc.

// exemplu i/o

#include <iostream>
using namespace std;

int main ()
{
  int i;
  cout << "Va rugam, introduceti o valoare intreaga: ";
  cin >> i;
  cout << "Valoarea introdusa este " << i;
  cout << " si dublul sau este " << i*2 << ".\n";
  return 0;
}
Va rugam, introduceti o valoare intreaga: 702
Valoarea introdusa este 702 si dublul sau este 1404.

După cum puteți vedea, extragere din cin pare să facă foarte simplă și directă sarcina de extragere a datelor de la intrarea standard. Dar această metodă are și un mare neajuns. Ce se întâmplă în exemplul de mai sus dacă utilizatorul introduce ceva ce nu poate fi interpretat ca număr întreg? Ei bine, în acest caz, operația de extragere eșuează. În mod implicit, aceasta permite prograumului să continue fără atribuirea unei valor varabilei i, producând rezultate nedeterminate dacp valoarea lui i va fi folosită mai târziu.

Acesta este un comportament deficitar al prgramului. Cele mai multe programe trebuie să se comporte într-o anume manieră, indeiferent de ceea ce tastează utilizatorul, gestionând în mod adecvat valorile invalide. Numai programele foarte simple ar trebui să se bazeze pe extrageri directe din cin, fără un control mai serios. Puțin mai târziu vom vedea cum poate fi folosis stringstreams pentru a avea un control mai bun asupra intrărilor date de utilizator.
Extragerile din cin pot, de asemenea, să fie înlănțuite, atfelt încât să se ceara mai multe informații într-o singură instrucțiune:

1
cin >> a >> b;

Aceasta este echivalentă cu:

1
2
cin >> a;
cin >> b;

În ambele cazuri, se așteaptă ca utilziatorul să introducă două valori, una pentru variabila a, iar cealaltă pentru variabila b. Se poate folosi orice fel de spațiu pentru a separa două operații consecutive de intrare; poate fi spațiu, tab sau un caracter new-line.

cin și string-uri

Operatorul de xtragere poate fi folosit cu cin pentru a obține șiruri de caractere la fel ca și cu celelalte tipuri de date fundamentale:

1
2
string sirul_meu;
cin >> sirul_meu;

Totuși, extragerea din cin ia în considerare separatorii (caracterele spațiu, tab, new-line...) ca terminatori ale valorii ce trebuie extrase și, de aceea, extragerea unui string înseamnă că se va prelua numai un singur cuvânt, nu o intreagă frază sau propoziție.

Pentru a obține o linie întreaga de la cin, există o funcție numită getline, care ia stream-ul (cin) ca prim argument și variabila string ca al doilea argument. De exemplu:

// cin cu string-uri
#include <iostream>
#include <string>
using namespace std;

int main ()
{
  string sirul_meu;
  cout << "Cum te numesti? ";
  getline (cin, sirul_meu);
  cout << "Hello " << sirul_meu << ".\n";
  cout << "Care este echipa ta favorita? ";
  getline (cin, sirul_meu);
  cout << "Mie imi place " << sirul_meu << ", de asemenea!\n";
  return 0;
}
Cum te numesti? Homer Simpson
Hello Homer Simpson.
Care este echipa ta favorita? The Isotopes
Mie imi place The Isotopes , de asemenea!

Să observăm că ambele au apelat funcția getline, am folosit același identificator de string (sirul_meu). În al doilea apel, programul doar a înlocuit conținutul anterior cu cel nou care a fost tastat.

Comportamentul standard este ca de fiecare dată când i se cer date utilizatorului, el să le completeze și apoi să apese tasta ENTER (sau RETURN). Aceasta se întâmplă, în general, în programele consolă și se poate realiza folosind getline pentru a obține date de intrare de la utlizator. De aceea, numai dacă aveți un motiv serios să nu o faceți, ar trebui să utilizați getline pentru preluarea datelor de intrare în programele consolă, în loc de extragerea din cin.

stringstream

Antetul standard <sstream> definește un tip numit stringstream care permite ca un string să fie tratat ca stream și, deci, să fie permise operațiile de extragere și inserare din/în string-uri în același fel ca și pentru cin și cout. Această caracteristică este foarte utilă în convertirea string-urilor la valori numerice și invers. De exemplu, pentru a extrage un întreg dintr-un șir putem scrie:

1
2
3
string sir ("1204");
int numar;
stringstream(sir) >> numar;

Aceasta declară un string cu valoarea inițială "1204" și o variabilă de tip int. Apoi, a treia linie folosește această variabilă pentru a extrage dintr-un stringstream construit din string. Această secvență de cod memorează valoarea numerică 1204 în variabila numar.

// stringstreams
#include <iostream>
#include <string>
#include <sstream>
using namespace std;

int main ()
{
  string sir;
  float pret=0;
  int cantitate=0;

  cout << "Introduceti pretul: ";
  getline (cin,sir);
  stringstream(sir) >> pret;
  cout << "Introduceti cantitatea: ";
  getline (cin,sir);
  stringstream(sir) >> cantitate;
  cout << "Pretul total: " << pret*cantitate << endl;
  return 0;
}
Introduceti pretul: 22.25
Introduceti cantitatea: 7
Pretul total: 155.75

În acest exemplu, colectăm indirect valori numerice de la intrarea standard indirectly: în loc să extragem valorile numerice direct de la cin, obținem linii într-un obiect string (sir), apoi extragem valorile din string în variabilele pret și cantitate. Deoarece acestea sunt valori numerice, se pot executa operații aritmetice cu ele, precum înmulțirea lor pentru a obține valoarea totală.

Cu această abordare, de a obține linii întregi și de a extrage conținutul lor, separăm procesul de preluare a informațiilor de la utilizator de del de intrepretare a lor ca date; astfel, procesul de preluare date este așa cum se așteaptă utilizatorul să fie și, în același timp, câștigăm controlul asupra transformării conținutului în date utile pentru program.
Index
Index