Bun venit tuturor incepatorilor si chiar avansatilor in domeniul limbajelor 
  de programare. t6e7ei
  Acesta este episodul pilot al unei serii de articole ce isi propune initierea 
  in cel mai popular limbaj la ora actuala, C++. 
  Pentru inceput, vor fi prezentate sintaxa, elemente de baza, apoi, dupa citeva 
  episoade se va trece la chestii mai avansate, programare orientata pe obiecte, programare 
  Windows si chiar programare pentru UNIX / LINUX. 
  Elementul de baza in toate articolele va fi exemplul. Veti gasi de fiecare data 
  coduri sursa pe care sa le puteti compila si executa. 
 Elemente da baza, sintaxa, biblioteci standard:
 Limbajul C este considerat a fi un limbaj de nivel mediu, spre deosebire de 
  Pascal sau
  Fox care sunt considerate de nivel inalt. 
  Ce insemna acest lucru? Inseamna ca ofera un control mai strict asupra procesorului, memoriei si a calculatorului in general. Pentru a scrie si executa programe 
  C aveti nevoie de un compilator (un program ce converteste textul sursa in cod executabil). Pentru 
  moment ne vom referi la compilatorul Borland C++ 3.1. Structura unui program C++ arata cam 
  asa:
 #include < biblioteca_standard_1.h >
  ...
  #include < biblioteca_standard_n.h > declaratii si definitii de variabile declaratii si definitii de functii functia main - elementul principal din program
 o variabila se defineste astfel:  tip_variabila nume_variabila a=valoarei;
 (elementele scrise intre paranteze patrate sunt optionale) tip_variabila poate 
  fi: • char: tip intreg cu semn cu valori cuprinse intre -128 si + 127 (pe 8 biti)
  • int: tip intreg cu semn cu valori cuprinse intre -32768 si + 32767 (pe 
  16 biti)
  • long: tip intreg cu semn cu valori cuprinse intre - 2147483648 si + 
  2147483647 (pe 32 biti)
 fiecare din tipurile de mai sus poate fi precedat de specificatorul unsigned:
 
 • unsigned char: tip intreg fara semn cu valori cuprinse intre 0 si 
  + 255 (pe 8 biti)
  • unsigned int: tip intreg fara semn cu valori cuprinse intre 0 si + 65535 
  (pe 16 biti)
  • unsigned long: tip intreg fara semn cu valori cuprinse intre 0 si + 
  4294967295 (pe 32 biti) alte tipuri: 
  • float: tip real in virgula mobila pe 32 biti
  • double: tip real in virgula mobila pe 64 biti
  • long double: tip real in virgula mobila pe 80 biti
 Nota: unsigned nu se poate folosi cu nici unul din tipurile reale. In toate compilatoarele 
  pentru
  Windows 32, tipul int este identic cu tipul long (32 de biti). Un echivalent 
  al 'vechiului' int (pe 16 biti) este tipul short. In anumite compilatoare pentru Windows 32, tipul long 
  double este identic cu tipul double (Ex. Microsoft Visual C++ 5, 6). 
  Variabile tablou: tip_var nume_varadimensiunei;
  Exemplu: int xa10i; // tablou de zece intregi 
 O functie (sau procedura) este o secventa de program ce executa o anume actiune, 
  de obicei generalizata. Poate avea propriile declaratii de variabile in corpul ei, variabile 
  care ii sunt locale si accesibile doar din interiorul ei. Declaratia unei functii arata astfel: tip_returnat nume_functie(paramatri functie)
  A corp_functie
  S  tip_returnat se refera la tipul de valoare returnat de functie, si poate fi 
  oricare din tipurile de mai sus, inclusiv de tipul void. Acest tip special indica faptul ca functia nu intoarce 
  nici un rezultat.
  Parametrii functiei sunt declarati astfel:  tip_parametru nume_parametru, ...
  Specificatorul void indica faptul ca functia nu primeste nici un parametru. 
  Exemple:  int functie(int x, int y)
  A return x+y;
  S
  Este declaratia unei functii ce primeste doi parametri de tip int, si intoarce 
  un rezultat de tip int
  (in cazul de fata, suma parametrilor). x si y se numesc parametri formali ai 
  functiei si sunt accesibili doar in interiorul corpului functiei A S.  void functie(int y)
  AS
  Este o functie ce primeste un parametru de tip int, dar nu face nimic. O functie 
  total inutila, bineinteles. 
  Nota:
  Nu se pot declara in program variabile de tip void. void variabila; // Gresit!!!
  Exemplu de program: 
  #include // este o biblioteca standard de functii
  // pentru operatii de intrare / iesire (tastatura) void main() // functie fara parametri, void nu este obligatoriu.
  A printf("Primul program C++\n");
  S
  Se afiseaza pe ecran textul dintre ghilimele, de cite ori rulati programul. 
  Primul program C++
  Primul program C++
  Primul program C++
  ...
  Ultima parte (\n) nu apare. Este doar un caracter de control ce semnaleaza trecerea 
  la o linie noua, altfel, textul urmator ar aparea in continuarea: (Primul program 
  C++ Primul program
  ...) Exemplul 2: 
  #include <stdio.h>  void main() // functie fara parametri, void nu este obligatoriu.
  A int n = 10; printf("n = %d\n", n);
  S
  Pe ecran apare: n = 10 
  Explicatii:
  %d este un specificator de format, ii spune functiei printf ca trebuie sa afiseze 
  in locul lui o valoare de tip intreg. Functia printf are un numar variabil de parametri. Vom 
  vedea mai incolo cum se pot defini astfel de functii.  exemplu: printf("Numere: %d %d %d", x, y, 10); 
  Se vor afisa valorile lui x, y, si apoi valoarea 10. 
  Bibliotecile Borland C++ contin foarte multe functii (citeva sute), si prezentarea 
  tuturor nu face subiectul acestor articole. Anumite functii vor fi descrise in momentul 
  in care sunt utilizate.
  Pentru celelalte se recomanda consultarea help-ului. 
  Instructiune if: 
  Sintaxa:  if (conditie)
  A instructiuni_1;
  S else
  A instructiuni_2;
  S
  Instructiunea for:
  Sintaxa:  for (var = valoare_initiala; conditie_de_continuare; instructiune_de_continuare)
  A instructiun1;
  S
  Exemplu:  int i; for (i = 0; i < 100; i++) A...S
  Se executa secventa A...S cu I luind valori de la 0 la 99. 
  Nota:
  Daca corpul unui for (sau if) contine o singura instructiune, nu mai sunt necesare 
  acoladele: 
  Exemplu:  for (j = 0; j <= 10; j++) printf("%d ", j);
  Efect: 0 1 2 3 4 5 6 7 8 9 10 
 for (j = 0; j <= 10; j++)
  A printf("%d ", j); printf("%d, ", j*j);
  S
  Efect: 0 0, 1 1, 2 4, 3 9 ...
  Va ofer acum doua surse. Trebuiesc compilate si apoi executate.
  #include <stdio.h> // Biblioteca standard cu functii de intrare / iesire
  #include <conio.h> // Biblioteca standard cu functii pentru lucru cu ecranul 
  in mod text
