Documente Academic
Documente Profesional
Documente Cultură
C
Versiunea 2.0
Manual de utilizare
CONCEPTUL DE FUNCIE
Un program C se compune din una sau mai multe funcii. Funcia este o
unitate lexical de program compilabil independent.
Una dintre funcii este funcie principal, numele ei este predefinit
i anume main.
Execuia programului ncepe cu prima instruciune din funcia
principal.
Dm n continuare 2 exemple de structuri de program (fiiere surs):
[directive de preprocesare]
[directive de preprocesare]
PASCAL C
...
gasita
2) double radical_n (double x, int n)
valoare
{ if (i < 0)
if (i = = 0)
else
}
return i;
return 0;
return i;
\t
S mai precizm c urmtoarele 3 caractere: spaiu,
tabulator orizontal se mai numesc spaii albe (white spaces).
newline
1.3.2. Nume
n limbajul C, un nume este o succesiune de litere i eventual
cifre, care ncepe cu o liter. Ca lungime un nume poate fi orict de lung
dar numai primele 32 de caractere se iau n considerare. Folosind notaia
BNF (vezi anexa) un nume se poate defini recursiv, ca mai jos:
<nume> ::= <litera> | <nume><litera> | <nume><cifra>
<litera> ::= A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Z|
a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|z|_
<cifra> ::= 0|1|2|3|4|5|6|7|8|9|
Numele se folosesc pentru denumirea variabilelor, tablourilor,
funciilor, etc.
Exemple:
A, _start, a_, matrice, matrice_patratica.
Dm i cteva contraxemple:
&B - conine caracterul &;
x+y - conine caracterul +;
1.3.3. Cuvinte cheie
Un cuvnt cheie este un cuvnt mprumutat din limba englez,
care are un neles predefinit. Aceste cuvinte se scriu cu litere mici. Un
cuvnt cheie nu poate avea alt utilizare ntr-un program C dect cea care
i-a fost predefinit. Fiind o succesiune de litere, un cuvnt cheie este un
nume. Lista cuvintelor cheie se d n anexa de la sfritul crii. Sensul
fiecrui cuvnt cheie va rezulta la definirea construciei n care se
utilizeaz.
Exemple:
for, do, if, while, else, break, return, int, long, double,
static, extern.
1.3.4. Tipuri de baz
n limbajul C distingem cteva tipuri predefinte de date care se mai
numesc tipuri de baz. n general un tip de dat are trei atribute bine
conturate:
mulimea valorilor;
reprezentarea (intern i extern)
comportamentul (adic operaiile ce se pot face cu acel tip).
n tabelul de mai jos dm cuvntul cheie, mulimea valorilor,
reprezentarea intern.
Cuvnt cheie Mulimea valorilor
Reprezentarea intern
Lungime (bii)
Formatul intern
int
16
reprezentare
short
16
reprezentare
binar
binar
long ntregii din [-231; 231 - 1]
unsigned
ntregii din [0; 216-1]
char
float
[-3.4*10-38; 3.4*1038]
simpl precizie
double
[-1.7*10-308; 1.7*10308]
dubl precizie
32
reprezentare binar
16
reprezentare binar
cod ASCII
32
virgul
flotant
64
virgul
flotant
octale
(cifre
16 bii
16 bii
32 bii
16 bii (o cifr
bii (o cifr pe 4
Constant flotant
O constant flotant este un numr raional care se compune din
urmtoarele elemente:
un semn (+ sau -) care poate lipsi pentru numerele pozitive;
o parte ntreag care poate fi i vid;
o parte fracionar care poate fi i vid;
un exponent care poate fi i vid.
Prezena prii fracionare este suficient pentru ca numrul
respectiv s reprezinte o constant flotant. Absena prii fracionare
implic prezena prii ntregi i a exponentului.
Partea ntreag reprezint o succesiune de cifre zecimale.
Partea fracionar se compune din caracterul punct urmat de o succesiune de
cifre zecimale, care poate fi i vid. Exponentul se compune din litera e
sau E urmat de un + sau -, opional, i un ir de cifre zecimale.
Constantele flotante se pstreaz n format flotant dubl
precizie.
Exemple:
3.14; 0.314e1; 3.1415926; 2.71828; 2.; 271828E-5.
Constant 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:
Constant caracter valoare cod ASCII
A
B
a
0
9
*
65
66
97
48
58
77
\b
\r
\n
\
\\
\v
\f
\0
8
13
10
39
92
11
12
0
Constant 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.
Exemple:
123; Limbajul C; sir de caractere; sir\; (irul vid).
Constanta
ir
de
caractere
se
reprezint
n
memoria
calculatorului printr-o succesiune de octei n care se pstreaz codurile
ASCII ale caracterelor irului, iar ultimul octet conine caracterul NUL
care marcheaz sfritul irului de caractere.
Dup cum se observ din exemplele date putem s folosim i convenia
cu backslash.
De reinut c X i X reprezint construcii diferite.
1.3.6. Variabile simple
Prin variabil nelegem o dat a crei valoare se poate schimba n
timpul execuiei programului care o conine. Unei variabile i se ataeaz
un nume prin intermediul cruia o putem referi sau modifica. Totodat
valorile pe care le poate lua o variabil trebuie s aparin aceluiai
tip. Corespondena dintre numele i tipul unei variabile se realizeaz
printr-o construcie special numit declaraie.
Dup modul de grupare datele sunt:
date izolate denumite i variabile simple;
date grupate:
- mulimi ordonate de date de acelai tip la care ne referim cu
indici,
- structuri n care date de tipuri diferite se grupeaz.
Declaraia de variabil simpl are formatul general:
tip list_de_nume;
unde list_de_nume este format fie dintr-un singur nume fie din mai
multe, separate prin virgule.
n limbajul
utilizate.
Exemple:
int a,b,c;
float x,y,z;
bii;
char car;
long i,j,k;
Tablouri
Un tablou ca orice variabil simpl trebuie declarat nainte de a fi
utilizat. Dac referirea la elementele tabloului se face cu un singur
indice se spune c tabloul este unidimensional (se mai numete vector);
dac
referirea
se
face
cu
doi
indici
tabloul
se
numete
bidimensional(matrice); iar cu n indici tabloul este n-dimensional.
Declaraia unui tablou n forma cea mai simpl este:
tip nume[l1][l2]...[ln];
unde:
l1, l2, ... ln sunt expresii constante care au valori ntregi ce
pot fi evaluate de compilator la ntlnirea lor.
Evident c se pot declara mai multe tablouri deodat i atunci numele
de tablouri se pot nirui ntr-o list, fiecare separat prin virgul.
Exemple:
int t[5];
float a[5][3];
Comentariu
simbolice
#define PROCENT 10
...
#define PROCENT 15
...
#undef PROCENT
...
#define DIM 100
// s-au definit doua constante simbolice DIM
#define DOI_PI (2*3.1415926)
// si DOI_PI
...
int vector[DIM];
// DIM va fi inlocuit cu 100
...
x=DOI_PI;
...
LECIA 2.
CLASE DE VARIABILE (DE MEMORIE)
Compilatorul C aloc memorie variabilelor din program de
dimensiune corespunztoare tipului fiecreia.
Memoria se aloc n 2 moduri:
static, repartizat ntr-o zon special asociat programului;
dinamic, repartizat ntr-o zon special numit stiv (se comport
ca o list LIFO).
n funcie de modul cum se aloc memorie, vom distinge mai multe
clase de variabile.
O prim clas de variabile este aceea a variabilelor globale crora
li se aloc memorie pe toat durata execuiei programului i ele pot fi
utilizate n orice funcie a programului. Alt clas de variabile este
clasa variabilelor locale, aceste variabile au o utilizare local la
nivelul unei funcii.
2.1. VARIABILE GLOBALE
O variabil global are o definiie i attea declaraii de
variabil extern cte sunt necesare.
Definiia unei variabile globale coincide sintactic cu o
declaraie obinuit, dar care este scris n afara oricrei funcii a
programului (fiierului surs). Implicit, definiia unei variabile globale
determin ca variabila respectiv s fie definit ncepnd din punctul
scrierii ei i pn la sfritul fiierului surs respectiv. De aceea se
f2
i
care intr n
f din fiierul
static unsigned t;
// definitia variabilei statice t, locala fisierului fisier2.c
void f1(...)
{ extern int i;
// declaratie externa pentru i
extern double d;
// declaratie externa pentru d
static int k;
// definitia variabilei statice k, locala functiei f1
/* in acest moment se pot folosi varibilele i,d, k si t */
...
}
void f2(...)
{ extern int i;
// declaratie externa pentru i
static double s;
// definitia variabilei statice s, locala functiei f2
/* se pot folosi variabilele i, s si t */
...
}
Variabila static x definit n fiierul fisier1.c nu poate fi
utilizat n fiierul fisier2.c. De asemenea, variabila static t nu poate
fi utilizat n fiierul fisier1.c. Variabila global d nu poate fi
utilizat n funcia f2, ea nefiind declarat ca i extern.
Observaii:
1o. Variabilele globale constituie un mijloc simplu de interfa
ntre funciile unui program. Se recomand a fi folosite cnd dorim
transferuri de valori ntre dou sau mai multe funcii n aa fel nct
modificrile realizate de o funcie s fie accesibile pentru toate
funciile programului. Nu trebuie s se fac abuz n utilizarea
variabilelor globale deoarece constituie i o surs potenial de erori,
pentru c accesul unui mare numr de funcii la anumite date globale
conduce deseori la modificri nedorite i greu evideniabile.
2o. Funciile sunt considerate cu atributul implicit extern. Dac
ntr-un program exist mai multe fiiere surs atunci o funcie poate fi
apelat oriunde, bine neles respectnd convenia definirii ei sau a
prototipului ei nainte de a fi folosit. Putem s limitm definind
funciile cu atributul static precednd antetul funciei prin cuvntul
*(unar)
&(unar)
++
--
(tip)
= = !=
&
^
|
&&
| |
? : (ternar)
= op= op poate fi: *(binar) / % +(binar) (binar) <<
>> & ^ |
,
3.3.1. Operatori aritmetici
Lista operatorilor aritmetici este redat mai jos:
- (minus unar);
+ (plus unar);
* / % operatori binari multiplicativi; (nmulire, mprire, restul
mpririi ntregi);
+ - operatori binari aditivi (adunare i scdere).
Operatorii de pe aceeai linie au aceeai prioritate. Cei unari
au prioritate mai mare dect cei binari. Operatorii multiplicativi au
prioritate mai mare dect cei aditivi.
Exemple:
int i,j,k;
float x,y;
double t[10];
// se dau cateva exemple de expresii folosind operatorii aritmetici
i*x+t[5];
-y+k;
i%j;
// daca i=9 si j=4 atunci i%j are valoarea 1
i/j;
// daca i=9 si j=4 atunci i/j are valoarea 2
x*-y;
// - este operatorul unar deci avem x*(-y)
3.3.2. Operatori relaionali
Lista operatorilor relaionali este redat astfel:
<
(mai mic)
<=
(mai mic sau egal; cele dou caractere ce compun operatorul
sunt concatenate)
>
(mai mare)
>=
(mai mare sau egal; cele dou caractere ce compun operatorul
sunt concatenate)
Toi operatorii relaionali au aceeai prioritate. Ea este mai
mic dect prioritatea operatorilor aditivi. Rezultatul aplicrii unui
operator relaional este 1 sau 0, dup cum operanzii se afl n relaia
definit de operatorul respectiv sau nu.
Exemple:
a= 4 i b= -5
atunci
a>0
are valoarea 1;
a<=0
are valoarea 0;
a+b>0
are valoarea 0;
a>=b
are valoarea 1;
a<0
are valoarea 1;
a+b>=b-a
are valoarea 1;
a+b<=(b-a)*(b-a) are valoarea 0;
3.3.3. Operatori de egalitate
Lista operatorilor de egalitate este redat mai jos:
|| 0 1 sau exclusiv 0 1
la dreapta care
lui 2; a >> 3
este
este
| 0 1 ^ 0 1
Observaii:
1o. Operanzii care nu ocup un cuvnt (16 bii) se extind la un
cuvnt. De exemplu expresia ~0 are ca rezultat un cuvnt cu toi bii egali
cu 1.
2o. Operatorii logici pe bii se execut bit cu bit spre deosebire de
operatorii logici care se evalueaz global. De exemplu dac x=2 i y=1 sunt
variabile de tip int atunci:
x&&y
are valoarea 1 pentru c ambii operanzi sunt
diferii de 0.
x&y are valoarea 0 conform schemei de mai jos
0000 0000 0000 0010
0000 0000 0000 0001
&
0000 0000 0000 0000
3o. Operatorul & se folosete frecvent pentru a anula bii din
configuraia unui cuvnt, iar operatorul | pentru a seta (pune) bii ntrun anumit mod;
4o. Operanzii trebuie s fie ntregi (de tipul int sau long).
5o. Atenie la deplasri nu se modific valoarea operandului; deci
trebuie s facem o atribuire; de exemplu a = a << 3 va modifica valoarea
lui a pe cnd a << 3 nu modific valoarea lui a.
Exemple:
Fie declaraia:
int i;
atunci expresia i >> 8 & 255 are ca rezultat valoarea celui mai
semnificativ octet a lui i; i >> 8 deplaseaz octetul mai semnificativ al
lui i n poziia mai puin semnificativ; se face apoi un I logic pe bii
cu masca 255 care pstreaz octetul mai puin semnificativ.
2) Fie expresia: (x >> 6) & ~(~ 0 << 3)
S presupunem c x are valoarea n bii 1010 1011 1000 1101.
Atunci x>>6 are valoarea
1111 1110 1010 1110
Al doilea operand pregtete o masc astfel:
~0
1111 1111 1111 1111
~0<<3
1111 1111 1111 1000
~(~0<<3)
0000 0000 0000 0110
Rezultatul final este
0000
1111
0000
dat de:
0000 0000 0111
1110 1010 1110
0000 0000 0110
simpl,
fie
variabil
cu
indici
sau
un
sizeof (data)
unde data poate fi:
numele unei variabile simple;
numele unui tablou;
numele unei structuri;
numele unui tip;
referirea la elementul unui tablou sau structur.
Exemple:
int i;
long l;
float f;
double d;
char c;
int itablou[5];
double dtablou[5];
sizeof (i)
sizeof (l)
sizeof (f)
sizeof (d)
sizeof (c)
sizeof (itablou[1])
sizeof (dtablou[1])
sizeof (itablou)
sizeof (dtablou)
// are valoarea 2;
// are valoarea 4;
// are valoarea 4;
// are valoarea 8;
// are valoarea 1;
// are valoarea 2;
// are valoarea 8;
// are valoarea 10;
// are valoarea 40;
char c;
expresii
conversii
i-j/k nu
a/b
tipul expresiei
int
a spre double
b spre double
nu
a spre double
x+y
i+a
i spre double
i-3.14
i+3
i+x
i-c
x+10
p-10
r*5
(double)(i/j)
double
i spre double
nu
i spre double
c spre int
10 spre double
10 spre unsigned
5 spre long
se realizeaz mprirea ntreag ntre
i i j i rezultatul se convertete spre double
double
double
double
int
double
int
double
unsigned
long
double
atunci
max=a
altfel
max=b
sfdac
n limbajul C se poate realiza acest proces cu ajutorul
operatorilor condiionali astfel:
max= a>b ? a : b
Dac a>b atunci expresia condiional are valoarea i tipul lui a
altfel expresia condiional are valoarea i tipul lui b.
Operatorul virgul
Operatorul , este folosit pentru gruparea mai multor expresii ntruna singur.
Cu ajutorul acestui operator (care are prioritatea cea mai mic) se
construiesc expresii de forma:
exp1, exp2,. . ., expn
Aceast expresie are valoarea i tipul ultimei expresii (deci a lui
expn).
Exemplu:
k= (i=10, j=j+5; i+j)
Se execut pe rnd cele dou atribuiri de la stnga la dreapta din
parantezele rotunde apoi se face suma i+j i n final se atribuie aceast
sum lui k,
LECIA 4.
INTRRI / IEIRI STANDARD
Limbajul C nu posed instruciuni de intrare / ieire. Aceste
operaii se realizeaz prin apeluri de funcii din bibliotecile standard
ale mediului de programare. De obicei astfel de funcii asigur interfaa
programului cu terminalul de la care s-a lansat, cu imprimanta, etc. Se
numesc intrri standard i ieiri standard intrrile respectiv ieirile de
la terminalul de la care s-a lansat programul. Totodat se presupune c
datele de intrare / ieire sunt organizate n fiiere.
Unui program C i se ataeaz n mod implicit urmtoarele
fiiere:
-
stdin
stdout
stderr
stdprn
stdaux
intrare standard;
ieire standard;
ieire standard pentru erori;
ieire pe imprimant;
intrare / ieire serial.
-una sau dou litere, care definesc tipul de conversie din formatul
intern n formatul extern:
prima litera poate fi l, ceea ce semnific conversia din formatul
intern long n formatul extern definit de specificator;
a doua liter este obligatorie ntotdeauna i are semnificaiile de
mai jos:
litera
pentru
X
pentru
u
c
corespunztor
s
- din ir de coduri ASCII ntr-un ir de caractere (atenie
ultimul cod este NUL (adic \0)
f
- din float sau double intern n d...d.d...d (implicit 6 cifre
zecimale la partea fracionar dac nu e prezent precizia)
e
- din float sau double intern n d.d...deddd (implicit 6
cifre zecimale la partea fracionar dac nu e prezent
precizia)
E
- din float sau double intern n d.d...dEddd (implicit 6
cifre zecimale la partea fracionar dac nu e prezent
precizia)
g
- se aplic una din conversiile definite de literele f i e
alegndu-se aceea care are un numr minim de poziii
G
- se aplic una din conversiile definite de literele f i E
alegndu-se aceea care are un numr minim de poziii
Observaie.
1o. Dac caracterul % nu este urmat de una din construciile de mai
sus atunci nu reprezint un specificator de format.
Funcia printf ntoarce lungimea total n octei a datelor
scrise la terminal sau valoarea simbolic EOF n caz de eroare. Precizm c
EOF este definit n fiierul header stdio.h astfel:
#define EOF 1.
Totodat funcia printf poate fi testat i astfel:
EOF= = printf (control, lista_expresii)
Dac are valoarea adevrat atunci la scrierea datelor s-a
produs o eroare.
Exemple:
1)
#include<stdio.h>
#include<math.h>
void main(void)
{ int i=10; long j=11;
float a=1.2, b=1.3;
double A=1.4; B=1.5;
clrscr();
// inceputul instructiunilor executabile; se sterge
ecranul
printf ("\ni*j = %d",i*j);
// incep afisarile
printf ("\ni*j = %5d",i*j);
printf ("\ni*j = %-5d",i*j);
* PC WORLD*
*PC WORLD *
* PC WO*
*PC WO *
4.2. FUNCIA STANDARD scanf
Funcia de bibliotec scanf realizeaz intrri cu format de la
intrarea standard stdin (intrare de la terminalul de la care s-a lansat
programul) i poate fi apelat printr-o instruciune de apel de forma:
scanf (control, lista_adrese);
Ca i n cazul funciei printf, parametrul control este
delimitat de ghilimele i poate conine texte i specificatori de format.
Caracterele albe din parametrul control sunt neglijate. Celelalte caractere
care nu fac parte dintr-un specificator de format, trebuie s existe la
intrare n poziii corespunztoare. Ele se folosesc n scopul realizrii
unor verificri asupra datelor care se citesc.
Un specificator de format ncepe i n acest caz prin
caracterul procent, apoi:
un caracter * opional;
un ir de cifre, opional, care definete lungimea maxim a cmpului
din care se citete data de sub controlul specificatorului de format;
una sau dou litere care definesc tipul conversiei din formatul
extern n formatul intern.
Cmpul controlat de un specificator de format ncepe cu primul
caracter care nu este alb i se termin:
fie la caracterul dup care urmeaz un caracter alb;
fie la caracterul dup care urmeaz un caracter care nu corespunde
specificatorului de format care controleaz acel cmp;
fie la caracterul prin care se ajunge la lungimea maxim indicat n
specificatorul de format.
d
- data din cmpul de intrare este un ir de cifre zecimale,
precedat eventual de un semn i se convertete din zecimal extern n binar
de tip int
o - ca i n cazul literei d, dar din octal extern n binar de tip
int.
x
- ca i n cazul literei d, dar din hexazecimal extern n binar
de tip int; se utilizeaz literele mici a-f sau mari A-F pentru cifrele mai
mari ca 9.
X
- ca i n cazul literei x;
u
- data este un ir de cifre zecimale care formeaz un numr
ntreg fr semn i se convertete din zecimal extern n binar tipul
unsigned.
c
- data se consider format din caracterul curent de la intrare
i parametrului corespunztor i se atribuie codul ASCII al acestui
caracter; n acest caz nu se face avans peste caracterele albe, ca i n
cazul celorlali specificatori.
s
- data se consider c este ir de caractere; irul ncepe,
conform regulii generale, cu primul caracter care nu este alb i se termin
la caracterul dup care urmeaz un caracter alb sau cnd s-au citit attea
caractere cte indic dimensiunea maxim din specificatorul de format;
f
- data de intrare reprezint un numr flotant; deci conversie
din flotant extern n virgul flotant simpl precizie; data care se
citete conine un punct sau un exponent, sau att punct ct i exponent.
Literele d, o, x i u pot fi precedate de litera l i n acest caz
conversia se realizeaz spre long, n loc de int.
De asemenea, litera f va fi precedat de litera l pentru a face
conversii spre formatul virgul flotant dubl precizie.
Lista_adrese conine adresele zonelor receptoare ale datelor citite
prin intermediul funciei scanf. Fiecare dintre parametri reprezint adresa
unei zone receptoare sub forma:
&nume
Ea determin adresa zonei de memorie rezervat variabilei nume.
Caracterul & din construcia de mai sus reprezint un operator unar,
numit operatorul adres. El are aceeai prioritate ca i ceilali operatori
unari din limbajul C.
Exemplu:
void main (void)
{ int i;
long n;
float x;
scanf ( %d %ld %f ,&i,&n,&x); // citeste datele din stdin si le atribuie lui i,n,x.
scanf( %d %*ld %f , &i,&x);
// caracterul * indica faptul ca valoarea pentru
variabila n
// nu se citeste
}
Funcia scanf returneaz numrul de cmpuri citite corect din
fiierul stdin. Dac apare o eroare la citire (din diverse motive de
exemplu neconcordan dintre specificatorul de format i datele din
fiierul stdin) atunci funcia nu va returna numrul total de cmpuri;
citirea se va ntrerupe n locul detectrii erorii i scanf va returna
numrul de cmpuri citite pn n acel moment. Deci de multe ori pentru a
ilustrare
grafic
celor
trei
D-structuri
se
continuare.
da
S1 C
nu da
S2 S C
S nu
.
Sn
S-a demonstrat ulterior (Bohm i Jacopini) c orice algoritm se poate
descrie doar cu D-structurile dar pentru o mai bun lizibilitate i
nelegere a programelor surs s-au adugat i iteraia postestat (REPEAT
... UNTIL), iteraia cu numr prestabilit de ciclri (FOR ... DO),
alternativa complet (IF ... THEN ... ELSE) i alternativa generalizat
(CASE ... OF).
n unele limbaje se folosesc i alte structuri pe lng cele de mai
sus pentru o ct mai fidel reflectare a algoritmului.
Dreptunghi Romb
Ptrat
ntlnite att n domeniile care pleac de la cele mai concrete forme ale
lumii materiale, cum sunt botanica, zoologia, biologia, etc ct i n
domenii care studiaz concepte dintre cele mai abstracte, cum ar fi
matematica sau filozofia.
Aceste ierarhii sunt rezultatul definirii conceptelor dup regula
includerii genul proxim i diferena specific.
Limbajul C dispune de un set bogat de instruciuni care permit
scrierea de:
programe structurate,
programe flexibile,
programe compacte.
Totodat limbajul C permite aplicarea metodelor de programare
procedural, programare modular i programare structurat. Pe lng aceste
metodologii limbajul C++ permite i programarea prin abstractizarea datelor
i programarea orientat spre obiecte.
Vom descrie n continuare instruciunile limbajului C. Ca o
caracteristic sintactic toate instruciunile limbajului se termin prin
caracterul ;, excepie fcnd instruciunile care se termin cu acolada
nchis.
Limbajul C dispune de un set bogat de instruciuni care permit
scrierea de:
programe structurate,
programe flexibile,
programe compacte.
Totodat limbajul C permite aplicarea metodelor de programare
procedural, programare modular i programare structurat. Pe lng aceste
metodologii limbajul C++ permite i programarea prin abstractizarea datelor
i programarea orientat spre obiecte.
Vom descrie n continuare instruciunile limbajului C. Ca o
caracteristic sintactic toate instruciunile limbajului se termin prin
caracterul ;, excepie fcnd instruciunile care se termin cu acolada
nchis.
5.2. INSTRUCIUNEA VID
Instruciunea vid se reduce la caracterul ;. Ea nu are nici un
efect. Adesea este nevoie de ea la construcii n care se cere prezena
unei instruciuni, dar nu este necesar s se execute nimic n punctul
respectiv.
5.3. INSTRUCIUNEA EXPRESIE
Instruciunea expresie se obine scriind punct i virgul dup
o expresie, deci:
expresie;
Exist cazuri particulare ale instruciunii expresie:
expresia de atribuire, care de altfel este cel mai important caz
particular al instruciunii expresie:
expresie;
apelul unei funcii:
nume_funcie (par1, par2, . . . parn);
incrementrile i decrementrile pre i post fixate:
variabil++; ++variabil;
variabil- -; - - variabil;
Exemplu:
void main (void)
{ int i;
float f;
double d;
i=10;
i++;
f=i;
d=++f;
putchar(a);
}
// instructiune de atribuire
// i se mareste cu 1
// instructiune de atribuire (valoarea lui i se converteste in float)
// incrementare lui f si atribuirea valorii lui d
// instructiune de apel
instructiune_1;
else
instructiune_2;
Efectul:
se evalueaz expresia din paranteze;
dac valoarea expresiei este diferit de zero (deci conform
conveniei are valoarea adevrat), atunci se execut instructiune_1, altfel
se execut instructiune_2; apoi n ambele cazuri se trece la instruciunea
urmtoare.
Observaii:
Citeste n
f=1
i=2
CtTimp i<=n execut
f=f*i;
i=i+1
SfritCtTimp
Scrie n,f
Programul n C este:
#include<stdio.h>
void main (void)
{ int n,i;
double f;
f=1.0;
i=2;
printf(\n dati n= );
scanf(%d,&n);
while (i<=n)
{ f=f*i;
i++;
}
printf(\nn=%d, iar n!=%g\n,n,f);
}
Corpul ciclului while se poate scrie mai compact astfel:
while (i<=n) f*=i++;
5.7. INSTRUCIUNEA for
Instruciunea for, ca i instruciunea while, se utilizeaz pentru a
realiza o structur repetitiv pretestat. Formatul instruciunii este:
for(exp1; exp2; exp3) instructiune;
Antetul ciclului este definit de for(exp1; exp2; exp3) iar
instructiune formeaz corpul ciclului. Prima expresie exp1 constituie
partea de iniializare a ciclului, iar exp3 este partea de reiniializare a
ciclului. Condiia de continuare a ciclului este exp2. De obicei exp1 i
exp3 reprezint atribuiri.
Efectul:
se execut secvena de iniializare definit de expresia exp1;
se evalueaz exp2; dac exp2 are valoarea zero, atunci se iese din
ciclu, adic se trece la instruciunea urmtoare instruciunii for, altfel
se execut instruciunea din corpul ciclului;
se execut apoi secvena de reiniializare definit de exp 3, apoi se
reia secvena de la punctul 2).
Observaii:
1o. Ca i n cazul instruciunii while, instruciunea din corpul
ciclului for poate s nu se execute niciodat dac exp2 are valoarea zero
chiar la prima evaluare.
2o. Expresiile din antetul instruciunii for pot fi i vide; totui
caracterele ; vor fi ntotdeauna prezente.
3o. Comparnd instruciunile for i while observm c instruciunea
for cu formatul anterior se poate realiza cu secvena urmtoare folosind
while:
exp1;
while (exp2)
{ instructiune;
exp3;
}
Invers, o instruciune while de forma: while (exp) instructiune este
echivalent cu urmtoarea instruciune for:
for(; exp; ) instructiune.
Autorii limbajului C propun ca instruciunea for s se foloseasc cu
prioritate pentru ciclurile care au pas.
Exemple:
Vom da o secven de instruciuni care nsumeaz elementele unui
tablou:
s=0;
for(i=0; i<n; i++) s=s+tab[i];
sau scris mai compact:
for (s=0, i=0; i<n; i++) s+=tab[i];
n continuare vom da un mic program
caracterelor citite de la intrarea standard stdin.
care
afieaz
numrul
#include <stdio.h>
void main(void)
{ long n;
for (n=0; getchar()!=EOF; n++);
printf (\nnumarul caracterelor citite =%ld\n,n);
}
sau scris cu instruciunea while
#include <stdio.h>
void main(void)
{ long n=0;
while (getchar()!=EOF) n++;
printf (\nnumarul caracterelor citite =%ld\n,n);
}
5.8. INSTRUCIUNEA do-while
Aceast
instruciune
realizeaz
structura
repetitiv
condiionat posterior (posttestat) dar modificat fa de REPEAT ..
UNTIL. Aceast instruciune s-a introdus pentru o mai mare flexibilitate n
scrierea programelor. Formatul ei este:
do
instructiune;
while (exp);
Efectul:
se execut instruciunea instructiune;
se evalueaz expresia exp din paranteze;
dac valoarea expresiei este zero se trece la instruciunea urmtoare
instruciunii
do-while;
altfel
se
revine
i
se
execut
din
nou
instructiune.
Observaii:
1o. Structura realizat de instruciunea do-while poate fi realizat
printr-o secven n care se folosete instruciunea while astfel:
instructiune;
while (exp) instructiune;
2o. Se observ c n cazul instruciunii do-while, corpul ciclului se
execut cel puin odat, spre deosebire de ciclurile while i for unde
corpul ciclului poate s nu se execute niciodat.
Exemplu:
Vom da un program care calculeaz rdcina ptrat dintr-un numr
real a>=0.
#include<stdio.h>
#define EPS 1e-10
void main (void)
{ double x1,x2,y,a;
clrscr();
// sterge ecranul
printf(\ndati un numar real pozitiv a=);
if (scanf(%lf,&a) !=1 || a<0)
printf (numarul citit nu este pozitiv\n);
else {
x2 = 1.0;
do {
x1 = x2;
x2 = 0.5 *(x1+a/x1);
// formula de iteratie
if ((y=x2-x1) < 0) y = -y;
}
while (y >= EPS);
printf (radacina patrata din:%g este: %.2lf\n,a,x2);
// 2 zecimale
} //sfirsit else
}
5.9. INSTRUCTIUNEA switch
Instruciunea switch permite realizarea structurii alternativa
generalizat. Ea este echivalent cu o imbricare de structuri de
alternativ simple. Utilizarea instruciunii switch face n schimb
programul mult mai clar.
Formatul instruciunii switch este urmtorul:
switch (exp)
{ case c1: sir1
break;
case c2:
sir2
break;
. . .
case cn:
default:
sirn
break;
sir
}
unde:
}
5.11. INSTRUCIUNEA continue
Formatul instruciunii este urmtorul:
continue;
Efectul:
n ciclurile while i do-while ea realizeaz saltul la evaluarea
expresiei care decide asupra continurii ciclului;
n ciclul for ea realizeaz saltul la pasul de reiniializare.
Observaie:
1o. Instruciunea continue se utilizeaz numai n corpul unui ciclu,
permind, dup caz, s se treac la pasul urmtor al ciclului sau s se
ias din ciclu.
5.12. INSTRUCIUNEA goto
Conform principiilor programrii structurate instruciunea goto
nu ar fi necesar. Dar ea a fost introdus n limbaj, deoarece, n anumite
cazuri, se dovedete a fi util, asigurnd o flexibilitate mai mare n
programare. De multe ori ieirea dintr-un ciclu imbricat n alte cicluri se
realizeaz mai simplu cu ajutorul instruciunii goto. n lipsa ei ar trebui
s folosim mai muli indicatori i teste asupra valorilor acestora pentru
ieirea din ciclu. Saltul fcut de goto se face la o instruciune care este
prefixat de o etichet.
Prin etichet vom nelege un nume urmat de caracterul :.
Etichetele sunt locale unei funcii.
Instruciunea goto are urmtorul format:
goto eticheta;
Efectul:
se realizeaz saltul la instruciunea prefixat de eticheta al crei
nume se afl scris dup cuvntul cheie goto.
5.13. APELUL I REVENIREA DINTR-O FUNCIE
5.13.1. Apelul unei funcii
n limbajul C funciile sunt de dou tipuri:
funcii care returneaz o valoare la revenirea din ele;
funcii care nu returneaz nici o valoare la revenirea din ele.
O funcie care nu returneaz nici o valoare la revenirea din ea se
apeleaz printr-o instruciune de apel. Ea are urmtorul format:
nume (lista_parametrilor_efectivi);
(*)
unde:
nume este numele funciei;
lista_parametrilor_efectivi este fie vid, fie se compune din una sau
mai multe expresii separate prin virgul.
Instruciunea de apel este un caz particular al instruciunii
expresie. Parametrii efectivi (de la apel) trebuie s corespund cu cei
formali (de la definirea funciei) prin ordine, tip i numr.
n cazul n care o funcie returneaz o valoare, ea poate fi apelat
fie printr-o instruciune de apel, fie sub forma unui operand al unei
expresii.
Observaii:
1o. Dac nu dorim s utilizm valoarea returnat
respectiv, apelul se face printr-o instruciune de apel.
de
funcia
1:
2:
3:
4:
tip
tip
tip
tip
nume
nume
nume
nume
(lista_declaratiilor_de_parametri);
(lista_ tipurilor_parametrilor);
(void);
();
al
funciei
care
determin
// prototipul functiei
reprezint
tip
dintr-o
declaraie
x=y;
p=&x;
(*p)++;
}
decrementare
se
pot
aplica
.
6.3.4. Diferena a doi pointeri
Doi pointeri care pointeaz spre elementele aceluiai tablou pot fi
sczui. Rezultatul diferenei a doi pointeri este definit astfel: fie t un
tablou de un tip oarecare i p i q doi pointeri, p conine adresa
elementului t[i] iar q conine adresa elementului t[i+n]. Atunci diferena
q-p are valoarea n.
6.3.5. Exemple
Vom da cteva funcii asupra irurilor de caractere:
funcia lungime
unsigned lungime (char*x)
{ int i;
for (i=0; *x != \0; i++) x++;
return i;
}
funcia copiaz
void copiaza(char *x, char *y)
{ while(*x++ = = *y++); }
funcia concateneaza
void concateneaza (char *x, char *y)
// concateneaza sirul de adresa y la sfarsitul sirului
// de adresa x
{ while (*x) x++;
// avans de adresa pana la sfarsitul sirului x
while (*x++= *y++);
}
funcia compara
int compara (char *x, char *y)
{ while (*x= = *y)
{ if (*x= = \0) return 0;
x++;
y++;
return *x - *y;
// daca diferenta caracterelor este
// negativa atunci x<y altfel x>y
}
}
6.4. ALOCAREA DINAMIC A MEMORIEI
Biblioteca
standard
a
limbajului
C
pune
la
dispoziia
utilizatorului funcii care permit alocarea de zone de memorie n timpul
execuiei programului. O astfel de zon de memorie poate fi utilizat
pentru a pstra date temporare. Zona respectiv poate fi eliberat n
momentul n care nu mai sunt necesare datele care au fost pstrate n ea.
Alocarea de zone de memorie i eliberarea lor n timpul execuiei
programelor permite gestionarea optim a memoriei de ctre programator. Un
astfel de mijloc de gestionare a memoriei l vom numi alocare dinamic a
memoriei.
Vom indica dou funcii din bibloteca limbajului C utilizate
frecvent n alocarea dinamic a memoriei. Prototipurile lor se afl n
fiierele standard alloc.h i stdlib.h, deci pentru a le utiliza vom
include unul din aceste fiiere.
Funcia malloc permite alocarea unui bloc de memorie a crui
dimensiune se specific n octei. Funcia returneaz un pointer spre
la
alocare,
deci
este
Exemplu:
Funcia memchar memoreaz un ir de caractere ntr-o zon de memorie
alocat prin funcia malloc. Ea returneaz adresa de nceput a zonei n
care s-a salvat irul de caractere, deci returneaz un pointer spre tipul
char.
#include <stdio.h>
#include <alloc.h>
#include <string.h>
char *memchar (char *s)
{
char *p;
if ((p=(char *)malloc(strlen(s)+1) ) != NULL
{
strcpy (p,s);
return p;
} else
return NULL;
}
Observaii:
1o. n fiierul stdio.h exist definiia constantei NULL.
2o. Fiierul alloc.h s-a inclus deoarece conine prototipul funciei
malloc.
3o. Fiierul string.h conine prototipurile funciilor strlen i
strcpy.
4o. Funcia malloc se apeleaz pentru a rezerva strlen(s)+1 octei;
strlen returneaz numrul de octei cuplai de caracterele proprii ale lui
s (fr caracterul NULL). Cum n zona de memorie rezervat prin malloc se
pstreaz i caracterul NULL, lungimea returnat de funcia strlen s-a
mrit cu 1.
5o. Pointerul returnat de malloc a fost convertit spre char *,
deoarece el este de tip void *. Acest pointer se atribuie lui p, deci p
pointeaz spre nceputul zonei de memorie alocate prin apelul funciei
malloc. Se testeaz dac acest pointer este diferit de NULL (deci dac s-a
putut aloca memoria de dimensiunea cerut). n caz afirmativ, se transfer
irul prin apelul funciei strcpy, returnndu-se apoi valoarea pointerului
p.
- argv[2]
- argv[3]
Observaii:
1o. Lansarea unui program se face cu prima instruciune a funciei
principale. Deci parametrii argc i argv au deja n acest moment valorile
indicate mai sus, putnd fi analizai chiar cu prima instruciune
executabil.
2o. n mod frecvent, aceti parametrii reprezint diferite opiuni
ale programului, date calendaristice, nume de fiiere, etc.
3o. argv[0] este ntotdeauna pointerul spre numele fiierului cu
imaginea executabil a programului.
void main ( int argc, char *argv[])
{ int i;
for (i=0; i<argc; i++;)
printf (%s\n,argv[i]);
}
void push(int x)
// pune pe stiva valoarea lui x
{ if (next < MAX)
stack [next++]=x;
else
printf (stiva este depasita\n);
}
int pop()
{ if (next >0)
else
}
void clear(void)
{
next=0;
}
// videaza stiva
LECIA 7.
RECURSIVITATE
Spunem c o funcie C este recursiv dac ea se autoapeleaz nainte
de a se reveni din ea. Funcia se poate reapela fie direct, fie indirect
(prin intermediul altor funcii).
La fiecare apel al unei funcii, parametrii i variabilele locale se
aloc pe stiv ntr-o zon independent. De asemenea, orice apel recursiv
al unei funcii va conduce la o revenire din funcie la instruciunea
urmtoare apelului respectiv. La revenirea dintr-o funcie se realizeaz
curarea stivei, adic zona de pe stiv afectat la apel parametrilor i
variabilelor automatice se elibereaz.
Un exemplu simplu de funcie apelata recursiv este funcia de calcul
al factorialului. Putem defini recursiv funcia factorial astfel:
factorial(n)= 1,
dac n=0
factorial(n)=n*factorial(n-1),
dac n>0
n limbajul C avem :
double factorial (int)
{ if (n= = 0)
return 1.0;
else
return n*factorial(n-1);
}
Observaii:
1o. n general, o funcie recursiv se poate realiza i nerecursiv,
adic fr s se autoapeleze.
2o. De obicei, recursivitatea nu conduce nici la economie de memorie
i nici la execuia mai rapid a programelor. Ea permite ns o descriere
mai compact i mai clar a funciilor. Acest lucru rezult i din exemplul
de mai sus de calcul al factorialului.
3o. n general, funciile recursive sunt de preferat pentru procese
care se definesc recursiv. Exist i excepii. De exemplu algoritmul de
generare a permutrilor de n obiecte poate fi descris recursiv astfel:
avnd n memorie toate cele (n-1)! permutri, atunci permutrile de n
obiecte se genereaz nsernd pe n n toate poziiile posibile ale fiecrei
permutri de n-1 obiecte. Dar ne aducem aminte c 10!=3628800 i
capacitatea stivei se depete repede.
Exemple:
determin
recursiv
suma
unor
elemente
de
tablou
a[1]+a[2]+ . . . + a[n]
#include <iostream.h>
#define MAX 100
int a[MAX];
// suma(n)= 0,
// suma(n)=suma(n-1) + a[n]
int suma(int n)
{ if (!n) return 0;
else
return a[n]+suma(n-1);
}
daca n=0
daca n>0
void main(void)
{int n,i;
cout << "dati n= ";
cin >> n;
for (i=1; i<=n; i++)
{
cout << "a[" << i << "]= ";
cin >> a[i];
}
cout << "suma numerelor este " << suma(n);
}
Programul determin recursiv
Fibonacci definit dup cum urmeaz:
termenul
al
fibonacci[0]=0
fibonacci[1]=1
fibonacci[n]=fibonacci[n-1]+fibonacci[n-2],
n-lea
din
dac n>1
irul
lui
#include<iostream.h>
long fibonacci (long n)
{if (!n)
return 0;
else if (n==1) return 1;
else
return fibonacci(n-1) + fibonacci(n-2);
}
void main (void)
{ long n;
cout << "dati n = ";
cin >> n;
cout << "fibo(" << n << ") =" << fibonacci (n);
}
Programul determina maximul dintr-un vector de numere astfel:
M(n)= a[1]
dac n=1
M(n)= max { M(n-1),a[n] }
dac n>1
#include<iostream.h>
#define MAX(x,y) (x > y ? x : y)
int a[100];
int M(int n)
{ if (n= =1)
else
}
return a[1];
return MAX (M(n-1), a[n]);
void main(void)
{int n,i;
cout << "dati n=";
cin >> n;
for (i=1; i<=n; i++)
{
cout << "a[" << i << "]= ";
cin >> a[i];
}
cout << "maximul este " << M(n);
}
5) Programul afiseaz un ir de caractere n mod recursiv, caracter
cu caracter, considernd c irul de caractere este format din primul
caracter(capul) + restul irului de caractere (coada).
#include <iostream.h>
#include <conio.h>
#define max 100
char sir [max];
int n;
void afis (int m)
{ if (m = = n+1) return;
else
{ cout << sir[m];
afis(m+1);
}
}
void main (void)
{int i;
do {
cout << "\ndati lungimea sirului =";
cin >> n;
}
while ( (n< 0) || (n > max));
Programul
sorteaz
prin
#define dim 50
#include <stdio.h>
#include <conio.h>
int x[dim+1],i,n;
void tipsir ()
{ for (i=1; i<=n; i++)
{
printf("%3d",x[i]);
if (!(i % 20)) printf ("\n");
}
}
void quik(int st, int dr)
{int i,j,y;
i=st; j=dr; y=x[i];
do {
while ((x[j] >= y) && (i<j)) j - -;
x[i]=x[j];
while ((x[i] <= y) && (i<j)) i++;
x[j]=x[i];
}
while (i != j);
x[i]=y;
if (st < i-1)
quik(st,i-1);
if (i+1 < dr)
quik(i+1,dr);
x[j]=x[i];
}
metoda
quicksort
un
vector
de
numere
{ int ziua;
char luna[11];
int anul;
};
O astfel de declaraie se numete declaraie de tip. S reinem c
unui nou tip de date nu i se aloc memorie, el este doar contabilizat ca un
nou tip utilizator pe lng tipurile predefinite ale limbajului C.
Formatul 2:
struct nume_structura
{ lista_declaratii
}lista_variabile;
Un astfel de format introduce tipul utilizator nume_structura i
declar o list de varibile n care fiecare element din list are tipul
nume_structur. Prin exemplu urmtor se introduc variabilele dc1 i dc2 ca
date elementare de tipul data_calendaristica i tabloul dc de 13
componente.
struct data_calendaristica
{ int ziua;
char luna[11];
int anul;
} dc1, dc2, dc[13];
Formatul 3:
struct
{ lista_declaraii
} lista_variabile;
Acest format se foloseste dac nu vrem sa dm nume noului tip
structurat i totodat dac nu mai vrem s-l folosim. Deci nu vom mai pute
declara alte date de tipul structurat nou introdus pentru c tipul nu are
nume.
Exemplu:
struct
{ int ziua;
char luna[11];
int anul;
} dc1, dc2, dc[13];
S-au declarat varibilele dc1, dc2 i tabloul dc avnd noul tip
structurat utilizator dar nu se mai dorete s declarm alte date de acest
tip.
Observaii:
1o. Dac se folosete formatul 1 atunci pentru a declara date de
tipul utilizator nou introdus se folosete o construcie de forma:
struct nume_ structura lista_variabile;
Compilatorul aloc memorie varibilelor din lista de variabile,
tratnd aceast construcie ca i declaraiile obinuite.
2o. Componentele unei structuri pot fi ele nsele date structurate. O
component care nu este structurat se numete component elementar.
3o. Ca i n cazul celorlalte tipuri de variabile se pot defini
structuri globale, statice sau automatice. Structurile statice se declar
precednd declaraiile lor prin cuvntul static, iar cele externe prin
cuvntul cheie extern.
4o. Elementele unei date de tip structur pot fi iniializate dup
modelul iniializrii variabilelor care au tipuri predefinite.
Exemple:
1) Introducem tipul utilizator data_calendaristica astfel:
struct data_calendaristica
{ int ziua;
char luna[11];
int anul;
};
pentru a iniializa o dat de tipul data_calendaristic vom scrie:
struct data_calendaristica dc1={31, martie, 1956};
2) Dac declarm un nou tip date_personale i n care vrem s folosim
tipul data_calendaristica, vom scrie:
struct date_personale
{ char nume[30];
char adresa[50];
struct
data_calendaristica
data_angajarii;
};
data_nasterii,
datei
dc
introdus
vom
in
folosi
dc
de
tipul
data_calendaristica
antetul
int
char
int
ziua;
luna[11];
anul;
} DC;
Prin aceast declaraie se atribuie denumirea DC tipului
structurat data_calendaristica. n continuare putem declara date de tip DC:
DC data_nasterii, data_angajarii;
DC data_curenta ={31,august,1998};
typedef int *PI;
Prin aceast declaraie se introduce un sinonim pentru tipul pointer
spre ntregi: int *.
Putem s declarm n continuare pointeri spre ntregi astfel:
PI p;
care este echivalent cu:
int *p;
4) Declaraia
{
double real;
double imaginar;
} COMPLEX;
typdef struct
8.4. UNIUNE
Limbajul C ofer utilizatorului posibilitatea de a folosi
aceeai zon de memorie pentru a pstra date de tipuri diferite n momente
diferite ale execuiei programului. Astfel, de exemplu, putem utiliza o
zon de memorie pentru a pstra la un moment dat o dat flotant, iar
ulterior s reutilizm aceeai zon pentru o dat ntreag sau de tip
pointer. Reutilizrile zonelor de memorie conduc la utilizarea mai
eficient a acesteia, uneori putndu-se obine o economie substanial a
spaiului de memorie alocat programului.
O
uniune
se
declar
printr-o
construcie
asemntoare
declaraiei de structur. Deosebirea const n nlocuirea cuvntului struct
prin union:
union nume
{ tip_membru_1;
. . .
tip_membru_2;
}
Exemplu:
union u
{ int i;
float f;
double d;
};
if (us.tip_curent = = INTREG)
else if (us.tip_curent = = FSIMPLU)
else if (us.tip_curent = = FDUBLU)
else eroare
// se foloseste us.uu.i
// se foloseste us.uu.f
// se foloseste us.uu.d
calculeaz
ariile
pentru
urmtoarele
figuri
// tipul figurii
// cerc
// patrat
// dreptunghi
// triunghi
switch (zfig.tip)
{case CERC:
// aria cercului
printf("raza=%g aria=%g\n", zfig.fig.raza, PI*zfig.fig.raza*zfig.fig.raza);
break;
case PATRAT:
// aria patratului
printf("latura =%g aria=%g\n",zfig.fig.lp, zfig.fig.lp*zfig.fig.lp);
break;
case DREPT:
// aria dreptunghiului
printf("lungimea =%g latimea =%g\n", zfig.fig.ld[0], zfig.fig.ld[1]);
printf("aria=%g\n", zfig.fig.ld[0]*zfig.fig.ld[1]);
break;
case TRIUNGHI:
// aria triunghiului
p=(zfig.fig.lt[0] + zfig.fig.lt[1] + zfig.fig.lt[2])/2;
if(p>zfig.fig.lt[0] && p>zfig.fig.lt[1] && p>zfig.fig.lt[2])
{p=p*(p-zfig.fig.lt[0])*(p-zfig.fig.lt[1])* (p-zfig.fig.lt[2]);
printf("a=%g b=%g c=%g\n", zfig.fig.lt[0], zfig.fig.lt[1], zfig.fig.lt[2]);
printf("aria = %g\n",sqrt(p));
}
else { printf ( laturile nu formeaza un triunghi);
break;
}
default :
// avans pana la newline sau EOF
while ((i = getchar()) != \n && i != EOF);
} // sfarsit switch
if (i = = EOF) break;
}
// sfarsit for
}
// sfarsit main
8.5. CAMP
Limbajul C permite utilizatorului definirea i prelucrarea
datelor pe bii. Utilizarea datelor pe bii este legat de folosirea
indicatorilor care de obicei sunt date care iau numai dou valori 0 sau 1.
Nu este justificat ca un astfel de indicator s fie pstrat ca
un ntreg pe 16 bii i nici mcar pe un octet. Indicatorul poate fi
pstrat pe un singur bit. n acest scop, limbajul C ofer posibilitatea de
a declara date care s se aloce pe bii (unul sau mai muli bii). Acest
lucru i gsete aplicare n programele de sistem. Astfel, de exemplu,
atributele variabilelor dintr-o tabel de simboluri pot fi pstrate pe
bii, ceea ce conduce la o economisire substanial a memoriei ocupate de
tabela respectiv.
Prin camp nelegem un ir de bii adiaceni coninui ntr-un
cuvnt calculator. Cmpurile se grupeaz formnd o structur.
Un cmp se declar ca i o component a unei structuri i el
are tipul unsigned (ntreg fr semn). Totodat n declaraia cmpului se
indic i dimensiunea lui n bii.
n general, o structur cu componente cmpuri are forma:
struct
{ camp1;
. . .
campn;
} nume;
unde campi (i=1,...,n) are unul din formatele de mai jos:
unsigned nume : lungime_n_bii
sau
: lungime_n_bii
Exemplu:
struct
{ unsigned a:1;
unsigned b:1;
unsigned c:2;
unsigned d:2;
unsigned e:3;
} indicatori;
Data indicatori se aloc ntr-un cuvnt calculator, adic pe 16
bii. Componentele ei sunt:
a un bit;
b un bit;
c doi bii;
d doi bii;
e trei bii.
La cmpuri ne putem referi la fel ca i la componentele oricrei
structuri. Deci la indicatorii de mai sus ne putem referi prin urmtoarele
construcii:
indicatori.a
indicatori.b
indicatori.c
indicatori.d
indicatori.e
Alocarea biilor este dependent de calculator. De obicei biii se
aloc de la dreapta spre stnga ca n figura de mai jos:
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
a
b
c
d
e
Observaii:
1o. Dac un cmp nu poate fi alocat n limitele unui cuvnt, el se
aloc n ntregime n cuvntul urmtor.
2o. Nici un cmp nu poate avea o dimensiune mai mare dect 16 bii.
3o. Formatul fr nume (al doilea format) pentru cmp se folosete
pentru cadraje. Acest lucru este util atunci cnd sunt zone de bii
neutilizate n cadrul unui cuvnt. De asemenea, utilizarea formatului cu
lungime egal cu zero permite ca alocarea cmpurilor urmtoare lui s se
fac n cuvntul urmtor.
4o. O structur care are i componente cmpuri poate avea i
componente obinuite.
5o. Nu se pot defini tablouri de cmpuri.
6o. Unui cmp nu i se poate aplica operatorul adres.
Cmpurile se utilizeaz frecvent la scrierea unor programe de sistem,
cum ar fi : drivere pentru periferice, compilatoare, etc.
Utilizarea
cmpurilor
poate
conduce
la
programe
cu
o
portabilitate redus. Totodat, accesul la date pe bii conduce la
creterea numrului de operaii, fiind necesare deplasri i operaii pe
bii suplimentare, fapt ce poate conduce att la creterea timpului de
execuie a programelor, ct i la creterea memoriei utilizate. Ori datele
pe bii se folosesc chiar n ideea de a economisi memorie.
8.6. TIPUL ENUMERAT
Tipul enumerat permite utilizatorului s foloseasc n program
nume sugestive n locul unor valori numerice. De exemplu, n locul
numrului unei luni calendaristice, se poate folosi denumirea ei:
ian
feb
mar
n locul valorilor 0 i 1 se pot folosi cuvintele FALS i ADEVRAT.
Prin aceasta, se introduce o mai mare claritate n programe, deoarece
valorile numerice sunt nlocuite prin diferite sensuri atribuite lor.
Un tip enumerat se introduce printr-o declaraie de forma:
enum nume {nume0, nume1, . . . , numen};
Prin aceast declaraie se definete tipul enumerat nume, iar nume i
are valoarea i. O form mai general a declaraiei de mai sus permite
programatorului s foreze valorile numelor din acolad. n acest scop, se
pot folosi construcii de forma:
numei= eci
unde eci este o expresie constant de tip int.
Cu alte cuvinte, unui nume i se poate atribui o valoare sau
valoarea lui coincide cu a numelui precedent mrit cu 1. Dac primului
nume din acolad nu i se atribuie o valoare, el are valoarea 0. Numele
nume0, nume1,. . . , numen trebuie s fie nume diferite. Ele sunt constante
i valoarea lor se stabilete prin declaraia n care au fost scrise.
Domeniul lor de valabilitate este definit de domeniul de valabilitate al
declaraiei prin care se definesc:
instruciunea compus care conine declaraia;
fiierul surs n care este scris declaraia, dac este extern
oricrei funcii.
Valorile atribuite lui nume0, nume1, . . . , numen sunt de obicei
diferite, dar unele pot s i coincid.
Dup ce s-a introdus un tip enumerat, se pot declara date de
tipul respectiv printr-o declaraie de forma:
enum nume lista_de_variabile;
Datele de tip enumerat se consider de tip int i
utiliza n program oriunde este legal s apar o dat de tip int.
Observaii:
1o. Se pot
utiliza,
ca
cazul
structurilor,
se
pot
construcii
de
forma:
enum nume {nume0, nume1,. . . , numen} lista_de_variabile;
sau
enum { nume0, nume1,. . . , numen} lista_de_variabile;
2o. De asemenea, se poate
atribui un nume unui tip enumerat:
utiliza
construcia
typedef
pentru
capul
#include <stdio.h>
#include <alloc.h>
typedef struct nod
// definirea tipului NOD
{
int nr;
int patrat;
struct nod* leg;
} NOD;
NOD *creaza(void)
// functia de creare, intoarce adresa capului
{ NOD *cap,*p,*pc;
int i,lung;
printf("\n\n\n\ creare lista simplu inlantuita\n\n");
lung = sizeof(NOD);
pc=(NOD *)malloc(lung);
// pc este un pointer curent, in el se vor pune adresel noi
cap=pc;
printf("dati informatia elementului : ");
scanf ("%d",&i);
while (i>0)
// crearea listei se termina la numar negativ
{ p=pc;
// pointer ce pastreaza adresa noua
p->nr=i;
// incarcarea informatiei
p->patrat=i*i;
pc=(NOD *)malloc(lung);
// se cere o noua adresa de memorie
p->leg=pc;
// se leaga pointerul leg la noua adresa
printf("dati informatia elementului : ");
scanf ("%d",&i);
}
p->leg=NULL;
// ultimul nod al listei are pointerul leg = NULL
free(pc);
// eliberarea ultimei adrese care de fapt nu face parte din lista
return cap;
// returneaza adresa capului listei
}
int df;
df = open (c:\\borlandc\\help.txt,O_APPEND);
Se deschide n adugare fiierul help.txt din directorul borlandc de
pe discul C.
10.2.2. Citirea dintr-un fiier (consultare)
Funcia folosit pentru operaia de citire dintr-un fiier n
memorie se numete read i are prototipul urmtor:
int read (int df, void *buf, unsigned lung);
unde:
- df este descriptorul de fiier a crui valoare a fost definit la
deschidere;
buf este pointerul spre zona de memorie n care se recepioneaz
nregistrarea care se citete;
lung este lungimea n octei a inregistrrii citite.
Observaii:
1o. La fiecare apel funcia returneaz nregistrarea curent. La
primul apel se citete prima nregistrare din fiier, la al doilea apel se
citete a doua, etc. Ordinea nregistrrilor n fiier este cea definit la
crearea fiierului.
2o. La un apel al funciei read se citesc cel mult lung octei
nregistrarea avnd definit lungimea la scrierea n fiier. Funcia
rentoarce numrul de octei citii, 0(zero) la sfrit de fiier, sau 1
la eroare. De obicei se folosesc frecvent nregistrri de 512 octei sau
chiar mai mari.
3o. Funcia read poate fi folosit pentru a citi de la intrarea
standard. n acest caz, descriptorul de fiier este 0 (stdin are 0, stdout
are 1, stderr are 2 stdprn are 3 stdaux are 4). Programatorul nu trebuie s
deschid fiierele standard deoarece ele sunt deschise automat la lansarea
n execuie a programului.
4o. Utilizarea funciei read, presupune includerea fiierului io.h.
// se inchide fisierul
}
Se afieaz coninutul fiierului fis1.dat
#include<io.h>
#include<fcntl.h>
#include <stdio.h>
#include <conio.h>
void main (void)
{int df;
char s[14];
df = open("fis1.dat", O_RDONLY);
// se deschide fisierul n citire
if (df != -1)
// se testeaza daca deschiderea e corecta
{ read (df, s, 14);
printf ("%.14s",s);
read (df, s, 14);
printf ("%.14s",s);
} else printf (nu s-a deschis fisierul);
close (df);
getch();
// se asteapta un caracter de la tastatura
}
programul urmtor copiaz intrarea standard la ieierea standard
folosind o zon tampon de 80 de caractere:
#define LZT 80
#include <io.h>
void main (void)
// copiaza intrarea standard la iesirea standard
{ char zona_tampon[LZT];
int i;
while ((i = read (0, zona_tampon, LZT)) > 0) write (1, zt, i);
}
10.3. NIVELUL SUPERIOR DE PRELUCRARE A FIIERELOR
Dup cum am amintit, la acest
ajutorul unor proceduri specializate.
nivel
fiierele
se
prelucreaz
cu
funciilor
open
creat.
mod este un pointer spre un ir de caractere care definete modul de
prelucrare al fiierului dup deschidere. Acest ir de caractere se
definete n felul urmtor:
- r
- deschidere n citire (read);
- w
- deschidere n scriere (write);
- a
- deschidere pentru adugare;
- r+
deschidere
pentru
modificare
(citire
sau
scriere);
- rb
- citire binar;
- wb
- scriere binar;
- r+b
- citire/scriere binar.
Observaii:
scrise
citite
caracter
cu
caracter,
standard
la
ieirea
#include <stdio.h>
void main (void)
{ int c;
while (( c = getc (stdin)) != EOF) putc (c, stdout);
}
Programul urmtor copiaz intrarea standard la imprimant.
standard
#include <stdio.h>
void main (void)
{ int c;
while (( c = getc (stdin)) != EOF) putc (c, stdprn);
}
Programul urmtor scrie la ieirea stdout caracterele unui fiier a
crui cale este argumentul din linia de comand. Dac nu exist un argument
n linia de comand, atunci se citete de la intrarea standard.
#include <stdio.h>
void main (int argc, char *argv[ ] )
{ FILE *pf;
int c;
if (argc = = 1)
pf = stdin;
// nu exista argument in linia de comanda
else
// se deschide fisierul a carui cale se afla in argv[1]
if (( pf = fopen (*++argv,r)) = = NULL)
{ printf (nu se poate deschide fisierul %s\n,*argv);
exit (1);
}
while (( c = getc (pf)) != EOF) putchar(c);
exit (0);
}
Operaiile de intrare-ieire cu format
Biblioteca standard a limbajului C conine funcii care permit
realizarea operaiilor de intrare/ieire cu format. Astfel se pot utiliza
funciile fscanf i fprintf, prima pentru citire cu format dintr-un fiier,
iar a doua pentru scriere cu format ntr-un fiier.
Funcia fscanf este asemntoare cu funcia scanf. Ea are un
parametru n plus fa de scanf. Acest parametru este un pointer spre tipul
FILE i el definete fiierul din care se face citirea. Acest pointer este
primul parametru al funciei fscanf. Funcia poate fi apelat printr-o
expresie de atribuire de forma:
nr = fscanf (pf, control, lista_de_parametrii );
unde :
pf este un pointer spre tipul FILE i valoarea lui a fost definit
prin apelul funciei fopen; definete fiierul din care se face citirea;
ceilali parametri sunt identici cu cei utilizai la apelul funciei
scanf.
Funcia fscanf, ca i funcia scanf, returneaz numrul cmpurilor
citite din fiier. La ntlnirea sfritului de fiier se returneaz
valoarea EOF definit n fiierul stdio.h. Pentru pf = stdin, funcia
fscanf este identic cu scanf.
Funcia fprintf , ca i funcia printf, returneaz numrul
caracterelor scrise n fiier sau 1 n caz de eroare. Pentru pf = stdout,
funcia fprintf este identic cu printf. De asemenea, se pot utiliza
pointerii standard obisnuii: stderr, stdaux, stdprn.
Exemplu:
Vom scrie un program cu ajutorul cruia se va crea un fiier cu numele
"FIS.DAT" i care conine nregistrri cu numele, prenumele i adresa unor
persoane.
#include <stdio.h>
void main(void)
{
int n=0, i=1;
// n este numarul de nregistrari ce se va scrie in fisier
char nume[25], prenume[30], adresa[50];
FILE *pf;
printf("\n Dati numarul de inregistrari n= ");
scanf("%d",&n);
pf=fopen("FIS.DAT","w");
if (pf = = NULL)
{ printf ("Eroare la deschidere");
return;
}
do
{
printf("\n Nume : ");
scanf("%s",nume);
printf("\n Prenume : ");
scanf("%s",prenume);
printf("\n Adresa : ");
scanf("%s",adresa);
fprintf(pf,"%s %s %s", nume, prenume, adresa);
i++;
} while (i<=n);
fclose(pf);
}
10.3. 5. Intrri-ieiri de iruri de caractere
Biblioteca standard a limbajului C conine funciile fgets i
fputs care permit citirea respectiv scrierea ntr-un fiier ale crui
nregistrri sunt iruri de caractere.
Funcia fgets are prototipul:
char *fgets (char *s, int n, FILE *pf);
unde:
s este pointerul spre zona n care se face citirea caracterelor;
n-1 este numrul maxim de caractere care se citesc;
pf este pointerul spre tipul FILE care definete fiierul din care se
face citirea.
De obicei s este numele unui tablou de tip char de dimensiune cel
puin n. irul se termin cu \0 (caracterul NUL). La ntlnirea
caracterului \n, citirea se oprete. n acest caz, n zona receptoare se
transfer caracterul \n i apoi caracterul NUL (\0).
n mod normal, funcia returneaz valoarea pointerului s. La
ntlnirea sfritului de fiier se returneaz valoarea NULL.
Funcia fputs scrie ntr-un fiier un ir de caractere care se
termin prin \0. Ea are prototipul:
int fputs (const char *s, FILE *pf);
unde:
s este pointerul spre zona care conine irul de caractere care se
scrie;
pf este pointerul spre zona care conine irul de caractere care se
scrie.
Funcia fputs returneaz codul ASCII al ultimului caracter scris sau
1 n caz de eroare.
Aceste funcii sunt realizate folosind funcia getc pentru fgets i
putc pentru fputs.
Pentru a citi de la intrarea standard stdin, se poate folosi funcia
gets, care nu mai are parametrii pf i n. Parametrul pf este implicit
stdin. Funcia gets citete caracterele de la intrarea standard pn la
ntlnirea caracterului \n care nu mai este pstrat n zona spre care
pointeaz s. irul de caractere citit se termin i n acest caz prin \0.
denumire
TELVIZOR
um
buc
cod
0001
pret
3000000
cantitate
200
#include <stdio.h>
#define MAX 60
typedef struct { char tip[2];
char den[MAX];
int val;
char unit[3];
long cod;
float pret;
float cant;
} ARTICOL;
de
la
punctele
a)
b)
au
fost
descrise
lecii
isprint
dac c este codul unui caracter imprimabil
inclusiv spaiu;
isspace
dac c reprezint spaiu, tabulator, retur de car, rnd
nou,
tabulator vertical, salt la nceput de pagin de imprimant.
isupper
dac c este codul unei litere mari;
isxdigit
dac c este codul unei cifre hexazecimale.
Exemplu:
Programul urmtor citete un fiier
literele mari cu litere mici. Cile spre cele
destinaie) sunt argumente n linia de comand:
argv[1]
este un pointer spre
argv[2]
este un pointer spre
i l rescrie schimbnd
dou fiiere (surs i
fiierul surs;
fiierul destinaie.
#include <stdio.h>
#include <ctype.h>
void main ( int argc, char *argv[ ] )
{ FILE *pf1, *pf2;
int c;
if (argc != 3)
{ printf (linia de comanda eronata\n);
exit(1);
}
if (( pf1 = fopen (argv[1],r) ) = = NULL
{ printf (nu se poate deschide fisierul%s\n, argv[1]);
exit(1);
}
if (( pf2 = fopen (argv[2],w) ) = = NULL
{ printf (nu se poate deschide fisierul%s\n, argv[2]);
exit(1);
}
while (( c = getc (pf1)) != EOF)
if (isascii(c) && isupper (c))
putc (c - A + a, pf2);
// c este codul unei litere mari
else
putc(c, pf2);
// c este codul unei litere mici
fclose (pf1);
fclose (pf2);
// afisarea fisierului destinatie
if (( pf2 = fopen (argv[2], r) = = NULL)
{ printf (nu se poate deschide in citire:%s\n, argv[2]);
exit(1);
}
while ((c = getc(pf2)) != EOF) putchar (c);
fclose (pf2);
}
11.2. MACROURI DE TRANSFORMARE A SIMBOLURILOR
n aceast clas distingem macrouri definite tot n fiierul
ctype.h. Prototipurile acestor macrouri sunt:
int toascii (int c);
returneaz ultimii 7 bii ai lui c
(care reprezint un
cod ASCII);
int tolower (int c);
transform pe c din liter mare n
liter mic;
transform
pe
din
liter
mic
liter mare.
11.3. CONVERSII
O dat are un format extern i un format intern. Prin conversie
nelegem o transformare a unei date dintr-un format al ei n cellalt.
Conversiile se pot face sub controlul unui format sau fr format. Dintre
funciile care realizeaz conversii sub controlul formatelor amintim:
printf;
fprintf;
scanf;
fscanf;
Aceste funcii au fost descrise n leciile anterioare. Vom da
n continuare cteva funcii care realizeaz conversii fr format i care
sunt utilizate mai frecvent. Aceste funcii au prototipurile n fiierul
stdlib.h.
Funcia atoi are prototipul:
int atoi (const char *ptr);
unde:
ptr este un pointer spre o zon de tip caracter ce conine cifre
zecimale care
sunt, eventual, precedate de semnul minus;
Efectul:
irul de cifre spre care pointeaz ptr este convertit din ntreg
zecimal n ntreg binar de tip int.
Observaie:
1o. Funcia returneaz rezultatul acestei conversii.
Funcia atol are prototipul:
long atol (const char *ptr);
unde:
ptr este un pointer spre o zon de tip caracter ce conine cifre
zecimale care
sunt, eventual, precedate de semnul minus;
Efectul:
irul de cifre spre care pointeaz ptr este convertit din ntreg
zecimal n ntreg binar de tip long.
Observaie:
1o. Funcia returneaz rezultatul acestei conversii.
Funcia atof are prototipul:
double atof (const char *ptr);
unde:
ptr este un pointer spre o zon de tip caracter ce conine cifre
zecimale care
sunt, eventual, precedate de semnul minus (poate conine marca
zecimal);
Efectul:
irul de cifre spre care pointeaz ptr este convertit n virgul
flotant dubl precizie.
Observaie:
1o. Funcia returneaz rezultatul acestei conversii.
Funcia itoa are prototipul:
char *itoa (int val, char *sir, int baza)
Efectul:
funciei
nseamn
se
realizeaz
Observaie:
1o. Fie irurile s1 i s2 de lungime l1 i l2. Atunci cele dou iruri
sunt egale dac:
l1=l2 ( au aceeai lungime);
s1[k] = s2 [k] pentru k=0,1,...,l1
2o. irul s1 este mai mic dect irul s2 dac exist un j, j 0 i j
min (l1, l2), astfel nct:
s1[j] < s2[j];
s1[k] = s2[k], pentru k=0,1, . . . , j-1.
3o. irul s1 este mai mare dect irul s2 dac exist un j, j 0 i j
(l1, l2), astfel inct:
s1[j] > s2[j];
s1[k] = s2[k], pentru k=0,1, . . . , j-1.
Funcia lungime:
unsigned strlen (const char *sir);
returneaz lungimea irului de caractere spre care pointeaz sir;
caracterul NUL care termin irul nu este numrat.
11.5. FUNCII DE CALCUL
Majoritatea funciilor matematice au prototipurile n fiierul
math.h. Multe dintre acestea se utilizeaz la calculul valorilor funciilor
elementare i au prototipul:
double nume (double x);
unde nume este unul din urmtoarele:
acos -arccos;
asin -arcsin;
atan -arctg;
cos
-cos;
sin
-sin;
exp
-ex;
log
-ln;
log10 -lg;
sqrt -rdcina ptrat;
ceil -returneaz cel mai mare ntreg mai mare sau egal cu x
(partea ntreag);
floor -returneaz cel mai mare ntreg mai mic sau egal cu x;
fabs -valoarea absolut;
sinh -sinus hiperbolic;
cosh -cosinus hiperbolic;
tanh -tangent hiperbolic;
Alte funcii:
double atan2 (double y, double x);
double pow (double x, double y);
double cabs (struct complex z);
- returneaz arctg(y/x);
- returneaz xy;
- returneaz modulul
numrului
complex;
double poly (double x, int n, double c[ ] )
returneaz
valoarea polinomului
de grad n n punctul x,
coeficienii
sunt c[0], . . . c[n].
n;
long labs (long n);
ntregul long n;
returneaz
valoarea
absolut
din
char *comanda)
execut
comand
DOS
pointeaz comanda;
si 1 la eroare.
prototipurile n stdlib.h i n process.h.
char
char
char
char
ti_min;
ti_hour;
ti_hund;
ti_sec;
};
Exemplu:
void main (void)
// afiseaza data si ora
{
struct date d;
struct time t;
getdate (&d);
gettime (&t);
printf (\n\t%02d/%02d/%04d,d.da_day, d.da_mon, d.da_year);
printf (\tora %02d:%02:%02\n, t.ti_hour, t.ti_min, t.ti_sec);
}
11.8. ALTE FUNCII DIVERSE DE UZ GENERAL
void clrscr (void);
prototipul n conio.h
void delay(unsigned i);
perioad de i
milisecunde;
void sleep(unsigned i);
perioad de i
secunde;
void nosound (void);
void sound(unsigned h);
egal cu h Hz.
suspend
execuia
programului
pentru
suspend
execuia
programului
pentru
LECIA 12.
GESTIUNEA ECRANULUI N MOD TEXT
Biblioteca standard a limbajelor C i C++ conine
pentru gestiunea ecranului. Acesta poate fi gestionat n 2 moduri:
modul text i
modul grafic.
funcii
placa
placa
placa
placa
HERCULES,
CGA, care
EGA, care
VGA, care
care
este
este
este
(*)
unde:
culoare_fond (background) = cifr ntre 0 i 7; (8 culori)
culoare_caracter (foreground) = ntreg ntre 0 i 15; (16 culori)
clipire = 128 (clipire) sau 0 (fr clipire)
Tabel cu numele culorilor:
Culoare
negru
albastru
verde
turcoaz
rou
purpuriu
maro
gri deschis
gri nchis
albastru deschis
verde deschis
turcoaz deschis
rou dechis
purpuriu magenta
galben
alb
clipire
Constant simbolic
BLACK
0
BLUE
GREEN
2
CYAN
3
RED
MAGENTA
BROWN
6
LIGHTGRAY
7
DARKGRAY
8
LIGHTBLUE
9
LIGHTGREEN
LIGHTCYAN
11
LIGHTRED
LIGHTMAGENTA
YELLOW
WHITE
15
BLINK
Valoare
1
4
5
10
12
13
14
128
Constant simbolic
alb/negru 40 coloane
color 40 coloane
alb/negru 80 coloane
color 80 coloane
monocrom
color 43 linii pentru EGA
i 50 linii pentru VGA
modul precedent
BW40
C40
BW80
C80
MONO
C4350
LASTMODE
Valoare
0
1
2
3
7
64
-1
cu
ajutorul
funciei
unde:
culoare este un ntreg cuprins ntre 0 i 7 cu semnificaia din
tabelul anterior al culorilor.
Culoarea caracterelor se seteaz cu ajutorul funciei textcolor
cu prototipul urmtor:
void textattr (int culoare);
unde:
culoare este un ntreg ntre 0 i 15.
Se pot seta ambele culori, precum i clipirea caracterului folosind
funcia textattr de prototip:
void textattr (int atribut);
unde:
atribut e definit cu ajutorul relaiei (*) de la nceputul leciei.
Observaie:
1o. Fiecare caracter de pe ecran se pstreaz pe doi octei:
pe un octet codul caracterului;
pe octetul urmtor atributul caracterului.
Exemple:
Programul urmtor seteaz o fereastr i modurile video alb/negru.
#include <conio.h>
void main (void)
{ textmode (BW80);
window (10,4,60,4);
clrscr ();
lowvideo ();
cputs(lowvideo);
normvideo ();
cputs (normvideo);
textmode (LASTMODE);
cprintf (\n\r Acionai o tast pentru a continua:);
getch ();
}
Programul urmtor afieaz toate combinaiile
pentru fond i caractere (adaptor EGA/VGA).
de
culori
#include <conio.h>
#include <stdio.h>
void main (void)
{ static char *tculoare [ ] = { 0 BLACK
negru,
1
BLUE
albastru,
2
GREEN
verde,
3
CYAN
turcoaz,
4
RED
rosu,
5
MAGENTA
purpuriu,
6
BROWN
maro,
7
LIGHTGRAY gri deschis,
8
DARKGRAY
gri inchis,
9
LIGHTBLUE
albastru deschis,
10
LIGHTGREEN verde deschis,
11
LIGHTCYAN turcoaz deschis,
12
LIGHTRED
rosu dechis,
13
LIGHTMAGENTA
purpuriu magenta,
14
YELLOW
galben ,
15
WHITE
alb};
int i,j,k;
struct text_info atribut;
gettextinfo (&atribut);
for (i = 0; i < 8; i++ )
// i alege culoarea fondului
{ window (3,2,60,20);
k=2;
textbackground (i);
clrscr();
for (j=0; j <10; j++, k++) // j alege culoarea caracterului
{ textcolor (j);
gotoxy (2,k);
if (i = = j) continue;
cputs (tculoare[j]);
}
gotoxy (1,18);
printf (actionati o tasta pentru contiuare\n);
getch();
}
window (atribut.winleft, atribut.wintop, atribut.winright, atribut.winbottom);
posibile
din
simbol
CGA
MCGA
EGA
EGA64
EGAMONO
IBM8514
HERCMONO
ATT400
VGA
PC3270
n zona spre care pointeaz graphmode se memoreaz una din valorile:
pentru CGA
valoare
simbol
CGAC0
CGAC1
CGAC2
CGAC3
corespunznd toate pentru o rezoluie de 320*200 de pixeli i permit
4 culori
CGAHI
are o rezoluie de 640*200 puncte i lucreaz numai alb/negru.
pentru EGA
valoare
simbol
valoare
simbol
0
1
2
de
fond
curent
se
poate
apela
se
poate
determina
apelnd
funcia
modific
culoarea
simultan
mai
palet
poate
folosind
fi
obinut
funcia
apelnd
urmtor
afieaz
codurile
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
void main (void)
{ int gd = DETECT, gm, i;
struct palettetype far *pal = (void *) 0;
initgraph (&gd, &gm, C:\\BORLANDC\\BGI);
pal = getdefaultpalette ();
for (i=0; i<16; i++)
culorilor
pentru
paleta
pe
pe
orizontal
vertical
Exemplu:
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
void main (void)
{ int gd = DETECT, gm, cul_fond, cul_desen, curent_x,curent_y, maxx, maxy;
initgraph (&gd, &gm, C:\\BORLANDC\\BGI);
cul_fond = getbkcolor();
cul_desen = getcolor();
maxx = getmaxx();
maxy = getmaxy();
curent_x = getx();
curent_y = gety();
closegraph();
printf (culoarea fondului = %d\n, cul_fond);
printf (culoare desenare = %d\n, cul_desen);
printf (abscisa maxima = %d\n, maxx);
printf (ordonata maxima = %d\n, maxy);
printf (abscisa curenta = %d\n, curent_x);
printf (ordonata curenta = %d\n, curent_y);
printf (acionai o tasta pentru terminare);
getch();
}
LECIA 14.
PROBLEME DIVERSE
De multe ori suntem pui n faa unor probleme pe care le
nelegem uor dar nu tim cum s le rezolvm ct mai simplu i elegant. V
propunem cteva metode care bine nsuite pot duce, uneori, la o rapid
rezolvare a problemelor dificile. Evident c, nu toate problemele pot fi
ncadrate n aceste tipare propuse dar fiecare programator poate s-i
formeze un astfel de "portofoliu" de metode cu care s poate aborda orice
problem. Metodele prezentate n continuare pot constitui un nceput.
14.1. GENERAREA COMBINRILOR
printf("\ndati m: ");
scanf ("%d",&m);
comb(0);
kod=1;
while (kod)
{ printf("\n");
for (i=1;i<=m;printf ("%3d",v[i++]));
kod = comb(kod);
}
getche();
}
14.2. METODA GREEDY
Se aplic problemelor n care se d o mulime A coninnd n date
(de orice natur i structur) de intrare cerndu-se s se determine o
submulime B (BA) care s ndeplineasc anumite condiii pentru a fi
acceptat. Cum, n general, exist mai multe astfel de submulimi (numite
soluii posibile) se mai d i un criteriu conform cruia dintre aceste
submulimi s alegem una singur (numit soluie optim) ca rezultat final.
Foarte multe probleme de cutare se nscriu n acest tip.
Menionm c, n general, soluiile posibile au urmtoarele
proprieti:
- se presupune c este soluie posibil;
- dac B este soluie posibili CB atunci i C este soluie
posibil;
Vom da n continuare o variant a tehnicii greedy (denumire care
n traducere nseamnn lcomie, nghiire) n care se pornete de la mulimea
vid. Apoi se alege pe rnd, ntr-un anumit fel, un element din A neales
nc. Dac adugarea lui la soluia parial anterior construit conduce la o
soluie posibil, atunci se adaug, altfel se alege un nou element. Tot acest
procedeu se repet pentru toate elementele din A. Dm n continuare n
pseudocod o procedur:
procedure GREEDY (n,A,B)
B:=;
for i=1,n do
call ALEGE (A,i,x);
call POSIBIL (B,x,cod);
if cod=1 then
call ADAUG (B,x);
endif;
endfor;
return;
end procedure
Despre procedurile apelate din GREEDY precizm urmtoarele:
procedura ALEGE furnizeaz n x un element din A aj{ai,...,an} i
interschimb ai cu aj; dac la fiecare pas se cerceteaz ai atunci procedura
se simplific;
procedura POSIBIL verific dac elementul x poate fi adugat sau nu
mulimii pariale construit pn la pasul curent furniznd o valoare
boolean cod cu semnificaia:
cod = 1, dac B U {x}, este soluie posibil
cod = 0, altfel
procedura ADAUG nlocuiete pe B cu B{x}.
Obs. Procedurile de mai sus nu sunt necesare ntotdeauna, acest fapt
depinznd de complexitatea problemei. Oricum trebuie reinut cadrul de
rezolvare al acestui tip de problem.
Problem rezolvat
.,xn}.
Se
cere
progresii
aritmetice
atunci
procedure BTA(n,a,b,h)
integer n;
array primul(n),ultimul(n),ratia(n),x(n);
k:=1;
x(1):=primul(1)-ratia(1);
while k>0 do
cod:=0;
while ( x(k)+ratia(k) ultimul(k) and cod=0 )
x(k):=x(k)+ratia(k);
if k(x(1),...,x(k)) then cod:=1 endif;
endwhile;
if cod=0 then
k:=k-1
else
if k=n then write (x(1),...,x(n))
else k:=k+1
x(k):=a(k)-h(k)
endif
endif;
endwhile;
return;
end procedure
unde:
- primul(n) reprezint vectorul primilor termeni ai progresiilor
aritmetice;
ultimul(n)
reprezint
vectorul
ultimilor
termeni
ai
progresiilor aritmetice;
- ratia(n) reprezint vectorul raiilor progresiilor aritmetice;
De
evitarea
(n algoritmul
evitarea
xSn.
Problem rezolvat
n cte moduri se pot aranja 8 dame pe tabla de ah astfel nct s nu
se "bat" reciproc. S se foloseasc al doilea algoritm dintre cei menionai
anterior.
Prima variant
Acest program respect algoritmul anterior cu unele mici
modificri. Facem precizarea c vectorul x conine n componenta x[i] numrul
coloanei de pe tabla de ah pe care se va afla dama de pe linia i. Tiprirea
va reprezenta o permutare (din cele 8! soluii posibile). Se vor afla 92 de
soluii. Lsm pe seama cititorului s deduc analogiile i diferenele ntre
algoritm i program.
#include <stdio.h>
#include <math.h>
void main (void)
{ int x[9],cod,k,i,nr;
k=1; x[1]=0;nr=0;
while (k>0)
{ cod=0;
while (((x[k]+1)<=8)&&(cod= =0))
{ x[k]++;
if ((k= =1) && (x[k]= =1)) cod=1;
else { i=1; cod=1;
while ((cod==1)&&(i<k))
{ if ((x[i]==x[k])||(abs(x[i]-x[k])==k-i)) cod=0;
i++;
}
}
}
if (cod= =0) k--;
else {if (k= =8)
{ printf("\n%3d. ",++nr);
for (i=1;i<9;printf("%d ",x[i++]));
}}
else x[++k]=0;
}
}
}
A doua variant:
#include <stdio.h>
#include <math.h>
#define n 100
int x[100],cod,k,nc,nsol;
int Verifica(void)
{ int i,cod1;
// cod1=1 conditiile de continuare
cod1=1;
// sunt verificate
if (k>1)
// cod1=0 in caz contrar;
for(i=1; i<= (k-1); i++)
{ if (x[k]= =x[i]) cod1=0;
if (abs(x[k]-x[i]) = = k-i) cod1=0; // (*)
}
return cod1;
}
void ScrieSolutie(void)
{ int i;
printf("\n%3d. ",++nsol);
for (i=1; i<=nc; printf("%3d",x[i++]));
}
void CitesteDate(void)
{ int i;
nsol=0;
clrscr();
nc=n+1;
while ((nc>n) || (nc<0))
{ printf ("Dati n = ");
scanf ("%d",&nc);
};
}
void main (void)
{ CitesteDate();
k=1; x[1]=0;
while (k>0)
{ cod=0;
while (((x[k]+1) <= nc) && (cod= =0))
{x[k]++;
cod=Verifica();
}
if (cod= =0) k--;
else {if (k==nc) ScrieSolutie();
else x[++k]=0;
}
}
}
A doua variant este modular, mai uor de neles i
generalizeaz problema damelor pn la tabla de ah de 100x100. Lsm pe
seama cititorului modificarea funciei ScrieSolutie pentru a afla n mod
grafic tabla de ah.
Dac n funcia Verifica se terge instruciunea notat cu (*)
atunci se obin toate permutrile de n obiecte.
Probleme propuse
14.3.1
S se rezolve problema turelor de ah dup al doilea algoritm. n cte
moduri se pot aranja n turnuri pe tabla de ah astfel nct s nu se "bat"
reciproc.
14.3.2.
S se afieze poziiile succesive ale unui cal pe tabla de ah, pornind
dintr-o poziie dat, astfel nct s fie atinse toate csuele tablei de
ah.
14.3.3.
Avnd un fiier cu o mulime de cuvinte din limba romn de aceeai
lungime k s se scrie un program C care afieaz toate careurile rebusiste
fr puncte negre. ( Problema e fascinant implicnd i cunotine
gramaticale dar i cunoscnd faptul c nu s-au construit careuri de 10x10
fr puncte negre manual i nici cu ajutorul calculatorului; se poate ncerca
apoi i cu k:=11,12, . . .).
14.3.4.
Un intreprinztor dispune de un capital C i are n variante de
investiii. Pentru fiecare investiie i cunoate fondurile de investiie f i
precum i beneficiile bi. Se cere un program care s deduc toate variantele
posibile de investiii al intreprinztorului. Se mai dau i condiiile Cci
i {1, . . . ,n}.
14.3.5.
Avnd un graf neorientat caracterizat prin matricea costurilor s se
determine prin bactraking circuitul de cost minim pornind dintr-un vrf dat.
14.3.6.
Avnd un graf neorientat caracterizat prin matricea de inciden a
vrfurilor s se determine prin bactraking mulimile interior stabile
maximale.
14.3.7.
S se determine toate cuvintele binare de lungime 10 care conin exact
5 cifre de 1.
14.3.8.
prin
call
DI
(1,n,)
obinndu-se
eps este lungimea maxim a unei secvene {ap,...,aq} notat prin (p,q)
pentru care se face prelucrarea direct fr a mai fi necesar mprirea n
subprobleme;
procedura PREL realizeaz prelucrarea direct a secvenelor (p,q);
procedura COMB realizeaz combinarea rezultatelor i ale
prelucrrii a dou secvene vecine (p,m) i (m+1,q) obinnd rezultatul
al prelucrrii ntregii secvene (p,q);
prin procedura IMPARTE se obine valoarea lui m.
Vom da ca exemplu problema sortrii cresctoare a unui ir de
ntregi prin interclasare.
deoarece secvenele (i,i+1) sunt uor de ordonat acestea vor constitui
secvenele ce se vor prelucra, deci eps = 1;
- m se va calcula ca (p+q)/2, deci nu mai e nevoie de procedura
special IMPARTE;
procedura COMB va interclasa ntotdeauna dou secvene (p,m) i (m+1,q)
ordonate cresctor;
vom folosi un vector x drept structur global i vom face toate
prelucrrile pe elementele sale nemaiavnd nevoie de zonele ,;
pentru zona vom folosi un vector local y n procedura COMB acesta
coninnd elementele corespondente din x dar ordonate cresctor; tot n
procedura COMB se vor copia apoi elementele lui y din poriunea (p,q) n x;
evident c procedurile din schema general a algoritmului sunt funcii
C cititorul fcnd analogiile necesare.
#include <stdio.h>
#include <conio.h>
#define nrelem 100
int x[nrelem];
int n;
void PREL (int p, int q)
{int aux;
if ((p<q) && (x[p] > x[q])) {
aux=x[p];
x[p]=x[q];
x[q]=aux;
}
}
void COMB (int inf, int mijloc, int sup)
{int i,j,k,l;
int y[nrelem];
i=k=inf;
j=mijloc+1;
while (i<=mijloc && j<=sup)
{ if (x[i] <= x[j])
y[k++]=x[i++];
else
y[k++]=x[j++];
}
for(l=i; l<=mijloc; y[k++]=x[l++]);
for(l=j; l<=sup; y[k++]=x[l++]);
for(k=inf; k<=sup; x[k++]=y[k]);
}
DI (p,m);
DI (m+1,q);
COMB (p,m,q);
}
return;
}
void main(void)
{int i;
clrscr();
printf ("dati nr de elemente\n");
scanf ("%d",&n);
for (i=1; i<=n; i++)
{printf("x[%d]=",i);
scanf("%d",&x[i]);
}
DI (1,n);
printf("\nsirul sortat crescator este:\n");
for (i=1; i<=n; i++) printf("x[%d]=%d\n",i,x[i]);
getch();
}
14.5. METODA PROGRAMRII DINAMICE
Aceast metod este aplicabil problemelor de optim n care
soluia poate fi privit ca rezultatul unui ir de decizii d1, . . . ,dn.
Fiecare decizie depinde de deciziile deja luate i nu este unic determinat
(spre deosebire de tehnica greedy unde fiecare decizie care se ia trebuie s
fie unic). Totodat este necesar s fie satisfcut una din variantele
principiului optimalitii pentru a putea fi aplicat aceast metod.
Vom formaliza acest principiu al optimalitii:
fie d1,...,dn un ir optim de decizii (SOD) care transform starea so n
starea sn, trecnd prin strile intermediare s1, . . . ,sn-1; vom nota acest
fapt prin (d1,dn) este SOD pentru perechea de stri (so,sn);
grafic procesul este descris ca n figura urmtoare:
d1
d2
dn
*----->*---->*------>* . . . *------>*
so
s1 s2
sn-1 sn
Vom da acum mai multe variante ale principiului optimalitii:
dac (d1,dn) este SOD pentru (so,sn) atunci (d2,dn) este SOD pentru
(s1,sn);
2) dac (d1,dn) este SOD pentru (so,sn) atunci i din {1, . . . ,n-1}
avem
a) (d1,di) este SOD pentru (so,si) SAU
b) (di+1,dn) este SOD pentru (si,sn).
3) dac (d1,dn) este SOD pentru (so,sn) atunci i din {1, . . . ,n-1}
avem
a) (d1,di) este SOD pentru (so,si) I
b) (di+1,dn) este SOD pentru (si,sn).
Ultima variant este cea mai general i mai complet. Odat
verificat o form a principiului optimalitii, metoda programrii dinamice
const n a scrie relaiile de recuren i apoi de a le rezolva. n general
relaiile de recuren sunt de 2 tipuri :
fiecare decizie di depinde de di+1,...,dn - relaii de recuren nainte,
deciziile vor fi luate n ordinea dn, dn-1, . . . ,d1;
fiecare decizie di depinde de d1, . . . ,di-1 - relaii de recuren
napoi, deciziile vor fi luate n ordinea d1, d2, . . . , dn.
Problem rezolvat
Fie G=(X,) un 1-graf orientat cruia i atam matricea
costurilor, (fiecare arc (i,j) este etichetat cu o valoare real strict
pozitiv). Se pune problema gsirii drumului de valoare minim (DVM) ntre
oricare 2 vrfuri i i j.
Rezolvare
Verificm prima variant a principiului optimalitii:
- fie i, i1, i2, . . . , im, j DVM ntre i i j atunci evident c i1, .
. . , im, j este DVM ntre i1 i
j;
- notm prin L(i,k) lungimea DVM dintre i i k, kX;
- notm deasemenea dkj valoarea arcului (k,j);
- ecuaiile de recuren sunt:
L(i,j) = min {L(i,k) + dkj)}
(k,j)
#include<stdio.h>
#include<values.h>
#define nn 10
int d[nn+1][nn+1],i,j,n;
int L(int i,int j)
{
int m=MAXINT;
int k,x=0;
if (i= =j) m=0;
else
for (k=1;k<=n;k++)
if (d[k][j] < MAXINT)
{ x=L(i,k)+d[k][j];
if (x<m) m=x;
}
return m;
}
void citestematrice(void)
{int i,j;
printf("\ndati dimensiunea matricii distantelor : ");
scanf("%d",&n);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{ printf("d[%d,%d]= ",i,j);
scanf ("%d",&d[i][j]);
}
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) if (d[i][j]= = -1) d[i][j]=MAXINT;
}
void citeste(void)
{ printf("\ndati varful initial : ");
scanf("%d",&i);
printf("\ndati varful final : ");
scanf("%d",&j);
}
void afiseaza(int val)
{ printf("\nvdlm intre varful %d si %d este %d",i,j,val);
}
void main(void)
{ int vdlm;
clrscr();
citestematrice();
citeste();
vdlm=L(i,j);
afiseaza(vdlm);
getch();
}
Probleme propuse
14.5.1.
Se d o matrice A=(aij), i=1,...,n; j=1,...,m cu elementele din mulimea
{0,1,2}. Dou elemente din A aij i akl se numesc 4-vecine dac i-k+j-l =
1.
Notm cu So, S1 i S2 submulimile formate din elementele matricii egale
cu 0, 1 respectiv 2. Submulimea S1 se mparte n grupuri astfel: aij i akl
fac parte din acelai grup dac sunt 4-vecine sau dac apq S1 : aij i apq
sunt 4-vecine iar apk i akl sunt din acelasi grup. Un element akl So l vom
numi spion al grupului G S1 dac aij G a.. akl i aij s fie vecine. Un
spion este perfect dac are toi vecinii din G.
Se cere:
a) cel mai numeros grup (S1) care are un singur spion (dac exist).
b) toate grupurile care au cel puin doi spioni perfeci.
14.5.2.
Se d o matrice cu elemente care au valori din {d,o}, care reprezint
un teren cu drumuri {d} i obstacole {o}. n acest teren se afl un tanc i o
int. Acest tanc poate primi comenzi pentru rotirea evii (cu 90o n ambele
sensuri), pentru deplasare (n direcia evii cu o linie sau cu o coloan)
sau pentru tragere (n direcia evii pentru a nimeri inta) n cazul n care
ntre tanc i int nu exist nici un obstacol. Considernd c deplasarea nu
se poate efectua prin obstacole, se cere cel mai scurt drum necesar tancului
pentru a putea distruge inta i irul comenzilor efectuate n cazul n care
exist un astfel de drum.
14.5.3.
Se d o matrice cu elemente din {0,1,2,3}, reprezentnd o pdure cu
capcane (0) i crri (1). n aceast pdure se afl o vulpe (2) i mai muli
lupi (3). Fiecare lup ncearc s se apropie de vulpe fr a ti unde se afl
capcanele, iar n cazul n care cade ntr-o capcan, moare. Vulpea ncearc
s se ndeprteze de cel mai apropiat lup, avnd ns posibilitatea s
descopere i capcanele i s le ocoleasc. Att vulpea ct i lupii i pot
modifica poziia doar cu o linie sau cu o coloan n fiecare moment. S se
spun dac vulpea reuete s scape de lupi.
14.5.4.
Se consider un teren dreptunghiular sub forma unei matrici A de m
linii i n coloane. Elementele aij ale matricii conin cotele (nlimile)
diferitelor poriuni astfel obinute. Se presupune c o bil se gsete pe o
poriune (io,jo) avnd cota a(io,jo).
Se cere un program care s precizeze toate traseele (ncepnd cu (io,jo)
) posibile pe care le poate urma bila spre a iei din teren, tiind c bila
se poate deplasa n orice poriune de teren 4-nvecinat cu o cot strict
inferioar cotei terenului pe care se gsete bila.
14.5.5.
Se cere un program care rezolv problema labirintului (nerecursiv).
O matrice de m linii i n coloane reprezint un labirint dac:
a(i,j) = o - semnificnd culoar;
ANEX
UN MEMENTO AL SINTAXEI LIMBAJULUI C
SINTAXA LIMBAJULUI C
a)
b)
c)
d)
e)
<Sufix_ntreg>
<Sufix_unsigned>[<Sufix_long>]<Sufix_long>[<Sufix_unsigned>]
::=
<Sufix_unsigned> ::= Uu
<Sufix_long> ::= Ll
<Constant_real> ::= <Constant_fract>[<Exponent>][<Sufix_real>]
<Cifr> .. <Exponent>[<Sufix_real>]
<Constant_fract> ::= [<Cifr>] .. . <Cifr>..<Cifr>.. .
<Exponent> ::= Ee[+-]<Cifr> ..
<Sufix_real> ::= FfLl
<Constant_enumerare> ::= <Nume>
<Constant_caracter> ::= '<Caracter_C> ..'L'<Caracter_C>'
<Caracter_C> ::= <Orice_caracter_tipribil_cu excepia: ' i \>
<Secven_escape>
<Secven_escape> ::= \"\'\?\\\a\b\f\n\r\t\v
\<Cifr_octal>[<Cifr_octal>[<Cifr_octal>]]
\x<Cifr_hexa>
..
<ir_de_caractere> ::= "[<Caracter_S> ..]"
<Caracter_S>
::=
\><Secvena_escape>
<Orice_caracter_tipribil_cu
<Operatori_i_semne_de_punctuaie >::=
excepia:
'
+-*/%^&~!=->+=-
=*=
/=%=^=&=!=<<>><<=>>== =<=
>=<>&&!!++-,()[]{};?:...
B. Declaraii
<Unitate_de_compilare> ::= <O_declaraie> ..
<O_declaraie> ::= <Def_funcie><Declaraie>;
<Declaraie> ::= [<Specificatori>][<List_declaratori>]
<Specificatori> ::= <Specificator> ..
<Specificator> ::= <Clas_memorare><Tip>typedef
<Clas_memorare> ::= autoregisterstaticextern
<Tip> ::= <Tip_simplu><Nume_typedef><Calificator>
<Descriere_tip_enumerare><Descriere_tip_neomogen>
<Tip_simplu> ::= charshortintlongsignedunsignedfloatdouble void
<Nume_typedef> ::= <Nume>
<Decl_cmpuri>;[<Decl_cmpuri>;] ..
*[<Calificator> ..]
::=
<Specif_funcie> ::=
[<Specif_funcie>
..]<Declarator>[<Declaraie>;]
externstatic<Tip>
C. Expresii
<Expr> ::= <Expresie>[,<Expresie>] ..
<Expresie>
<Expr_condiional>|<Expr_unar><Oper_atribuire><Expresie>
<Oper_atribuire> ::= +*=/=%=+=-=<<=>>=&=^=!=
<Expr_condiional> ::= <Expr_SAU_logic>
<Expr_SAU_logic> ? <Expr> : <Expr_condiional>
::=
<Expr_SAU_logic>
<Expr_I_logic>
::=
<Expr_I_logic> ::=
<Expr_I_logic><Expr_SAU_logic>
!!
::=
<Expr_deplasare>
<Expr_relaional>
::=
<
<Expr_relaional>
>
<Expr_relaional>
<=
<Expr_relaional>
>=
<Expr_deplasare>
<Expr_deplasare>
<Expr_deplasare>
<Expr_deplasare>
<Expr_aditiv>
::=
<Expr_aditiv>
<Expr_deplasare>
<<
::=
<Expr_multiplicativ><Expr_aditiv>
<Expr_aditiv>
<Expr_multiplicativ>
<Expr_multiplicativ>
<Expr_multiplicativ>::=
<Expr_prefixat>
<Expr_multiplicativ> / <Expr_prefixat>
<Expr_multiplicativ> % <Expr_prefixat>
<Expr_prefixat> ::= <Expr_unar>(<Decl_tip>)<Expr_prefixat>
<Expr_unar> ::= <Expr_postfixat><Op_unar><Expr_prefixat>
++<Expr_unar> --<Expr_unar>sizeof<Expr_unar>
sizeof(<Decl_tip>)
<Op_unar> ::= &*+-~!
<Expr_postfixat> ::= <Termen><Expr_postfixat>[<Expr>]
<Expr_postfixat>(<List_Expresii>) <Expr_postfixat> .
<Nume>
<Expr_postfixat>
->
<Nume><Expr_postfixat>
++
<Expr_postfixat>-<Termen> ::= <Nume><Constant><ir_de_caractere>(<Expr>)
<List_Expresii> ::= [<Expr>] ..
<Expr_constant> ::= <Expr_condiional>
D. Instruciuni
<Instr>::=
<Instr_etichetat><Instr_compus>
<Instr_expresie>Instr_de_selecie>
<Instr_de_ciclare><Instr_de_salt>
<Instr_etichetat> ::= <Nume>:<Instr>case <Expr_constant { :<Instr>
default : <Instr>
<Instr_compus> ::= <Bloc>
<Bloc> ::= {[<Declaraie>;] .. [<Instr>] ..}
<Instr_expresie> ::= [<Expr>];
while (<Expr>)<Instr>;
do <Instr> while (<Expr>);
for ( [<Expr>];[<Expr>];[<Expr>] ) [<Instr>];
CUPRINS
BIBLIOGRAFIE
Brian W.Kerninghan, Dennis M. Ritchie, The C Programming Language, INC.
Englewood Cliffs, New Jersey, 1978.
Liviu Negrescu, Limbajul C, Editura Libris, Cluj-Napoca, 1997.
G. Moldovan, M. Lupea, V.Cioban, Probleme pentru programare n limbajul
C, Litografia Universitii Babe-Bolyai, Cluj-Napoca, 1995.