Documente Academic
Documente Profesional
Documente Cultură
LIMBAJUL C/C + +
I.1. Prezentarea limbajului C: vocabular, tipuri de
date, constante, variabile, operatori i expresii
Un program este un text ce specific aciuni care vor fi executate de un
procesor. Scrierea unui program se face ntr-un limbaj de programare.
Un limbaj de programare are vocabular i reguli de sintax.
Vocabularul este format din uniti lexicale: cele mai simple elemente cu
semnificaie lingvistic.
Sintaxa: ansamblu de reguli pe baza crora se combin elementele
vocabularului (unitile lexicale) pentru a obine fraze corecte (instruciuni,
secvene de instruciuni, declarare de variabile etc).
Elementele vocabularului sunt alctuite din caractere.
Orice caracter este reprezentat n calculator n codul ASCII (American
Standard Code for Information Interchange), printr-un numr natural unic, cuprins
ntre 0 i 255 .
Caracterele sunt simboluri grupate n litere, cifre i semne speciale, astfel:
- literele mari ale alfabetului englez cu codurile 65,...,90: A, B, ..., X, Y, Z
- literele mici ale alfabetului englez cu codurile 97,...,122: a, b, ..., x, y, z
- cifrele bazei zece, care au codurile in 48,...,57: 0, 1, 2, ... ,9
- liniua de subliniere _
- semne de punctuaie i semne speciale : , . : ? ( ) [ ] { } < > ! | \ / ~ # & ^
+-*%
Unitile lexicale ale limbajului C/C++ sunt: identificatori, cuvinte cheie,
constante, iruri, operatori i separatori. La scrierea lor se folosesc reguli precise
date de sintaxa limbajului prin utilizarea setului de caractere al codului ASCII.
const
unsigned
signed
goto
do
while
double
break
switch
register
extern
float
continue
void
sizeof
if
int
else
case
typedef
return
short
for
default
volatile
static
I.1.2. Comentariu
n redactarea programelor se folosesc o serie de texte care dau explicaii cu
privire la program, la prile sale la variabilele utilizate etc. Aceste texte explicative
se adreseaz utilizatorilor; se numesc comentarii i sunt ignorate de compilator.
n limbajul C un comentariu ncepe prin /* i se termin prin */.
n C++ un comentariu care ncape pe un rnd poate fi scris dup //.
I.1.5. Constante
O constant este o valoare fix care apare literalmente n codul surs al unui
program. Tipul i valoarea constantei sunt determinate de modul n care constanta
este scris. Constantele pot fi de mai multe tipuri: ntreg, flotant(real), caracter, ir
de caractere. Aceste constante sunt folosite, de exemplu, pentru a iniializarea
variabilelor.
Constante ntregi
O constant ntreag este un numr ntreg reprezentat n cod complementar
fa de 2 pe 16 bii sau pe 32 bii dac nu ncape pe 16 bii. Exemple: 7, -3, 0.
n cazul n care dorim ca o constant ntreag din intervalul -32768 ...
+32767 s fie reprezentat pe 32 bii (implicit astfel de constante se reprezint pe
16 bii), vom termina constanta respectiv prin L sau l, adic i impunem tipul long.
Exemplu -10L.
Dac, la o constant ntreag, adugm sufixul U sau u, atunci form tipul
constantei la unsigned int sau unsigned long. Dac adugm sufixul UL sau ul sau
Ul sau uL constanta va fi de tipul unsigned long.
O constant ntreag, precedat de un zero nesemnificativ se consider scris
n sistemul de numeraie cu baza 8.
O constant ntreag care ncepe cu 0X sau 0x se consider scris n
sistemul de numeraie cu baza 16 (cifrele hexazecimale sunt 0...9, a...f sau
A...F). n rest se consider c baza de numeraie este 10.
Exemple:
Constanta
1234
02322
0x4D2
Tip
int
int /* octal */
Int /* hexazecimal */
Constanta
123456789L
1234U
123456789UL
Tip
long
unsigned int
unsigned long int
Constante flotante
Atunci cnd ncercm s reprezentm n memoria calculatorului un numr
real, cutm de fapt cel mai apropiat numr real reprezentabil n calculator i
aproximm numrul iniial cu acesta din urm. Ca rezultat, putem efectua calcule
complexe cu o precizie rezonabil.
Constantele reale sunt reprezentate n virgul mobil prin notaia clasic cu
mantis i exponent.
Sintaxa: partea ntreag . partea fracionar {E|e} exponentul
Pot lipsi fie partea ntreag, fie partea fracionar, dar nu ambele.
Pot lipsi punctul zecimal cu partea fracionar sau litera E cu exponentul dar
nu ambele. Semnul + este opional pentru numerele nenegative.
Exemple:
3.1415921
4.3E20
-.2e+15
2e-5
-12.
.34
-.125
/* pentru numrul 4.3*1020 */
/* pentru numrul 0.2*1015 */
/* pentru numrul 2*10-5 */
tip
double
double
float
long double
Constante caracter
O constant caracter reprezint un caracter i are ca valoare codul ASCII al
caracterului respectiv. O constant caracter grafic se poate scrie incluznd
caracterul respectiv ntre caractere apostrof.
Exemple:
literele mari au codurile ASCII n intervalul [65,90]
'A' > 65, ... , 'Z' > 90.
literele mici au codurile ASCII n intervalul [97,122]
'a' > 97, ... ,'z' > 122
cifrele au codurile ASCII n intervalul [48,57]
'0' > 48, ... ,'9' > 57
constanta '*' are valoarea 77
Caracterele negrafice cu excepia caracterului DEL (care are codul 127), au
coduri ASCII mai mici dect 32. O parte dintre aceste caractere formeaz categoria
caracterelor de control i au notaii speciale de tipul \caracter.
Constante ir de caractere
O constant ir de caractere este o succesiune de zero sau mai multe
caractere delimitate prin ghilimele. Ghilimelele nu fac parte din irul de caractere.
Dac dorim s folosim caractere negrafice n compunerea unui ir de caractere,
atunci putem folosi convenia de utilizare a caracterului \. Dac dorim s
reprezentm chiar caracterul ghilimele, atunci vom scrie \", de asemenea pentru
backslash scriem \\.
Exemple:
"123"
"1\"2"
-reprezint succesiunea 1"2
"a\\b"
-reprezint succesiunea a\b
"c:\\tc\\bgi"
-reprezint succesiunea c:\tc\bgi
Un ir de caractere poate fi continuat de pe un rnd pe altul, dac nainte de
a aciona tasta <enter> se va tasta \.
Constanta ir de caractere se reprezint printr-o succesiune de octei n care
se pstreaz codurile ASCII ale caracterelor irului, iar ultimul octet conine
totdeauna caracterul NULL pentru a marca sfritul irului. De aici rezult c, de
exemplu, 'A' i "A" sunt construcii diferite. Prima reprezint o constant caracter
care se pstreaz pe un singur octet n memorie. A doua, reprezint un ir de
caractere i se pstreaz pe doi octei, primul octet conine valoarea codului
ASCII al lui A, iar cel de-al doilea conine caracterul NULL, adic valoarea 0.
I.1.6. Variabile
Prin variabil nelegem o zon temporar de stocare a datelor a crei
valoare se poate schimba n timpul execuiei programului. Unei variabile i se
asociaz un nume prin intermediul cruia putem avea acces la valoarea ei i un tip
de date care stabilete valorile pe care le poate lua variabila. Corespondena ntre
numele i tipul unei variabile se realizeaz printr-o construcie special numit
declaraie. Toate variabilele utilizate ntr-un program trebuie declarate naintea
utilizrii lor.
O declaraie de variabil are urmtoarea sintax:
< tip > < lista de variabile >
unde lista conine unul sau mai multe nume de variabile desprite prin
virgule.
Exemple:
int i,j,X;
unsigned long k;
float a,b;
char c;
Sunt situaii n care variabilele trebuie s fie grupate din punct de vedere
logic. Tablourile reprezint grupuri unidimensionale sau multidimensionale de
variabile de acelai tip. Declaraia de tablou conine tipul comun al elementelor
sale, numele tabloului i numrul de elemente pentru fiecare dimensiune incluse
ntre paranteze drepte.
<tip> <lista de elemente>;
respectiv,
a[0][0],
a[1][0],
a[0][1],
a[1][1],
a[0][2],
a[1][2],
...
a[99][0]
a[99][1],
a[99][2].
Operatori
Prioritate
Mod de
asociere
()
[]
::
.
->
15
(tip)
14
Categoria de operatori
Dimensiune n octei
Alocare memorie
Dezalocare memorie
Adres
Coninut adres
Semn
Negaie
Incrementare, decrementare
Dereferenierea
pointerilor
membrii claselor
Multiplicativi
Aditivi
Deplasare
Relaionali
Egalitate
I la nivel de bit
SAU EXCLUSIV la nivel de bit
SAU la nivel de bit
I logic
SAU logic
Condiional
Atribuire
Operatorul virgul
Operatori
sizeof
new
delete
&
*
+ !
~
++ -spre .*
->*
* / %
+ << >>
< <= > >=
= = !=
&
^
|
&&
||
?:
=
+= -= *= /=
%= &= |= ^=
<<= >>=
,
Prioritate
Mod de
asociere
13
12
11
10
9
8
7
6
5
4
3
2
1
0
Operatori aritmetici
Operatorii + i unari se aplic unui singur operand i se folosesc la
stabilrea semnului operandului: pozitiv sau negativ.
Operatorul * reprezint operatorul de nmulire al operanzilor la care se
aplic.
Operatorul / reprezint operatorul de mprire. Dac ambii operanzi sunt
ntregi (char, int, unsigned, long), se realizeaz o mprire ntreag, adic ne
furnizeaz ctul mpririi.
Operatorul % are ca rezultat restul mpririi dintre doi operanzi ntregi.
Operatorii binari + i reprezint operaiile obinuite de adunare i scdere.
Exemple:
int a, b;
float x, y;
Dac a=3 i b=7 atunci b/a are valoarea 2 iar b%a are valoarea 1.
Dac x=9 i y=2 atunci x/y are valoarea 4.5.
Expresia x*y are sens, aici este operatorul unar.
sau postfixai:
operand++
operand--
Operatori relaionali
Operatorii relaionali sunt <, <=, >, >=, ==, !=.
Rezultatul aplicrii unui operator relaional este 1 sau 0 dup cum operanzii
se afl n relaia definit de operatorul respectiv sau nu.
De exemplu, dac a=5 i b=6 atunci expresia a<=b are valoarea 1, iar
expresia a+1>b are valoarea 0.
Operatorul == (egal) furnizeaz 1 dac operanzii sunt egali i zero n caz
contrar. Operatorul != (diferit) furnizeaz 1 dac operanzii nu sunt egali i zero n
caz contrar.
Exemple:
Dac x=2 i y =-1 atunci expresia x==y are valoarea 0, expresia x!=y are
valoarea 1, expresia x+y==1 are valoarea 1.
Operatori logici
!
negaie logic,operator unar.
&& I logic.
||
SAU logic.
10
00000101
00100100
x | y = -----------00100101
00000101
~ x= -------------
11
00100001
11111010
Operatorul & se poate utiliza la anulri de bii, de exemplu:
a & 0x00ff are ca valoare, valoarea octetului mai puin semnificativ al
valorii variabilei a (primii 8 bii sunt nlocuii cu 0, iar urmtorii 8 bii coincid cu
cei ai lui a).
Operatorul | se poate utiliza la la setri de bii, de exemplu:
a | 0x00ff primii 8 bii ai rezultatului coincid cu cei ai lui a, iar
urmtorii 8 sunt 1.
Operatorul <<, operator binar, realizeaz deplasarea la stnga a valorii
primului operand cu un numr de poziii binare egal cu valoarea celui de-al doilea
operand al su, biii liberi din dreapta se completeaz cu zero. Aceast operaie este
echivalent cu o nmulire cu puteri ale lui 2.
Exemplu.
x=7 n baza 2 se scrie 0000 0000 0000 0111
x <<2 va produce 0000 0000 0001 1100 deplasarea cu o poziie spre stnga
i adugarea unui zero. Valoarea sa este 28 adica 7*22
Operatorul >>, operator binar, realizeaz deplasarea la dreapta a valorii
primului operand cu un numr de poziii binare egal cu valoarea celui de-al doilea
operand al su. Aceast operaie este echivalent cu o mprire cu puteri ale lui 2.
In cazul deplasarii spre dreapta, biii liberi din stnga se completeaz
automat cu zero numai dac numrul este nenegativ. Dac numrul este negativ,
din necesitatea de a conserva semnul (reprezentat n bitul cel mai semnificativ cu
1), biii liberi din stnga se completeaz cu 1.
Exemple:
19>>3 are ca rezultat numrul binar 0000 0000 0000 0010 egal cu 2 adic
19/23.
x=-9 se reprezint n binar n cod complementar fa de 2. Acesta se obine
adunnd la complementul fa de unu al numrului, valoarea 1.
Deci 9 se obine ca ~ 9+1.
9 se reprezint prin:
0000 0000 0000 1001
~ 9 se repretint prin:
1111 1111 1111 0110
~ 9 +1 se reprezint prin:
1111 1111 1111 0111
atunci 9 se reprezint prin: 1111 1111 1111 0111
x>>2 va produce:
1111 1111 1111 1101
Operatori de atribuire
Operatorul = se utilizeaz n construcii de forma v = expresie.
Aceast construcie se numete expresie de atribuire i este un caz particular
de expresie. Tipul ei coincide cu tipul lui v, iar valoarea ei este chiar valoarea
atribuit lui v. Rezult c o expresie de forma:
v1 = (v = expresie)
este legal.
Deoarece operatorii de atribuire se evalueaz de la dreapta la stnga expresia
de mai sus se poate scrie fr paranteze.
n general, putem realiza atribuiri multiple de forma
12
vn=vn-1=...=v1=expresie.
n cazul unei expresii de atribuire, dac expresia din dreapta semnului egal
are un tip diferit de cel al variabilei v, atunci nti se convertete valoarea ei spre
tipul variabilei v i pe urm se realizeaz atribuirea.
Pentru operaia de atribuire putem folosi operatorii de atribuire combinat:
op=
Unde prin op se nelege unul din operatorii binari aritmetici sau logici pe
bii, adic: *, /, %, +, -, &, |, ^, <<, >>.
Expresia:
v op= expresie
este echivalent cu
v = v op (expresie)
Exemple:
Expresia:
x=x+5 este echivalent cu x+=5.
Expresia x=x^y este echivalent cu x^=y.
Expresia x=x<<y este echivalent cu x<<=y.
Expresia:
x/=y+3 este echivalent cu x=x/(y+3).
Expresia:
tab[i*j+1]=tab[i*j+1]*z
este echivalent cu
tab[i*j+1]*=z.
Expresia C=C*n/k, cu C, n i k de tip ntreg, nu produce acelai
rezultat cu C*=n/k, de exemplu pentru C=20, n=5, k=2 prima expresie furnizeaz
rezultatul 50, iar a doua 40 (C*=n/k este echivalent cu C=C*(n/k)).
13
Operatori condiionali
Operatorii condiionali se utilizeaz n evaluri de expresii care prezint
alternative. Ei sunt ?:.
O astfel de expresie are formatul:
exp1 ? exp2 : exp3
Operatorul virgul
Exist cazuri n care este util s grupm mai multe expresii ntr-una singur,
expresii care s se evalueze succesiv. n acest scop se folosete operatorul virgul
care separ secvena de expresii, acestea grupndu-se ntr-o singur expresie.
Expresia:
exp1, exp2, ... , expn
va avea ca valoare i tip valoarea i tipul lui expn, deci cu a ultimei expresii.
Exemple:
k=(x=10, y=2*i-5, z=3*j, x+y+z);
Se execut pe rnd cele trei atribuiri, apoi se efectueaz suma x+y+z care se
atribuie lui k.
++i, --j
unde data este numele unei variabile, al unui tablou, al unui tip etc.
Exemple:
int i;
float x;
char c;
double d;
int tab[10];
sizeof(i)
sizeof(x)
sizeof(float)
sizeof(c)
sizeof(tab)
sizeof(tab[i])
-furnizeaz valoarea 2
-furnizeaz valoarea 4
-furnizeaz valoarea 4
-furnizeaz valoarea 1
-furnizeaz valoarea 20
-furnizeaz valoarea 2
14
Operatori parantez
Operatorul parantez rotund () se utilizeaz pentru a impune o alt
ordine n efectuarea operaiilor. O expresie inclus ntre paranteze rotunde
formeaz un operand.
Parantezele rotunde se utilizeaz i la apelul funciilor.
Parantezele ptrate [] includ expresii care reprezint indici. Ele formeaz
operatorul de indexare.
Operatori de adres
Operatorul & returneaz adresa unei variabile. Astfel, dac x este o
variabil, &x va fi adresa variabilei x.
Operatorul * returneaz valoarea de la o anumit adres. Astfel, dac p este
pointer la tipul char, *p va fi caracterul referit de p.
15
Un program C se compune din una sau mai multe funcii. Fiecare funcie are
un nume. Orice program scris n limbajul C, indiferent de complexitate, trebuie s
conin o funcie, numit funcie principal, al crui nume este main.
Aceast funcie preia controlul de la sistemul de operare n momentul n care
programul este lansat n execuie i l red la terminarea execuiei.
Execuia unui program C nseamn execuia instruciunilor din funcia
main.
Structura unei funcii este urmtoarea:
<tip> <nume>( <lista parametrilor formali>) //antet
{
<declaraii i instruciuni> //corpul funciei
}
16
Exemple:
int g(float x, long n)
{
...
}
void f(void)
{
...
}
void main()
{...}
I.2.1. Preprocesare
Un program C poate suporta anumite prelucrri nainte de compilare. O
astfel de prelucrare se numete preprocesare. Ea se realizeaz printr-un program
special numit preprocesor. Preprocesorul este apelat automat nainte de a ncepe
compilarea.
Prin intermediul preprocesorului se pot realiza:
includeri de fiiere standard i utilizator;
definirea de macrodefiniii;
compilare condiionat.
17
I.2.3. Macrodefiniii
O alt construcie tratat de preprocesor este construcia define cu
formatul:
#define <nume> <succesiune de caractere>
Macrodefiniii cu argumente
Directiva #define poate fi folosit i n sintaxa:
#define <nume>(<list de parametri>) <corp macrodefinie>
18
Exemplu:
#define MAX(a,b) ((a)>(b)?(a):(b))
...
x=max(k+5,m)
2.
#if expresieConstant
text1
#else
text2
#endif
3.
#ifdef identificator //dac identificator a aprut ntr-o directiv #define
text
#endif
4.
#ifdef identificator // dac identificator a aprut ntr-o directiv #define
text1
#else
text2
#endif
5.
#ifndef identificator //dac identificator nu a aprut ntr-o directiv #define
text
#endif
6.
#ifndef identificator //dac identificator nu a aprut ntr-o directiv #define
text1
#else
text2
#endif
19
20
21
2.
#include <iostream.h>
void main()
{ char s[20];
cin>>s; cout<<s;
}
22
3.
#include <iostream.h>
void main()
{ char* a="xyzw";
cout<<"sirul a="<<a<<" adresa sirului a="<<(void*)a;
}
Intrare/
ieire
formateaz datele numerice n zecimal valabil E
pn la resetare
formateaz datele numerice n octal, valabil E
pn la resetare
formateaz datele numerice n hexazecimal, E
valabil pn la resetare
stabilete baza de numeraie la baza (8,10,16), E
valabil pn la resetare
stabilete la w numrul de poziii pe care se va E
afia urmtoarea dat de scris.
stabilete numrul de cifre aflat dup punctul E
zecimal. comanda este valabil pn la
reapelare.
stabilete caracterul de umplere, implicit spaiu, E
valabil pn la resetare
activeaz indicatorii de format specificai n I/E
variabila f.
dezactiveaz indicatorii de format specificai n I/E
variabila f.
elibereaz un stream
E
scrie un caracter "newline" i elibereaz E
streamul
Scrie un caracter null
E
ignor caracterele de tip spaiu
I
Scop
23
Exemplu:
#include<iostream.h>
#include<iomanip.h>
void main()
{ cout<<hex<<100<<endl;
cout<<dec <<setfill('*')<<setw(5)<<100<<endl;
}
24
Exemplu de utilizare:
Urmtorul program copiaz caracterele din streamul de intrare cin (pn la
ntlnirea caracterului CTRL Z) n streamul de ieire cout.
#include <iostream.h>
void main()
{ char c;
while((c=cin.get())!=EOF) cout.put(c);
}
3) istream& get(unsigned char&)
4) istream& get( signed char& )
25
26
Returneaz
citire.
Exemplu de apel:
void main()
{ int x; char y[25];
cin>>x>>y;
cout<<cin.gcount();
}
Dac tastm:
27
n mod curent ecranul este format din 25 linii i 80 coloane. Colul stnga
sus al ecranului are coordonatele (1,1). Colul dreapta jos al ecranului are n mod
curent coordonatele (80,25).
Prezentm cteva funcii, uzuale, pentru gestiunea ecranului:
15) void window(int x1,int y1,int x2,int y2);
28
Dac sunt prezente, declaraiile definesc variabile care sunt valabile numai
n instruciunea compus respectiv. Dup paranteza nchis a unei instruciuni
compuse nu se pune ";"
Structura unei funcii poate fi considerat ca fiind:
<antetul funciei>
<instruciune compus>
I.4.3. Instruciunea if
Instruciunea if implementeaz structura alternativ.
Ea are unul din formatele:
Formatul 1:
if(<expresie>)
<instruciune1>
else
<instruciune2>
29
Formatul 2:
if(<expresie>) <instruciune>
Trebuie inut seama de faptul c else este asociat celui mai apropiat if.
Pentru a determina un alt mod de asociere se pot utiliza delimitatorii de bloc.
if ( <expresie1> )
{ if ( <expresie2 > ) <instruciune1 > }
else <instruciune2 >
n acest mod else se asociaz primului if i nu celui deal doilea care este
mai apropiat.
Exemplu de utilizare a instruciunii if:
Programul urmtor calculeaz valoarea funciei
4 x 2 2 x 1,
f ( x) 50 ,
2 x 2 8 x 1,
dac x 0
dac x 0
dac x 0
// Afisarea rezultatului
30
x[j]=aux;
// Afisarea vectorului:
cout<<" vectorul inversat este:";
i=0;
while(i<n)
{ cout<<x[i]<<" ";
i++;
}
}
31
Sangamagrama(anul 1400)
12
k 0
1
3
2k 1
#include<iostream.h>
#include<iomanip.h>
#include <math.h> // pentru fabsl =valoarea absoluta
long double Pi()
{ long double eps=1.0e-20;
long double pi=1.0, pia=0,t=1;
/* pi=valoarea la pasul curent, k;
pia=valoarea de la pasul anterior;
t=(-1/3)^k ;
*/
unsigned long k=1;
while(fabsl(pi-pia)>eps)
{ pia=pi;
t*=-1.0/3.0;
pi+=t/(2*k+1);
k++;
}
// cout<<k<<endl;
return sqrt(12)*pi;
}
void main()
{ cout<<endl<<setw(22)<<setprecision(20)<<Pi()<<endl;}
unde
<exp1> se numete expresie de iniializare i se evalueaz o singur dat,
naintea primei iteraii, realiznd iniializarea ciclului. Uzual, ea atribuie o valoare
iniial variabilei de control a ciclului. Valoarea sau expresia de iniializare poate
lipsi in situaia n care iniializarea ciclului este fcut n afara sa, sau poate conine
mai multe expresii de iniializare separate prin operatorul virgul.
<exp2> se numete expresie de testare i se execut naintea fiecrei iteraii,
reprezentnd condiia de continuare aciclului. Ciclul se termin cnd aceast
expresie devine fals. Dac <exp2> lipsete, se consider c expresia de test este
adevrat tot timpul, iar ciclul se execut fr ntrerupere.
32
este echivalent cu
for( ; <exp> ; ) <instruciune>
Instruciunea:
for(;;) <instruciune>
definete un ciclu "infinit" din care se iese prin alte mijloace dect cele
obinuite.
Exemple de utilizare a instruciunii for:
(a) k k
x
k!
k 0
n
33
3) Fie a0, a1,, an-1 i x0, x1,, xn-1, numere reale ce se introduc de la tastatur
n 1
#include<iostream.h>
void main()
{float a[100],x[100],S;
int n,i;
cout<<"n="; cin>>n;
for(i=0;i<n;i++) { cout<<"a"<<i<<"="; cin>>a[i]; }
for(i=0;i<n;i++) { cout<<"x"<<i<<"="; cin>>x[i]; }
S=0;
for(i=0;i<n;i++)
S=S+a[i]*x[i];
cout<<"S="<<S;
}
34
35
36
do
{ ..
if() continue;
..
}
while(expr);
37
reiniializare.
Astfel, programul
#include<iostream.h>
void main()
{ int i;
for (i = 0; i < 5; i++)
{ if (i == 3) continue;
printf("i = %d\n",i);
}
cout<<"valoarea lui i la iesirea din ciclul for este <<i;
}
38
unde
<c1>,<c2>,...,<cn> sunt expresii constante de tip ntreg,
<expresie> este o expresie de tip ntreg (orice tip ntreg),
<sir1>,...,<sirn> sunt iruri de instruciuni (un astfel de ir poate fi i vid).
Efect:
1) Se evalueaz <expresie>.
2) Se compar valoarea expresiei <expresie>, succesiv, cu valorile
<c1>,<c2>,...,<cn>.
sin x, k 1
cos x, k 2
f(x,k) tg x,
k3
ctg x, k 4
39
case 3: f=tan(r);
break;
case 4: f=1/tan(r);
break;
default: f=sqrt(5+2*sin(r)+3*cos(r));
}
cout<<"f("<<k<<","<<x<<")="<<f<<endl;
}
O funcie de forma
<tip returnat> <nume funcie>(<lista parametrilor formali>)
{ ... }
40
41
cout<<n=; cin>>n;
if(prim(n))cout<<n<< este numar prim <<endl;
else
cout<<n<< nu este numar prim <<endl;
}
Exemplu:
float f()
{ int k;
static int a[5];
// ...
}
42
locale. Variabila tablou a, descris prin cuvntul cheie static, i pstreaz aceeai
adres pe toat durata programului, adres pe care o primete la nceputul
executrii programului. Variabilei k i se aloc spaiu pe stiv de fiecare dat cnd
se execut funcia f(), la adrese care pot fi diferite.
Declaraia informativ "extern"
Pentru ca o variabil global s poat fi folosit de funcii situate n alt fiier
surs, sau n cadrul aceluiai fiier n funcii anterioare declarrii variabilei, trebuie
ca acea variabil s fie descris printr-o declaraie "extern" n funciile
respective sau n afara oricrei funcii ale noului fiier. Acum fiierele pot fi
compilate separat i linkeditate mpreun.
Exemplu:
Fiierul F1.CPP
...
int x,y;
...
Fiierul F2.CPP
...
extern int x,y;
int suma(){return x+y;}
43
sau
static <tip> <nume> = <expresie>;
44
Exemplul 1:
#include<iostream.h>
void incrementare()
{ int i=1;
static int k=1;
i++;
k++;
cout<<"i="<<i<<", k="<<k<<endl;
}
void main()
{ incrementare();
incrementare();
incrementare();
}
45
sau
static <tip> <nume> [<dim>]={<e1>,<e2>,...,<en>};
<tip><nume>[<dim1>][<dim2>]={{<e11>,<e12>,...,<e1 m1>},
{<e21>,<e21>,...,<e2 m2>},
...
{<en1>,<en1>,...,<en mn>}
};
sau
static <tip> <nume> [<dim1>][<dim2>]={{<e11>,<e12>,...,<e1 m1>},
{<e21>,<e21>,...,<e2 m2>},
...
{<en1>,<en1>,...,<en mn>}
};
Numerele m1, m2,..., mn, pot fi mai mici dect <dim2> n oricare din
acoladele corespunztoare ale tabloului, de asemenea n poate fi mai mic dect
<dim1>. n aceste situaii restul elementelor tabloului vor fi iniializate cu 0. Dac n
este egal cu <dim1>, atunci <dim1> poate fi omis, dar <dim2> este obligatoriu.
ntr-o modalitate asemntoare se pot iniializa i tablouri cu mai multe
dimensiuni.
Exemplu
int a[2][3]={ {1,2,3},
{4,5,6}
};
sau
int t[][3]={1,2,3,4,5,6};
sau
static char <nume>[<dim>]=<sir de caractere>;
46
char t[4]={'a','b','c','\0'};
i cu:
char t[]="abc";
47
48
49
2) Parcurgere n spiral
Fie a o matrice cu m linii i n coloane. S se construiasc vectorul b cu m*n
elemente obinute prin parcurgerea matricei n spiral, din colul din stnga-sus
ctre dreapta, pn n centrul matricei.
#include<iostream.h>
#include<iomanip.h> //pentru setw
void citireMatrice(int a[10][10],int m, int n)
{ int i,j;
for(i=0;i<m;i++)
{ cout<<"linia "<<i<<":";
for(j=0;j<n;j++)
cin>>a[i][j];
}
}
void afisareMatrice(int a[10][10],int m,int n)
{ int i,j;
for(i=0;i<m;i++)
{ for(j=0;j<n;j++)
cout<<setw(6)<<a[i][j];
cout<<endl;
}
}
void parcurgereInSpirala(int a[10][10], int m, int n,
int b[], int mn )
{ int k,p,q,r,i,j;
k=0;
p=0; q=m-1; r=n-1; //p,q,r definesc conturul de parcurs (p,p)->(p,q)->(q,r)->(r,p-1)
while(k<m*n)
{ for(j=p;j<=r;j++)b[k++]=a[p][j]; //parcurgere stanga->dreapta
for(i=p+1;i<=q;i++)b[k++]=a[i][r]; //sus ->jos (col. din dreapta)
for(j=r-1;j>=p;j--)b[k++]=a[q][j]; // dreapta->stanga(linia de jos)
for(i=q-1;i>=p+1;i--)b[k++]=a[i][p]; // jos->sus (col din stanga)
p++;q--;r--; //urmatorul contur
}
}
void afisareVector(int b[],int n)
{ for(int i=0;i<n;i++)cout<<b[i]<<" "; }
void main()
{int a[10][10],m,n;
int b[100],mn;
cout<<"nr. linii="; cin >>m;
cout<<"nr. coloane="; cin >>n;
mn=m*n;
citireMatrice(a,m,n);
afisareMatrice(a,m,n);
parcurgereInSpirala(a, m, n, b, mn);
cout<<"Vectorul obtinut prin parcurgerea matricei in spirala:"<<endl;
afisareVector(b,mn);
}
50
51
void main()
{long a[20][20]={{1,2,3,4,5},
{1,2,3,4,5},
{1,2,3,4,5},
{1,2,3,4,5},
{1,2,3,4,5}};
cout<<sumaTrSus(a,5)<<endl;
cout<<sumaTrStanga(a,5)<<endl;
cout<<sumaTrJos(a,5)<<endl;
cout<<sumaTrDreapta(a,5)<<endl;
}
4) Cutare binar
Algoritmul de cutare binar este un algoritm de cutare folosit pentru a gsi
un element ntr-un vector ordonat. Fie a un vector ordonat cresctor i x un
element ce se caut n vectorul a. Valoarea x este comparat cu valoarea
elementului din mijlocul vectorului a. Dac cele dou valori sunt egale, algoritmul
se termin. Dac valoarea lui x este mai mic dect acea valoare, cutarea se
efectueaz, prin acelai procedeu, pentru elementele de la nceputul vectorului
pn la mijloc, iar dac este mai mare, cutarea se efectueaz de la mijlocul
vectorului pn la sfritul su. ntruct la fiecare pas cardinalul mulimii de
elemente n care se efectueaz cutarea se njumtete, algoritmul are
complexitate logaritmic.
#include<iostream.h>
#include<stdlib.h>
int caut(long a[],int n,long x)
{ int i=0,j=n-1,m;
while(i<=j)
{ m=(i+j)/2;
if(a[m]==x) return m;// x se gaseste pe pozitia m
if(x<a[m])j=m-1;
else i=m+1;
}
return -1; // x nu se gaseste in vectorul a
}
void main()
{
long a[100], x;
int n, poz;
cout<<"n=";
cin>>n;
cout<<"Tastati "<<n<<" elemente in ordine crescatoare, "
<<"separate prin spatiu:"<<endl;
cin>>a[0];
52
for(int i=1;i<n;i++)
{cin>>a[i];
if(a[i]<a[i-1])
{ cout<<"vectorul nu este ordonat crescator"<<endl;
return;
}
}
while(1)
{cout<<"Tastati valoarea lui x "
<<" (sau CTRL+Z pentru sfarsit):";
cin>>x; if(cin.eof()) break;
poz=caut(a,n,x);
if(poz>=0)
cout<<x<<" se gaseste in vectorul a pe pozitia "
<<poz<<endl;
else
cout<<x<<" nu se gaseste in vectorul a"<<endl;
}
53
54
for(i=0;i<26;i++)
{ if(a[i]!=0)printf("Litera %c apare de %d ori \n",
(char)(i+97),a[i]);
if(b[i]!=0)printf("Litera %c apare de %d ori \n",
(char)(i+65),b[i]);
}
}
55
56
void main()
{ int u[100], v[100],s[100],d[100],p[100],r[100];
dim=100;
cout<<"u=";
citire(u);
cout<<"v=";
citire(v);
suma(u,v,s);
afisare(u); cout<<"+"; afisare(v);
cout<<"="; afisare(w); cout<<endl;
if(comparare(u,v)>0)diferenta(u,v,d);
else diferenta(v,u,d);
cout<<"|";afisare(u); cout<<"-"; afisare(v);
cout<<"| ="; afisare(d); cout<<endl;
int ok=produs(u,v,p);
afisare(u); cout<<"*"; afisare(v);
cout<<"="; afisare(p);
if(!ok)cout<<"esec! dim prea mica"; cout<<endl;
long q,rest;
cout<<"q="; cin>>q;
impartire(u,q,r,rest);
afisare(u); cout<<":"; cout<<q<<"="; afisare(r);
cout<<" rest "<<rest<<endl;
}
8) Fiind date n numere ntregi a1, a2,..., an nu n mod necesar diferite, exist
totdeauna o submulime a acestei mulimi de numere, cu proprietatea c suma
elementelor sale este divizibil prin n. Urmtorul program determin o astfel de
submulime.
Soluie.
Fie s k a1 a 2 a k , k 1,, n .
Dac ()s k a.. nsk problema este rezolvat, altfel resturile sunt nenule
() k{1,2,...,n} i aparin mulimii {1,...,n-1} () dou sume
cu resturi egale. Fie sk i si, i<k, dou asemenea sume nsk-si.
Dac sk mod n = r, vom memora indicele k n variabila rest[r]. n
situaia n care n rest[r] este deja memorat un indice nu ne rmne dect s
afim soluia.
#include<iostream.h>
int a[101],rest[101],n;
void citeste()
{ cout<<"n="; cin>>n;
cout<<"Tastati "<<n<<" numere:";
int i;
57
for(i=1;i<=n;i++){ cin>>a[i];rest[i]=-1;}
rest[0]=0;
}
void solutie()
{ int s,k,i,r;
s=0;
for(k=1;k<=n;k++)
{s+=a[k];
r=s%n;
if(rest[r]==-1) rest[r]=k;
else { cout<<"Solutie:";
for(i=rest[r]+1; i<=k; i++)
cout<<a[i]<<" ";
cout<<endl;
return;
}
}
}
void main()
{ citeste();
solutie();
}
58
59
abxcy=(unsigned long)10000*a+1000*b+100*x+10*c+y;
k
n n 1
n k 1 k n i 1
1 2
k
i
i 1
#include<iostream.h>
void main()
{ long C,n,k,i;
// Citirea lui n si k:
cout<<"n="; cin>>n;
cout<<"k="; cin>>k;
// Calculul combinarilor:
C=1; i=1;
while(i<=k)
{ C*=(n-i+1)/i;
i++;
}
// Afisarea rezultatului:
cout<<"C("<<n<<","<<k<<")="<<C<<endl;
}
cu
while(i<=k)
{ C=C*(n-i+1)/i;
i++;
}
I.9. Pointeri
Pointerii se utilizeaz pentru a face referire la date prin adresele lor.
ntr-o variabil de tip pointer putem pstra adresa unei date n loc de a
memora data nsi sau putem pstra adresa unei funcii. Schimbnd adresa
memorat n pointer, putem manipula informaii din diverse locaii de memorie.
60
Aici p i q sunt pointeri ctre date de tip float, iar t este o variabil de tip
float.
Utilizarea pointerilor se face cu doi operatori unari:
& - operatorul adresa (de referentiere) - pentru aflarea adresei din memorie
a unei variabile;
* - operatorul de indirectare (de deferentiere) - care furnizeaz valoarea din
zona de memorie spre care pointeaz pointerul operand.
Dac x este o variabil atunci operatorul unar & aplicat lui x, &x, ne
furnizeaz adresa lui x. Dac dorim ca pointerul p s indice pe x, putem utiliza
atribuirea:
p=&x;
Dac p este o variabil de tip pointer atunci operatorul unar * aplicat lui p,
*p, ne furnizeaz variabila a crei adres este memorat n p.
Exemplu:
int a,*adr;
adr=&a; // acum a i *adr reprezint aceeai dat.
a=100; // este echivalent cu: *adr=100;
*adr=200; // este echivalent cu: a=200;
Exist cazuri n care dorim ca un pointer s fie utilizat cu mai multe tipuri de
date. n acest caz, la declararea lui nu dorim s precizm un tip anume. Aceasta se
realizeaz astfel:
void *<nume>;
61
Operaii cu pointeri
Asupra pointerilor se pot face urmtoarele operaii: atribuire, comparare,
adunare, scdere, incrementare, decrementare.
Adunarea i scderea unui ntreg dintr-un pointer.
Dac p este un pointer avnd declaraia:
<tip> *p;
62
63
Fie declaraia
int t[5];
Deoarece t[0] este o variabil simpl, adresa sa este &t[0], deci vom avea:
t==&t[0].
Tablouri de pointeri
Datele de tip pointer pot fi organizate n tablouri la fel ca i alte tipuri de
date. Pentru a descrie un tablou de pointeri se folosete o construcie de forma:
<tip> *<nume>[<dim>];
64
65
{ while(*dest++=*sursa++); }
#include<iostream.h>
void main()
{ char a[25],b[25];
cout<<"Sirul a="; cin>>a;
copiaza(a,b);
cout<<"Sirul a are "<<lungime(a)<<" caractere."<<endl;
cout<<"Sirul b este "<<b<<endl;
}
Observaii:
-Incrementarea unui pointer este mai rapid dect indexarea unui tablou.
-Biblioteca <string.h> conine funcii pentru determinarea lungimii unui ir
de caractere,
pentru compararea, localizarea i copierea irurilor, pentru
transformarea caracterelor n majuscule sau minuscule(strlen, strcmp, strchr, strstr,
strcpy, strcat, strupr, strlwr etc.).
66
n varianta 1. operatorul new aloc, dac este posibil, spaiul necesar tipului
<tip>, i returneaz adresa zonei de memorie alocate.
n varianta 2. variabila dinamic creat cu new se iniializeaz cu valoarea
expresiei <expresie>.
Varianta 3. se folosete pentru alocarea a <dim> variabile dinamice de tipul
<tip> (un tablou liniar cu <dim> elemente). Iniializarea tablourilor nu este
posibil.
Exemple:
int *p, *q,*r;
p=new int;
// se aloc memorie pentru un ntreg
q=new int(7); // se aloc memorie pentru un ntreg i se iniializeaz variabila cu 7
r=new long[10]; // se aloc un tablou de 10 ntregi
Exemple:
delete p;
delete r;
Prezentm mai jos trei variante de utilizare a unui vector alocat dinamic:
1.
#include <iostream.h>
void main()
67
{ int *a,n;
cout<<"n=";
cin>>n;
a=new int[n]; // alocare vector
for(int i=0;i<n; i++)
{ cout<<"a"<<i<<"="; cin>>*(a+i);}
cout<<"a=(";
for(i=0;i<n; i++)
cout<<*(a+i)<<",";
cout<<"\b)"<<endl;
delete a;
}
2.
#include <iostream.h>
void main()
{ int *a,n;
cout<<"n=";
cin>>n;
a=new int[n]; // alocare vector
for(int i=0;i<n; i++)
{cout<<"a"<<i<<"="; cin>>a[i];}
cout<<"a=(";
for(i=0;i<n; i++)
cout<<a[i]<<",";
cout<<"\b)"<<endl;
delete a;
}
3.
#include <iostream.h>
void main()
{ int *a, n;
cout<<"n="; cin>>n;
a=new int[n]-1; // astfel, elementele vectorului sunt a[1], a[2], ..., a[n]
for(int i=1;i<=n; i++) { cout<<"a"<<i<<"="; cin>>a[i]; }
cout<<"a=(";
for( i=1;i<=n; i++) cout<<a[i]<<",";
cout<<"\b)"<<endl;
a++; // revenire la adresa returnat de new
delete a;
}
68
Dac avem tipul de dat T, prin T& sau T & (cu spaiu dup T) sau T & (cu
spaiu dup T i dup &) vom nelege o referin (o trimitere) la un obiect de tipul
T.
Exemplu:
int x=10;
int& r=x; // r i x refer acum acelai obiect
r=20; // echivalent cu x=20;
x=30;
// echivalent cu r=30;
Variabila r de mai sus, este o referin la variabila x de tip int. Acest lucru
nseamn c identificatorii r i x permit accesul la aceeai zon de memorie. Prin
urmare, x i r sunt sinonime. Iniializarea unei referine (trimiteri) n declaraia sa
este obligatorie (dac nu este folosit ca argument al unei funcii), dar aceast
iniializare nu trebuie confundat cu atribuirea; ea definete pur i simplu un alt
nume (un alias) al obiectului cu care a fost iniializat. n exemplul de mai sus r
este un nou nume pentru x. O referin nu mai poate fi modificat dup iniializare.
Ea refer ntotdeauna acelai obiect stabilit prin iniializare s-l desemneze. Pentru
a obine un pointer la obiectul desemnat de referina r, se poate folosi &r.
Referinele sunt utile i cnd sunt folosite ca argumente pentru funcii.
Exemplu:
#include<iostream.h>
void interschimba(int& a,int& b)
{int aux=a; a=b; b=c; }
void main()
{ int x=10,y=20;
interschimba (x,y);
cout<<"x="<<x<<"y="<<y;
}
69
int& g()
{ int& x= *new int; //Am dat un nume variabilei anonime *new int
...
return x;
}
Funcia g() ntoarce variabila de tipul int alocat dinamic.
70
{ semafor =0;
for(j=0;j<n;j++)
if(a[i]==b[j]) { semafor =1;break;}
if(semafor ==0)c[p++]=a[i];
}
}
void main()
{ int u[100],v[100],w[100];
int n1,n2,n3;
cout<<"Multimea U:"<<endl;
citire(u,n1);
cout<<"Multimea V:"<<endl;
citire(v,n2);
int op;
do
{ clrscr();
cout<<"U=";afisare(u,n1);cout<<endl;
cout<<"V=";afisare(v,n2);cout<<endl;
cout<<"1 - intersectie"<<endl;
cout<<"2 - reuniune"<<endl;
cout<<"3 - diferenta"<<endl;
cout<<"4 - STOP"<<endl;
cout<<"Tastati optiunea:";
cin>>op;
switch(op)
{ case 1:intersectie(u,n1,v,n2,w,n3);
cout<<"U intersectat cu V=";
afisare(w,n3); cout<<endl;
break;
case 2:reuniune(u,n1,v,n2,w,n3);
cout<<"U reunit cu V=";
afisare(w,n3);cout<<endl;
break;
case 3:diferenta(u,n1,v,n2,w,n3);
cout<<"U-V="; afisare(w,n3); cout<<endl;
break;
}
getch();
}
while(op!=4);
}
71
Putem optimiza algoritmul astfel: dac a=bq+r , 0r<b scdem din relaia (1)
relaia (2) multiplicat cu q.
long euclid1(long a,long b,long &m, long &n)
{ long m1=1,n1=0,u,v;
m=0; n=1;
long q=a/b, r=a%b;
while(r)
{ u=m1,v=n1; m1=m,n1=n;
m=u-q*m; n=v-q*n;
a=b; b=r; q=a/b; r=a%b;
}
return b;
}
In limbajul C, a%b r (b, b) , de exemplu pentru a=-65, b=10 avem
72
73
74
75
}
}
void main()
{ clrscr();
long n=1000000;
PAPC(n,5);
cout<<"in intervalul [2, "<<n<<"] exista:"<<endl;
for(int i=0;i<10;i++)
if(nr[i]>0)
cout<<nr[i]<<" progresii formate din "
<<i+3<<" termeni nr. prime consecutive"<<endl;
}
76
void main()
{ int **a,n=4;
alocare(a,n);
cit(a,n);
scr(a,n);
dezalocare(a,n);
}
77
De exemplu:
const char *p ="abcd"; // p este un pointer la o constant
p[3]='a';
// eroare !
p="efgh";
// p indic spre alt obiect
78
n acest exemplu CULOARE este o variabil de tip asumat int, deci putem
scrie:
CULOARE=rosu;
sau
CULOARE=6;
sau
CULOARE=100;
Exemple:
79
sau
int f1(float,double);
2. void f2(int a[],int b[]);
sau
void f2(int [],int []);
3. long f3(int x[4][4]);
sau
long f3(int [][]);
4.
#include <iostream.h>
void f(int [][]);
void main()
{ int a[][2]={0,1,0,2};
f(a);
}
void f(int x[][2])
{ cout<<x[1][1]; }
Exemple:
1.
Declaraia:
natural a;
Declaraia:
ptrchr s="abc",t="zxc";
3.
80
Declaraia:
vector y={1,2,3,4};
Declaraia:
matr x={{1,1},{1,2}};
Exemplu:
int (*adrF)();
sau
adrF=&f();
deoarece f() reprezint valoarea returnat de funcia f() iar &f() este adresa
rezultatului furnizat de funcie, dac acest rezultat este o referin. Apelarea
funciei a crei adres este memorat ntr-o variabil pointer se poate face, pentru
exemplul de mai sus, n una din variantele:
a)
b)
adrF()
(*adrF)()
81
82
83
Exemplu:
struct complex{float re,im;} c1,c2,c3[10];
84
Exemplu:
complex z1,z2,*p;
Fie declaraia:
complex x,y,*p;
Cmpurile componente ale unui date structurate pot fi referite n dou feluri:
direct, prin numele structurii urmat de "." i de numele cmpului
Exemple:
x.re, x.im, y.re, y.im
indirect, prin adresa structurii urmat de > i de numele cmpului
Exemple:
p>re, p>im
85
86
int n =cit(P);
float S=arie(P,n);
punct C=centruGr(P,n);
cout<<setprecision(4);
cout<<"Aria poligonului="<<S<<endl;
cout<<"Centru de greutate este C("<<C.x<<","
<<C.y<<")"<<endl;
}
87
Datele din variabila x vor fi privite ca ntregi dac selectm x.i sau reale
dac selectm x.t.
Cmpurile i i t se refer la aceeai adres:
n x.i se memoreaz sizeof(int) octei la aceast adres;
n x.t se memoreaz sizeof(float) octei care ncep la aceast adres.
88
1 dac n 0,
fact(n)
n fact(n 1) dac n 1
#include <stdio.h>
int fact(int n)
{ if(n==0) return 1;
return n*fact(n-1);
}
89
void main()
{ int n;
clrscr();
printf (n = ) ; scanf (%d, &n) ;
printf ( %d!=%d,n, fact(n));
}
Apelul lui fact(4) declaneaz un lan de apeluri ale lui fact pentru 3, 2, 1,0
dup care urmeaz revenirea din apeluri i evaluarea lui fact pentru 0,1,2,3,4.
fact(4)
4 fact(3)
3 fact(2)
2 fact(1)
1 fact(0)
1
Stiva
Vida
Apel
fact(4)
Apel
fact(3)
Apel
fact(2)
Apel
fact(1)
Apel
fact(0)
Pentru fiecare din aceste apeluri, n stiv se vor depune parametrii actuali:
4,3,2,1,0. Strile stivei dup ieirea din autoapel sunt urmatoarele:
0
1
90
fact(0)
=
1
fact(1)
=
1*1
fact(2)
=
1*1*2
fact(3)
=1*1*
2*3
fact(4)
=1*1*
2*3*4
Stiva
vida
fib : N N ,
1, n 0 sau n 1,
fib(n)
fib(n 1) fib(n 2), n 2
Error! Reference source not found.
long fib(int n)
{ if (n==0||n==1) return 1;
return fib(n-1) + fib(n- 2);
}
Varianta iterativa:
long fib(int n)
{ long f1=1,f2=1,f;
if(n==0||n==1)return 1;
for(k=2;k<=n;k++)
{ f=f2+f1; f1=f2; f2=f; }
return f;
}
dac m 0
n 1,
91
5) Calculul determinanilor
Programul urmtor calculeaz valoarea determinantului unei matrice
ptratic de ordinul n,
92
a 00
a10
a 01
a11
a n 1 0
a n 1 1
det( A)
... a 0 n 1
... a1n 1
,
....
... a n 1 n 1
a 00 a11 a 01 a10 ,
n2
det( A)
n 1 (1) j a M , n 2
0j
0j
j 0
unde M 0 j este minorul lui a0 j (determinantul obinut din cel iniial, prin
suprimarea liniei 0, coloana j).
Dac det(A)0 putem calcula inversa matricei A dup formula
A 1
1
A* ,
det( A)
93
A.
m[ii][jj] = A[i][j];
ii++;
}
jj++;
}
return m;
}
float det(float **A, int n)
{ int i, j, p,k;
float d;
if (n==1)return A[0][0];
if (n == 2) return A[0][0]*A[1][1] - A[1][0]*A[0][1];
//altfel, dezvoltare dupa linia 0
d = 0;
for (p = 0 ; p < n ; p++)
{ float **m=minor(A,n,0,p);
d += pow(-1.0, p) * A[0][p] * det(m, n-1);
dezalocare(m,n-1);
}
return d;
}
float ** adjuncta(float **A,int n)
{ float **B=alocare(n);
float **m;
int i,j,l,k;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{ m=minor(A,n,i,j);
B[j][i]=pow(-1,i+j)*det(m,n-1);
}
return B;
}
void afisare(float **A,int n)
// afisarea matricei patratice de ordin n
{ int i,j;
for(i=0;i<n;i++)
{for(j=0;j<n;j++)
cout<<setw(8)<<A[i][j]<<" ";
cout<<endl;
}
}
void main()
{ float A[4][4]={{2,1,-1,3},
{1,-1,2,2},
{4,-2,3,1},
{-2,2,1,-1}};
94
float **m=alocare(4);
clrscr();
//copierea matricei A in zona alocata dinamic
for(int i=0;i<4;i++)
{ for(int j=0;j<4;j++) m[i][j]=A[i][j];}
cout<< "d="<<det(m,4)<<endl;
float **b=adjuncta(m,4);
cout<<"Adjuncta lu A:"<<endl;
afisare(b,4);
}
95
return 1+fig(i-1,j-1)+fig(i-1,j)+fig(i-1,j+1)+
fig(i,j-1)+fig(i,j+1)+
fig(i+1,j-1)+fig(i+1,j)+fig(i+1,j+1);
}
return 0;
}
int figNR(int i,int j)
{int *x=new int[n], *y=new int[n], k=0, nr=0;
x[k]=i; y[k]=j; a[i][j]=-1;
while(k>=0)
{i=x[k]; j=y[k];
k--; nr++;
if(a[i-1][j-1]==1)
{ k++; x[k]=i-1; y[k]=j-1; a[i-1][j-1]=-1;};
if(a[i-1][j]==1)
{ k++; x[k]=i-1; y[k]=j; a[i-1][j]=-1; };
if(a[i-1][j+1]==1)
{ k++; x[k]=i-1; y[k]=j+1; a[i-1][j+1]=-1;};
if(a[i][j-1]==1)
{ k++; x[k]=i; y[k]=j-1; a[i][j-1]=-1; };
if(a[i][j+1]==1)
{ k++; x[k]=i; y[k]=j+1; a[i][j+1]=-1; };
if(a[i+1][j-1]==1)
{ k++; x[k]=i+1; y[k]=j-1; a[i+1][j-1]=-1;};
if(a[i+1][j]==1)
{ k++; x[k]=i+1; y[k]=j; a[i+1][j]=-1; };
if(a[i+1][j+1]==1)
{ k++; x[k]=i+1; y[k]=j+1; a[i+1][j+1]=-1;};
}
delete x; delete y;
return nr;
}
void generare()
{ int i,j,k,m;
randomize();
m=1+random(n*n);
for(k=1;k<=m;k++)
{ i=1+random(n);
j=1+random(n);
a[i][j]=1;
}
}
void afisare()
{ int i,j;
for(i=1;i<=n;i++)
{ for(j=1;j<=n;j++) cout<<' '<<a[i][j];
cout<<endl;
}
}
void main()
{ int i,j,k=0;
96
generare();
afisare();
cout<<" rezolvare utilizind varianta recursiva"<<endl;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if (a[i][j]==1)
{ k++;
cout<<"fig "<<k<<" = "<<fig(i,j)<<" patrate"<<endl;
}
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
a[i][j]=-a[i][j];
cout<<"rezolvare utilizind varianta nerecursiva"<<endl;
k=0;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if (a[i][j]==1)
{ k++;
cout<<"fig "<<k<<" = "<<figNR(i,j)<<" patrate"
<<endl;
}
}
97
Inserare
tergere
// alocare
98
q=p;
q=new nod;
q->inf=p->inf; /* copiaz informaia din celula indicat de p n celula indicat de
q. */
*q=*p; // copiaz coninutul celulei pointate de p n celula pointat de q.
p->leg=q; /* face ca n partea de legtur a variabilei desemnate de p
s se treac adresa variabilei desemnate de q. */
q->leg=0;
99
#include<iostream.h>
#include<conio.h>
struct nod
{int inf;
nod *leg;
};
int inserare(nod *&cap,int x)
{
nod *p=cap;
cap=new nod; // variabila cap va fi nenul daca alocarea s-a fcut cu succes
if (!cap) return 0;// spatiu insuficient
cap->inf=x;
cap->leg=p;
return 1;
}
void extragere(nod *&cap,int &x)
{
nod *p=cap;
x=cap->inf;
cap=cap->leg;
delete p;
}
void listare(nod *cap)
{ while (cap){ cout<<cap->inf<<" "; cap=cap->leg;} }
int virf(nod *cap){ return cap->inf; }
void stergere(nod *&cap)
{ nod *p;
while(cap)
{ p=cap;
cap=cap->leg;
delete p;
}
}
void main()
{nod *s=0; // Stiva vida
int op,x;
do
{cout<<"1 -Inserare"<<endl;
cout<<"2 -Extragere"<<endl;
cout<<"3 -Listare"<<endl;
cout<<"4 -Virf"<<endl;
cout<<"5 -Stergere"<<endl;
cout<<"9 -Stop"<<endl;
cout<<"Tastati optiunea: ";
cin>>op;
100
switch(op)
{case 1:cout<<"x=";cin>>x;inserare(s,x);
break;
case 2:if (s==0) cout<<"stiva vida"<<endl;
else {extragere(s,x);
cout<<"Am extras elementul "<<x<<endl;
}
break;
case 3:cout<<"Continut stiva: ";
listare(s);
cout<<endl;
break;
case 4:if (s==0) cout<<"Stiva vida"<<endl;
else cout<<"Virf ="<<virf(s)<<endl;
break;
case 5:stergere(s);
}
}
while(op!=9);
}
I.23.2. Coada
Prin coad nelegem o list n care introducerile se fac la un capt al listei,
numit baza cozii, iar extragerile se fac la cellalt capt al listei numit vrful cozii.
Alocarea nlnuit a cozilor presupune cunoaterea adresei primului
element al cozii (vrful cozii) i a adresei ultimului element al cozii (baza cozii).
n alocarea nlnuit, legturile merg ca mai jos:
Error! Reference source not found.
Urmtorul program implementeaz funcii de lucru cu o list de tip coad:
Structura nod cuprinde cmpurile unei celule: inf partea de informaie i
leg partea de legtur.
Funcia int inserare(nod *&prim, nod *&ultim, int x);
realizeaz inserarea elementului x n coad. Dac nu este spaiu suficient funcia va
returna 0 desemnnd eecul operaiei de inserare, altfel va returna 1 - inserare cu
succes.
Funcia void extragere(nod *&prim, int &x); extrage
elementul din vrful cozii.
Funcia void listare(nod *prim); afieaz elementele cozii.
#include<iostream.h>
#include<conio.h>
struct nod
{int inf;
nod *leg;
};
int inserare(nod *&prim,nod *&ultim,int x)
101
{ if (prim==0)prim=ultim=new nod;
else ultim=ultim->leg=new nod;
if(!ultim) return 0; //esec la alocare
ultim->inf=x; ultim->leg=0;
return 1; // inserare cu succes;
}
void extragere(nod *&prim,int &x)
{ nod *p=prim;
x=prim->inf; prim=prim->leg;
delete p;
}
void listare(nod *prim)
{ while(prim)
{cout<<prim->inf<<" "; prim=prim->leg; }
}
int virf(nod *prim){ return prim->inf; }
void stergere(nod *&prim)
{ nod *p;
while(prim)
{ p=prim;
prim=prim->leg;
delete p;
}
}
void main()
{ nod *prim=0,*ultim;// coada vida
int op,x;
do
{ cout<<"1 -Adaugare"<<endl;
cout<<"2 -Extragere"<<endl;
cout<<"3 -Listare"<<endl;
cout<<"4 -Virf"<<endl;
cout<<"5 -Stergere"<<endl;
cout<<"9 -Stop"<<endl;
cout<<"Tastati optiunea: ";
cin>>op;
switch(op)
{ case 1:cout<<"x=";cin>>x;
inserare(prim,ultim,x);
break;
case 2:if (prim==0) cout<<"coada vida"<<endl;
else { extragere(prim,x);
cout<<"Am extras elementul "<<x<<endl;
}
break;
case 3:cout<<" Coada este:";
listare(prim); cout<<endl;
break;
case 4:if (prim==0) cout<<"Coada vida"<<endl;
102
I.24. Arbori
Prin arbore nelegem o mulime finit de elemente, numite noduri
A={A1, A2, ... , An}, n>0 care are urmtoarele proprieti:
exist un nod i numai unul numit rdcina arborelui;
celelalte noduri (dac mai exist) sunt submulimi disjuncte ale lui A, care
formeaz fiecare cte un arbore. Arborii respectivi se numesc subarbori ai
rdcinii. ntr-un arbore exist noduri crora nu le mai corespund arbori. Un astfel
de nod se numete nod terminal sau frunz. Un nod rdcin este numit nod tat,
rdcina unui arbore al su este numit nod fiu iar subarborii sunt descendenii lui.
O alt noiune este aceea de nivel. Rdcina arborelui are nivelul 1.
Dac un nod are nivelul n, atunci fiii lui au nivelul n+1.
Dac subarborii unui nod se consider ntr-o anumit ordine, subarborele se
numete ordonat.
103
#include<iostream.h>
struct nodArb
{ int inf;
nodArb *ls,*ld;
};
void creArb(nodArb *& p)
{ int x;
cout<<"inf nod(sau punct ptr. sf. ramura):";
if(cin>>x)
{ p=new nodArb;
p->inf=x;
p->ls=0;
p->ld=0;
cout<<" nod stanga:";
creArb(p->ls);
cout<<" nod dreapta:";
creArb(p->ld);
}
else
{cin.clear();cin.ignore(80,'\n');}
}
void prelNod(int x)
{ cout<<x<<" "; }
104
105
cout<<endl;
106
nodA* *leg;
};
struct nod
{ nodA * inf;
nod *leg;
};
void inS(nod *&cap,nodA *x ) // inserare n stiv
{ nod *p=cap;
cap=new nod;
if (!cap) {cout<<"Spatiu insuficient" ;return;};
cap->inf=x;
cap->leg=p;
}
void outS(nod *&cap,nodA * &x) //extragere din stiv
{ nod *p=cap;
x=cap->inf;
cap=cap->leg;
delete p;
}
void inC(nod *&prim,nod *&ultim,nodA* x) // inserare n coad
{ if (prim==0)prim=ultim=new nod;
else ultim=ultim->leg=new nod;
ultim->inf=x;
ultim->leg=0;
}
void outC(nod *&prim,nodA* &x) //extragere din coad
{ nod *p=prim;
x=prim->inf;
prim=prim->leg;
delete p;
}
void prelNod(int x){cout<<x<<" ";}
void creArb(nodA * &rad)
{ nod *S=0; //pointer la stiv
int n;
int inf,nrfii;
nodA *p;
cout<<"Nr.total de noduri:"; cin>>n;
cout<<"Nodurile se vor introduce in postordine"<<endl;
for(int i=1;i<=n;i++)
{ cout<<"inf. nod "<<i<<":";
cin>>inf;
cout<<"nr.fii"; cin>>nrfii;
p=new nodA;
p->inf=inf;
p->nrfii=nrfii;
if(nrfii>0) p->leg=new nodA*[nrfii];
for(int k=nrfii;k>=1;k--)
if(S) outS(S,p->leg[k-1]);
107
108
0x02
ios::ate
ios::app
0x04
0x08
ios::trunc
0x10
ios::nocreate
0x20
ios::noreplace 0x40
ios::binary
0x80
Observaie. Pentru activarea mai multor bii se poate folosi operatorul "sau"
binar (|).
Argumentul modProtectie poate lua urmtoarele valori:
0 fiier normal, fr restricii de acces (valoare implicit);
1 fiier de tip "read-only";
109
2 fiier ascuns;
4 fiier de tip sistem;
8 bit de arhivare activ.
Se pot specifica mai multe dintre atribute folosind operatorul "sau" binar (|).
Exemple:
ifstream f;
f.open("f1.dat");
ofstream g;
g.open("f2.dat");
fstream h;
h.open("f3.dat",ios::in|ios::out);
/* pentru a deschide un fiier fstream", pentru operaii de intrare/ieire
trebuie s specificm att ios::in ct i ios::out. */
110
111
I.25.1. Aplicaii
1) Urmtorul program conine funcii pentru crearea i exploatarea unui
fiier text.
#include<fstream.h>
#include<iomanip.h>
struct punct { float x,y;};
void creareFisier()
{ ofstream f("punct.dat");
punct P; int i=1;
cout<<"P"<<i<<"(x y):";
while(cin>>P.x>>P.y) /* citire pn la introducerea unui caracter invalid
pentru tipul numeric */
{ f<<P.x<<" "<<P.y<<endl; // scriere n fiier
i++;
cout<<"P"<<i<<"(x y):";
}
cin.clear(); // Anularea indicatorului de eroare
cin.ignore(80,'\n');
f.close();
}
void citireFisier(punct P[],int &n)
{ ifstream f("punct.dat");
for(n=0; ;n++)
{ f>>P[n].x>>P[n].y;
if(f.eof())break;
}
f.close();
}
void afisareVector(float P[],int n)
{for(int i=0; i<n; i++)
cout<<P<<i<<(<<P[i].x<<","<<P[I].y<<) ;
cout<<endl;
112
}
void main()
{ punct P[100];int n;
creareFisier();
citireFisier(P,n);
afisareVector(P,n);
}
113
{ofstream f(denFis,ios::out|ios::binary);
f.close();
actFis(denFis);
}
void list(char *denFis) //Listare fiier
{ ifstream f(denFis,ios::in|ios::binary);
inregistrare art;
while (1)
{ f.read( (unsigned char*)&art,sizeof(art));
if(f.eof())break;
afis(art); cout<<endl;
}
f.close();
}
void sit(char *denFis)
{ ifstream f(denFis,ios::in|ios::binary);
inregistrare art;
clrscr();
float v=0,tvl=0,tvg=0;
f.read( (unsigned char*)&art,sizeof(art));
if(f.eof()){cout<<" fisier vid "; return;}
int luna=art.ll;
cout<<" SITUATIA APROVIZIONARII "<<endl;
cout<<setprecision(2)<<setiosflags(ios::fixed);
while (! f.eof())
{ if (luna!=art.ll )
{ cout<<"Total luna "
<<setw(2)<<luna<<setw(44)<<tvl<<endl;
tvg+=tvl;
tvl=0;
luna=art.ll;
}
v=art.cant * art.pret;
afis(art);
cout<<setw(10)<<v<<endl;
tvl+=v;
f.read( (unsigned char*)&art,sizeof(art));
}
cout<<"Total luna "<<setw(2)<<luna
<<setw(44)<<tvl<<endl;
tvg+=tvl;
cout<<"Total general"<<setw(44)<<tvg<<endl;
f.close();
}
void main()
{int op;
do
{ cout<<" 1- creare"<<endl;
cout<<" 2- listare"<<endl;
114
cout<<" 3- sit"<<endl;
cout<<" 4- act"<<endl;
cout<<" 9- stop"<<endl;
cout<<"tastati optiunea:"; cin>>op;
switch (op)
{ case 1: creFis("fisier.dat");
break;
case 2: list("fisier.dat");
break;
case 3: sit("fisier.dat");
break;
case 4: actFis("fisier.dat");
break;
}
}
while (op!=9);
}
115