int n = 10; // Variabila globala initializata la declaratie
  // Variabilele globale ( declarate in afara oricarei functii
  // sunt accesibile de oriunde ( dupa declaratie )
void dreptunghi( int x1, int y1, int x2, int y2 )
  // Functia primeste parametri 4 intregi si ca efect
  // deseneaza cadrul unui dreptunghi pe ecran de coordonate
  // x1,y1 si x2,y2.
  A int i; // Variabila locala functiei dreptunghi.
  // nu este accesibila decit in cadrul functiei dreptunghi.
 for ( i=x1; i<=x2; i++ )
  A gotoxy( i,y1 ); // functie <conio.h> ce pozitioneaza cursorul
  // la pozitia i, y1 printf("Û"); // caracterul 219
 gotoxy( i,y2 ); printf("Û");
  S
 for ( i=y1; i<=y2; i++ )
  A gotoxy( x1,i ); // functie <conio.h> ce pozitioneaza cursorul
  // la pozitia i, y1 printf("Û");
 gotoxy( x2,i ); printf("Û");
  S
  S
void main()
  A clrscr(); // functie <conio.h> ce sterge ecranul in mod text textmode(3);
 dreptunghi( 1,1, 79,25 ); dreptunghi( 10,10, 20,20 ); dreptunghi( 12,12, 18,18 ); dreptunghi( 15,15, 60,23 );
  S
/*
  Se observa ca daca dreptunghiul ce se doreste a fi desenat ajunge in coltul din dreapta jos al ecranului ( 80,25 ), rezultatul nu este cel dorit. Asta din cauza ca la scrierea pe ultima pozitie de pe ecran, functia printf deplaseaza continutul acestuia cu o linie in sus ( exact ca la un teleimprimator ).
*/
#include <stdio.h>
  #include <conio.h>
