Documente Academic
Documente Profesional
Documente Cultură
Dorin BoKu
2001-2002
n loc de introducere
Dup iniierea n programare, cu sprijinul altor cursuri,
paralele cu programarea sau complementare n cel mai bun
neles al cuvntului, iat-ne btnd, cu nelepciune
sporit, la poarta unei lumi n care vom vedea aceleai
concepte ntr-o micare care respect rigorile unui joc nou,
mult mai interesant din punct de vedere al mptimiilor n
ale programrii. Avem de lmurit i adncit dou teme de
meditaie mari i importante pentru formarea oricrui
informatician :
Autorul
2
I BAZELE C++. LIMBAJUL C
3
1 Privire de ansamblu asupra limbajului C
1.1 Despre originile limbajului C
Legenda spune c C a fost inventat i implementat de Dennis Ritchie pe un
calculator DEC PDP-11, care utiliza sistemul de operare UNIX. Virtual, C este
rezultatul unui proces de dezvoltare complex, la care putem spune c a participat
ntreaga comunitate preocupat de ridicarea performanelor n munca de
programare. De fapt, strmoi direci ai limbajului C pot fi considerate limbajele
BCPL (creat de Martin Richards) i limbajul B (inventat de Ken Thompson). n
anii 70, limbajul B a influenat n cel mai nalt grad specificarea limbajului C. Mult
timp, standardul de facto pentru C a fost versiunea ce nsoea sistemul de
operare UNIX. Acest standard a fost descris pentru prima dat n cartea The C
Programming Language, scris de Brian Kernigan i Dennis Ritchie, aprut n
1978 la editura Prentice Hall. Odat cu creterea popularitii calculatoarelor
personale, au fost create numeroase implementri de C, ceea ce a generat o
problem nou: compatibilitatea implementrilor. Pentru rezolvarea acestei
probleme, n vara anului 1983, a fost nfiinat un comitet pentru crearea unui
standard ANSI (American National Standard Institute) care avea ca sarcin
specificarea definitiv a limbajului C. Standardul ANSI C a fost adoptat n
decembrie 1989, primele copii devenind disponibile la nceputul lui 1990. La ora
actual, toate compilatoarele C/C++ se aliniaz la standardul ANSI C. Totodat
standardul ANSI C este o baz pentru propunerea de standard ANSI C++(Bazat
pe limbajul C, C++ adaug extinderi care permit programarea obiect orientat).
Evident, vom reveni asupra topicii C++.
4
beneficiaz de un cadru mult mai liberal (controalele compilatorului nu mai sunt
att de severe ca n Pascal).
Spre deosebire de un limbaj de nivel nalt, C nu face aproape nici un
control n timpul executrii unui program. Responsabilitatea de a evita
producerea erorilor i de a le dibui i corecta, dac le-a ocazionat, este a
programatorului.
C permite lucrul direct cu bii, octei cuvinte i pointeri ceea ce l face
potrivit pentru programare la nivel de sistem.
5
algoritmi cu limpezime, elegan i eficien. n C un bloc de cod poate fi creat
incluznd ntre acolade un grup de instruciuni.
6
Auto double Int struct
Break else Long switch
Case enum Register typedef
Char extern Return union
Const float Short unsigned
Continue for Signed void
Default goto Sizeof volatile
Do if Static while
Tabelul 1 Cele 32 cuvinte-cheie definite de standardul ANSI C
Toate programele C constau din una sau mai multe funcii a cror
sintax i semantic o vom prezenta n seciunile urmtoare.
7
s rezolve anumite probleme. Aceast nou abordare o vom dezbate treptat n
seciunile care vor urma.
8
2 Expresii n C
n aceast seciune vom trece n revist propunerile limbajului C n ceea ce
provete posibilitatea de a utiliza expresii. Toate limbajele de programare
acord o atenie special noiunii de expresie deoarece, n ultim analiz, orice
transformare a datelor de intrare ale unui program este realizat prin intermediul
uneia sau a mai multor expresii. Aa cum vom descoperi pe parcurs, C este un
limbaj mult mai flexibil dect alte limbaje n materie de definire i utilizare a
expresiilor. Ceea ce este foarte limpede n acest moment este faptul c
expresiile sunt realizate cu ajutorul elementelor atomice numite date i
operatori. Datele pot fi reprezentate cu ajutorul constantelor sau prin intermediul
variabilelor. Ajungem, evident, la problema tipurilor de date suportate de C.
9
Tip de dat Dimensiune reprezenatre Domeniul valoric minimal
n bii
char 8 -127..127
unsigned char 8 0..255
signed char 8 -127..127
int 16 -32767..32767
unsigned int 16 0..65535
signed int 16 Similar cu int
short int 16 Similar int
unsigned short int 16 0..65535
signed short int 16 Similar cu short int
long int 32 -2.147.483.647..2.147.483.647
signed long int 32 Similar cu long int
unsigned long int 32 0..4.294.967.295
float 32 6 zecimale exacte
double 64 10 zecimale exacte
long double 80 10 zecimale exacte
10
liter sau o liniu de subliniere; urmtoarele pot fi litere, cifre sau liniua de
subliniere.
Exemple de identificatori:
Coreci Incoreci
numr_de pagini 1_valoare_returnat
_limita1 ok!
ok_ switch..conversie
2.4 Variabile C
Aa cum s-a aflat i n alte mprejurri, o variabil este numele unei locaii de
memorie utilizat pentru a pstra o valoare care poate fi modificat de
program.
nainte de a fi utilizate n program, variabilele trebuie declarate. Declararea unei
variabile n C are forma:
<Tip> <List_de_variabile>;
<Tip> trebuie s fie un tip de dat valid (predefinit sau definit de utilizator)
precedat, eventual, de un specificator de conversie.
<List_de_variabile> poate consta dintr-un nume de identificator sau mai multe
nume de identificatori separate prin virgul.
Exemple de declaraii de variabile:
int nr_pag;
char opt,ch;
unsigned i, j;
11
2.5 Variabile locale n C
Variabilele declarate n interiorul unei funcii sunt numite variabile locale. O
parte din literatura C/C++ numete aceste variabile automatice. innd cont de
asemnarea evident cu variabilele locale din Pascal, de exemplu, vom folosi
termenul de variabil local.
Afirmaia cea mai important referitor la variabilele locale este urmtoarea:
Directive preprocesor
Declaraii globale
Declaraie funcie_1
:
Declaraie funcie_n
int main()
{
Declaraii de date ale programului principal
Instruciuni program principal
Orice program C conine obligatoriu o funcie al crei nume este main
}
Implementare funcie_1
:
Implementare funcie_n
12
care nu mai insistm deoarece standardul ANSI C ca i standardul ANSI C++
descurajeaz, respectiv interzice utilizarea cii clasice.
n C++ declararea unei funcii se face apelnd la prototipuri.
n sfrit, implementarea unei funcii nseamn o construcie sintactic de tipul:
<Antet funcie>
{
<Declaratii de date>
<Instructiuni executabile>
}
void f1(void)
{
int x;
x=12;
}
void f2(void)
{
int x;
x=-128;
}
void fexemplu(void)
{
int i;
printf(Introduceti un numar:);
13
scanf(%d,&i);
if (i>0)
{
char nume [40];
printf(Numele Dvs.:);
gets(nume);
}
}
Din exemplul de mai sus reinem doar faptul c, n situaia n care numrul
preluat de la tastatur (cu ajutorul rutinei de uz general scanf ) este mai mare
dect zero, atunci devine activ blocul de cod n care se declar variabila nume.
Aceast variabil este distrus la ieirea din acest bloc de cod.
Prin urmare, un avantaj potenial: variabilei nume i se aloc memorie numai
dac se activeaz blocul de cod, ceea ce nseamn economie de memorie.
Este absolut evident faptul c se declar ntr-un bloc de cod una sau mai multe
variabile strict necesare n acest bloc de cod; n acest mod prevenim, ntr-o
oarecare msur, apariia unor efecte secundare. Mai semnalm o diferen
important ntre modul de declarare a variabilelor locale n C fa de C++.
n C trebuie declarate toate variabilele locale la nceputul blocului n care
intenionm s le definim, nainte de orice instruciune executabil. n C++ nu
mai exist aceast restricie. Astfel c secvena de cod C:
void f(void)
{
int i;
i=10;
int j;
j=20;
}
14
2.7 Variabile globale
Variabilele globale, spre deosebire de cele locale, sunt cunoscute n tot
programul i pot fi utilizate de ctre orice zon a codului. Totodat, ele i
pstraz valoarea tot timpul execuiei programului. Variabilele globale se
creaz prin declarare n afara oricrei funcii. Orice expresie are acces la ele,
indiferent de tipul blocului de cod n care se afl expresia. De semnalat faptul c
o variabil global este vizibil n orice bloc de cod al programului ct timp n
respectivul bloc de cod nu a fost declarat o variabil cu acelai nume, de
acelai tip. n caz afirmativ, n blocul de cod este prioritar referirea la variabila
local.
Stocarea variabilelor globale este fcut de compilator ntr-o zon de memorie,
special alocat. Variabilele globale sunt utile atunci cnd mai multe funcii ale
aceluiai program folosesc aceleai date. Utilizarea excesiv a variabilelor
globale ar trebui evitat deoarece:
Ocup memoria pe tot timpul execuiei programului, nu doar cnd sunt
necesare;
Dac o funcie utilizeaz o variabil global n locul uneia locale, atunci
funcia i pierde din generalitate, bazndu-se pe ceva exterior logicii ei;
Variabile globale multe nseamn efecte secundare necunoscute i
nedorite.
15
fi modificat de condiii externe, fiind protejat de modificri accidentale n
programul n care este declarat.
extern
Deoarece C/C++ permit seciunilor separate ale unui program s fie compilate
independent i s li se editeze legturile mpreun, trebuie s existe o modalitate
de a comunica tuturor fiierelor variabilele globale necesare programului.
Scenariul cruia trebuie s i facem fa este urmtorul: Cum putem informa
toate fiierele care compun un program C despre variabilele globale utilizate?.
Soluia este urmtoarea : Se declar variabilele globale ntr-un fiier, care este
de preferat s conin i funcia principal a programului, aceleai variabile
declarndu-se i n toate fiierele care folosesc variabilele globale, nsoite de
specificatorul extern.
static
Variabilele de tip static sunt variabile permanente n interiorul funciei sau
fiierului n care se gsesc. Spre deosebire de variabilele globale, ele nu sunt
cunoscute n afara funciei sau fiierului, dar i pstreaz valoarea ntre dou
apelri. Aceast caracteristic este folositoare la scrierea de funcii generice i
de bibliotec , utilizabile de alte programe. Specificatorul static are efecte diferite
asupra variabilelor locale i globale.
16
Aplicnd specificatorul static unei variabile globale, cerem compilatorului s
creeze o variabil global care este cunoscut doar n fiierul n care a fost
declarat. Aceasta nseamn c, dei variabila este global, rutine din alte
fiiere nu au acces la ea i nu i pot modifica coninutul.
register
Specificatorul de stocare register se aplic, prin tradiie, doar variabilelor de tip
int i char. Totui standardul ANSI C i d definiia astfel nct poate fi folosit
pentru orice tip de variabil. Iniial, register cerea compilatorului s pstreze
valoarea unei variabile ntr-un registru din CPU, nu n memoria RAM, unde
variabilele sunt stocate, de regul. Scopul unei astfel de cereri: spor de vitez n
timpul operaiilor asupra variabilei. Actualmente, definiia specificatorului register
a fost mult extins, acesta putnd fi aplicat oricrui tip de variabil. Standardul
ANSI C stipuleaz, simplu, c register este o indicaie dat compilatorului c
obiectul vizat va fi utilizat preferenial din punct de vedere al vitezei.
Specificatorul se poate aplica doar variabilelor locale i parametrilor formali. Prin
urmare, nu sunt permise variabile globale de tip register.
auto
Specificatorul auto este, practic, nefolosit, fiind reclamat doar de motive de
compatibilitate ntre codul C i codul C++.
Exemple:
char ch=A;
int media=0;
float bilant=0;
Constante C
17
Constantele se refer la valori fixe pe care programul nu poate s le modifice.
Constantele pot fi de oricare din tipurile fundamentale de date. Modul n care se
reprezint n program fiecare constant depinde de tipul su.
Constantele de tip caracter sunt incluse ntre ghilimele simple. A i % sunt
exemple de constante de tip caracter. C definete i caractere multioctet, n
mediile care nu utilizeaz limba englez. O situaie asemntoare se ntlnete
i n Delphi.
Constantele de tip ntreg sunt specificate ca numere fr parte fracionar. De
exemplu, 3 i -15 sunt exemple de constante ntregi.
Constantele n virgul mobil cer punctul zecimal urmat de partea zecimal a
numrului. 0.75 este un exemplu de constant care apeleaz la virgula mobil.
Limbajul C permite i notaia tiinific, cunoscut i n alte limbaje.
De asemenea, C stabilete pentru o constant numeric cel mai scurt tip de date
compatibil care o poate pstra. Astfel c, -10 este implicit un int, 60.000 este
unsigned int iar 120.000 este un long int. Tipul constantei numerice poate fi
specificat i explicit ca n exemplele din Tabelul 3.
Dup cum se vede, constantele n virgul mobil sunt asimilate implicit tipului
double.
18
Constante de tip ir
C admite, cum era i firesc i constanta de tip ir de caractere. O constant ir
este o succesiune de caractere delimitat de ghilimele. A nu se confunda irurile
de caractere cu caracterele. a i a sunt constante de tipuri diferite( disticie
care, n Pascal, nu este operat sintactic, vorbind.
Codul Semnificaia
\b Backspace
\f form feed (=Salt la pagin nou)
\n CR+LF
\r CR
\t tab orizontal
\ Ghilimele
\ Apostrof
\0 Null
\\ Backslash
\v tabulare vertical
\a Alert
\N constant n octal; N este constanta
\xN constant n hexazecimal; N este constanta
Tabelul 4 Coduri backslash n C
2.11 Operatori n C
C dispune de foarte muli operatori. De fapt, C acord acestora o importan mult
mai mare n comparaie cu alte limbaje. C definete, n esen, patru clase de
operatori: aritmetici, relaionali, logici i de aciune la nivel de bit. Pentru
anumite sarcini, C are operatori suplimentari.
Operatorul de atribuire
Operatorul de atribuire poate fi folosit, n C, n cadrul oricrei expresii valide,
lucru care nu este permis n majoritatea limbajelor de programare (inclusiv
Pascal), care trateaz operatorul de atribuire ca pe un caz de instruciune
special. Sintaxa de aplicare a operatorului de atribuire n C este:
<Nume_variabil> = <Expresie>;
19
Membrul stng al atribuirii trebuie s fie o variabil sau un pointer, nu o funcie
sau o constant.
int nri;
char car;
float nrr;
void functie(void)
{
car=nri; /* Linia 1 */
nri=nrr; /* Linia 2 */
nrr=car; /* Linia 3 */
nrr=nri; /* Linia 4 */
}
n Linia 1, n variabila car ajung primii 8 bii cei mai puin semnificativi ai
variabilei nri. Dac nri este cuprins ntre 0 i 255, car i nri vor avea valori
identice .a.m.d.. Presupunnd c sistemul de calcul are cuvntul de 16 bii,
Tabelul 5 prezint posibilele pierderi de informaie care pot s apar la
conversia de tip n atribuiri.
Atribuiri multiple
C permite atribuirea aceleeai valori mai multor variabile prin utilizarea atribuirii
multiple ntr-o singur instruciune de atribuire. De exemplu instruciunea:
x = y = z = 0;
20
permite setarea la 0 a variabilelor x,y,z. Programatorii profesioniti folosesc
masiv atribuirea multipl pentru a obine cod performant.
S mai adugm o observaie interesant pentru un programator profesionist. O
atribuire de tipul:
<Variabil>=<Variabil>+<Expresie> (1)
este echivalent semantic cu sintaxa:
<Variabil>+=<Expresie> (2)
Dei s-ar putea s vin peste mn unor programatori, acetia trebuie s tie
c pentru compilator sintaxa (2) este de preferat sintaxei (1) din punct de vedere
al calitii codului generat.
Aadar,
x=x+1
este totuna cu:
x+=1.
Operatori aritmetici
Tabelul 6 prezint operatorii aritmetici din C.
Operator Aciune
- Scdere, de asemenea i minus unar
+ Adunare
* nmulire
/ mprire
% Modul
-- Decrementare
++ Incrementare
Tabelul 6 Operatori aritmetici n C
21
Exist, totui, o diferen ntre forma cu prefix i forma cu sufix, dac operatorii
sunt utilizai ntr-o expresie. Atunci cnd operatorii preced variabila, C
efectueaz operaiile corespunztoare lor, nainte de a evalua expresia.
Atunci cnd operatorii succed variabila, C efectuiaz operaiile corespunztoare
lor, dup evaluarea expresiei. Majoritatea compilatoarelor C/C++ produc rapid
un cod obiect eficient pentru operaiile de incrementare i decrementare (cod
mai bun dect cel obinut prin utilizarea atribuirii clasice echivalente). Pe acest
considerent, recomandarea de a utiliza aceti operatori de cte ori este posibil
este fireasc. n sfrit, ordinea de preceden a operatorilor aritmetici este:
Operatori relaionali
Operator Aciune
> Mai mare dect
>= Mai mare sau egal
< Mai mic dect
<= Mai mic sau egal
== Egal
!= Diferit
Operatori logici
Operator Aciune
&& AND (I)
|| OR (SAU)
! NOT (NEGAT)
Tabelul 7 Operatorii relaionali i logici n C.
22
De ordinul cel mai nalt !
>, >=, <, <=
==, !=
&&
De ordinul cel mai cobort ||
Tabelul 8 Relaia de preceden ntre operatorii relaionali i logici
Evident, parantezele pot fi utilizate pentru a modifica ordinea fireasc de
evaluare a unei expresii relaionale i/sau logice.
Operator Aciune
& AND
| OR
^ OR exclusiv (XOR)
~ Complement fa de 1 (NOT)
>> Deplasare la dreapta
<< Deplasare la stnga
Tabelul 9 Operatorii de aciune pentru bii
<Operand_1> <Operator><Operand_2>
Operatorii de deplasare a biilor >> i << deplaseaz toi biii dintr-o variabil la
dreapta sau la stnga. Sintaxa asociat este:
23
Sensul operaiei de shiftare este cel precizat la un curs de Bazele logice ale
sistemelor de calcul.
Precizri referitoare la operatorii suplimentari pot fi gsite n [1].
Operatorul ?
C propune un operator unar foarte puternic i util care poate nlocui anumite
instruciuni de forma dac atunci altfel.
z Se evaluiaz <Expresie_1>;
z Dac <Expresie_1> este adevrat se evaluiaz <Expresie_2> i
rezultatul evalurii ei i se atribuie expresiei globale;
z Dac <Expresie_1> este fals. atunci se evaluiaz <Expresie_3> i
rezultatul evaluirii acesteia este atribuit expresiei globale.
Aceast semantic este evideniat i de exemplul de mai jos de utilizare
a operatorului ?.
X=24;
X=X<24 ? 1:X+1;
X=24;
if (X<24) X=1
else X=X+1;
Operatorii & i *
Un pointer este adresa din memorie a unei variabile. O variabil de tip pointer
este declarat explicit pentru a reine un pointer ctre un obiect de un tip
specificat. Cunoaterea adresei unei variabile poate fi de mare utilitate n
anumite situaii. n C pointerii au trei funcii principale.
24
O atribuire de tipul :
adr=&Numar_Elemente;
este util pentru a obine n variabila adr adresa din memorie a variabilei
Numar_Elemente. Aceast adres este adresa locaiei din memorie ncepnd de
la care se pstreaz coninutul variabilei Numar_Elemente.
Al doilea operator pentru pointeri este * , oarecum complementar operatorului
&. i operatorul * este unar, returnnd valoarea din variabila localizat la
adresa specificat. Astfel , dup execuia secvenei:
adr=&Numar_Elemente;
nr=*adr ;
Exemplu
#include <stdio.h>
void main(void)
{
int destinatar,sursa;
int *m;
sursa=10;
m=&sursa;
destinatar=*m;
printf (%d, destinatar);
}
25
sizeof este un operator unar utilizat n timpul compilrii care returneaz lungimea
n octei a variabilei sau a specificatorului de tip dintre parantezele asociate de
sintax operatorului. Sintaxa de utilizare a operatorului:
sizeof ( <Nume_Variabila>)
sau
sizeof <Nume_Variabila>
struct tangajat
{
char nume[80];
int varsta;
float salariu;
} angajat;
struct tangajat *pangajat=&angajat;
angajat . salariu:=1100000;
pangajat->salariu=1100000;
26
Un comentariu este o not explicativ pentru programatori, ignorat complet de
compilator n C comentariile sunt delimitate de perechile de caractere /* */.
Compilatorul C ignor orice text aflat ntre aceti delimitatori.
Exemple de comentarii:
sau
Compilatoarele C++ accept i comentarii care ncep cu secvena //, dar se pot
ntinde pe o singur linie, astfel:
27
3 Reprezentarea structurilor de prelucrare n C/C++
Limbajul C nu propune o revoluie de fond n ceea ce privete problema
reprezentrii structurilor de prelucrare. Vine, ns, cu o serie de inovaii
interesante, n ceea ce privete flexibilitatea i varietatea propunerilor de
reprezentare. Nu spunem nici o noutate amintind c reprezentarea structurilor
de prelucrare se bazeaz pe combinarea, dac se poate, profesional, a
instruciunilor executabile ale limbajului. Potrivit standardelor ANSI C i ANSI
C++ instruciunile sunt mprite n urmtoarele grupe:
Instruciuni de selecie
Instruciuni iterative
Instruciuni de salt
Instruciuni de etichetare
Instruciuni bloc
Instruciunile de selecie cuprind enunurile if i switch.
n categoria instruciunilor iterative intr enunurile while, for i do-while.
Instruciunile de salt desemneaz n C instruciunile break, continue, goto i
return.
Instruciunile de etichetare includ enunurile case i default (implicate, esenial,
n sintaxa i semantica instruciunii switch i etichetele (discutate relativ la
instruciunea goto. Problematica instruciunilor expresie am discutat-o, pe larg,
n seciunea precedent. De asemenea, blocul de cod este, deja, o noiune cu
care ne-am familiarizat. De altfel, aa cum n Pascal, secvena de cod cuprins
ntre begin i end era numit i instruciune compus, standardul ANSI C++
propune, aceeai denumire, ca denumire alternativ pentru blocul de cod.
28
3.2 Instruciuni de selecie n C
C admite dou tipuri de instruciuni de selecie: if i switch.
if
Sintaxa general a instruciunii if este urmtoarea:
if (<Expresie>) {}
else {};
29
Instruciunea if poate fi imbricat. n caz de imbricare, clauza else se refer
ntotdeauna la cea mai apropiat instruciune if situat n amonte, n acelai bloc
cu else i neasociat nc cu un else, ca n exemplul:
#include <stdio.h>
#include <conio.h>
#include <string.h>;
void main()
{
float A,B,X;
clrscr();
gotoxy(20,12);
printf("____________________________________");
gotoxy(20,13);
printf(" Rezolvarea unei ecuatii de gradul I");
gotoxy(20,14);
printf(" A=");
gotoxy(20,15);
printf(" B=");
gotoxy(20,17);
printf("____________________________________");
gotoxy(20+strlen(" A="),14);
scanf("%f",&A);
gotoxy(20+strlen(" B="),15);
scanf("%f",&B);
gotoxy(20,17);
printf("_____________________________________");
if (A==0)
if (B==0)
{
gotoxy(20,16);
printf("Ecuatie nedetrminata!!!");
getch();
}
else
{
gotoxy(20,16);
printf("Ecuatie imposibila!!!"); getch();
}
else
{
X=B/A;
gotoxy(20,16);
printf("Solutia ecuatiei este:%f",X); getch();
}
}
30
Destul de frecvent instruciunea if este utilizat i n construcia numit
scara if-else-if avnd sintaxa general:
if (<Expresie_1>)
<Instruciune_1>;
else if (<Expresie_2>)
<Instruciune_2>;
else if (<Expresie_3>)
<Instruciune_3>;
:
:
else if (<Expresie_k>)
<Instruciune_k>;
:
Reamintim c, n anumite situaii, putem utiliza operatorul ? pentru a nlocui
instruciunea if-else de forma:
if (<Expresie>)
<Expresie_1>;
else
<Expresie_2>;
cu o construcie de forma:
<Expresie>?<Expresi_1>:<Expresie_2>;
switch
C permite reprezentarea structurilor alternative cu mai multe ramuri utiliznd n
acest scop instruciune switch avnd sintaxa:
switch (<Expresie>) {
case <Constanta_1>:
<Secvena_de_instruciuni_1>
break;
case <Constanta_2>:
<Secvena_de_instruciuni_2>
break;
:
case <Constanta_k>:
<Secvena_de_instruciuni_k>
break;
default
<secvena_de_instruciuni>
}
31
Semantica instruciunii este urmtoarea: se compar valoarea expresiei
<Expresie> cu valorile constantelor specificate n instruciunile case. Cnd se
ntlnete o coinciden, se execut secvena de instruciuni asociat acelui
case pn la instruciunea break sau pn cnd se ajunge la finalul instruciunii
switch. Instruciunea default se execut dac nu este ntlnit nici o
coinciden. Clauza default este opional i dac nu este prezent, atunci cnd
nu avem nici o coinciden nu se execut nici o aciune.
Standardul ANSI C stipuleaz c switch poate s aib cel mult 257 de clauze
case. Standardul propus de ANSI C++ recomand s se poat introduce cel mult
16.384 clauze case. n practic, din motive de eficien, se urmrete limitarea
numrului de clauze case ntr-o instruciune switch.
Instruciunea case nu poate fi utilizat dect n contextul instruciunii switch.
Instruciunea break este o instruciune de salt n C, fiind utilizat pentru a
determina ieirea forat din anumite tipuri de structuri (switch, for, do-while).
Ilustrm modul de utilizare a instruciunii switch prin exemplul de mai jos.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
void main()
{
int x;
char Ras;
clrscr();
x=random(2);
switch(x+2){
case 3:
{
gotoxy(20,10);
printf("Switch atins...");
break;
}
default:
{
gotoxy(20,10);
printf("Switch ocolit...");
}
}
Ras=getch();
}
32
-Dac n instruciunea switch sunt utilizate constante de tip caracter, ele
sunt automat convertite n ntregi.
O astfel de sintax permite multe variante constructive ale buclei for. n general
vorbind, ns:
-<Iniializare> este o instruciune de atribuire utilizat pentru a iniializa
variabila de control a buclei;
-<Condiie> este o expresie relaional care determin condiia de ieire
din bucl;
-<Increment> definete modul n care se modific variabila de control a
buclei de fiecare dat cnd aceasta se repet.
De remarcat faptul c cele trei seciuni trebuie separate prin punct i virgul.
Aadar, bucla for se execut ct timp <Condiie> este adevrat. Dac
<Condiie> devine fals, atunci execuia programului continu cu instruciunea
care urmeaz construciei for, dac aceasta exist.
Maniera clasic de utilizare a buclei for n C, o prezentm n exemplul de mai
jos.
#include <stdio.h>
#include <iostream.h>
#include <conio.h>
long int fact( int n);
void main()
{
clrscr();
gotoxy(20,12);
int nr;
cout<<"Introduceti numarul:";
cin>>nr;
33
gotoxy(20,14);
cout<<"Factorial("<<nr<<")="<<fact(nr);
getch();
}
long int fact(int n)
{
long int f;
int i;
f=1;
/*-------------------------------------------------------------------
/* Bucla for clasic cu o singur variabil de control
/*-------------------------------------------------------------------
for (i=2;i<=n;i++)
f=f*i;
return f;
}
Exemplul de cod C prezentat mai sus permite calculul factorialului pentru un
numr natural dat. Exemplul arat, anticipnd, modul de utilizare a conceptului
de funcie n C++.
#include <conio.h>
#include <stdio.h>
#include <string.h>
#include <dos.h>;
34
void converg(int linie, char *mesaj);
//Functia principala
void main()
{
clrscr();
gotoxy(20,12);
converg(12,"Acesta este un test pentru functia converg().");
}
for (i=ls,j=cs;i<=j;i++,j--)
{
gotoxy(i,linie);printf("%c",mesaj[i-ls]);
delay(50); //prototipul in fisierul antet <dos.h>
gotoxy(j,linie);printf("%c",mesaj[strlen(mesaj)-1-cs+j]);
}
getch();
}
for ( ; ; )
35
#include <stdio.h>
#include <conio.h>
#include <ctype.h> //Contine prototipul functiei toupper
void main()
{
int sw;
char ras;
sw=1;
/* Bucla while n aciune
while(sw)
{
gotoxy(20,12);
printf("Continuam(D,N):");
ras=getch();
if (toupper(ras)=='N')
sw=0;
}
}
do {
<Instruciune>;
} while <Condiie>;
Bucla do-while se repet pn cnd <Condiie> devine fals. Dm, mai jos, un
exemplu practic de utilizare a buclei do-while (afiarea/ selectarea opiunilor unui
program C).
:
char prelopt()
{
int c;
clrscr();
gotoxy(20,9);
printf( "Optiunile programului...");
gotoxy(20,11);
printf("1-Preluare elemente vector");
gotoxy(20,12);
printf("2-Determinare suma");
gotoxy(20,13);
printf("3-Terminare program");
36
gotoxy(20,15);
printf("Optiunea Dvs.:");
/* Utilizare bucl do-while
do
c=getch();
while ((c!='1')&&(c!='2')&&(c!='3'));
return c;
};
:
Alte instruciuni C
Aa cum rezult i din exemplele prezentate, n C mai sunt intens folosite
urmtoarele instruciuni: return, exit, break , continue i goto.
return [<Expresie>]
Funcia exit()
exit (<Cod_de_retur>);
Instruciunea break
Are dou utilizri. Poate fi folosit, dup cum am vzut deja pentru a ncheia un
case dintr-o instruciune switch, sau pentru a determina ncheierea imediat a
unei bucle.
Instruciunea continue
Foreaz trecerea la urmtoarea iteraie a unei bucle, determinnd ignorarea
restului codului iteraiei n care se afl.
Nu facem meniuni speciale referitor la instruciunea goto.
37
38
4 Operaii I/O relativ la perifericele standard
Ne propunem n acest modul s prezentm funciile C care fac parte din
sistemul I/O referitor la efectuarea operaiilor de introducere a datelor de la
tastatur i afiare a acestora pe ecranul monitorului.
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
void main()
{
char car;
do
{
car=getche();
car=toupper(car);
putchar(car);
39
}
while (car!='\033');
}
Prototipul funciei toupper() se afl (aa cum am mai spus-o) n fiierul antet
ctype.h. Se observ c citirea se face cu ecou pe ecranul monitorului. Este cazul
s spunem c programatorul n C/C++ are de fcut o serie de descoperiri
folositoare n ceea ce privete oferta numeroaselor fiiere antet livrate odat cu
compilatorul. Prezentarea tuturor acestor funcii, fie i numai prina antet, nu este
de loc o treab uoar, din punct de vedere al volumului. De aceea. n acest
suport de curs adresm cititorului invitaia de a descoperi, cu ajutorul help-ului on
line i a unor cri care nu fac economie de spaiu, potenialul structurat n
fiierele antet.
#include <stdio.h>
#include <conio.h>
void main()
{
char s[30];
clrscr();
gotoxy(20,10);
printf("Introduceti un sir de caractere:");
gets(s);
gotoxy(20,11);
printf("Sirul introdus :");
puts(s);
getch();
clrscr();
}
40
#include <stdio.h>
#include <conio.h>
void main()
{
char s;
char *p;
clrscr();
gotoxy(20,10);
p=&s
printf("Introduceti un sir de caractere:");
gets(p);
gotoxy(20,11);
printf("Sirul introdus :");
puts(p);
getch();
clrscr();
}
int scanf( const char *format [, address, ...]); {Fiierul antet gazd :stdio.h}
int printf(const char *format [, argument, ..]); {Fiierul antet gazd :stdio.h}
printf()
Returneaz, cu destinaia ecran, numrul de caractere scrise sau, dac apare o
eroare, o valoare negativ. Parametrul format se compune din dou tipuri de
simboluri. Primul tip l formeaz caracterele care vor fi afiate pe ecran. Al doilea
tip se refer la specificatorii de format cu ajutorul crora se stabilete modul n
care sunt afiate argumentele care urmeaz. Un specificator de format ncepe cu
un semn % i este urmat de un cod de format. Trebuie s existe acelai numr
de argumente ca i acela al specificatorilor de format i, totodat, specificatorii
de format i argumentele se asociaz n ordinea de la stnga la dreapta.
41
Codurile de format disponibile pentru printf() sunt:
Cod Format
%c Caracter
%d Numere ntregi n baza 10, cu semn
%I Numere ntregi n baza 10, cu semn
%e Notaie tiinific (cu litera e)
%E Notaie tiinific (cu litera E)
%f Numr zecimal n virgul mobil
%g Folosete %e sau %f , anume, care din ele este mai mic
%G Folosete %E sau %f , anume, care din ele este mai mic
%o Numr n octal, fr semn
%s ir de caractere
%u Numere ntregi zecimale fr semn
%x Numere hexazecimale fr semn (cu litere mici)
%X Numere hexazecimale, fr semn, cu litere mari
%p Afieaz un pointer
%n Argumentul asociat este un pointer de tip ntreg n care a fost
plasat numrul de caractere scrise pn atunci.
%% Afieaz un semn %
#include <stdio.h>
#include <conio.h>
void main()
{
int numara;
printf("Acesta%n este un test...\n",&numara);
printf("%d",numara);
getch();
}
#include <stdio.h>
#include <conio.h>
void main()
{
int numara;
42
clrscr();
printf("Acesta%n este un test...\n",&numara);
printf("Aliniere la dreapta.......\n");
printf("%10d\n",numara);
printf("Aliniere la stanga .......\n");
printf("%-d\n",numara);
printf("Completare cu zerouri.....\n");
printf("%010d\n",numara);
getch();
}
scanf()
Este o rutin de uz general pentru intrri de la consol. Ea poate s citeasc
toate tipurile de date ncorporate i s fac automat conversia numerelor n
format intern corect. Se aseamn mult cu complementara ei printf(). Ca funcie,
scanf() returneaz numrul de elemente crora li s-a atribuit cu succes o
valoare. Dac apare o eroare scanf() returneaz EOF. Argumentul format
determin modul n care vor fi citite valorile n variabilele din lista de argumente.
Codurile de format disponibile pentru scanf() sunt prezentate n tabelul de mai
jos.
Cod Format
%c Citete un singur caracter
%d Citete un numr ntreg n baza 10
%I Citete un numr ntreg n baza 10
%e Citete un numr n virgul mobil
%E Citete un numr n virgul mobil
%f Citete un numr n virgul mobil
%g Citete un numr n virgul mobil
%o Citete un numr n octal
%s Citete un ir de caractere
%u Numere ntregi zecimale fr semn
%x Citete un numr n hexazecimal
%p Citete un pointer
%n Argumentul asociat este un pointer de tip ntreg n care a fost
plasat numrul de caractere citite pn atunci.
%u Citete un ntreg fr semn
%[] Caut un set de caractere
Tabelul 10. O parte din codurile pentru formatarea operaiilor I/I relativ la
periferice standard
Primul exemplu de cod prezentat mai jos ilustreaz ideea de scanset posibil la
utilizarea funciei scanf(). Definirea unui scanset nseamn, de fapt c citirea
corespunztoare unei variabile este validat ct timp caracterele citite se
potrivesc celor definite n scanset.
43
Al doilea exemplu este conceput n ideea c valoarea variabilei n2 va fi citit
numai dup introducerea de la tastatur a dou caractere virgul. Acest
mecanism permite, printre altele, definirea ca separator la introducerea datelor a
altui caracter dect <CR>.
#include <stdio.h>
#include <conio.h>
void main()
{
char sir[3];
clrscr();
#include <stdio.h>
#include <conio.h>
void main()
{
int n1,n2;
clrscr();
scanf("%d,,%d",&n1,&n2);
printf("%d\n",n1);
printf("%d\n",n2);
getch();
}
44
Constanta Valoare Mod Text Caracterisrici
LASTMODE -1 Precedentul mod text
BW40 0 Black and white 40 coloane
C40 1 Color 40 coloane
BW80 2 Black and white 80 coloane
C80 3 Color 80 coloane
MONO 7 Monochrome 80 coloane
C4350 64 EGA and VGA 50 linii
Tabelul 11. Moduri video text standard
Aceste moduri text pot fi selectate cu ajutorul funciei textmode(), al crei antet
se afl tot n conio.h i face parte tot din arsenalul C de lucru cu ecranul n mod
text. Tot n mod text, putem controla culorile textului i ale fondului (background-
ul). Sintaxa funciilor cu care realizm controlul culorilor este:
textcolor(<Culoare>);
textbackground(<Culoare>);
Parametrul <Culoare> poate lua una din valorile prezentate n tabelul de mai jos:
45
clreol() se utilizeaz pentru tergerea liniei curente ncepnd cu coloana
pe care se afl cursorul i pn la sfritul liniei.
gotoxy(col,lin) permite poziionarea cursorului pe linia i coloana
specificate.
De asemenea, pot fi de interes, n anumite situaii, urmtoarele funcii:
window(css,lss,cdj,ldj);
Definete coordonatele ferestrei text active.
wherex();
Returneaz coloana curent a cursorului.
wherey();
Returneaz linia curent a cursorului.
gettext() i puttext()
Permit citirea/scrierea memoriei video n mod text, ca n exemplul de mai
jos.
#include <conio.h>
//tergere ecran
clrscr();
gotoxy(1, 25);
cprintf(" Apasati o tasta pentru a restaura ecranul...");
getch();
46
//Refacere coninut memorie video, utiliznd datele salvate n variabila buffer
puttext(1, 1, 80, 24, buffer);
gotoxy(1, 25);
cprintf("Apasati o tasta pentru a termina...");
getch();
return 0;
}
#Include facilcrt.h
#include <conio.h>
#include <stdio.h>
#include <string.h>
//Activare video-invers
void avideo()
{
textcolor(BLACK);
textbackground(WHITE);
}
//dezactivare video-invers
void dvideo()
{
textcolor(WHITE);
textbackground(BLACK);
}
47
gotoxy(col,linia);
cprintf(sir);
}
}
48
5 Matrice i iruri
O matrice este o colecie de variabile de acelai tip, apelate cu acelai nume.
Accesul la un anumit element al matricei se face cu ajutorul unui indice. n C
toate matricile constau n locaii de memorie contigue. Cel mai mic indice
corespunde primului element iar cel mai mare ultimului element. Matricele pot
avea una sau mai multe dimensiuni. Ca i n alte limbaje, cea mai simpl matrice
este irul. n C irul este o matrice de caractere terminate cu un caracter NULL.
Aceast caracteristic ofer limbajului C mai mult putere i eficien dect
posed alte limbaje.
Semnalm, de asemenea, faptul c n C, exist o strns legtur ntre matrice
i pointeri.
<Tip> <Nume_variabil>[<Dimensiune>];
<Tip> declar tipul de baz al matricei, care este tipul fiecrui element al
su.
<Dimensiune> indic numrul maximal de elemente pe care le poate
conine matricea.
Total_octei = sizeof(<Tip>)*<Dimensiune>
float sir[10];
49
float *p;
float sir[10];
p=sir;
<Tip> <Nume_variabil>[<Dimensiune_1>][<Dimensiune_2>];
int matr[10][20];
50
Adresarea elementelor matricei se bazeaz pe premiza c, dup fiecare
dimensiune, indexarea ncepe de la 0. De asemenea, facem precizarea c,
atunci cnd o matrice bidimensional este utilizat ca un argument pentru o
funcie, se transmite doar un pointer ctre primul element al matricei. ns,
parametrul care primete o matrice bidimensional trebuie s defineasc cel
puin numrul de coloane, necesare compilatorului pentru a indexa corect
matricea. De urmrit exemplul de mai jos de cod C care permite calculul sumei
elementelor strict pozitive de pe diagonala principala a unei matrice patratice .
#include<stdio.h>
#include<conio.h>
51
//Apelare functie cu parametru matrice transmisa ca pointer static
sespdp(matr);
}
<Tip> <Nume_variabil>[<Dim_1>][<Dim_2>][Dim_n];
#include<stdio.h>
#include<conio.h>
#include "facilcrt.h"
#include<stdlib.h>
//Directiva #define permite specificarea unor macrouri
#define lmaxs 100
#define optiuni "1234"
//Solutie modularizata C pentru problema determinrii
//ortogonalitatii a doi vectori reali
char prelopt();
void prelvec();
int ortogon();
float sir1[lmaxs],sir2[lmaxs];
int dims;
void main()
{
for(; ;)
{
switch (prelopt())
{
case '1':
{ prelvec();
break;
}
case '2':
{ ortogon();
break;
};
case '3': exit(0);
}
52
}
}
char prelopt()
{
char opt;
clrscr();
gotoxy(20,9);
cprintf("Optiunile programului....");
gotoxy(20,10);
cprintf("1- Preluare vectori");
gotoxy(20,11);
cprintf("2- Determinare ortogonalitate....");
gotoxy(20,12);
cprintf("3- Terminare program");
makewin2(20,9,55,12);
gotoxy(20,15);
cprintf("Optiunea Dvs.:");
makewin2(20,15,55,15);
do
{
gotoxy(20+strlen("Optiunea Dvs.:"),15);
opt=getch();
}
while (strchr(optiuni,opt)==NULL);
return opt;
}
void prelvec()
{
int i,col;
clrscr();
gotoxy(20,9);
cprintf("Dimensiune vectori:");
makewin2(20,9,20+strlen("Dimensiune vectori:"),9);
gotoxy(22+strlen("Dimensiune vectori:"),9);
col=strlen("Dimensiune vectori:");
makewin2(22+col,9,30+col,9);
gotoxy(23+col,9);
cscanf("%d",&dims);
clrscr();
gotoxy(20,9);
cprintf("Preluarea componentelor primului vector...");
makewin2(20,9,20+strlen("Preluarea componentelor primului vector..."),12);
for (i=0;i<dims;i++)
{
53
gotoxy(20,10);
cprintf("Elementul [ %d ]=",i);
cscanf("%f",&sir1[i]);
}
clrscr();
gotoxy(20,9);
cprintf("Preluarea componentelor celui de-al doilea vector...");
makewin2(20,9,20+strlen("Preluarea componentelor celui de-al doilea
vector..."),12);
for (i=0;i<dims;i++)
{
gotoxy(20,10);
cprintf("Elementul [ %d ]=",i);
cscanf("%f",&sir2[i]);
}
}
int ortogon()
{
float suma;
int i;
suma=0;
for (i=0;i<dims;i++)
suma=suma+sir1[i]*sir2[i];
clrscr();
if (suma)
{
gotoxy(20,10);
textcolor(RED+BLINK);
cprintf("Vectorii nu sunt ortogonali!!");
makewin2(20,10,21+strlen("Vectorii nu sunt ortogonali!!"),10);
getch();
textcolor(WHITE);
}
else
{
gotoxy(20,10);
textcolor(GREEN+BLINK);
cprintf("Vectorii sunt ortogonali!!");
makewin2(20,10,21+strlen("Vectorii sunt ortogonali!!"),10);
getch();
textcolor(WHITE);
};
}
54
Se cuvine s mai fac o parantez referitoare la insistena cu care apar n
programele C/C++ construcii sintactice care ncep cu #, precum #include,
#define. Aceste construcii fac parte din categoria instruciunilor care se
adreseaz compilatorului i se mai numesc i directive pentru preprocesor. dei
nu fac parte din limbajul C/C++ aceste directive lrgesc sfera de aciune a
programelor C/C++. Am vzut deja care este utilitatea directivei preprocesor
#include. S spunem, totodat, faptul c, directiva pentru preprocesor #define
permite definirea unor macrouri astfel:
55
6 Pointeri
Un pointer este o variabil care poate conine o adres de memorie. Aceast
adres este localizarea n memorie a unui alt obiect (de regul o alt variabil).
De exemplu, dac o variabil conine adresa alteia, despre prima se spune c
este un pointer la cea de-a doua. O variabil de tip pointer se declar n C astfel:
<Tip> * <Nume>;
unde <Tip> este tipul de baz al pointerului iar <Nume> este numele variabilei
pointer. Tipul de baz al pointerului definete tipul de variabil ctre care indic
pointerul. Practic, orice tip de pointer poate s indice orice n memorie.
Problema este, ns, c aritmetica pointerilor este integral raportat la tipul
de baz al pointerului.
Expresii cu pointeri
n general, expresiile care implic pointeri se conformeaz acelorai reguli ca i
celelalte expresii. Exist, totui, o serie de particulariti pe care le vom evidenia
n acest paragraf n ceea ce privete aritmetica pointerilor.
Astfel:
Atribuirile sunt permise ntre pointeri concordani ca tip.
Pointerilor li se poate aplica operatorul ++ (incrementare) ca mai jos
:
int *p;
int mat[10];
:
p=&mat[0];
:
p++; // Operatorul de incrementare aplicat pointerului p
p- -;
:
n urma aplicrii operatorului de incrementare pointerului p, care coninea adresa
primului element al tabloului unidimensional mat, offset-ul acestuia este
incrementat cu 2, adic att ct este lungimea n octei a tipului de baz al
pointerului p.
Pointerilor li se poate aplica operatorul - - (decrementare) .
n urma aplicrii operatorului de decrementare pointerului p, care coninea
adresa celui de-al doilea element al tabloului unidimensional mat, offset-ul
acestuia este decrementat cu 2, adic att ct este lungimea n octei a tipului de
baz al pointerului p.
56
De asemenea, putem aduna sau scdea ntregi la, sau din pointeri. De
exemplu:
:
p=p+10;
:
face ca p s indice al 10-lea element de acelai tip cu tipul de baz al lui p,
relativ la elementul curent. n exemplul de mai jos ilustrm utilitatea aritmeticii
pointerilor n contextul lucrului cu matrice.
#include<stdio.h>
#include<conio.h>
int matr[10][10]; //matrice de intregi bidimensionala
int *p; // pointer la intregi
int dimm;
void main()
{
int i,j,el;
clrscr();
gotoxy(20,10);cprintf("Dimensiune matrice :");
scanf("%d",&dimm);
clrscr();
for(i=0;i<dimm;i++)
for(j=0;j<dimm;j++)
{
gotoxy(20,12);
cprintf("Elementul[ %d , %d ]=",i,j);
scanf("%d",&el);
matr[i][j]=el;
};
p=&matr[0][0]; //p refera primul element al matricei
for (i=0;i<dimm;i++)
cprintf("\r\n Ref_poin=%d",*(p+i)); //modificare offset p in expresie
getch();
p=&matr[0][0];
for (i=0;i<dimm;i++)
{
cprintf("\r\n Ref_poin=%d",*(p));
p=p+1; //modificare offset p prin incrementare
}
getch();
p=&matr[0][0];
for (i=0;i<dimm;i++)
{
cprintf("\r\n Ref_poin=%d",*(p));
p++; //aplicare operator de incrementare
57
}
getch();
}
Memoria alocat de funciile de alocare dinamic din C este obinut din HEAP-
zona de memorie liber situat ntre zona permanent a memoriei programului i
stiv.
Nucleul sistemului de alocare din C const din funciile malloc() i free().
Aceste instrumente de alocare lucreaz n pereche, folosind zona de memorie
liber pentru a stabili i a pstra o list cu memoria disponibil.
Funcia malloc() aloc memorie, avnd urmtorul prototip:
58
modul de utilizare a funciei memcpy, n situaia n care se dorete copierea
coninutului memoriei de la o anumit adres la alt adres. De remarcat,
totodat, faptul c bibliotecile C au numeroase alte funcii pentru a satisface
cerinele de alocare/ manipulare dinamic a memoriei n programele utilizator.
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<string.h>
void main()
{
char c[20];
int *p;
//pointer generic
void *x;
int nr=10000;
p=&nr;
clrscr();
gotoxy(20,10);
59
7 Structuri
O structur este, pragmatic vorbind, un grup de variabile reunite sub acelai
nume, ceea ce permite un mod convenabil de manipulare a unor date care au
afiniti semantice ntre ele. O declarare de structur formeaz un ablon care
poate fi folosit pentru a crea structuri efective. n C, variabilele care fac parte din
structur se numesc membri ai structurii. Uzual, membrii structurii se mai
numesc i elemente sau cmpuri. Aa cum vom vedea mai jos, o structur
poate ncapsula i metode de prelucrare a datelor, dac programatorul dorete
s abstractizeze tipuri de date cu suport struct.
Sintaxa general pentru declararea unei structuri este:
struct <Nume_generic>
{
<Tip> <Nume_membru_1>;
<Tip> <Nume_membru_2>;
:
<Tip> <Nume_membru_n>;
:
<Tip returnat> <Nume functie>(<Lista de parametri>);
} <Variabila_1>,[<Variabila_k>];
n cazul n care n definiia structurii este ncapsulat i o metod atunci la
implementare se folosete sintaxa:
#include<stdio.h>
#include<conio.h>
typedef struct
{
char matricol[6];
char nume[30];
float media;
void setstud(char matr[],char num[],float med);
} TStud;
void TStud::setstud(char matr[],char num[],float med)
{
strcpy(matricol,matr);
strcpy(nume,num);
media=med;
60
};
void main()
{
clrscr();
TStud stud;
stud.setstud("12","Mihai Guramare",10);
printf("Matricol :%s\n",stud.matricol);
printf("Nume :%s\n",stud.nume);
printf("Media :%f",stud.media);
getch();
}
<Variabila_structurat> . <Nume_membru>
#include<conio.h>
#include<iostream.h>
#include<string.h>
void main()
{
typedef struct TPers{
char nume[30];
float salariu;
} TPers;
TPers pers;
strcpy(pers.nume,"Test typedef + struct.");
pers.salariu=1200000;
clrscr();
cout<<pers.nume<<"\r\n"<<pers.salariu;
getch();
}
#include<conio.h>
#include<iostream.h>
#include<string.h>
void main()
{
61
typedef struct TPers{
char nume[30];
float salariu;
} TPers;
TPers *pers;
typedef struct
{
tip1 nume1:lungime1;
tip2 nume2:lungime2;
...
tipn numen:lungimen;
} TOctet;
Tipurile pot lua una din valorile int, unsigned, signed, pentru majoritatea
compilatoarelor.
#include<stdio.h>
#include<conio.h>
#include<string.h>
typedef struct
{
unsigned bit :1;
unsigned :7;
unsigned :7;
unsigned bits:1;
} TOctet;
TOctet Octet;
62
int nr=1;
int *pointer;
void main()
{
int i;
pointer=&nr;
memcpy(&Octet,pointer,sizeof(int));
clrscr();
printf("Bitul 0 : %i\n",Octet.bit);
printf("Bitul de semn: %i\n",Octet.bits);
getch();
}
63
8 Uniuni
O uniune este o locaie de memorie care este partajat n momente diferite ntre
dou sau mai multe variabile diferite.
Sintaxa generala i modul de utilizare pot fi deduse din exemplul de mai jos.
#include<stdio.h>
#include<conio.h>
#include<string.h>
typedef union
{
int codsal;
float salar;
} TUSal;
void main()
{
clrscr();
TUSal vunion;
vunion.codsal=10;
printf("Cod confidential salariu:%i\n",vunion.codsal);
vunion.salar=1000.50;
printf("Salariu :%f",vunion.salar);
getch();
}
64
II Programarea C++
65
1 Introducere
Programarea orientat pe obiecte (POO) este expresia, n materie de codificare
a proiectelor, a paradigmei care presupune modelarea orientat pe obiecte a
sistemelor soft.
POO este o paradigm care ctig tot mai muli adereni datorit calitilor
pe care le au produsele i sistemele soft realizate n spiritul conceptelor i
principiilor promovate de aceasta. Rezultant a unor direcii diverse de
cercetare i experimentare (programare structurat, programare modular,
programare orientat pe structuri abstracte, reprezentarea cunotinelor n
sisteme expert, etc.) POO, aplicat corect poate rezolva, parial sau
integral, multe din problemele obsedante ale ingineriei softului, n genere:
reutilizarea codului, extinderea/modificarea cu minim de efort a sistemelor
soft, ascunderea detaliilor de implementare fa de anumite categorii de
utilizatori ai sistemelor soft. n acest mod platforma POO poate ajuta
programatorii i companiile de soft s realizeze produse i sisteme soft
performante, n timp util i la un pre sczut.
1. 1 Concepte POO
Orice demers de modelare orientat pe obiecte apeleaz la o serie de concepte
specifice paradigmei POO.
Astfel, pentru modelarea unui sistem soft se opereaz frecvent cu:
1. Concepte ale teoriei generale a sistemelor (sistem, subsistem,
descompunere, agregare, structur, etc.)
2. Concepte care provin din arsenalul conceptual al modelrii n genere
a sistemelor i produselor soft (modul, modularizare, interfa, tip de dat,
structur de date, ascunderea informaiei, etc.).
Tuturor acestora li se adaug principiile cu ajutorul crora aceste concepte devin
operaionale.
Paradigma POO a intrat n competiia pentru modernizarea i mbuntirea
real a procesului de realizare a unui sistem soft cu un set propriu de concepte i
principii.
Prezentm mai nti conceptele cheie ale paradigmei POO.
Este evident faptul c identificarea unei clase este n mod normal, rezultatul unui
demers cognitiv care presupune caracterizarea unui obiect prin nsuirile lui
(informaionale i comportamentale) care i definesc apartenena la o anumit
clas de obiecte. Aadar, conceptul de clas adun laolalt datele i metodele
de prelucrare a acestora.
66
Acesta este un exerciiu de ndemnare a crui rezolvare o poate nva oricine
care ncearc, are rbdare cu el nsui i citete cum procedeaz iniiaii cnd
ntlnesc astfel de exerciii. Aa cum va reiei din implementarea conceptului de
clas n C++, de exemplu, conceptul de clas este o abstracie care
pregtete un anumit tip de background pentru descrierea soluiei unei
probleme date. Fr a intra prea mult n problem s amintim, totui, c
modelnd obiect orientat soluiile problemelor noastre ne asigurm o serie
de avantaje imediate i de perspectiv n ceea ce privete gestiunea relaiei
dintre domeniul problemei i domeniul soluiei n ingineria sistemelor soft.
67
Este evident faptul c obiectul care emite mesajul trebuie s cunoasc protocolul
de comunicaie al obiectului receptor.
De asemenea, se subnelege faptul c mesajul trimis de obiectul emitor va
provoca o reacie(= un rspuns) din partea obiectului receptor.
1. 2 Principiile POO
Noutatea POO, ca paradigm este ilustrat i de principiile pe care le
promoveaz pentru a completa potenialul oferit de concepte. Promovarea
sistematic a principiilor pe care le prezentm n continuare promite, dar
nu garanteaz, realizarea unor produse, sisteme sau platforme soft
remarcabile din punct de vedere al performanelor i al efortului de
ntreinere.
68
Acest principiu este de mare utilitate n transmiterea sistematic a similaritilor
de la o clas la alta. Principiul poate fi aplicat cu succes doar n conjuncie cu
operatorii conceptuali complementari:generalizarea i specializarea.
Generalizarea apare n relaia dintre o clas i una sau mai multe versiuni mai
rafinate ale acesteia. Este, n limbajul de specialitate, relaia dintre clasa de
baz (sau superclas) i clasele derivate (sau subclase).
Atributele i operaiile comune sunt grupate n superclas i se spune c sunt
motenite de subclase.
Se poate spune c motenirea se refer la mecanismul de a transmite atribute i
operaii de-a lungul unei relaii de generalizare. Evident, simpla motenire a
proprietilor unei clase nu rezolv nici o problem din punct de vedere
conceptual. Utilitatea principiului motenirii este reliefat n condiiile aplicrii
operatorului de specializare, prin care subclasa rafineaz (specializeaz)
superclasa.
Implementarea motenirii nu creeaz probleme deosebite de nelegere i
utilizare.
69
2 Implementarea C++ a POO
2.1 Definirea claselor
Pentru a putea lucra cu obiecte n C++ trebuie, n prealabil, s definim forma lor
general folosind n acest scop cuvntul cheie class. O clas este similar,
sintactic vorbind, cu o structur. Forma general a unei declaraii de clas care
nu motenete nici o alt clas este urmtoarea:
Pentru datele i funciile care fac parte din definiia unei clase se
obinuiesc i denumirile de variabile membre, respectiv, funcii membre
sau, pur i simplu, membri.
70
#include <conio.h>
#include <string.h>
#include <iostream.h>
pers.setfields("Radu Vasile",1,10000);
pers.afis();
}
71
anumitor categorii de utilizatori accesul la membrii clasei, definind pentru
comunicaia cu alte clase i categorii de utilizatori ceea ce se numete interfaa
clasei.
Evident, se poate face o oarecare analogie ntre clas i structur; analogia
cade, ns, n momentul n care se pune problema manevrabilitii instanelor
celor dou tipuri de concepte sau atunci cnd este vorba de motenire i
polimorfism. Un exemplu ceva mai apropiat de realitatea preocuprilor unui
programator C++ poate fi programul care implementeaz o stiv de ntregi,
prezentat n continuare.
#include <iostream.h>
#include <conio.h>
#define SIZE 100
72
int stack::pop()
{
if(top==0)
{
gotoxy(20,24);
cout<<"Depasire inferioara stiva!!!";
getch();
return 0;
};
top--;
return st[top];
}
//Functia principala
void main()
{
int i;
stack st1,st2;
st1.init();
st2.init();
for (i=0;i<=9;i++)
{
st1.push(i);
st2.push(9-i);
}
clrscr();
for (i=0;i<=9;i++)
{
gotoxy(35,wherey()+1);
cout<<st1.pop()<<"*****";
cout<<st2.pop()<<endl;
}
getch();
}
73
Modificatorii de protecie utilizai n <Lista_claselor_de_baz> definesc protecia
n clasa derivat a elementelor motenite. Prezentm sub form tabelar accesul
la elementele motenite de clasa derivat n funcie de protecia fiecrui element
i de modificatorul de protecie asociat n <Lista_claselor_de_baz>.
Exemplu
#include <iostream.h>
class CB
{
protected:
int i,j;
//Pentru un program care utilizeaz aceast clas
//sau pentru alt clas care nu se afl n relaie
//de derivare cu CB I,j sunt private din punct de
//vedere al accesului. i,j sunt accesibile unei clase derivate.
public:
void setij(int a, int b) {i=a;j=b}
void dispij() { cout<<i<< <<j<<endl;}
}
class CD:public CB
{
int k;
public:
void setk(){k=I*j;}
void dispk(){cout<<k<<endl;}
74
}
void main()
{
CD ob;
ob.setij(2,3); //OK!
ob.dispij(); //OK
ob.setk();
ob.dispk ();
}
Exemplu
#include <iostream.h>
class CB
{
protected:
int i,j;
//Pentru un program care utilizeaz aceast clas
//sau pentru alt clas care nu se afl n relaie
//de derivare cu CB i, j sunt private din punct de
//vedere al accesului. i,j sunt accesibile unei clase derivate.
public:
void setij(int a, int b) {i=a;j=b}
void dispij() { cout<<i<< <<j<<endl;}
}
class CD:protected CB
{
int k;
public:
void setk(){setij(10,20);k=I*j;}
void disptot(){cout<<k<< ;dispij();}
}
void main()
{
CD ob;
ob.setij(2,3); //ilegal!
ob.setk(); //OK!, membru public n CD
75
ob.setk();
ob.disptot (); //OK!
ob.dispij(); //ilegal! Membru protected n CD
}
Constructori i destructori
Este un fapt obinuit necesitatea ca unele elemente ale unui obiect s fie
iniializate. Pentru a degreva programatorul de o asemenea sarcin de rutin,
compilatorul C++ genereaz cod care permite obiectelor s se iniializeze
singure. Aceast iniializare automat este efectuat prin intermediul unei funcii
membru speciale a clasei definitoare numit constructor.
76
Foarte important mi se pare s semnalez i existena unui constructor
special, numit constructor de copiere. Acesta are rolul de a atribui datele unui
obiect altuia. Mai mult, poate fi apelat chiar la definirea obiectelor. Dac
programatorul nu definete propriul constructor de copiere, compilatorul adaug
automat un astfel de constructor. n exemplul de mai jos se pot urmri elemente
de sintax i semantic care trebuie cunoscute cnd se lucreaz cu constructori
n diferite ipostaze.
#include<stdio.h>
#include<conio.h>
//Definire clas
class intreg
{
public:
int a;
//Constructor parametrizat
intreg(int v)
{
printf("Constructor parametrizat\n");
getch();
a=v;
}
//Constructor de copiere
intreg (intreg& v)
{
a=v.a;
printf("Constructor de copiere\n");
getch();
}
void dispa()
{
printf("a=%i\n",a);
getch();
};
};
void main()
{
clrscr();
//Declarare obiect static cu iniializare;
intreg x=100;
x.dispa();
//Declarare obiect static cu iniializare prin copiere
intreg y=x;
77
y.dispa();
}
Evident, o clas poate avea mai muli constructori, ceea ce este tot n beneficiul
programatorilor.
<Pointer>=new <Tip>;
delete <Pointer> ;
78
<Pointer>=new <Tip> (<Valoare_iniial>);
ca n exemplul:
int *p;
p=new int(10);
delete [ ] <Pointer>
<Pointer_la_obiect>=new <Clasa>;
<Pointer_la_obiect>=new <Clasa>(<Lista_valori>);
#include <iostream.h>
#include <conio.h>
#define SIZE 100
79
// Definirea clasei stack
class stack
{
int st[SIZE];
int top;
public:
stack(); //constructor
~stack(); //destructor
void push(int i);
int pop();
};
//Implementare constructor
stack::stack()
{
top=0;
gotoxy(20,24);
cout<<"Stiva este initializata";
getch();
clrscr();
}
stack::~stack()
{
gotoxy(20,24);
cout<<"Stiva este distrusa!!";
getch();
clrscr();
}
80
{
if(top==0)
{
gotoxy(20,24);
cout<<"Depasire inferioara stiva!!!";
getch();
return 0;
};
top--;
return st[top];
}
//Functia principala
void main()
{
int i;
stack st1,st2;
for (i=0;i<=9;i++)
{
st1.push(i);
st2.push(9-i);
}
clrscr();
for (i=0;i<=9;i++)
{
gotoxy(35,wherey()+1);
cout<<st1.pop()<<"*****";
cout<<st2.pop()<<endl;
}
getch();
}
Funcii virtuale
O funcie virtual este o funcie declarat virtual n clasa de baz i redefinit
ntr-un lan de derivare asociat respectivei clase de baz. O funcie virtual
definete o clas general de aciuni. O redefinire a ei introduce o metod
specific. n esen, o funcie virtual declarat n clasa de baz acioneaz ca
un substitut pentru pstrarea elementelor care specific o clas general de
aciuni, stabilind elementele de interfa. Redefinirea unei funcii virtuale ntr-o
81
clas derivat ofer operaiile efective pe care le execut funcia. Utilizate static,
funciile virtuale se comport ca oricare alt funcie membru a clasei .
Capabilitile funciilor virtuale ies n eviden atunci cnd sunt apelate n context
dinamic.
Exemplu
#include <iostream.h>
#include <conio.h>
//Clasa de baza care are doua functii membri publici
//o functie ordinara
//cealalta functie virtuala
class CB
{
public:
void f()
{
cout<<"CB::f()"<<endl;
getch();
}
virtual void g() //funcie virtual
{
cout<<"CB::g()"<<endl;
getch();
}
};
82
void ExecPolim(CB *p);
void main()
{
CB *pb=new CB;
CD *pd=new CD;
clrscr();
pb->f();
pb->g();
pd->f();
pd->g();
clrscr();
cout<<"Apel polimorfic in context CB"<<endl;
ExecPolim(pb);
cout<<"Apel polimorfic in context CD"<<endl;
ExecPolim(pd);
delete pb;
delete pd;
};
La prima vedere redefinirea unei funcii virtuale ntr-o clas derivat pare similar
cu suprancrcarea unei funcii. Nu este aa, deoarece exist mai multe
diferene:
@Prototipul pentru o funcie virtual redefinit trebuie s coincid cu
prototipul specificat n clasa de baz.
@Funciile virtuale nu pot s fie membri de tip static ai clasei din care fac
parte i nu pot fi nici friend
Funciile obinuite suport suprancrcarea; funciile virtuale suport
suprascrierea.
n cele ce urmeaz facem o serie de precizri relativ la clauza virtual.
83
Deoarece n C++ motenirea este ierarhizat este normal ca funciile virtuale s
fie, de asemenea, ierarhizate. Acestea nseamn c, atunci cnd o clas
derivat nu suprascrie o funcie virtual, este utilizat prima redefinire gsit n
ordinea invers derivrii.
O clas care conine cel puin o funcie virtual pur se numete clas
abstract. O clas abstract nu poate fi utilizat pentru crearea de obiecte dar
poate fi utilizat pentru a crea pointeri i referine spre astfel de clase permind
astfel manifestrile polimorfice n timpul execuiei.
#include <iostream.h>
#include <conio.h>
//functia abs este definita in trei moduri diferite
int abs(int i);
double abs(double d);
long abs(long l);
void main()
{
clrscr();
84
cout<<abs(-10);
cout<<abs(-10.0);
cout<<abs(-10L);
getch();
}
int abs(int i)
{
gotoxy(20,10);cout<<"Varianta int !!! :";
return i<0 ?-i:i;
}
double abs(double d)
{
gotoxy(20,12);cout<<"Varianta double!!! :";
return d<0 ?-d:d;
}
long abs(long l)
{
gotoxy(20,14);cout<<"Varianta long !!! :";
return l<0 ?-l:l;
}
85
Este posibil s se permit unei funcii care nu este membru al unei clase s aib
acces la membrii privai ai clasei declarnd-o ca funcie prieten a clasei (friend).
Aadar, o funcie prieten are acces la membrii private i protected ai clasei
creia i este prieten. Sintaxa pentru declararea unei funcii prietene este:
#include<conio.h>
#include <iostream.h>
#define liber 0
#define ocupat 1
class Clasa2
{
//<ocupat> daca o metoda a clasei a scris pe ecran
//<liber> in caz contrar
int stare;
public:
void setare_stare(int val);
friend int ecran_liber(Clasa1 a,Clasa2 b);
};
86
int ecran_liber(Clasa1 a, Clasa2 b)
{
if (a.stare ||b.stare)
return 0;
else
return 1;
}
void main()
{
Clasa1 x;
Clasa2 y;
x.setare_stare(ocupat);
y.setare_stare(liber);
if (ecran_liber(x,y))
{
clrscr();
gotoxy(20,12);
cout<<"Ecranul este liber...";
getch();
}
else
{
clrscr();
gotoxy(20,12);
cout<<"Ecranul este ocupat...";
getch();
};
x.setare_stare(liber);
y.setare_stare(liber);
if (ecran_liber(x,y))
{
clrscr();
gotoxy(20,12);
cout<<"Ecranul este liber...";
getch();
}
else
{
clrscr();
gotoxy(20,12);
cout<<"Ecranul este ocupat...";
getch();
};
}
87
2.7 Suprancrcarea operatorilor
Polimorfismul este realizat n C++ i prin suprancrcarea operatorilor. Dup
cum s-a vzut n numeroase exemple, n C++ se pot folosi operatorii >> i <<
pentru a efectua operaii I/O relativ la consol. Aceti operatori pot efectua
aceste operaii suplimentare (tiut fiind faptul c pot funciona i ca operatorii de
shiftare la nivel de bii) deoarece operaiile sunt suprancrcate n fiierul antet
IOSTREAM.H. Cnd un operator este suprancrcat, el capt o semnificaie
suplimentar relativ la o anumit clas fr s-i piard vreunul din nelesurile
iniiale. Majoritatea operatorilor din C++ pot fi suprancrcai, stabilind
semnificaia lor relativ la o anumit clas.
Limbajul C++ permite suprancrcarea numai a operatorilor existeni n limbaj.
Dintre acetia nu pot fi suprancrcai operatorii: . :: ? : .
S mai precizm faptul c, prin suprancrcarea operatorilor nu se poate
schimba n-aritatea, prioritatea sau asociativitatea operatorilor, acestea fiind
elemente predefinite pentru tipuri predefinite i deci ele se vor menine i pentru
tipuri abstracte.
Prin n-aritate nelegem c operatorul este unar sau binar.
Suprancrcarea operatorilor se realizeaz cu ajutorul unor funcii membre sau
prietene speciale. Specificul acestora se afl n numele lor. El se compune din
cuvntul cheie operator i unul sau mai multe caractere care definesc operatorul
care se suprancarc. ntre cuvntul cheie operator i caracterele care definesc
operatorul care se suprancarc se afl cel puin un spaiu alb. Felul n care sunt
scrise funciile operator difer pentru cele de tip membru de cele de tip friend.
//Operaii specifice
Funciile operator membre au un singur parametru sau nici unul. n cazul n care
au un parametru, acesta se refer la operandul din dreapta al operatorului.
Cellalt operand ajunge la operator prin intermediul pointerului special this.
88
Astfel stnd lucrurile, trebuie s avem grij de eventualitatea ca operandul din
stnga s fie o constant, ceea ce nseamn ca nu mai avem context de apel
pentru operatorul redefinit.
Inivitm cititorul s urmreasc exemplul de mai jos.
#include<conio.h>
#include<iostream.h>
//prototipul operatorului +
complex operator+(complex &op2);
};
void complex::disp_nc()
{
cout<<x<<"+i*"<<y;
};
//Implementare operator +
//Aceasta sintaxa transforma apelul <ob1+ob2>
//in +(ob2) ob1 fiind accesibil prin pointerul
//special <this>
complex complex::operator+(complex &op2)
{
complex temp;
temp.x=op2.x+x;
temp.y=op2.y+y;
return temp;
89
};
void main()
{
complex tamp1,tamp2;
complex *pod1,*pod2;
complex ob1(10,10),ob2(11,11);
clrscr();
gotoxy(20,10);cout<<"Primul numar complex ->:";
ob1.disp_nc();
getch();
gotoxy(20,11);cout<<"Al doilea numar complex->:";
ob2.disp_nc();
getch();
ob1=ob1+ob2;
gotoxy(20,13);cout<<"Suma numerelor complexe->:";
ob1.disp_nc();
getch();
pod1=new complex(200,200);
pod2=new complex(300,300);
tamp1=*pod1;
clrscr();
gotoxy(20,10);cout<<"Al treilea numar complex ->:";
tamp1.disp_nc();
tamp2=*pod2;
gotoxy(20,11);cout<<"Al patrulea numar complex ->:";
tamp2.disp_nc();
90
Invitm cititorul s urmreasc utilizarea funciilor friend la suprancrcare n
Exerciiul 6 de la Capitolul aplicativ al prezentului suport de curs.
#include
declaraii clase de baz
declaraii clase derivate
prototipuri de funcii nemembre
main()
{
:
}
definiii de funcii ne-membre
91
3 Bazele sistemului I/O n C++
Pe lng faptul c permite sistemul de I/O din C, C++ definete propriul su
sistem I/O orientat pe obiecte. Ca i sistemul de I/O din C, cel din C++ este
complet integrat. Aceasta nseamn c diferitele tipuri de operaii I/O sunt doar
perspective diferite ale aceluiai mecanism. Aceast perspectiv integratoare
asupra operaiilor I/O are la baz, att n C ct i n C++, conceptul de flux
(stream).
Fluxuri binare
Un flux binar este o secven de octei ntr-o coresponden biunivoc cu cei de
la echipamentul extern.
Fiiere
n C/C++ un fiier poate s fie: un fiier de pe disc, tastatura, ecranul monitorului,
imprimanta,etc. Un flux se asociaz cu un anumit fiier efectund o operaie de
deschidere. Odat deschis fiierul, este posibil schimbul de date ntre el i
programul utilizator care l-a deschis.
De observat faptul, trivial pentru cunosctori, c nu toate fiierele au aceleai
posibiliti. De exemplu, un fiier de pe disc poate s admit un acces aleator la
datele stocate n el, n timp ce imprimanta nu o poate face. Astfel c, putem
concluziona, pentru claritate:
92
Pentru sistemul I/O din C/C++ toate fluxurile sunt la fel dar nu i
fiierele.
Fluxurile cin, cout, cerr corespund fluxurilor stdin, stdout, stderr din C. Implicit,
fluxurile standard sunt folosite pentru a comunica cu consola. ns, n mediile
care admit redirecionarea I/O, fluxurile standard pot fi redirecionate spre alte
echipamente sau fiiere.
93
I/O formatate n C++
Sistemul de I/O din C++ v permite s formatai operaiile I/O, aa cum se
ntmpla i n cazul utilizrii funciilor C pentru operaii I/O, precum: printf,
cprintf, scanf,etc. De exemplu, se poate specifica mrimea unui cmp, baza
unui numr, numrul de cifre dup punctul zecimal,etc. Operatorii din C++
utilizai pentru introducerea informaiilor de formatare sunt >> i <<.
Exist dou ci nrudite, dar conceptual diferite, prin care se pot formata datele.
n primul rnd, putem avea acces direct la diferii membri ai clasei ios. n al
doilea rnd, putem folosi funcii speciale numite manipulatori, care pot fi incluse
n expresii de I/O.
Prezentm, n continuare modul de utilizare a manipulatorilor de formate, datorit
accesibilitii mai mari a acestora.
Manipulatorii standard sunt prezentai n tabelul de mai jos.
94
argumentul ntreg de tip
long
setprecision(int p) cout<<setprecision(6); Stabilete precizia
cin>>setprecision(10); conversiei n virgul
mobil la numrul
specificat de zecimale
setw(int w) cout<<setw(6)<<var; Stabilete mrimea unui
cin>>setw(24)>>buf cmp la numrul specificat
de caractere
ws cin ws; Elimin spaiile libere din
fluxul de intrare
Tabelul 16. Manipulatori de formatare a operaiilor I/O n C++
#include<iostream.h>
#include<iomanip.h>
#include<conio.h>
#include<stdio.h>
void main()
{
95
double nr;
clrscr();
gotoxy(10,6);
nr=7./3.;
gotoxy(5,6);
cout<<"Afisare numar in virgula mobila/ format implicit...";
gotoxy(10,7);
cout<<nr;
gotoxy(5,9);
cout<<"Afisare numar in virgula mobila/ cu precizia specificata...";
gotoxy(10,10);
cout<<setprecision(10)<<nr;
gotoxy(5,12);
cout<<"Afisare numar in virgula mobila/ format virgula fixa...";
gotoxy(10,13);
cout.setf(ios::fixed);
cout<<setprecision(10)<<nr;
gotoxy(5,15);
cout<<"Afisare numar in virgula mobila/ format virgula fixa...";
gotoxy(10,16);
cout.setf(ios::scientific);
cout<<setprecision(10)<<nr;
gotoxy(5,18);
cout<<"Afisare numar in virgula mobila/ format virgula fixa...";
gotoxy(10,19);
cout.setf(ios::scientific|ios::showpos);
cout<<setprecision(10)<<nr;
getch();
}
96
fluxuri: de intrare, de ieire i de intrare/ieire. Pentru a crea un flux de intrare,
trebuie s-l declarai ca fiind din clasa ifstream. Pentru a crea un flux de ieire,
trebuie s-l declarai ca fiind din clasa ofstream. Fluxurile care efectuiaz att
operaii de intrare ct i operaii de ieire, trebuie declarate ca fiind din clasa
fstream. Odat declarat fluxul, o modalitate de a-i asocia un fiier extern o
reprezint utilizarea funciei open() avnd prototipul:
Putei specifica mai mult de un mod de lucru pentru un fiier, folosind operatorul
pe bii SAU cu modurile respective. De exemplu, pentru deschiderea unui fiier
pentru ieire i poziionarea pointerului la sfritul lui se folosesc modurile
ios::out i ios::ate astfel:
97
Scrierea i citirea fiierelor text
Sunt dou operaii foarte uoare, realizate apelnd la operatorii >> i << ntr-un
mod asemntor operaiilor referitoare la consola sistemului, cu deosebirea c n
loc s folosii cin i cout apelai la un flux legat de un fiier . Codul de mai jos
arat cum poate fi afiat pe ecranul monitorului coninutul unui fiier text.
#include <fstream.h>
#include <stdlib.h>
#include<conio.h>
char c;
clrscr();
while (in.get(c))
{
if (wherey()>20)
{
gotoxy(20,24);
cout<<"Press any key to continue...";
getch();
clrscr();
}
cout<<c;
}
in.close();
}
98
Exist dou modaliti de a scrie i citi date binare ntr-un fiier. Prima
modalitate se refer la utilizarea funciilor get() i put(). Aceste funcii sunt
orientate pe octei, ceea ce nseamn c get() va citi un octet de date iar put() va
scrie un octet de date.
Funcia get() are mai multe forme; o prezentm, n continuare, mpreun cu
omoloaga ei put(), pe cea mai des folosit:
#include<stdlib.h>
#include <fstream.h>
void main(int argc, char *argv)
{
//Verific daca sunt suficiente argumente
if(argc<3)
{
cerr<<"Mod de utilizare : filecopy <fisier sursa> <fisier destinatie>\n";
exit(0);
}
//Deschide fisierul de intrare si il conecteaza la fluxul ins
ifstream ins(argv[1]);
if(!ins)
{
cerr<<"Nu pot deschide fisierul sursa:"<<argv[1];
exit(1);
}
//Deschide fisierul de iesire si il conecteaza la fluxul outs
ofstream outs(argv[2]);
if(!outs)
{
cerr<<"Nu pot deschide fisierul sursa:"<<argv[2];
exit(1);
}
//Citeste din sursa si scrie in destinatie
char c;
while(ins.get(c) && outs) outs.put(c);
99
}
A doua modalitate de a citi i scrie blocuri de date n binar este folosirea funciilor
din C++ read() i write(). Prototipurile lor sunt:
Funcia read() citete numar octei din fluxul asociat i l pune n buffer-ul indicat
de buf . Funcia write() scrie n fluxul asociat numar octei citii din buffer-ul spre
care indic buf.
Detectarea EOF
Putei s detectai sfritul fiierului folosind funcia membru eof() ,care are acest
prototip:
int eof();
#include <fstream.h>
#include <ctype.h>
#include <iomanip.h>
#include <stdlib.h>
#include<conio.h>
void main(int argc,char *argv[])
{
if (argc!=2)
{
cerr<<"Mod de utilizare : lishex <nume fisier CPP>\n";
exit(0);
}
ifstream in(argv[1],ios::in|ios::binary);
if (!in)
{
cerr<<"Fisierul nu poate fi deschis!";
exit(0);
}
register int i,j;
int count=0;
char c[16];
cout.setf(ios::uppercase);
clrscr();
100
while(!in.eof())
{
for(i=0;i<16 && !in.eof();i++)
{
in.get(c[i]);
}
if (i<16) i--;
for(j=0;j<i;j++)
cout<<setw(3)<<hex<<(int) c[j];
for(;j<16;j++)
cout<<"\t";
for(j=0;j<i;j++)
if(isprint(c[j])) cout<<c[j];
else cout<<".";
cout<<endl;
count++;
if(count==16)
{
count=0;
cout<<"Press ENTER to continue!";
getch();
clrscr();
cout<<endl;
}
}
in.close();
}
streamoff este un tip definit n IOSTREAM.H, capabil s conin cea mai mare
valoare valid pe care o poate avea offset, iar seek_dir este o enumerare care
are aceste valori:
ios::beg
ios::cur
ios::end
Sistemul de I/O din C++ opereaz cu doi pointeri asociai unui fiier. Unul este
pointerul de get , care specific unde va aprea urmtoarea operaie de intrare
n fiier. Cellalt este pointerul de put i specific unde va avea loc urmtoarea
101
operaie de ieire. Dup fiecare operaie de intrare sau ieire, pointerul
corespunztor este avansat automat, secvenial. Dar, folosirea funciilor seekg()
i seekp() permite un acces nesecvenial la datele din fiier.
seekg() i seekp() deplaseaz pointerul de nregistrare cu offset octei fa de
origine.
102
3 Programare generic n C++
n programarea profesional apar nenumrate situaii n care reutilizarea codului
presupune o soluie de un anumit tip pentru o problem dat. Situaia la care ne
referim n aceast seciune este, potenial vorbind, urmtoarea: Ce putem face
pentru a comprima codul surs n situaia n care structuri de date, diferite
ca tip, suport prelucrri similare.
Soluia acestei probleme de stil de programare o reprezint programarea
generic. Exprimndu-ne n termenii limbajului C, o funcie generic definete
un set general de operaii care vor fi aplicate unor tipuri de date diferite.
Ca un exemplu, o soluie generic pentru modelarea unei stive este un pretext
ideal pentru precizarea ideilor principale ale programrii generice.
Altfel spus, dac dorim o stiv, n care, de la caz la caz, s putem pstra numere
ntregi, numere reale sau iruri de caractere (deci tipuri de date diferite),
operaiile fiind aceleai ( push() i pop() ), este clar c ne aflm n situaia n
care avem nevoie de suport pentru scrierea de cod cu proprieti generice.
Dac n Pascal programarea generic se baza pe tipuri procedurale i
programarea la nivel de octet, n C++ exist suport evoluat pentru programare
generic, sub forma abloanelor. Cu un ablon, n C++ se poate crea o funcie
generic sau o clas generic.
Funcii TEMPLATE
O funcie template este o funcie ablon, avnd unul sau mai muli parametri
formali de un tip generic. n funcie de nevoile de utilizare a acestei funcii,
compilatorul genereaz funcii propriu-zise, nlocuind tipul generic cu un tip
concret. Tipul concret poate fi orice tip fundamental, derivat sau clas predefinit.
Considerm un exemplu. Fie funcia max(x,y) care returneaz valoarea maxim
a argumentelor sale. Tipul variabilelor x i y trebuie, obligatoriu, specificat n
momentul compilrii. Soluia clasic const n redefinirea (over-loading) funciei
max pentru fiecare tip al argumentelor x i y (de observat i cele spuse la
paragraful 2.2 relativ la funcii suprancrcate n C++).
Trebuie, aadar, s definim mai multe versiuni ale funciei max.
103
Mecanismul template permite definirea o singur dat a ablonului de funcii,
dup care se genereaz automat funciile propriu-zise n concordan cu
necesitile de utilizare, dar ,evident, n faza de compilare.
De precizat urmtoarele:
@Caracterele < i > fac parte din sintaxa obligatorie.
@Lista de parametri formali ai unei funcii ablon trebuie s utilizeze toate
tipurile de date generice.
@n cazul funciilor template nu se fac conversii
@Funcia care are acelai nume i acelai numr de parametri cu o funcie
ablon se numete caz exceptat (Suprancrcarea explicit este prioritar).
#include <conio.h>
#include<iostream.h>
104
clrscr();
i=10;
j=2;
k=13;
l=-7;
#include <conio.h>
#include <stdio.h>
#include <string.h>
#include <iostream.h>
#include <ctype.h>
void main()
{
105
clrscr();
int i=0;
//***************************************
//Citire persoane de la tastatura
do
{
gotoxy(20,12);
cout<<"Numele persoanei:";clreol();
cin>>pers[i].np;
gotoxy(20,13);
cout<<"Matricola:";clreol();
cin>>pers[i].key;
gotoxy(20,14);
cout<<"Mai aveti(D,N):";
i++;
}
//***************************************
//Listare persoane pe ecranul monitorului
//in ordinea citirii de la tastatura
while(toupper(getch())!='N');
clrscr();
cout<<"Listare persoane in ordinea citirii de la tastatura..."<<endl;
cout<<"_______________________________________________"<<endl;
for(int j=0;j<i;j++)
{
if (wherey()>10)
{
cout<<"______________________________________________"<<endl;
cout<<"Pentru continuare apasati o tasta..."<<endl;
getch();
clrscr();
cout<<"Listare persoane in ordinea citirii de la tastatura..."<<endl;
cout<<"_______________________________________________"<<endl;
};
cout.width(30);cout.setf(ios::left);
cout<<pers[j].np<<" "<<pers[j].key<<endl;
};
getch();
//*************************************
//Sortare persoane
int sortat;
do
{
sortat=1;
106
for(int j=0;j<i-1;j++)
{
switch(comp(pers[j],pers[j+1]))
{
case 1: {
tam=pers[j];
pers[j]=pers[j+1];
pers[j+1]=tam;
sortat=0;
};
};
};
}
while(!sortat);
//****************************************
//Listare persoane dupa sortare in ordinea
//crescatoare a matricolelor
clrscr();
cout<<"Listare persoane dupa sortare........................."<<endl;
cout<<"____________________________________________"<<endl;
for(int k=0;k<i;k++)
{
if (wherey()>10)
{
cout<<"_____________________________________________"<<endl;
cout<<"Pentru continuare apasati o tasta..."<<endl;
getch();
clrscr();
cout<<"Listare persoane dupa sortare........................."<<endl;
cout<<"______________________________________________"<<endl;
};
cout.width(30);cout.setf(ios::left);
cout<<pers[k].np<<" "<<pers[k].key<<endl;
};
getch();
}
Clase TEMPLATE
O clas template definete un ablon pe baza cruia se pot genera clase
propriu-zise. Din acest motiv, o clas template se mai numete i clas generic
, clas generator sau metaclas.
107
n cadrul clasei ablon se pot declara atribute informaionale de un tip ambiguu,
care sunt particularizate n cadrul clasei generat pe baza ablonului. Evident, i
n acest caz, generarea se face n faza de compilare n concordan cu cerinele
clientului.
Sintaxa la specificarea clasei:
#include <iostream.h>
#include <stdlib.h>
#include <conio.h>
//***************************************
//Definire clasa matrice generica
template <class ATip>
class genmat
{
ATip a[SIZE];
public:
genmat();
ATip &operator [ ](int i); //Suprancrcare operator [ ]
};
//***************************************
//Implementare constructor clasa generica
template <class ATip> genmat<ATip>::genmat()
{
register int i;
for(i=0;i<SIZE;i++)
a[i]=i;
};
108
//***************************************
//Implementare supraincarcare operator [ ]
template <class ATip> ATip &genmat<ATip>::operator[ ](int i)
{
if(i<0 ||i>SIZE-1)
{
cerr<<"Valoare indice eronata...";
getch();
exit(1);
};
return a[i];
};
//***************************************
//Functia principala
void main()
{
genmat<int> intob;
genmat<double> doubob;
int i;
clrscr();
cout<<"Matrice de intregi..."<<endl;
for(i=0;i<SIZE;i++)
intob[i]=i;
for(i=0;i<SIZE;i++)
cout<<intob[i]<<endl;
getch();
clrscr();
cout<<"Matrice de reali dubla precizie..."<<endl;
for(i=0;i<SIZE;i++)
doubob[i]=(double)i/3;
for(i=0;i<SIZE;i++)
cout<<doubob[i]<<endl;
getch();
clrscr();
intob[100]=100;
};
109
class Cstack
{
T * v; //pointer la varful stivei
T * p; //pointer la pozitia curenta din stiva
int dim; //dimensiunea stivei
public:
Cstack(int sz)
{
v=p=new T [dim=sz]; //alocare dinamica de memorie pentru p i v
}
~Cstack()
{
delete [ ] v;
}
void push(T a)
{
*p++=a;
};
T pop()
{
return *-p
}
}
CStack<char> sc(100);
#include <iostream.h>
#include <conio.h>
110
T *top;
int dims;
public:
CStack( int sz) //constructor
{
v=top=new T[dims=sz];
}
~CStack() //destructor
{
delete [ ] v;
}
T pop()
{
return *--top; //Notatie prescurtata echibvalenta cu - -top; return *top
}
};
//Functia principala
void main()
{
int i;
//Primul exemplu de instantiere a stivei generice ;numere ntregi
CStack<int> st1(20);
//ncarcare stiva
for (i=0;i<=9;i++)
{
st1.push(i);
}
111
//Al doilea exemplu de instantiere a stivei generice; caractere, ncepand cu A
CStack<char> st2(20);
//ncarcare stiva
for (i=65;i<75;i++)
{
st2.push((char) i);
}
112
4 Tratarea excepiilor
Programatorii adevrai trebuie s ia n calcul i posibilitatea de a crea programe
robuste, care fac fa att cerinelor specificate dar nerafinate suficient, ct i
cerinelor nespecificate dar formulate de utilizator, din diverse motive.
Programele care au aceste caliti se numesc robuste.
n programarea clasic soluia acestei probleme se putea numi, destul de exact
spus, programare defensiv. Seamn puin cu conducerea preventiv din
oferie dac ne gndim c programnd defensiv, n fond punem rul nainte,
deci nu ne bazm pe cumsecdenia i buna pregtire a utilizatorului.
Pentru a face fa cerinelor legate de problema tratrii excepiilor (aa se
numesc n jargon profesional erorile care apar n timpul execuiei programelor)
anumite limbaje de programare ofer suport adecvat. A include aici limbaje
precum Delphi, C++, Java, Visual C.
Nu toate compilatoarele de C++ ofer suport, dar standardul ANSI C++ cere
acest lucru n mod explicit. Compilatoarele din familia Borland incepnd cu
versiunea 4.0 ofer acest suport.
Esenialul din punctul de vedere al programatorului C++ este ca el s-i formeze
abilitatea de a scrie n jurul aplicaiilor cod C++ care ndeplinete funcia de
handler de excepii.
Suportul sintactic C++ pentru tratarea excepiilor se rezum la trei cuvinte cheie,
a cror semantic preliminar o prezentm n Tabelul xxxxx.
try{
//blocul try
//if(eroare) throw valoare_excepie;
}
catch (Tip_excepie Nume_variabil ){
//Prelucrarea excepiei
}
113
n cadrul acestei forme generalizate, valoarea valoare_excepie lansat trebuie
s corespund tipului Tip_excepie .
#include <iostream.h>
void main()
{
cout<<"Start"<<endl;
try
{
cout<<"In interiorul blocului try"<<endl;
throw 100;
cout<<"Nu se va executa";
}
catch (int i)
{
cout<<"Am captat o excepie --valoarea este:";
cout<<i <<endl;
}
cout<<"Sfarsit";
};
#include <iostream>
void XHandler(int test)
{
cout<<"Inauntrul functiei XHandler, test are
valoarea:"<<test<<endl;
if(test) throw test;
114
};
void main()
{
cout<<"Start:"<<endl;
try
{
cout<<"Inauntrul blocului try"<<endl;
XHandler(1);
XHandler(2);
XHandler(0);
}
catch(int i)
{
cout<<"Am captat o exceptie. Valoarea este:";
cout<<i<<endl;
};
cout<<"Sfarsit";
};
#include <iostream.h>
void XHandler(int test)
{
try
{
if(test) throw test;
}
catch(int i)
{
cout<<"Am captat exceptia nr.: "<<i<<endl;
}
};
void main()
{
cout<<"Start: "<<endl;
XHandler(1);
XHandler(2);
XHandler(0);
XHandler(3);
cout<< "Sfarsit";
115
};
try
{
//instruciuni
}
catch (tip1)
{
//tratare excepie 1
}
catch(tip2)
{
//tratare excepie 2
}
:
catch(tipn)
{
//tratare excepie n
}
#include <iostream.h>
void XHandler(int test)
{
try
{
if(test==0)
throw test;
if(test==1)
throw "Sir de caractere";
116
if(test==2)
throw 121.25;
}
catch(int i)
{
cout<<"Am captat exceptia #:"<<i<<endl;
}
catch(char *sir)
{
cout<<"Am captat exceptia de tip sir de
caractere:"<<sir<<endl;
}
catch(double d)
{
cout<<"Am captat exceptia #:"<<d<<endl;
}
};
void main()
{
XHandler(0);
XHandler(1);
XHandler(2);
cout<<"Sfarsit";
};
try
{
//Instructiuni
}
catch()
{
//tratarea exceptiei
}
117
Pentru exemplificare propun codul de mai jos.
#include <iostream.h>
void XHandler(int test)
{
try
{
if(test==0)
throw test;
if(test==1)
throw 'a';
if(test==2)
throw 121.25;
}
catch()
{
cout<<"Am captat o exceptie"<<endl;
}
};
void main()
{
cout<<"Start:"<<endl;
XHandler(0);
XHandler(1);
XHandler(2);
cout<<"Sfarsit";
};
Evident, prelucrrile din cadrul blocului catch generic trebuie s fie independente
de tipul erorii.
Mecanismul captrii excepiilor explicite poate fi combinat cu mecanismul
excepiilor generice ca n exemplul de mai jos.
#include <iostream.h>
void XHandler(int test)
{
try
{
if(test==0)
throw test;
if(test==1)
throw 'a';
if(test==2)
throw 121.25;
}
catch(int i)
118
{
cout<<"Am captat o exceptie de tip intreg"<<endl;
}
catch()
{
cout<<"Am captat o exceptie generica"<<endl;
}
};
void main()
{
cout<<"Start:"<<endl;
XHandler(0);
XHandler(1);
XHandler(2);
cout<<"Sfarsit";
};
Restrictionarea exceptiilor
Pe msur ce programele dumneavoastr devin mai complexe, ele vor apela
frecvent funcii din cadrul unui bloc try. Atunci cnd programele dumneavoastr
apeleaz funcii dintr-un bloc try, putei restriciona tipurile de excepii pe care
funcia apelat le poate lansa. De asemenea putei preveni lansarea oricrei
excepii dintr-o anumit funcie.
119
#include <iostream.h>
void XHandler(int test) throw(int, char, double)
{
if(test==0)
throw test;
if(test==1)
throw 'a';
if(test==2)
throw 121.25;
}
void main()
{
cout<<"Start:"<<endl;
try
{
XHandler(0);
}
catch(int i)
{
cout<<"Am captat un intreg"<<endl;
}
catch(char c)
{
cout<<"Am captat un caracter"<<endl;
}
catch(double d)
{
cout<<"Am captat un double"<<endl;
}
cout<<"Sfarsit";
};
#include <iostream.h>
void XHandler(void)
{
try
{
120
throw "Salve";
}
catch(char *)
{
cout<<"Am captat char* in XHandler "<<endl;
throw;
}
void main()
{
cout<<"Start"<<endl;
try
{
XHandler();
}
catch(char *)
{
cout<<"Am captat char * in main"<<endl;
}
cout<<"Sfarsit";
};
#include <iostream.h>
void div (double a, double b)
{
try
{
if(!b) throw b;
cout<<"a/b="<<a/b<<endl;
}
catch(double b)
{
cout<<"Nu se poate imparti la zero"<<endl;
}
}
void main()
{
double i,j;
do
121
{
cout<<Introduceti numaratorul (0 pentru stop):"<<endl;
cin i;
cout<<Introduceti numitorul :"<<endl;
cin j;
div(i,j);
} while (i!=0);
};
122
III Cteva aplicaii care au n spate
C sau C++
123
1 Sortarea elementelor unui ir de numere reale prin metoda bulelor.
Program pretext pentru modularizare. Se utilizeaz fiierul antet facilcrt.h
prezentat n continuarea acestei seciuni.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include"facilcrt.h"
#include<string.h>
void prelsir();
char prelopt();
void sort();
int dims;
float x[ _lms];
//Functia principala..
void main()
{
char op;
do
{
op=prelopt();
switch (op)
{
case '1': prelsir();
break;
case '2': sort();
break;
}
}
while (op!='3');
}
{
char c;
do
{
textcolor(RED);
124
textbackground(CYAN);
clrscr();
gotoxy(20,8) ;cprintf("Optiunile programului sunt:");
gotoxy(20,9) ;cprintf("1-Preluare elemente sir");
gotoxy(20,10);cprintf("2-Sortare/afisare sir");
gotoxy(20,11);cprintf("3-Terminare program");
makewin2(20,8,60,11);
makewin2(20,14,60,14);
gotoxy(20,14);cprintf("Optiunea Dvs.:");
c=getch();
}
while (strchr(_optiune,c)==NULL);
return c;
};
//Determinare maxim...
void sort()
{
float aux;
int i,sortat;
125
if (x[i]>x[i+1])
{
aux=x[i];
x[i]=x[i+1];
x[i+1]=aux;
sortat=0;
}
}
}
while(!sortat);
126
2 Fier antet care ncapsuleaz cteva faciliti de lucru n mod text, utile
pentru realizarea unor interfee agreabile ale programelor cu utilizatorii.
Numit n exemplul precedent prin facilcrt.h.
#include <conio.h>
#include <stdio.h>
#include <string.h>
#define css 1
for (i=ls,j=cs;i<=j;i++,j--)
{
gotoxy(i,linie);
printf("%c",mesaj[i-ls]);
delay(50); //prototipul in fisierul antet <dos.h>
gotoxy(j,linie);
printf("%c",mesaj[strlen(mesaj)-1-cs+j]);
}
getch();
}
//Activare video-invers
void avideo()
{
textcolor(BLACK);
textbackground(WHITE);
}
//dezactivare video-invers
void dvideo()
{
textcolor(WHITE);
textbackground(BLACK);
}
127
sw=sw && ((ld-ls+1)>=strlen(sir));
if (sw)
{
col=ls+(ld-ls+1-strlen(sir))/2;
gotoxy(col,linia);
cprintf(sir);
}
}
128
printf("Coordonate ecran eronate!!!");
getch();
}
}
129
3 Aplicaie pretext pentru lucru cu tablouri, folosind pointeri.
Mai precis, codul prezentat mai jos rezolv urmtoarele probleme:
-alocarea dinamic a memoriei pentru un tablou bidimensional cu
numr de linii i coloane precizate;
-citirea elementelor unui tablou bidimensional;
-transpunerea unei matrice;
-afiarea elementelor unei matrice;
#include <conio.h>
#include<iostream.h>
int i,j;
//Transpunerea matricei
void transpun(int **p,int **q,int nl,int nc)
130
{
for(i=0;i<nl;i++)
for(j=0;j<nc;j++)
q[j][i]=p[i][j];
};
//Functia principala
void main()
{
int **pmat;
int **q;
int nl=6,nc=2;
clrscr();
almemmat(pmat,nl,nc);
almemmat(q,nc,nl);
citmat(pmat,nl,nc);
transpun(pmat,q,nl,nc);
afismat(q,nc,nl);
getch();
};
131
4 Sortarea unui ir de numere ntregi prin metoda HEAP_SORT. Se
utilizeaz reprezentarea liniar a unui arbore binar.
#include<iostream.h>
#include<conio.h>
132
while(y>0)
{
temp=list[0];
list[0]=list[y-1];
list[y-1]=temp;
--y;
walk_down(list,0,y);
}
}
void main()
{
list_type list;
int i,nrel;
clrscr();
gotoxy(20,10);
cout<<"Numar de elemente in lista:";
cin>>nrel;
clrscr();
for(i=0;i<nrel;i++)
{
gotoxy(20,11);
clreol();
cout<<"Elementul[ "<<i<<" ]=";
cin>>list[i];
}
heap_sort(list,nrel);
clrscr();
for(i=0;i<nrel;i++)
cout<<list[i]<<endl;
getch();
}
133
5 Rasfoirea unui fiier text i contorizarea apariiilor unui caracter ntr-un
fisier text utiliznd fluxuri binare.
#include <fstream.h>
#include <stdlib.h>
#include "facilcrt.h"
char optiuni[]="1234";
char *nf;
int sfs;
134
int cont;
clrscr();
gotoxy(20,10);
cout<<"Caracterul:";
makewin2(20,10,60,11);
gotoxy(20+strlen("Caracterul:"),10);
cin>>c;
if(sfs)
{
ifstream in(nf,ios::in | ios::binary);
if(!in)
{
sfs=0;
gotoxy(1,24);
textcolor(RED+BLINK);
cprintf("Fisierul indicat nu poate fi deschis...");
getch();
sfs=0;
textcolor(WHITE);
}
else
{
char ch;
cont=0;
while(in)
{
in.get(ch);
if(ch==c)
cont++;
}
gotoxy(20,11);
cout<<"Numar de aparitii:"<<cont;
getch();
}
}
else
{
gotoxy(1,24);
textcolor(RED+BLINK);
cprintf("Selectati mai intai fisierul...");
getch();
textcolor(WHITE);
}
}
135
{
char *n;
sfs=1;
clrscr();
gotoxy(20,10);
cout<<"Numele fisierului de rasfoit:";
makewin2(15,10,65,10);
do
{
strcpy(n,"");
gotoxy(20+strlen("Numele fisierului de rasfoit:"),10);
gets(n);
}
while(strlen(n)==0);
return n;
}
136
clrscr();
}
cout<<ch;
}
getch();
}
}
else
{
gotoxy(1,24);
textcolor(RED+BLINK);
cprintf("Selectati mai intai fisierul...");
getch();
textcolor(WHITE);
}
}
137
6 Modelarea C a unor faciliti de lucru cu memoria video n mod text.
Exemplul de cod prezentat mai jos ilustreaz, n alt context, utilitatea
pointerilor, precum i o serie de elemente tehnice referitoare la
scrierea/citirea n/din memoria video, atunci cnd se lucreaz n mod text.
#ifndef _stdio_h
#include<stdio.h>
#define _stdio_h
#endif
#ifndef _conio_h
#include<conio.h>
#define _conio_h
#endif
#ifndef _string_h
#include<string.h>
#define _string_h
#endif
#define startcol1 16
#define startcol2 36
#define startcol3 56
#include<dos.h>
#include<iostream.h>
#include<stdlib.h>
138
//Functia seteaza adresa memoriei video in functie de
//modul video curent
void setvptr()
{
int vmod;
vmod=mod_video();
if((vmod!=2)&&(vmod!=3)&&(vmod!=7))
{
cout<<"Video trebuie sa fie in modul text cu 80 de
coloane.";
exit(1);
}
if(vmod==7)
mem_vid=(char far *) 0xB0000000;
else mem_vid=(char far *)0xB8000000;
}
139
gotoxy(1,1);
for(int i=0;i<78;i++)
printf("\xf");
gotoxy(16,2);printf("Cod Caracter");
gotoxy(36,2);printf("Cod Caracter");
gotoxy(56,2);printf("Cod Caracter\n");
for(i=0;i<78;i++)
printf("\xf");
}
140
case 2:
{
cc=startcol2;
break;
}
case 3:
{
cc=startcol3;
break;
};
}
lin++;
gotoxy(cc,nrcan+lin);printf("%i",i);
gotoxy(cc+7,nrcan+lin);printf("%c",(char)i);
};
gotoxy(1,23);
for(j=0;j<78;j++)
printf("\xf");
gotoxy(1,24);
printf("Pentru terminare apasati o tasta....");
getch();
}
141
7 Modelarea C++ a operaiilor cu iruri de caractere. Problem pretext
pentru aplicarea corect a principiului ncapsulrii, pentru utilizarea n
funcie de cerine a constructorilor n specificarea comportamentului unei
clase, pentru redefinirea unor operatori uzuali n lucru cu iruri de
caractere (concatenarea polimorfic, adresarea unui caracter al tabloului
de caractere, etc.).
#include <stdio.h>
#include<string.h>
//*****************************************************
//Clasa modeleaza lucrul cu siruri de caractere in C++
//class string
{
int lsir; //lungimea sirului
char *psir; //tablou de caractere alocat dinamic
public:
142
string operator+(string & x);
//Destructor clasa
~string();
//*****************************************************
//Implementare functii membre
143
//Implementare redefinire operator atribuire obiect
void string::operator=(string x)
{
delete psir;
lsir=x.lsir;
psir=new char[lsir];
strcpy(psir,x.psir);
}
144
//Implementare concatenare a doua siruri
string string::operator+(string & x)
{
string s;
strcat(s.psir,psir); strcat(s.psir,x.psir);
s.lsir=lsir+x.lsir-1;
return s;
}
//Implementare destructor
string::~string()
{
delete psir;
}
145
};
146
8 Aplicatie care ilustreaza lucrul cu fisiere cu tip in C++
Din nou o problem pretext, care se refer la actualizarea unui fiier n care
se pstreaz ntrebrile unui test i rspunsurile corecte, presupunnd c o
ntrebare are mai multe alternative de rspuns.
#include <conio.h>
#include <stdio.h>
#include <iostream.h>
#include <ctype.h>
#include<stdlib.h>
#include <string.h>
#include <fstream.h>
char optiuni[]="1234567";
char *nf;
int sfs,nri;
//Tipul inregistrare
typedef struct struct_test
{
int nr_intrebare;
int alt_corecta;
} t_inr_fis;
//Variabila inregistrare
t_inr_fis inr;
147
void main()
{
char op;
sfs=0;
do
{
op=prelopt();
switch(op)
{
case '1': nf=selnumef();
break;
case '2': crefis();
break;
case '3': adinfis();
break;
case '4': {
clrscr();
gotoxy(10,12);
cout<<"Numar intrebare inregistrare de
sters:";
cin>>nri;
steinfis(nri);
break;
};
case '5': vizfis();
break;
case '6': {
clrscr();
gotoxy(10,12);
cout<<"Numar inregistrare de selectat:";
cin>>nri;
selin(nri);
break;
};
case '7': break;
}
}
while (op!='7');
};
148
ftestin.read((unsigned char*) &inr,sizeof(t_inr_fis));
if(!ftestin.eof())
{
clrscr();
gotoxy(10,12);
cout<<"Nr. intrebare :";
cout<<inr.nr_intrebare;
gotoxy(10,13);
cout<<"Alternativa corecta:";
cout<<inr.alt_corecta;
getch();
ftestin.close();
};
}
else
{
gotoxy(1,24);
cout<<"Selectati sau creati mai intai un fisier!....";
getch();
}
};
149
//Implementare crefis()
void crefis()
{
ofstream ftestout;
clrscr();
gotoxy(20,10);
cout<<"Nume fisier de creat:";
cin>>nf;
ftestout.open(nf,ios::out|ios::binary);
sfs=1;
char ras;
do
{
clrscr();
gotoxy(20,10);cout<<"Numar intrebare:";
cin>>inr.nr_intrebare;
gotoxy(20,11);cout<<"Raspuns corect :";
cin>>inr.alt_corecta;
ftestout.write((unsigned char *) &inr,
sizeof(t_inr_fis));
gotoxy(20,12);cout<<"Mai aveti de introdus(D,N):";
ras=getch();
}
while (!(toupper(ras)=='N'));
ftestout.close();
}
//Implementare adinfis()
void adinfis()
{
if (sfs)
{
ofstream ftestout;
clrscr();
gotoxy(20,10);
ftestout.open(nf,ios::app|ios::binary);
char ras;
do
{
clrscr();
gotoxy(20,10);cout<<"Numar intrebare:";
cin>>inr.nr_intrebare;
gotoxy(20,11);cout<<"Raspuns corect :";
cin>>inr.alt_corecta;
ftestout.write((unsigned char *) &inr,
sizeof(t_inr_fis));
150
gotoxy(20,12);cout<<"Mai aveti de introdus(D,N):";
ras=getch();
}
while (!(toupper(ras)=='N'));
ftestout.close();
}
else
{
gotoxy(1,24);
cout<<"Selectati sau creati mai intai un fisier!....";
getch();
}
}
//Implementare vizfis()
void vizfis()
{
if (sfs)
{
ifstream ftestin;
ftestin.open(nf,ios::in|ios::binary);
while (!ftestin.eof())
{
clrscr();
ftestin.read((unsigned char*)&inr,sizeof(t_inr_fis));
if(!ftestin.eof())
{
gotoxy(10,12);
cout<<"Nr. intrebare :";
cout<<inr.nr_intrebare;
gotoxy(10,13);
cout<<"Alternativa corecta:";
cout<<inr.alt_corecta;
getch();
};
};
ftestin.close();
}
else
{
gotoxy(1,24);
cout<<"Selectati sau creati mai intai un fisier!....";
getch();
}
}
151
//Implementare selnumef()
char *selnumef()
{
char *n;
sfs=1;
clrscr();
gotoxy(20,10);
cout<<"Numele fisierului de lucru:";
do
{
strcpy(n,"");
gotoxy(20+strlen("Numele fisierului de lucru:"),10);
gets(n);
}
while(strlen(n)==0);
return n;
}
//Implementare prelopt()
char prelopt()
{
clrscr();
gotoxy(20,8);
cout<<"Optiunile programului...";
gotoxy(20,9);
cout<<"__________________________________________";
gotoxy(20,11);
cout<<"1-Selectare fisier structura test";
gotoxy(20,12);
cout<<"2-Creare fisier structura test";
gotoxy(20,13);
cout<<"3-Adaugare date in fisierul structura test";
gotoxy(20,14);
cout<<"4-Stergerea unei inregistrari din fisier";
gotoxy(20,15);
cout<<"5-Vizualizare date fisier structura";
gotoxy(20,16);
cout<<"6-Afisare inregistrare de numar specificat";
gotoxy(20,17);
cout<<"7-Terminare program";
gotoxy(20,19);
cout<<"__________________________________________";
gotoxy(20,20);
cout<<" Alegerea Dvs.:";
gotoxy(20+strlen(" Alegerea Dvs.:"),20);
char op;
152
do
op=getch();
while (strchr(optiuni,op)==NULL);
return op;
};
153
BIBLIOGRAFIE MINIMAL
[1]. N. Barkakati Borland C++ 4, Ghidul programatorului,
Editura Teora, 1997
[2]. K., Jamsa, L. Klander Totul despre C i C++, Editura Teora,
2000
[3]. I. Mulea C++ pentru avansai, Editura
Microinformatica, 1994
[4]. L. Negrescu Limbajele C i C++ pentru nceptori,
Limbajul C++, volumul 2, Editura Albastr,
Cluj-Napoca, 2000
[5]. L. Negrescu Limbajele C i C++ pentru nceptori,
Limbajul C, volumul 1, Editura Albastr,
Cluj-Napoca, 2000
[6]. D. M. Popovici, C++. Tehnologia orientat pe obiecte.
I. M. Popovici, Aplicaii,
I. Tnase Teora, 1996
Lista crilor din care se poate nva cte ceva despre C++ si lumea
POO este deschis, la fel de deschis ca mintea oricrui student care nu
i-a greit culoarul pe care alearg pentru a deveni un profesionist.
154
Subiecte pentru examenul la disciplina
Programare Obiect Orientat, Anul II INFO
FUNDAMENTE
Operatori n C/C++.
Tablouri C/C++.
155
Uniuni.
PARADIGMA POO
Fluxuri C/C++.
156
Scurte consideraii relativ la problema evalurii la
disciplina POO
157
face pentru a confirma superioritatea omului n raport cu alte
vieuitoare i nu numai.
Pentru a m face mai bine neles, n cele ce urmeaz voi arunca
cteva idei care ar vrea s sugereze modul n care, ca profesor,
neleg s evaluez lucrarea unui student.
158