Programare C
Programare C
Bibliografie
Brian W. Kernighan, Dennis M. Ritchie
Programarea in limbaj C
Al Kelley, Ira Pohl: A Book on C - Programming in
C, Addison Wesley, Reading
Herbert Schildt: C Manual Complet, Bucuresti, Ed.
Teora 1998
E. Horowitz, S. Sahni, S. Anderson - Freed:
Fundamentals of Data Structures in C, Computer
1
Primul program C
#include <stdio.h>
int main(void)
{
printf(“Salut!\n”);
printf(“Iata primul program C!”);
return 0;
}
2
Caracterele limbajului C
Litere:
A B C D… X Y Z
a b c d …x y z
Cifre: 0 123456789
Alte caractere:
+-*/=(){}[]<>„“!#%&_
|^ ~ \ . , ; : ?
Caractere spaţiu: blank, newline,tab, etc.
3
Tipuri standard
Tipul char
Tipurile standard întregi:
5 tipuri întregi cu semn: signed char, short int,
int, long int, şi long long int.
5 tipuri întregi fără semn: desemnate de cuvântul
unsigned (tipuri ce ocupă aceeaşi cantitate de
memorie)
Tipuri reale flotante: float, double,şi long
double.
4
Tipuri de date standard
ECHIVALENTE
signed short int short
unsigned short int unsigned
short
signed int int
unsigned int unsigned
signed long int long
unsigned long int unsigned
long
5
Declaraţii
Forma unei declaraţii:
tip variabila;
tip var1, var2, …, varn;
tip variabila = expresie_constanta;
Variabile globale: declararea lor se face la începutul
programului, în afara oricarei funcţii.
Variabile locale: declararea se face în corpul funcţiei, la
început.
char c;
signed char sc;
int i;
int suma = 0;
long j;
float x;
float pi = 3.14;
double y;
6
Tipul întreg
int
sizeof(int) = 2 sau 4 octeti
short int sau short
sizeof(short)=2, {-32768,…,32767}
long int sau long
sizeof(long) = 4
{-2 147 483 648, …, 2 147 483 647}
signed int, signed short int,
signed long int
7
Întregi fără semn
unsigned int
unsigned short int
{0,…,65535}
unsigned long int
8
Întregi “foarte scurţi”: char
sizeof(char) = 1
9
Citiri, afişări
10
Constante - exemplu
/* Exemple de constante caracter */
#include <stdio.h>
int main(){
char a, b, c, d;
a = 'A'; b = 65; c = '\101'; d = '\x41';
printf("%c %c %c %c\n", a, b, c, d);
printf("%c %d %o %x\n", a, a, a, a);
return 0;
}
/*
A A A A
A 65 101 41
*/
11
Codurile ASCII
# include <stdio.h>
int main (void){
short c;
for(c=0; c<= 127; c++){
printf("cod ASCII:%d",c);
printf(" caracter:%c\n",c);
}
return 0;
}
/* for(c=„a‟; c<=„z‟; c++) */
12
Macrourile getchar() si putchar()
Sunt definite in <stdio.h>
Citire caracter de la tastatură
Scriere caracter pe ecran
#include <stdio.h>
int main(void){
char c;
while ((c=getchar()) != EOF)
{putchar(c); putchar(c);}
return 0;
}
//123456abcd
//112233445566aabbccdd
13
Operaţii, Funcţii în biblioteci
14
Operatorii ++ şi --
15
Tipul flotant (real)
float
Numere reale în simplă precizie
sizeof(float) = 4
10-37 <= abs(f) <= 1038
6 cifre semnificative
double
Numere reale în dublă precizie
sizeof(double) = 8
10-307 <= abs(f) <= 10308
15 cifre semnificative
16
Tipul flotant (real)
long double
Numere reale în “extra” dublă precizie
sizeof(float) = 12
10-4931 <= abs(f) <= 104932
18 cifre semnificative
Limitele se găsesc în <float.h>
Operaţii:
+ - * /
== != < <= > >=
17
Constante reale
18
Funcţii (în biblioteca <math.h> )
19
Citire, afişare
citirea unui float
printf(“x: “);
scanf(“%f”, &x);
afişarea unui float
float pi = 3.14;
printf(“pi = %f”, pi);
citirea unui double
printf(“x: “);
scanf(“%lf”, &x);
afisarea unui double
double pi = 3.14L;
printf(“pi = %lf”, pi);
20
Utilizare typedef
21
Date booleene (logice)
Nu exista un tip special pentru date logice;
Domeniul de valori: {false, true}
false = 0
Operaţii:
! && || == !=
O declaraţie posibilă:
typedef enum {false = 0, true = 1} bool;
bool x, y;
22
Expresii logice
expresie_relationala ::=
expr < expr | expr > expr
| expr <= expr | expr >= expr
| expr == expr | expr != expr
expresie_logica ::= ! expr
| expr || expr
| expr && expr
23
Valoarea expresiilor relaţionale
pozitiv 0 1 0 1 0 1
zero 0 0 1 1 1 0
negativ 1 0 1 0 0 1
24
Valoarea expresiilor logice ||
Nu se
0 1
evaluează
1 dacă exp2 0
=0 Se evaluează
0 dacă exp2 = 0
25
Valoarea expresiilor logice &&
Nu se
=0 0
evaluează
1 dacă exp2 0
0 Se evaluează
0 dacă exp2 = 0
26
Exemple
27
Operatorul condiţional ?:
28
Operatorul condiţional ?: Exemple
x >= 0 ? x : y
x > y ? x : y
x>y ? x>z ? x :z : y>z ? y : z
#include <stdio.h>
int main(void){
int a=1, b=2, c=3;
int x, y, z;
x = a?b:c?a:b;
y = (a?b:c)?a:b; /* asociere stanga */
z = a?b:(c?a:b); /* asociere dreapta */
printf("x = %d, y = %d, z = %d\n", x, y, z);
}
/* x = 2, y = 1, z = 2 */
29
Operatorul “=“ (Expresia de atribuire)
Expresia de atribuire:
exp1 = exp2
exp1 este o “L-value” (obiect din memorie: variabilă,
variabilă tablou cu indici, etc.)
Tipul expresiei este tipul lui exp1
Se evaluează exp2 apoi exp1 capătă valoarea lui
exp2, eventual convertită.
Aşadar, operatorul = modifică valoarea operandului
stâng
Valoarea expresiei este valoarea lui exp1 după
evaluare
Operatorul = este drept asociativ
30
Operatorul “=“ (Expresia de atribuire)
Exemple:
x = sqrt(9)
a = ( b = 2) + ( c = 3)
a = b = c = 0 echivalenta cu
a = (b = (c = 0))
while((c = getchar()) != EOF) putchar(c);
Nu confundaţi e1 = e2 cu e1 == e2
a = 22;
if ( a == 0)printf(“nul”)
else printf(“nenul”); /* nenul */
if ( a = 0)printf(“nul”)
else printf(“nenul”); /* nul */
31
Operatori de atribuire compusă
32
Operatorul virgulă,
Exemple:
a = 1, b = 2
i = 1, j = 2, ++k + 1
k != 1, ++x * 2.0 + 1
for(suma = 0, i = 1; i <= n; suma += i, ++i);
33
Tipul void
34
Operatorul sizeof()
sizeof(char)<=sizeof(short)<=sizeof(int)<=sizeof(long)
sizeof(signed)=sizeof(unsigned) = sizeof(int)
sizeof(float)<=sizeof(double)<=sizeof(long double)
35
Operatorul sizeof()
#include<stdio.h>
int main(void){
int x=1; double y=9; long z=0;
printf("Operatorul sizeof()\n\n\n");
printf("sizeof(char) = %2u\n",sizeof(char));
printf("sizeof(int) = %2u\n",sizeof(int));
printf("sizeof(short) = %2u\n",sizeof(short));
printf("sizeof(long) = %2u\n",sizeof(long));
printf("sizeof(float) = %2u\n",sizeof(float));
printf("sizeof(double) = %2u\n",sizeof(double));
printf("sizeof(long double) = %2u\n",sizeof(long
double));
printf("sizeof(x +y + z) = %2u\n",sizeof(x+y+z));
printf("sizeof(void) = %2u\n",sizeof(void));
return 0;
}
36
Operatorul sizeof()
Rezultatul executiei Visual C++ (Djgpp):
sizeof(char) = 1
sizeof(int) = 4
sizeof(short) = 2
sizeof(long) = 4
sizeof(float) = 4
sizeof(double) = 8
sizeof(long double) = 8 ( 12 Djgpp)
sizeof(x +y + z) = 8
sizeof(void) = 0 (1 Djgpp)
37
Precedenţa operatorilor
OPERATORI ASOCIERE
() ++ -- (postfix) stânga
++ -- (prefix) ! & (adresa) dreapta
* (deref ) + - (unari) sizeof()
* / % stânga
+ - stânga
< <= > >= stânga
== != stânga
&& stânga
|| stânga
?: dreapta
= += -= *= /= %= dreapta
, (operatorul virgulă) stânga
38
Forţarea tipului - cast
39
Exemplu cast
#include <stdio.h>
int main(void){
int i, j; double x, y, z, t;
i=5/2; x=5/2; y=(double)(5/2);
j=(double)5/2; z=(double)5/2;
t=5./2;
printf(“%d, %g, %g, %d, %g, %g\n”,
i, x, y, j, z, t);
}
/* 2, 2, 2, 2, 2.5, 2.5 */
40
Fişiere în bibliotecă relative la tipuri
41
Instrucţiuni
Expresii: ; expresie;
Intreruperea secvenţei:
continue; break; return expr;
42
Instrucţiunea expresie
43
Instrucţiunea compusă (bloc)
instr_compusa ::=
{{lista_declaratii}0+{lista_instructiuni}0+}
o Grupează instrucţiuni într-o unitate executabilă.
44
Instrucţiunea compusă - Exemple
{
a += b += c;
printf(“a = %d, b = %d, c = %d\n, a, b, c);
}
if(x > y){
int temp;
temp = x; x = y; y = temp;
}
{
int a, b, c;
{
b = 2;c = 3;a = b += c;
}
printf(“a= %d”, a);
}
45
Instrucţiunile condiţionale if şi if-else
46
Instrucţiunile condiţionale if şi if-else
Exemple:
if(b == a) aria = a*a;
if(x < y)
min = x;
else
min = y;
if(a%2){
if(b%2) p = 1;
}else p = 2;
47
Instrucţiunile if şi if-else - Exemple
if (i>j)
if(k>l)
if(i>k) max = i;
else max = k;
else
if(i>l) max = i;
else max = l;
else
if(k>l)
if(j>k) max = j;
else max = k;
else
if(j>l) max = j;
else max = l;
48
“Dangling else Problem”
if (a == 1)
if (b == 2)
printf("*****\n");
else
printf("ooooo\n");
Nu lăsaţi forma codului să vă ducă în
eroare! Regula este: else este ataşat
celui mai apropiat if.
49
If-else-exemplu
int main(void){
float x, y, rezultat;
char operator;
printf("Expresia:(numar operator numar)\n");
scanf("%f %c %f", &x, &operator, &y);
if(operator == '+')
rezultat = x+y;
else if(operator == '-')
rezultat = x-y;
else if(operator == '*')
rezultat = x*y;
else if(operator == '/')
rezultat = x/y;
else{
printf("Eroare in scrierea expresiei!");
return 1;
}
printf("Rezultatul este: %f\n", rezultat);
return 0;
}
50
Instrucţiunea switch
switch(expresie_intreaga){
case exp_const1: instr1
case exp_const2: instr2
…
case exp_constn: instrn
default: instructiune
}
51
Instrucţiunea switch
Valoarea expresiei expresie_intreaga, care este de tip
int, se compară cu constantele exp_const.
scanf("%d", &i);
switch(i){
case 1: printf(" 1");
case 2: printf(" 2");
case 3: printf(" 3");
case 4: printf(" 4");
default: printf(" blabla! ");
}
2
2 3 4 blabla!
53
Instrucţiunea switch - exemple
scanf("%d", &i);
switch(i){
case 1: printf(" 1"); break;
case 2: printf(" 2"); break;
case 3: printf(" 3"); break;
case 4: printf(" 4"); break;
default: printf(" blabla! ");
}
2
2
54
Instrucţiunea switch - exemple
switch (nota)
{
case 1:
case 2:
case 3:
case 4:
printf("Nota nesatisfacatoare.");
break;
//...
}
55
Instrucţiunea while
instructiunea_while ::=
while(expresie) instructiune
while (expresie){
instructiune
}
instructiunea_urmatoare
56
Instrucţiunea while
57
Instrucţiunea do..while
instructiunea_do..while ::=
do instructiune while(expresie);
do{
instructiune
} while (expresie);
instructiunea_urmatoare
Se execută instructiune.
58
Instrucţiunea do..while
do{
c = getchar();
} while(c == ' ');
do{
printf("Introdu un intreg pozitiv:");
scanf("%d", &n);
if(error = (n <= 0))
printf("\nEroare! Mai incearca!\n");
}while(error);
59
Exemplu - calculator
#include <stdio.h>
int main(void){
float x, y, rezultat;
char operator, c;
int ERROR;
printf("Calculator pentru expresii de forma
numar operator numar\n");
printf("Folositi operatorii + - * / \n");
60
Exemplu - calculator
do{
ERROR = 0;
printf("Expresia: ");
scanf("%f %c %f", &x, &operator, &y);
switch(operator){
case '+': rezultat = x+y; break;
case '-': rezultat = x-y; break;
case '*': rezultat = x*y; break;
case '/': if(y != 0) rezultat = x/y;
else { printf("Impartire prin zero!\n");ERROR = 1;}
break;
61
Instrucţiunea for
instructiunea_for ::=
for (expr1; expr2; expr3) instructiune
63
Instrucţiunea for
64
Instrucţiunea for - exemplu
s 0 s = 0;
for i 1 to n do for (i = 1; i <= n; ++i)
s s + i s += i;
a 1 a = 1;
for i 1 to k do for (i = 1; i <= k; ++i)
a a * 2 a *= 2;
s 0 s = 0;
for i n downto 1 do for (i = n; i > 0; --i)
s s + i s += i;
65
Instrucţiunea for - exemplu
#define N 100
int i, suma=0;
for(i = 1; i<=N; i++)suma+=i;
int suma, i;
for(suma = 0, i=0; i <= N; suma += ++i);
int i = 0;
char c;
for(; (c = getchar()) != '\n'; ++i)
putchar(c);
66
Instrucţiunea for - exemplu
i = 1;
suma = 0;
for(;i <= N;++i) suma += i;
i = 1;
suma = 0;
for(;i <= N;) suma += i++;
i = 1;
suma = 0;
for(;;) suma += i++; // Bucla infinita
67
Instrucţiuni de întrerupere a secvenţei
continue;
se referă la bucla(for, while, do..while) cea mai
apropiată.
întrerupe execuţia iteraţiei curente şi trece
controlul la iteraţia următoare.
break;
se referă la bucla(for, while) sau instr. switch cea
mai apropiată.
produce ieşirea din bucla sau din switch şi trece
controlul la instrucţiunea următoare
68
Exemplu – for..continue
#include<stdio.h>
#define N 100
int main(){
int i, suma=0;
for(i = 1; i<=N; i++){
if(i%3 != 0) continue;
suma+=i;
}
printf("suma = %d", suma);
return 0;
}
/* suma = 1683 */
69
Exemplu – while..continue
70
Exemplu – for – continue - break
#include <stdio.h>
int main(void){
for(putchar('1');putchar('2');putchar('3')){
putchar('4');
continue;
// break;
putchar('5');
}
return 0;
}
71
continue vs. break
int t; int t;
for(;;){ for(;;){
scanf("%d",&t); scanf("%d",&t);
if(t==0)continue; if(t==0) break;
printf("%d\t",t); printf("%d\t",t);
} }
72
Pointeri
Declararea unei variabile pointer:
tip *nume_var_pointer;
nume_var_pointer este o variabilă ce poate
avea valori adrese din memorie ce conţin
valori de tip tip.
Exemple:
int *p, i; // int *p; int i;
p = 0;
p = NULL;
p = &i;
p = (int*) 232;
p “pointează la i”, “conţine adresa lui i”,
“referenţiază la i”.
73
Pointeri
Operatorul de dereferenţiere
(indirectare) * : int *p;
p este pointer, *p este valoarea variabilei
ce are adresa p
Valoarea directă a lui p este adresa unei
locaţii iar *p este valoarea indirectă a lui
p : ceea ce este memorat în locaţie
int a = 1, *p; a 1 p ?
p = &a; a 1 p
74
Pointeri
75
Pointeri
p == &i p == (&i) 1
**&p *(*(&p)) 3
r = &x r = (&x) eroare!
3**p/*q+2 (((3*(*p)))/(*q))+2 3
*(r=&j)*=*p (*(r=(&j)))*=(*p) 15
76
Pointeri
p = 0; p = 1;
p = (int*)1 ; v = 1;
p = v = q; p = q;
p = (int*)q; &3;
q = (float*)v; &(k+8);
*((int*)333); *333;
77
Pointeri
#include <stdio.h>
int main(void){
int i=5, *p = &i;
float *q;
void *v;
q = (float*)p;
v = q;
printf("p = %p, *p = %d\n", p, *p);
printf("q = %p, *q = %f\n", q, *q);
printf("v = %p, *v = %f\n", v, *((float*)v));
printf("(int*)456 = %p, *((int*)456) = %d\n", (int*)456,
*((int*)456));
return 0;
}
/*
p = 8fb3c, *p = 5
q = 8fb3c, *q = 0.000000
v = 8fb3c, *v = 0.000000
(int*)456 = 1c8, *((int*)456) = 0
*/
78
Funcţii
int suma(int n)
function suma(n) {
s 0 int s = 0;
for i 1 to n do int i;
s s + i for(i=1; i<=n; ++i)
return s s += i;
end return s;
}
79
Funcţii
Corpul functiei
80
Funcţii
nume_functie(expr1,…)
Argumente
Argumentele sunt expresii ce
substitue parametrii la un apel:
parametrii funcţiei sunt iniţializaţi cu
valorile argumentelor.
81
Funcţii: legarea parametrilor (apel prin valoare)
int sqr(int x)
x int
{
return x*x
} o copie
82
Funcţii: parametri pointeri
void dubleaza(int *x)
{ x int*
*x += *x;
*x int
}
a int 23
46
int a = 23;
adr
dubleaza(&a);
/* a == 46 */
83
Funcţii
#include <stdio.h>
void swap(int x, int y){
int temp = x; x = y; y = temp;
printf("x = %d, y = %d\n", x, y);
}
int main(void){
int a = 2, b = 3;
swap(a, b); // x = 3, y = 2
printf("a = %d, b = %d\n",a, b);
// a = 2, b = 3
return 0;
}
84
Funcţii
#include <stdio.h>
void swap(int *x, int *y){
int temp = *x; *x = *y; *y = temp;
printf("*x = %d, *y = %d\n", *x, *y);
}
int main(void){
int a = 2, b = 3;
swap(&a, &b); // *x = 3, *y = 2
printf("a = %d, b = %d\n",a, b);
// a = 3, b = 2
return 0;
}
85
Funcţii: parametri
parametri de intrare
int sqr(int x) {
return x*x
} intrare ieşire
parametri de iesire
int imparte(int x, int y, int *q, int *r) {
if (!y) return 1;
*q = x / y;
*r = x % y;
return 0;
}
parametri de intrare+iesire
void dubleaza(int *x) {
*x += *x;
}
86
Declarare tablouri unidimensionale
#define NMAX 15
int a[NMAX];
0 1 NMAX-1
a int[NMAX] ...
a[0] int
a[1] int
a[NMAX-1] int
87
Numele unui tablou
88
Parcurgerea unui tablou
p=a;
/* Varianta 4 */ for (i=0; i < n; ++i)
suma += p[i];
89
Aritmetica pointerilor
int *p; sizeof(int)
p p+1
double *p;
sizeof(double)
p p+1
90
Aritmetica pointerilor
p1 = a;
q1 = p1+1;
printf("%d",q1-p1);
printf("%d, %d", sizeof(int), (int)q1 - (int)p1);
q1 - p1 = 1
sizeof(int) = 4, (int)q1 - (int)p1 = 4
91
Aritmetica pointerilor
p2 = c;
q3 = p3+1;
printf("%d",q3-p3);
printf("%d, %d", sizeof(double),
(int)q3 - (int)p3);
q3 - p3 = 1
sizeof(double) = 8, (int)q3 - (int)p3 = 8
92
Tablourile ca parametri
void insert_sort(int a[], int n)
{
//...
}
/* utilizare */
int w[100];
...
insert_sort(w, 10);
93
Tablourile ca parametri
suma(v, 100);
suma(v, 8);
suma(&v[4], k-6);
suma(v+4, k-6);
94
Tablouri bidimensionale
int a[2][3];
a int[2][3]
a[0][0] int
a[0][1] int
a[0][2] int
a[1][0] int
a[1][1] int
a[1][2] int
95
Parcurgerea unui tablou bidimensional
double a[MMAX][NMAX]; /* decl. tablou bidim. */
double suma; /* suma elemenetelor din tablou */
suma = 0;
for (i = 0; i < m; i++)
for(j = 0; j < n; j++)
suma += a[i][j];
96
Tablouri bi-dim. văzute ca tablouri uni-dim.
a int[2][3]
a[0] int[3]
a[1] int[3]
97
Funcţia de alocare a memoriei
coloana 0 coloana 1 ...
linia 0 a[0][0] a[0][1] ...
linia 1 a[1][0] a[1][1] ...
... ... ... ...
98
Tablouri bidimensionale ca parametri
int minmax(int t[][NMAX],int i0,int j0,
int m,int n)
{
//...
}
/* utilizare */
if (minmax(a,i,j,m,n))
{
// ...
}
99
Iniţializarea tablourilor
100
Tablouri de char - Şiruri de caractere
Declarare şiruri:
#define MAX_SIR 100
...
char s[MAX_SIR];
Declarare cu iniţializare:
char s[] = “un sir” /* echivalent cu */
char s[7] = {„u‟, „n‟, „ „, „s‟, „i‟, „r‟, „\0‟}
Citirea unui sir:
printf("Sirul: ");
scanf("%s", s);
101
Tablouri de char - Şiruri de caractere
Determinarea lungimii:
lg = 0;
while (s[lg] != '\0') lg++;
i=0; j=lg-1;
while (s[i]==s[j] && i<j)
{ i++; j--; }
if (i >= j)
printf("\nSirul este palindrom.\n");
else printf("\nSirul nu este palindrom.\n");
102
Macrouri si functii pentru siruri
In fisierul ctype.h
issspace(c), isdigit(c), islower(c), …
In fisierul string.h
char *strcat(char *s1, const char *s2);
int strcmp(const char *s1,const char*s2);
103
Tipuri enumerative
o declaratie de forma
enum zi {lu, ma, mi, jo, vi, si, du};
declara un tip cu numele enum zi si cu constantele lu, ma,
mi, jo, vi, si, du
105
Structuri simple
106
Tipuri enumerative si Structuri simple
[Link] int
107
Structuri simple
108
Asocierea de sinonime pentru structuri
109
Asocierea de sinonime pentru structuri
110
Structuri complexe
un jucator are nume, o mana de carti si o suma de bani
typedef struct Jucator
{
char* nume;
Carte mana[4];
long suma;
} Jucator;
o masa are un numar si 4 jucatori
typedef struct Masa
{
int nr;
Jucator jucator[4];
} Masa;
111
Structuri complexe
112
Variabile dinamice - creare
double *px;
px = (double*)malloc(sizeof(double));
/* sau */
px = (double*)calloc(1, sizeof(double));
px double*
*px double
113
Variabile dinamice - distrugere
free(px);
px double*
*px double
114
Alocare tablouri 1
Alocare
double **a;
a = (double **)calloc(m,
sizeof(double*));
for (i=0; i<n; i++)
a[i] = (double *)calloc(n,
sizeof(double));
a[1][2] = 3.14;
printf("%lf", a[1][2]);
115
Alocare tablouri 2
Alocare
double *p;
p=(double *)calloc(m*n, sizeof(double));
a = (double **)calloc(m,
sizeof(double*));
for (i=0; i<m; i++)
a[i] = p+i*n;
a[1][2] = 3.1415;
L Elt[MAX] …
e0 en-1
0 nrElt-1 MAX-1
117
Lista liniara: implementare cu tablouri
#include "elt.h"
119
Lista liniara: implementare cu tablouri
int insereaza( Llin *l, Elt elt, int k )
{
int j;
121
Lista liniara: implementare cu tablouri
122
Lista liniara: implementare cu tablouri
Llin lista;
listaVida(&lista);
for (i=1; i<8; i++)
{
e = i;
if (coderr = insereaza(&lista, e, i-1))
printf("\n ERR LLIN: %d\n", coderr);
}
parcurge(&lista, afiseazaInt);
123
Liste liniare: implementarea cu liste inlantuite
L = (e0,…, en-1)
[Link]
e0 e1 … en-1
124
Liste liniare: implementarea cu liste inlantuite
/* testeaza exceptiile */
if ((k < 0) || (k > l->nrElt))
return ERR_LLIN_INDEX_GRESIT;
126
Liste liniare: implementarea cu liste inlantuite
/* stabileste noile legaturi */
if ((k == 0) || (l->prim == NULL)) { // primul sau
lista vida
q->succ = l->prim;
l->prim = q;
}
else { // nu-i primul si lista nevida
for (p = l->prim, j = 0; j < k-1; j++)
p = p->succ;
q->succ = p->succ;
p->succ = q;
}
int i, e, coderr;
Llin lista;
listaVida(&lista);
for (i=1; i<8; i++)
{
e = i;
if (coderr = insereaza(&lista, e, i-1))
printf("\n ERR LLIN: %d\n", coderr);
}
parcurge(&lista, afiseazaInt);
128
Domeniul de vizibilitate – “scope”
Un nume (variabilă, funcţie) poate fi utilizat numai după
ce a fost declarat. Declaraţia descrie proprietăţile
numelui
129
Domeniul de vizibilitate – “scope”
130
Domeniul de vizibilitate
#include <stdio.h>
variabila globala
int a;
int f(int x)
{
int y; parametru
y = x + a;
{
double a;
a = (double)y * 2.0;
variabila locala
y += (int) a;
}
a = y – x;
}
131
Exemplu
{
int a = 1, b = 2, c = 3;
printf(“%2d%2d%2d\n”, a, b, c); /* 1 2 3 */
{
int b = 4; float c = 5.0f;
printf(“%2d%2d%4.1f\n”, a, b, c); /* 1 4 5.0 */
a = b;
{
int c; c = b;
printf(“%2d%2d%2d\n”, a, b, c); /* 4 4 4 */
}
printf(“%2d%2d%4.1f\n”, a, b, c); /* 4 4 5.0 */
}
printf(“%2d%2d%2d\n”, a, b, c); /* 4 2 3 */
}
132
Clase de alocare a memoriei
Zona de memorie utilizată de un program C
cuprinde 4 subzone:
Zona text: codul programului
Zona de date: variabilele globale
Zona stivă: date temporare (variabilele locale)
Zona heap: memoria dinamică
Clasele de alocare a variabilelor:
Statică: în zona de date temporare
Auto: în stivă
Dinamică: în heap , alocate dinamic
Register: într-un registru de memorie
133
Alocarea implicită
Durata de viaţă vs. domeniu de vizibilitate
Variabile Variabile
globale locale
statică auto
Alocare la compilare la execuţie bloc
Iniţializare cu zero nu
134
Clase de alocare
Se poate utiliza cuvântul cheie auto în
declararea variabileor locale:
auto int a, b, c;
auto double f;
135
Clase de alocare - exemplu
/* fisierul main.c */
int a = 1, b = 2, c = 3; /* variabile globale */
int f(void); /* prototip */
int main(void){
printf(“a = %d, b = %d, c = %d, f() = %d\n”);
}
/* fisierul f.c */
int f(void){
extern int a; /* cauta a in afara fisierului
*/
int b, c; /* b, c locale */
a = b = c = 22;
return (a + b + c);
}
136
Clasa de alocare static - local
137
Exemplu
#include <stdio.h>
int f(void);
int main(void) {
int i;
for (i=0; i<10; i++){
if(!(i%3))
printf("\nFunctia f() este apelata a %d-a oara.", f());
}
return 0;
}
int f(void) {
static int nr_apeluri=0;
nr_apeluri++;
return nr_apeluri;
}
/*
Functia f() este apelata a 1-a oara.
Functia f() este apelata a 2-a oara.
Functia f() este apelata a 3-a oara.
Functia f() este apelata a 4-a oara.
*/
138
Clasa de alocare static - extern
O variabilă globală declarată static are
domeniul de vizibilitate redus la fişierul sursă
în care este declarată, doar după declaraţia sa:
int f(void){
/*variabila v nu este vizibila*/
}
static int v;
void g(void){
/* v este vizibila aici */
}
O funcţie definită/declarată static este vizibilă
doar în fişierul în care apare definiţia sa
139
Clasa de alocare static - extern
140
Clasa de alocare register
O variabilă declarată register solicită
sistemului alocarea ei într-un registru maşină,
dacă este posibil
Se utilizează pentru variabile “foarte
solicitate”, pentru mărirea vitezei de execuţie:
{
register int i;
for(i = 0; i < N; ++i){
/*… */
}
} /* se elibereaza registrul */
141
Domeniul de vizibilitate - rezumat
Într-un fişier (resp. bloc) un identificator este vizibil după
declararea sa până la sfârşitul fişierului (resp. blocului) cu
excepţia blocurilor(resp. subblocurilor) în care este
redeclarat
#define nume_macrodef
#define nume_macrodef macrodef
#define nume_macrodef(lista_arg)
#define nume_macrodef(lista_arg) macrodef
nume_macrodef ::= identificator
arg ::= identificator
lista_arg ::= arg |lista_arg, arg
macrodef ::= sir_unitati_lexicale_si_arg
143
Directivele #include si #define
#define pi 3.14159
#define egal ==
#define citeste scanf
#define patrat(x) ((x)*(x))
#define cub(x) (patrat(x)*(x))
#define min(x,y) (((x)<(y))?(x):(y))
#define printTablou(a, n, sirControl) \
for (i = 0; i < n; i++) \
printf(sirControl, a[i]); \
putchar(„\n‟)
#define new(X) (X*)malloc(sizeof(X))
144
#define Exemplu
#include <stdio.h>
#define swap(t,a,b) {t temp=a;a=b;b=temp;}
int main(){
int i=10, j=20;
float x=1.23,y=3.21;
printf("\ni=%d, j=%d, x=%f, y=%f",i,j,x,y);
swap(int,i,j);
swap(float,x,y);
printf("\ni=%d, j=%d, x=%f, y=%f",i,j,x,y);
return 0;
}
/*
i=10, j=20, x=1.230000, y=3.210000
i=20, j=10, x=3.210000, y=1.230000
*/
145
Macroul assert() din assert.h
Se utilizează în programe pentru a ne asigura că valoarea
unei expresii este cea pe care o anticipăm
#include <assert.h>
void f(char *p, int n){
assert( p != NULL):
assert(n > 0 && n < 10);
/*…*/
}
146
Macrouri în stdio.h şi ctype.h
#define getchar() getc(stdin)
#define putchar(c) putc((c), stdout)
#define NULL ((void*)0)
147
Macrouri predefinite
148
Macrouri predefinite
#include <stdio.h>
int main(void){
printf("Macrourile predefinite: \n");
printf("__DATE__ = %s\n", __DATE__);
printf("__FILE__ = %s\n", __FILE__);
printf("__LINE__ = %d\n", __LINE__);
printf("__STDC__ = %d\n", __STDC__);
printf("__TIME__ = %s\n", __TIME__);
return 0;
}
/*
Macrourile predefinite:
__DATE__ = Dec 4 2006
__FILE__ = ../Surse/Macro.c
__LINE__ = 6
__STDC__ = 1
__TIME__ = 17:43:24
*/
149
Operaţii bit cu bit
Se aplică expresiilor întregi
Complement ~ b = ~a;
Conjuncţie & c = a & b;
Disjuncţie | c = a | b;
Sau exclusiv ^ c = a ^ b;
Deplasare (shift) stânga <<
b = a << 5; x <<= 3;
Deplasare (shift) dreapta >>
b = a >> 5; x >>= 3;
Mască: constantă ce se utilizează pentru a
extrage biţii convenabili: 1, 255=28-1
150
Operatorii bit cu bit - precedenţa
151
Precedenţa operatorilor
OPERATORI ASOCIERE
() [] . -> ++ -- (postfix) stânga
++ -- (prefix) ! ~ & (adresa) dreapta
* (dereferentiere ) + - (unari) sizeof(tip)
* / % stânga
+ - stânga
<< >> stânga
< <= > >= stânga
== != stânga
& stânga
^ stânga
| stânga
&& stânga
|| stânga
?: dreapta
= += -= *= /= %= >>= <<= &= ^= |= dreapta
, (operatorul virgula) stânga
152
Operaţii bit cu bit – Exemplul 1
#include <stdio.h>
#include <limits.h>
void print_bit_cu_bit(int x, const char* s)
{
int i;
int n = sizeof(int)*CHAR_BIT;
int mask = 1 << (n-1);
printf("%s", s);
for (i=1; i <= n; i++) {
putchar(((x & mask) == 0)? '0' : '1');
x <<= 1;
if (i%CHAR_BIT == 0 && i<n)
putchar(' ');
}
printf("\n");
}
153
Operaţii bit cu bit – Exemplul 1
void main(int x){
int a = 0xA5b73, b = 0Xb0c8722;
int c = ~a, d = a&b, e = a|b, f =a^b;
print_bit_cu_bit(a, " a = ");
print_bit_cu_bit(b, " b = ");
print_bit_cu_bit(c, " ~a = ");
print_bit_cu_bit(d, "a&b = ");
print_bit_cu_bit(e, "a|b = ");
print_bit_cu_bit(f, "a^b = ");
print_bit_cu_bit(a<<3, "a<<3= ");
print_bit_cu_bit(b>>6, "b>>6= ");
}
154
Calificatorul const
const float pi = 3.14
pi este o constanta float cu memorie auto
valoarea variabilei pi nu mai poate fi modificata dupa
initializare
const int a = 5;
int *p = &a;
o atribuire de forma *p = ... poate modifica valoarea
variabilei a
compilatorul ar trebui sa sesizeze si sa se “plângă”
const int a = 5;
const int *p = &a;
p este un pointer la o constanta int si valoarea sa
initiala este adresa lui a
p NU este o constanta; o atribuire p = &b este OK
o atribuire de forma *p = ... NU mai este posibila
155
Calificatorul const
const int a = 5;
const int * const p = &a;
p este un pointer constant la o constanta int
o atribuire p = &b NU este OK
157
Fişiere. Structura FILE
Starea curentă a unui fişier este descrisă într-o structură
numită FILE şi care este definită în stdio.h
Programatorul poate folosi fişiere fără să cunoască în detaliu
structura FILE
159
Fişiere
memoria
*fp FILE informatii despre fisier
interna
fp FILE*
memoria
externa fisier
160
Fişiere. Structura FILE
FILE *inf, *outf, *f;
În stdio.h sunt definiţi pointerii:
stdin: fişierul standard de intrare
stdout: fişierul standard de ieşire
stderr: fişierul standard pentru erori
162
Funcţiile fclose(), fflush(), freopen()
int fclose(FILE *fp);
Realizează cele necesare pentru a închide un fişier:
goleşte buffer-ul şi întrerupe orice legătură între fişier
şi pointerul fp
Dacă se execută cu succes returnează zero
Dacă apare o eroare sau fişierul este deja închis se
returneaza EOF
int fflush(FILE *fp)
buffer
memoria
externa fisier
164
Funcţiile fprintf(), printf(), sprintf()
int fprintf(FILE *pf, const char *format, ...);
int printf(const char *format, ...);
165
Funcţiile fprintf(), printf(), sprintf()
caracter_de_conversie ::=
c|d|i|u|o|x|X|e|E|f|g|G|s|p|n|%
166
Funcţiile fprintf(), printf(), sprintf()
167
Funcţiile fscanf(), scanf(), sscanf()
168
Functiile fscanf(), scanf(), sscanf()
int i;
char c;
char sir[15];
scanf(“%d , %*s %% %c %7s %s”,
&i, &c, sir,&sir[7]);
Dacă stream-ul de intrare este:
45 , sir_ce_se_ignora % A string_citit**
45 se memoreaza in i
, se potriveste cu , din format
Este ignorat sirul sir_ce_se_ignora
% se potriveste cu % din format
A se memoreaza in c
string_ se memoreaza in sir[0]..sir[6] iar in sir[6] se pune „\0‟
citit** se memoreaza in sir[7]..sir[13] iar in sir[14] se pune „\0‟
169
Functii de intrare/iesire caracter
int fgetc(FILE *stream);
int getc(FILE *stream);
int getchar(void);
char*fgets(char *s, int n, FILE *stream);
char*gets(char *s);
170
Functii de intrare/iesire caracter
int fputc(int c, FILE *stream);
int putc(int c, FILE *stream);
int putchar(int c);
int fputs(const char *s, FILE *stream);
int puts(const char *s);
int ungetc(int c, FILE *stream);
171
Exemplu
/* Copiere fisier cu modificare litere mici */
/*..*/
char file_name[MAXSTRING];
int c;
FILE *ifp, *ofp;
172
Functii de citire/scriere fara format
size_t fread(void *ptr, size_t size,
sizet nelem, FILE *stream);
173
Functii de acces aleator
int fseek(FILE *fp, long offset, int place);
Exemple:
pozitionarea la sfirsitul fisierului
fseek(fp, 0, SEEK_END)
pozitionarea la caracterul precedent
fseek(fp, -1, SEEK_CUR)
pozitionarea la inceputul fisierului
fseek(fp, 0, SEEK_SET)
174
Functii de acces aleator
long ftell(FILE *fp);
Returneaza valoarea curenta a
indicatorului de pozitie in fisierul fp; la
fisierele binare este numarul de octeti de
la inceputul fisierului, pentru cele text
depinde de sistem
176
Exemplu
/* Scrierea unui fisier de la sfarsit */
/*..*/
char file_name[MAXSTRING];
int c;
FILE *ifp;
177
Functii pentru controlul erorilor
int feof(FILE *fp);
Intoarce o valoare nenula daca indicatorul end-of-file este
setat pentru fp
178
Parametri in linia de comanda
I:\AlgsiProg\Exemple>[Link] f_in f_out
utilizarea argumentelor
finp = fopen(arg[1],"r");
fout = fopen(arg[2],"w");
179