int nra10i; // Numar maxim de numere int n;
void main()
  A clrscr();
 printf( "Cite numere? " ); scanf( "%d", &n ); // functie <stdio.h> pentru citirea de 
  la tastatura
  // parametrul al doilea, &n, semnifica adresa variabile n
 if ( n <= 0 || n > 10 ) // daca n <= 0 SAU n > 10
  A printf( "Numar invalid ( 1 - 10 )\n" ); return;
  S
 for ( int i = 0; i < n; i++ )
  A printf( "\nnra%di = ", i ); scanf( "%d", &nraii );
  S
 int m = n-1;
 int sorted = 0;
 while ( sorted == 0 ) // atit timp cit sorted este egal de 0
  A sorted = 1;
 for ( i = 0; i < m; i++ ) if ( nraii > nrai+1i ) // daca nu sunt in ordine, se inverseaza
  A int aux = nraii; nraii = nrai+1i; nrai+1i =aux;
 sorted = 0;
  S
 m--; // m se decrementeaza deoarece dupa fiecare parcurgere a
  // sirului, pe ultima pozitie se va afla elementul de valoare maxima
  S
 printf( "\n" ); for ( i = 0; i < n; i++ ) printf( "%d ",nraii );
 printf( "\n" );
  S
  Utilizarea functiilor grafice oferite de
  Borland C++ 3.1.
  Elementele de grafica prezentate in acest articol nu sunt specifice doar mediului 
  de dezvoltare BC31 ( Borland C++ 3.1 ), ele fiind pre- zente in orice compilator 
  C++ ce poate scoate executabile DOS standard si respecta specificatiile ANSI ( American National 
  Standards
  Institute ). 
 Elemente pregatitoare: 
  Pentru utilizarea facilitatilor grafice, trebuie procedat astfel: 
 1. in meniul principal, selectati: Options, Linker, Libraries...;
  In caseta de dialog aparuta selectati optiunea Graphics Library. 
  2. pe la inceputul programului dv. scrieti linia: 
  #include <graphics.h>
 3. in functia main initializati modul grafic:  int driver, mod; detectgraph( &driver, &mod ); initgraph( &driver, &mod, "C:\\BC31\\BGI" );
 Explicatii: 
  Driver si mod sunt doua variabile intregi pe care functia detectgraph le initializeaza 
  cu valori corespunzatoare celui mai adecvat mod video. Compilatorul are intern 
  o tabela cu driverele grafice pe care le suporta ( fisiere cu extensia BGI ) si cu modurile proprii 
  fiecarui driver. Dupa apelarea functiei detectgraph, variabila driver va contine numarul de ordine 
  al celui mai adecvat driver, iar variabila mod numarul de ordine al celui mai adecvat mod grafic 
  specific driverului respectiv. 
  De exemplu, daca aveti o placa grafica compatibila VGA, functia detectgraph 
  va seta valori corespunzand driverului EGAVGA.BGI si modului grafic 640x480 x 16 culori. 
  Pentru o placa video mai veche de tip EGA, driverul detectat ar fi acelasi, dar modul 
  grafic ar fi 640x350 x
  16 culori. 
  Variabilele mai sus mentionate sunt apoi trimise ca parametri prin adresa functiei initgraph, ce realizeaza efectiv trecerea placii video in modul corespunzator. 
  Al treilea parametru este calea spre fisierele driver BGI, in cazul de fata C:\BC31\BGI. Se observa 
  folosirea secventei
  \\, care intr-un program C,C++ produce caracterul '\'.  
 Exemplu: sa desenam un cerc galben: 
  #include <conio.h>
  #include <stdio.h>
 void main()
  A int dr, mo; detectgraph( &dr, &mo ); initgraph( &dr, &mo, "C:\\BC31\\BGI";
 setcolor( 14 ); // numarul culorii variaza de la 0 la 15, 14 fiind culoarea 
  galben circle( 320, 240, 100 );
 getch(); closegraph();
  S
  Functia circle( x,y, r ); are ca efect desenarea unui cerc de centru x si y 
  si raza r. Exemple de alte functii grafice:  line( x1,y1, x2,y2 ); // deseneaza o linie intre punctele de coordonate
  // (x1,y1) si (x2,y2). Nu modifica pozitia punctului curent
 lineto( x,y ); // deseneaza o linie din punctul curent pina in punctul
  // ( x,y ), care devine astfel punct curent.
 linerel( rx,ry ); // deseneaza o linie din punctul curent pina in
  // punctul de coordonate relative ( rx,ry ), care
  // devine apoi punct curent.
 putpixel( x,y, c ); // deseneaza un pixel in punctul (x,y) de culoare c
 moveto( x,y ); // muta pozitia curenta in punctul (x,y). Nu deseneaza nimic. moverel( rx,ry ); // muta pozitia curenta cu rx pozitii la dreapta si ry
  // pozitii in sus. rx si ry pot lua si valori negative.
  // Valabil si pentru linerel.
  Explicatii: 
  Pozitia curenta este un punct fictiv de pe ecran, situat la inceput in coltul 
  (0,0). Este folosit si modificat de functii ca lineto, linerel, moveto, moverel, outtext, 
  etc... 
  Originea ecranului este in coltul din stinga sus, axa OX este orientata de la 
  stinga spre dreapta, axa OY de sus in jos. 
 (0,0) -> (639,0)
  _____________________________________________________
  | | |
  V | |
  | |
  | |
  | |
  | |
  | |
  | |
  | |
  | |
  | |
  | |
  ______________________________________________________
  (0,479) (639,479)
  Exemplu: grafic1.cpp - Un program care afiseaza un desen simplu. Sa incercam 
  urmatorul exemplu: grafic2.cpp 
  #include >conio.h>
  #include <math.h>
  #include <dos.h>
  #include <graphics.h>
 void main()
  A int dr, mo; detectgraph( &dr, &mo ); initgraph( &dr, &mo, "C:\\BC31\\BGI" );
 float u = 0.0;
  while( !kbhit() ) // atit timp cit nu se apasa nici o tasta...
  A cleardevice(); // sterge ecranul line( 320, 240, 320 + 200*cos(u), 240 + 150*sin(u) ); fillellipse( 320 + 200*cos(u), 240 + 150*sin(u), 50, 50 );
 u += 0.01;
  S
  S
  Daca rulati acest program, veti observa un efect neplacut de intermitenta a 
  colorarii elipsei, si chiar a liniei, efect numit flicker. Cauza este ca intre stergerea 
  ecranului ( cleardevice ) si redesenarea elipsei, monitorul are timp sa afiseze citeva cadre cu ecranul 
  negru. Cum se poate avita aceasta? Exista doua metode: folosirea mai multor pagini video si 
  sincronizarea desenarii cu frecventa de afisare a monitorului, care va face obiectul unui 
  articol viitor. 
  Ce inseamna mai multe pagini video? Inseamna ca avem mai multe zone de desenare, fiecare din ele ( pagina ) avind dimensiunea ecranului. In timp ce pe monitor 
  avem imaginea uneia din ele, noi desenam nestingheriti in cealalta. Cind am terminat de desenat, 
  inversam intre ele pagina vizibila si pagina de desenare. Putem apoi relua operatiunea, in 
  timp ce se vede o imagine, noi pregatim imaginea urmatoare. 
  Interschimbarea paginilor video se face cu ajutorul functiilor grafice setactivepage() 
  si setvisualpage(). 
  Vom lucra in modul VGA imediat inferior celui returnat de functia detectgraph 
  pentru o placa VGA, mod cu o rezolutie mai slaba ( 640x350 x 16 ) dar care admite doua 
  pagini video: pagina 0 si pagina 1. Utilizam o variabila video ce initial are valoarea 0. 
  O secventa de tipul:  setactivepage(video); setvisualpage(1-video); video = 1-video;
 Provoaca interschimbarea paginilor si comutarea variabilei video din 0 in 
  1 si invers. Vom utiliza aceasta secventa in programul grafic3.cpp pentru imbunatatirea efectelor 
  grafice. 
  Totusi, chiar daca se observa o oarecare imbunatatire a afisarii, cei cu acceleratoare grafice cu peste 512K, vor observa in continuare fenomenul de clipire. Asta 
  deoarece placile video mai noi nu mai asteapta semnalul de vertical retrace pentru a schimba 
  paginile video. 
  Ce este semnalul vertical retrace? Este momentul in care monitorul a terminat 
  de afisat un cadru de imagine, moment in care se poate efectua in siguranta schimbarea 
  paginii de afisare. Pentru acest lucru sunt necesare citeva cunostinte de limbaj de asamblare. 
  
  Cam atit deocamdata. In articolul viitor vom vedea cum se poate folosi modul 
  grafic
  320x200 x 256 culori si cam ce se poate face cu el ( rotatii de paleta, deplasari 
  de imagini,
  (pseudo)morphing, si altele ). 
  Pointeri si tablouri 
 Sa consideram acum ca avem nevoie sa vedem de ce trebuie sa identificam tipul 
  unei variabile spre care pointeaza un pointer, ca in: 
 int *ptr;
 Un motiv ar fi ca mai tarziu, cand ptr pointeaza spre ceva, daca 
  scriem: 
 *ptr = 2;
 compilatorul va sti citi baiti sa copieze in locatia de memorie spre care 
  pointeaza ptr. Daca ptr a fost definit ca pointind spre un intreg, doi asemenea baiti vor fi copiati, 
  pentru un long 4 baiti vor fi copiati. Dar definirea tipului spre care pointeaza un pointer permite un numar 
  de cai interesante in care compilatorul poate interpreta codul. De exemplu, sa consideram un bloc 
  de memorie constituit din zece intregi in linie. Astfel, 20 de baiti vor fi alocati pentru 
  10 intregi. 
  Acum, sa presupunem ca punem ptr sa pointeze spre primul dintre acesti intregi. 
  Sa presupunem, mai departe, ca acest intreg este locat la adresa 100). Ce 
  s-ar putea intampla cand am scrie : 
 ptr + 1; ?
 Deoarece compilatorul stie ca este vorba de un pointer (adica valoarea acestuia 
  este o adresa) si ca acesta pointeaza spre un intreg, aduna 2 la ptr in loc de 1, astfel incit 
  pointerul sa pointeze spre urmatorul intreg, la locatia de memorie 102. In mod similar, daca 
  ptr ar fi fost definit ca pointer spre long, compilatorul ar fi adunat 4 in loc de 1. Acelasi lucru se 
  intampla si cu celelalte tipuri de date, cum ar fi float, double sau structurile definite de utilizator. 
  In mod similar, ++ptr si ptr++ vor fi echivalent interpretate ca ptr+1, cu sensul discutat in paragraful 
  anterior. Deoarece un bloc de 10 intregi situat continuu in memorie este, prin definitie, 
  un tablou, de intregi, se contureaza o interesanta relatie intre tablouri si pointeri. Sa consideram urmatorul 
  tablou: 
 int tabai = A1,23,17,4,-5,100S;
 Avem un tablou cu sase intregi. Am putea referi fiecare dintre acesti 
  intregi prin-un index cu valori de la 0 la 5, adica de la taba0i pina la taba5i. Am putea insa sa accesam 
  aceste elemente prin intermendiul unui pointer ca mai jos: 
 int *ptr; ptr = &taba0i; /* face ca pointerul nostru sa pointeze spre primul intreg din tablou */
 si sa le tiparim folosind notatia tablourilor sau prin dereferentierea pointerului 
  nostru. Programul urmator ilustreaza acest lucru: 
 #include <stdio.h> int tabai = A1,23,17,4,-5,100S; int *ptr; int main(void)A int i; ptr = &taba0i; /* point our pointer to the array */ printf("\n\n"); for(i = 0; i < 6; i++)A printf("taba%di = %d ",i,tabaii);  printf("ptr + %d = %d\n",i, *(ptr + i));
  S return 0;
  S
  Daca veti compila programul de mai sus, veti observa ca liniile in care se face 
  afisarea dau rezultate identice. De notat este si modul in care s-a facut dereferentierea 
  pointerului in a doua linie de afisare : s-a adunat i la acesta si abia dupa s-a dereferentiat noul 
  pointer. In C, standardul specifica faptul ca oriunde am folosit &nume_variabilaa0i am 
  putea folosi doar nume_variabila, astfel ca am putea schimba linia 
 ptr = &taba0i;
 cu 
 ptr = tab;
 Acest lucru conduce multe carti la a spune ca numele unui tablou este un pointer. 
  Desi acest lucru este adevarat, este preferabil sa va ginditi la numele de tablouri 
  ca la pointeri constanti. De exemplu, putem scrie ptr = tab; dar nu putem scrie tab = ptr;. 
  
  Motivul este ca ptr este o variabila, pe cind tab este o constanta, locatia 
  la care va fi stocat primul element al tabloului nu mai poate fi schimbat odata ce tabai a 
  fost declarat. 
  Deocamdata atit la rubrica "C/C++", in numarul urmator vom continua 
  explicatiile asupra acestui capitol "spinos" si vom analiza, probabil, structurile mai 
  in detaliu.