borland c manual
DESCRIPTION
Borland c ManualTRANSCRIPT
-
BORLAND
C
Versiunea 2.0
Manual de utilizare
-
STRUCTURA GENERAL A UNUI PROGRAM C
1.1. ISTORIC, CONCEPIE, EVOLUIE
Limbajul C a fost finalizat n 1972 de Dennis M. Ritchie i Brian W.
Kernighan de la firma american Bell Laboratories.
Prima versiune a limbajului se numete BCPL apoi urmtoarele poart
numele de A, B i C. Cei doi autori au dezvoltat aceste prime versiuni n
jurul sistemului de operare UNIX.
La vremea respectiv din aproximativ 13000 linii surs ale UNIX-ului
doar 200 de linii surs nu erau scrise n limbajul C. De acest fapt se
leag detractorii limbajului care spun c limbajul C nu este un limbaj
deosebit ci doar un fel de limbaj oficial al sistemului de operare UNIX.
n anul 1978 apare manualul The C Programming Language care este de
fapt i prima standardizare a limbajului. Cei doi autori intr astfel n
istorie...
Dup anul 1980 odat cu dezvoltarea hardware apar i primele PC-uri
iar acestea implic i produse software adecvate. Principalele firme
productoare de sofware -MICROSOFT i BORLAND - au dezvoltat unelte
adecvate pentru programarea i utilizarea limbajului C. Deocamdat firma
BORLAND deine supremaia prin versiunile mediului BORLAND C. Cele mai
folosite sunt versiunile 2.0, 3.1, 4.0. n ultimii doi ani au aprut aa
numitele medii visuale: VISUAL C versiunile 4.5 i 5.0 care sunt de fapt
extensii ale mediului BORLAND C adaptate programrii orientate obiect i
interfeei grafice WINDOWS 95. Mediile de programare BORLANDC pot compila 3
tipuri de programe surs C:
fiiere cu extensia .C (fiiere cu prg. standard C); fiiere cu extensia .CP (fiiere cu prg. C+,); fiiere cu extensia .CPP (fiiere cu programe C++).
Menionm c limbajul C++ a fost elaborat de Bjarne Stroustrup de la
AT&T. El este un superset al limbajului C i permite principalele concepte
ale programrii prin abstractizarea datelor i programrii orientate spre
obiecte.
Limbajul C este un limbaj hibrid avnd faciliti caracteristice
limbajelor de asamblare ct i faciliti ale limbajelor de nalt nivel.
Cteva dintre principalele caracteristici ale limbajului C sunt:
portabilitate: chiar dac acest concept nu-i definit foarte riguros spunem c un program este portabil dac el poate fi transferat uor de
la un tip de calculator la altul; limbajul C este un astfel de limbaj;
flexibilitate: compilatorul face un numr mai redus de controale (face multe conversii implicite);
programare structurat: limbajul are principalele structuri ale programrii structurate: structura secvenial, structura iterativ i
structura de selecie;
compactizare: unele instruciuni sunt scrise foarte compact; de exemplu i:=i+1 se poate scrie mai scurt ca i++;
lucrul pe bii i calcule cu adrese.
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]
[declaraii de date globale]
[declaraie prototip funcia f1 . . .
declaraie prototip funcia fn]
[Void main (void)
{ declaraii
instruciuni instruciuni
}]
[Implementare funcia f1]
. . .
[Implementare funcia fn]
[directive de preprocesare]
[declaraii de date globale]
[declaraie prototip funcia f1 . . .
declaraie prototip funcia fn]
[Void main (void)
{ declaraii
instruciuni instruciuni
}]
[implementare funcia f1]
. . .
[implementare funcia fn]
Funcia principal main este obligatorie pentru orice program
celelalte elemente fiind optionale. Pentru ca o anumit funcie s poat fi
apelat e necesar ca ea s aib declarat prototipul dac implementarea
(definiia) ei se afl dup funcia main (exemplul 1). Dac funcia
principal se afl la sfritul fiierului atunci nu mai e necesar
prototipul funciei apelate ci doar implementarea ei (exemplul 2).
Comparnd structura unui program C cu structura unui program PASCAL se
observ nivelul de imbricare diferit. n PASCAL apare o imbricare a
procedurilor i funciilor pe cnd n C nu exist o astfel de imbricare
(rmne la nivelul fiecrei funcii dac e cazul).
PASCAL C
...
1.2.1. Definiia unei funcii
Definiia unei funcii n limbajul C se compune din antet i corp. O
funcie poate fi apelat dac este precedat de definiia sau de prototipul
ei. Aceste lucruri care sunt valabile n limbajul C se regsesc i n
limbajul C++.
Antet i prototip
Antetul simplificat al unei funcii n C are formatul:
tip nume_funcie (lista_parametrilor_formali)
unde: tip - reprezint tipul valorii returnate de funcie sau dac
funcia nu
-
returneaz nici o valoare se pune cuvntul cheie void;
nume_funcie - reprezint un identificator clasic format dintr-un
mixaj
de litere i cifre, primul caracter fiind obligatoriu litera;
printre litere se numr i liniua de subliniere;
lista_parametrilor_formali nume de variabile separate prin virgule.
Exemple:
1) double radical (double x) // calculeaza radacina patrata din x si returneaza valoarea gasita
2) double radical_n (double x, int n) // calculeaza radacina de ordinul n din x
Prototipul unei funcii este asemntor antetului dar la sfrit se
pune caracterul ;
1.2.3. Corpul unei funcii
Corpul unei funcii C se compune din declaraii de variabile locale
i instruciuni scrise ntre acolade conform figurii de mai jos.
{ declaraii
instruciuni
}
i pentru c autorii limbajului C consider c un limbaj de
programare se nva mai repede scriind i executnd programe ct mai
timpuriu vom da un mic exemplu de funcie.
int modul (int i) // determina valoarea absoluta a intregului i si returneaza aceasta valoare
{ if (i < 0) return i; if (i = = 0) return 0; else return i; }
1.3. CONSTRUCIILE DE BAZ ALE LIMBAJULUI
1.3.1. Caractere
Limbajul C folosete setul de caractere al codului ASCII care se
codific prin numere ntregi din intervalul [0,127], adic 128 de coduri.
Un astfel de ntreg se pstreaz pe un BYTE (OCTET) adic pe 8 bii.
Mulimea caracterelor se mparte n trei grupe:
- caractere negrafice (coduri cuprinse ntre 00=NUL i 31) i
127=DEL;
- spaiu (codul 32);
- caractere grafice (coduri cuprinse ntre 33 i 126).
Caracterele grafice se mpart la rndul lor n:
litere mari (coduri ntre 65 i 90);
litere mici (coduri ntre 97 i 122);
cifre (coduri ntre 48 i 59);
caractere speciale (celelalte coduri).
Caracterele negrafice au diferite funcii. Astfel codul 10 semnific
LF (Line Feed), adic deplaseaz cursorul pe linia urmtoare n coloana 1,
iar codul 13 semnific CR (Carriage Return) adic deplaseaz cursorul n
coloana 1 aceeai linie. n limbajul C combinaia celor dou caractere se
noteaz prin:
\n
i are semnificaia trecerii cursorului la linie nou i coloana 1
(newline).
Tabulatorul orizontal (deplasarea cursorului peste un anumit numr de
poziii) se precizeaz prin notaia:
-
\t
S mai precizm c urmtoarele 3 caractere: spaiu, newline i
tabulator orizontal se mai numesc spaii albe (white spaces).
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:
::= | |
::= 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|_
::= 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.
Reprezentarea intern
Cuvnt cheie Mulimea valorilor Lungime (bii) Formatul intern
int ntregii din [-215; 215-1] 16 reprezentare
binar
short ntregii din [-215; 215-1] 16 reprezentare
binar
long ntregii din [-231; 231 - 1] 32 reprezentare binar
unsigned ntregii din [0; 216-1] 16 reprezentare binar
char 8 cod ASCII
float [-3.4*10-38; 3.4*1038] 32 virgul flotant
simpl precizie
double [-1.7*10-308; 1.7*10308] 64 virgul flotant
dubl precizie
-
Facem precizarea c se poate folosi i combinaia unsigned long
pentru ntregii fr semn n dubl precizie.
Cu tipurile de baz se pot defini i tipuri utilizator folosind
instruciunea struct.
1.3.5. Constante
O constant are un tip i o valoare. Att tipul ct i valoarea
unei constante se definesc prin caracterele care compun constanta
respectiv.
Constant ntreag zecimal
O constant ntreag este un ir de cifre care eventual este
prefixat de un semn (+ sau -) i postfixat de litera L sau l. O constant
ntreag se reprezint n binar pe 16 sau 32 de bii. Sufixul L sau l
foreaz reprezentarea pe 32 de bii.
Constant ntreag octal
O constant ntreag octal este un ir de cifre octale (cifre
cuprinse ntre 0 i 7) precedat de un zero nesemnificativ.
Constant ntreag hexazecimal
O constant ntreag hexazecimal este un ir de cifre hexazecimale
prefixat cu 0x sau 0X.
Exemple:
Reprezentare Interpretare
12345 ntreg zecimal reprezentat n binar pe 16 bii
-12345 ntreg zecimal reprezentat n binar pe 16 bii
12345L ntreg zecimal reprezentat n binar pe 32 bii
012345 ntreg octal reprezentat n binar pe 16 bii (o cifr
octal pe 3 bii)
0xabcd ntreg hexa reprezentat n binar pe 16 bii (o cifr pe 4
bii)
12345678 ntreg zecimal reprezentat pe 32 de bii
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 65
B 66
a 97
0 48
9 58
* 77
Anumite caractere negrafice au notaii speciale la scrierea
crora se utilizeaz caracterul backslash (\). Dm n continuare un tabel
cu cele mai folosite caractere negrafice:
Caracter Reprezentare ca i constant caracter Valoare cod ASCII
Backspace \b 8
Retur de car \r 13
Newline \n 10
Apostrof \ 39
Backslash \\ 92
Tabulator vertical \v 11
Salt pagin imprimant \f 12
Carcterul NUL \0 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 C trebuie declarate toate variabilele nainte de a fi
utilizate.
Exemple:
int a,b,c; // a, b, c sunt variabile de tip int reprezentate in binar pe 2 octei; float x,y,z; // x, y, z sunt variabile de tip float in format flotant simpla precizie pe 32 de
bii; char car; // car este o variabila de tip char pe 1 octeti poate conine coduri ASCII; long i,j,k; // i, j, k sunt variabile de tip long in format binar pe 32 de bii.
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]; // s-a declarat un tablou unidimensional de 5 componente; float a[5][3]; // s-a declarat un tablou bidimensional de 5*3=15 componente;
La elementele unui tablou ne referim prin variabile cu indici.
O variabil cu indici se compune din numele tabloului urmat de unul sau mai
muli indici, fiecare indice fiind inclus n paranteze drepte. Numrul
indicilor definete dimensiunea tabloului. Indicii sunt expresii care au
valori ntregi. Limita inferioar a indicilor este zero. Astfel dac t este
tabloul de tip int n exemplul de mai sus, elementele lui sunt:
t[0], t[1], t[2], t[3], t[4].
n cazul matricii a declarate mai sus elementele ei vor fi:
prima linie: a[0][0], a[0][1], a[0][2];
a doua linie: a[1][0], a[1][1], a[1][2];
...
a cincea linie: a[4][0], a[4][1], a[4][2];
Deci pentru dimensiunea k indicele variaz ntre 0 i lk-1.
Repartizarea memoriei pentru un tablou se face astfel: pentru
fiecare element al tabloului se repartizeaz o zon de memorie necesar n
conformitate cu tipul tabloului respectiv (pentru tipul int cte 2 octei,
pentru tipul float cte 4 octei, etc). Numele unui tablou este un pointer,
el poate fi utilizat n diferite construcii i el are ca valoare adresa
primului su element.
n desenul urmtor se indic repartizarea memoriei pentru
tabloul t din exemplul de mai nainte:
t
adresa lui
t[0]
t[0] t[1] t[2] t[3] t[4]
Comentariu
-
n limbajul C un comentariu se scrie ntre /* i */ pe oricte
rnduri. ntre /* i */ se poate scrie o succesiune arbitrar de caractere,
care ns nu poate s conin secvena de terminare (adic */). Comentariul
poate fi inserat ntr-un program n orice poziie n care este legal s
apar un caracter alb. El constituie o explicaie pentru programator sau
pentru utilizator. Compilatorul nu interpreteaz comentariul n nici un
mod. Comentariul se recomand a fi inserat n punctele n care
programatorul poate lmuri prin explicaii, anumite aspecte ale procesului
de calcul sau ale datelor utilizate. n mediile BORLAND C exist i o alt
convenie de a marca un comentariu la nivelul unui rnd cu ajutorul a dou
caractere slash (//), convenie pe care am folosit-o de altfel n exemplele
anterioare.
1.4. PREPROCESARE
Un program surs C poate fi prelucrat nainte de a fi compilat.
O astfel de prelucrare se numete preprocesare sau precompilare. Acest
lucru se realizeaz printr-un program special numit preprocesor. Acesta
este apelat automat nainte de a ncepe compilarea.
Preprocesorul limbajului C realizeaz urmtoarele:
includeri de alte fiiere (de obicei fiiere surs);
definiii i apeluri de macrouri simple;
compilare condiionat.
1.4.1. Includerea unui fiier surs
Fiierele surs pot fi incluse cu ajutorul directivei include.
Dou formate se folosesc pentru a include un fiier surs n locul n
care apare directiva (de obicei se pune la nceputul programului):
#include specificator_de_fisier
sau
#include
unde: specificator_de_fiier trebuie s fie un nume de fiier valid
din punct de vedere al sistemului de operare DOS i de obicei are extensia
.h sau .c.
Prima variant este folosit de obicei cnd fiierele de inclus sunt
furnizate de utilizator; dac nu este indicat calea atunci fiierele sunt
cutate n directorul curent i apoi n directoarele setate pentru
directiva include.
A doua variant este folosit pentru ncorporarea unui fiier
standard care se caut n directoarele setate pentru directiva include (de
obicei astfel de fiiere standard sunt livrate n biblioteci ataate
mediului de programare C).
Odat localizat fiierul dintr-o directiv include se
nlocuiete aceasta prin textul fiierului surs. Deci compilatorul nu va
mai ntlni directiva include ci textul fiierului inclus de preprocesor.
Includerile de fiiere se fac de obicei la nceput pentru ca
textele fiierelor surs (date i funcii) s poat fi utilizate n tot
fiierul surs de lucru. De aceea, la nceputul fiierelor surs vom
ntlni mai multe includeri de fiiere standard: stdio.h, stdlib.h, etc.
Textul unui fiier inclus poate la rndul su s conin directiva include.
Fiierul stdio.h (prescurtarea de la standard input output header) conine
printre altele i funciile standard de intrare-ieire printf i scanf.
Fiierele cu extensia .h se mai numesc i fiiere header (fiiere care se
pun la nceputul fiierului surs). Un alt exemplu de fiier header este
iostream.h folosit n mediul BORLAND C care conine funciile cin (console
input) i cout (console output).
-
1.4.2. Constante simbolice
Cu directiva define se pot defini constante simbolice i
macrouri. Constantele simbolice se definesc astfel:
#define nume succesiune_de_caractere
Preprocesorul substituie nume cu succesiune_de_caractere peste
tot n fiierul surs care urmeaz poziiei directivei define. Dac
succesiune_de_caractere nu ncape pe un rnd atunci se poate continua pe
rndul urmtor scriind caracterul \ la sfritul primului rnd.
Numele nume definit ca mai sus se spune c este o constant
simbolic. Se recomand ca nume s fie scris cu litere majuscule pentru a
scoate n eviden c este o constant simbolic.
Construcia succesiune_de_caractere folosit pentru a defini o
constant simbolic poate la rndul ei s conin alte constante simbolice.
O constant simbolic poate fi redefinit (tot cu define) sau
poate fi anihilat cu undef (#undef nume).
Exemple:
1) #define PROCENT 10 // din acest punct al fisierului sursa se substituie
// PROCENT cu 10 . . . #define PROCENT 15 // de aici PROCENT se substituie cu 15 . . . #undef PROCENT // din acest punct constanta simbolica PROCENT
// isi inceteaza existenta . . . #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
-
recomand ca definiiile variabilelor globale s fie scrise la nceputul
fiierului surs, pentru a fi accesate n orice funcie a fiierului.
Pentru a utiliza variabilele globale i n alte funcii situate
n alte fiiere surs dect n cel n care sunt definite, ele trebuie
declarate ca externe n funciile respective.
O declaraie de variabil extern coincide cu o declaraie obinuit
doar c ncepe cu cuvntul cheie extern.
Exemplu:
fiierul n care sunt declarate ca variabile globale fiierul n care sunt folosite ca variabile externe
int i; float f; void functie(. . .) void main(void) { extern int i; { i = 10; extern double f; . . . . . . f = 3.14; f = f*i; . . . . . . } }
Variabilele i i f sunt declarate n afara funciei main i n afara
oricrei funcii, deci sunt variabile globale. Ele pot fi folosite n toate
funciile din fiierul surs care conine definiiile lor. Pentru a le
utiliza n funcii situate n alte fiiere surs dect n cel n care sunt
definite ele sunt declarate ca externe. Deci variabilele i i f sunt
declarate ca externe n funcia functie din al doilea fiier surs. Cele
dou fiiere surs care pot fi scrise n momente i de persoane diferite se
pot asambla ntr-un singur program cu ajutorul directivei de preprocesare
include.
2.2. VARIABILE LOCALE
Variabilele locale nu sunt valabile n tot programul. Ele au o
utilizare local n dou feluri:
ca i variabile automatice (alocate pe stiv) la nivelul unei
funcii;
ca i variabile statice (alocate n zona programului) la nivel de
fiier (eventual i la nivelul unei funcii).
Variabilele declarate n interiorul unei funcii i care nu sunt
declarate ca externe sunt variabile locale. Lor li se aloc memorie pe
stiv la intrarea n funcia n care sunt declarate. La ieirea din
funcie, stiva se reface la coninutul dinaintea apelului i variabilele
locale pierd alocarea. Deci ori de cte ori se apeleaz o funcie,
variabilele locale acesteia (denumite i variabile automatice) se aloc
(primesc memorie) pe stiv i la ieirea din funcie variabilele locale
sunt terse din stiv.
Variabilele locale pot s nu fie alocate pe stiv, ci ntr-o
zon de memorie destinat acestui scop. O astfel de variabil local se
numete variabil static. O variabil local static se declar printr-o
declaraie obinuit, precedat de cuvntul cheie static. O variabil
static poate fi declarat att n corpul unei funcii ct i n afara
oricrei funcii. n cazul unei variabile statice declarat n interiorul
unei funcii alocarea nu se face pe stiv ci ntr-o zon de memorie
destinat acestui scop, aceasta fiind deosebirea esenial fa de
variabilele automatice. n cazul n care o variabil static este declarat
n afara funciilor, ea este definit din punctul n care a fost declarat
i pn la sfritul fiierului surs care conine declaraia ei. Spre
deosebire de variabilele globale, o variabil static nu poate fi declarat
ca extern i deci nu poate fi utilizat n funciile din alte fiiere
surs diferite de cel n care a fost declarat.
Se recomand ca tablourile mari s fie declarate statice, deoarece
dac sunt automatice pot depi capacitatea stivei (care are implicit 4K
octei).
Exemple:
-
Fiierul fisier1.c este un fiier surs care conine 2 variabile
globale i i d , o variabil static x i dou funcii f i main. Funcia
main conine variabila static a iar funcia f conine variabila static b.
int i; // definiia variabilei globale i double d; // definiia variabilei globale d static int x; // definiia variabilei statice x, locala fisierului fisier1.c void main (void) { static char a; // definiia variabilei statice a, locala funciei main float c; // definiia variabilei automatice c, locala funciei main /* in acest moment se pot folosi variabilele i,d,x,a si c */ . . . }
{ int p; // definiia variabilei automatice p, locala funciei f
static float b; // definiia variabilei statice b, locala funciei f /* in acest moment se pot folosi variabilele i,d,x, p si b */ . . . } Variabilele a i c fiind locale funciei main nu pot fi
utilizate n funcia f. Analog, variabilele p i b sunt locale n funcia
f, nu pot fi utilizate n funcia main.
Fiierul fisier2.c conine funciile f1 i f2 care intr n
componena aceluiai program ca i funciile main i f din fiierul
fisier1.c
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
-
cheie static. Astfel funcia respectiv devine local i deci apelabil
doar n fiierul n care este definit.
2.3. VARIABILE REGISTRU
Limbajul C ofer posibilitatea de a aloca anumite variabile n
regitri microprocesorului. Deoarece regitri constituie un tip de memorie
ultrarapid n anumite cazuri se poate economisi att timp de execuie ct
i memorie. Se pot aloca n regitri numai parametrii funciilor i
variabilele automatice de tip int, char i de tip pointer. O variabil
registru se declar n mod obinuit, precednd declaraia ei prin cuvntul
rezervat register.
Alocarea ntr-un registru a unei variabile se face numai dac
exist un registru disponibil. n caz contrar, variabila registru se aloc
pe stiv exact ca o variabil automatic. Alocarea se face n ordinea
declarrii variabilelor registru.
Exemplu:
void f (register int i) { register char c; register int j; . . . } Mai nti se aloc parametrul i ntr-un registru, apoi se aloc
c i j n ali doi regitri.
Se recomand alocarea n regitri a variabilelor care au o
utilizare mare, de exemplu a indicilor de tablouri.
2.4. INIIALIZARE
Variabilelor li se pot atribui valori iniiale. Pentru
variabilele globale valorile iniiale se atribuie prin definiiile lor, iar
n cazul celorlalte variabile se pot atribui valori prin declaraiile lor.
Pentru c de multe ori am folosit cuvintele definiia variabilelor sau
declaraiile varibilelor precizm c ele au neles distinct n anumite
contexte. O variabil global se definete o singur dat i se poate
declara ori de cte ori e necesar utilizarea ei n alte fiiere (evident
declarat extern). n cazul celorlalte tipuri de variabile definiiile i
declaraiile coincid. Totodat definiia i declaraia (prototipul) unei
funcii nu coincid.
O variabil simpl se poate iniializa printr-o declaraie de
forma:
tip nume=expresie;
Variabilelor globale i statice li se atribuie valori iniiale
la lansarea programului. Expresia utilizat n cazul acestor variabile
trebuie s fie o expresie constant care s poat fi evaluat de compilator
la ntlnirea ei. Aceasta, deoarece variabilele globale i statice se
iniializeaz prin valori definite la compilare.
Variabilele automatice se iniializeaz la execuie, de fiecare
dat cnd se activeaz funcia n care sunt declarate. Din aceast cauz,
nu mai este necesar ca expresia s fie o expresie constant. Totui, la
ntlnirea ei, trebuie s fie definii operanzii expresiei de iniializare.
Exemplu:
void f(int n) { int i=10; int k=i+n; . . . } La ntlnirea expresiei i+n sunt deja definii ambii operanzi:
-
i a fost n prealabil iniializat cu valoarea 10;
n are o valoare care e transferat la apel.
Variabilele globale i statice neiniializate au implicit valoarea
egal cu zero, iar varibilele automatice neiniializate au o valoare
iniial imprevizibil.
Tablourile se pot iniializa printr-o list de expresii incluse
ntre acolade. Astfel un tablou unidimensional se poate iniializa folosind
urmtorul format:
tip nume[n] = { exp1, exp2, . . . expn }
La iniializarea tablourilor se pot utiliza numai expresii
constante. Numrul expresiilor poate fi mai mic dect numrul elementelor
tabloului. Elementele neiniializate au valoarea zero n cazul tablourilor
globale i statice. Dac se iniializeaz fiecare element al tabloului
atunci numrul n al elementelor acestuia nu mai este obligatoriu n
declaraia tabloului respectiv. Deci se poate scrie astfel:
tip nume[ ] = { exp1, exp2, . . . expn};
Numrul elementelor tabloului se consider c este egal cu cel al
expresiilor care realizeaz iniializarea lor.
Pentru un tablou bidimensional vom folosi urmtoarea structur:
tip nume [n][m] = { {exp11, exp12, . . . exp1m}, // pentru linia
nti
{exp21, exp22, . . . exp2m}, // pentru linia a doua
. . .
{expn1, expn2, . . . expnm}, // pentru ultima linie
};
Numrul expresiilor poate fi mai mic dect m n oricare din
acoladele corespunztoare celor n linii ale tabloului bidimensional. n
acest caz se poate omite doar numrul n (al liniilor tablourilor), m fiind
obligatoriu. Formatul de iniializare a tablourilor bidimensionale se
extinde imediat pentru tablouri cu mai multe dimensiuni.
Tablourile de tip caracter pot fi iniializate folosind un
format mai simplu dect cel indicat anterior. Astfel. un tablou de tip
caracter se poate iniializa printr-o declaraie de forma:
char sir[n] = ir_de_caractere;
Evident, marginea superioar n poate fi omis i n acest caz.
Totodat compilatorul pune automat caracterul NUL dup ultimul caracter al
irului utilizat n iniializare.
Exemple:
1) int itab[] = {1,2,3,4,5} // tabloul de tip intreg are 5 elemente itab[0] = 1,. . . itab[4] = 5 2) int m[3][3] = {{-1,0,1},{-1},{0,1}}; // tabloul are 3 linii si 3 coloane.
Elementele primei linii sunt iniializate astfel:
m[0][0] = 1;
m[0][1] = 0;
m[0][2] = 1;
n linia a doua se iniializeaz numai m[1][0] = -1; Dac tabloul ar
fi declarat global sau static atunci m[1][1] i m[1][2] ar avea valoarea
zero. Altfel ele au o valoare imprevizibil.
Elementele ultimei linii se iniializeaz astfel:
m[2][0] = 0;
m[2][1] = 1;
-
declaraiile de mai jos sunt identice:
char sir [ ] = {L,I,M,B,A,J,U,L, ,C}; char sir [ ] = {LIMBAJUL C};
LECIA 3.
EXPRESII, OPERANZI, OPERATORI
3.1. EXPRESII
O expresie n limbajul C este format fie dintr-un operand fie din
mai muli operanzi legai ntre ei prin operatori. O expresie are o valoare
i un tip care se determin aplicnd operatorii conform prioritilor i
asociativitii acestora.
n limbajul C operatorii se asociaz de la stnga la dreapta,
exceptnd operatorii unari i de atribuire, care se asociaz de la dreapta
la stnga.. Totodat pot fi folosite parantezele rotunde pentru a impune o
anumit ordine n executarea operaiilor.
3.2. OPERANZI
Un operand n limbajul C poate fi una din urmtoarele elemente:
o constant;
o constant simbolic;
numele unei variabile simple;
numele unui tablou;
numele unei structuri;
numele unei funcii;
referirea la elementul unui tablou (variabil cu indici);
referirea la elementul unei structuri;
apelul unei funcii;
o expresie inclus n paranteze rotunde.
Unele dintre elementele de mai sus nu au fost nc definite, ele se
vor prezenta n leciile viitoare.
Exemple: 9876 - constant ntreag;
x - variabil simpl;
t[i][3] - variabil cu indici;
0xabcd - constant hexazecimal;
t - nume de tablou;
(expresie) - expresie inclus n paranteze rotunde.
f1 - numele unei funcii
3.3. OPERATORI
Operatorii limbajului C pot fi grupai n mai multe clase, dar oricum
ei pot fi folosii mpreun ntr-o aceeai expresie. Operatorii au ariti
diferite: unari, binari, ternari i totodat o anumit prioritate implicit
care e redat n tabelul de mai jos. Operatorii de aceeai prioritate se
afl trecui n aceeai linie. Liniile tabelulul conin operatorii
limbajului C n ordinea descresctoare a prioritilor. Astfel n prima
linie se afl operatorii de prioritate maxim, iar n ultima linie
operatorul virgul cu prioritatea cea mai mic. Cu excepia operatorilor
., ->,&,*, a parantezelor rotunde (folosite la definiia i apelul
funciilor) i a parantezelor drepte (folosite la variabilele cu indici)
ceilali operatori vor fi explicai n aceast lecie.
( ) [ ] . ->
- (unar) +(unar) *(unar) &(unar) ! ~ ++ -- (tip)
sizeof
* / %
+ -
>
< = >
-
= = !=
&
^
|
&&
| |
? : (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 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;
a0 are valoarea 0;
a>=b are valoarea 1;
a=b-a are valoarea 1;
a+b
-
= = (egal; dou semne = concatenate)
!= (diferit; semnele sunt concatenate).
Operatorii de egalitate au ambii aceeai prioritate i este
imediat mai mic dect a operatorilor relaionali. Operatorul = =
testeaz egalitatea a doi operanzi. Dac operanzii sunt egali atunci
rezultatul operaiei = = este 1, n caz contrar este 0. Operatorul !=
furnizeaz rezultatul 1 cnd cei doi operanzi sunt diferii i 0 cnd sunt
egali.
Exemple:
a= 2 i b=-1
atunci
a= =b are valoarea 0;
a!=b are valoarea 1;
a*b!=a+b are valoarea 1;
3.3.4. Operatori logici
Lista operatorilor logici este redat mai jos:
! (negaia logic - operator unar);
&& (I logic);
|| (SAU logic).
Operatorul ! are aceeai prioritate cu operatorii unari +
i -. Operatorul && este mai prioritar dect operatorul ||, dar are o
prioritate mai mic dect operatorii de egalitate.
n limbajul C nu exist valori logice speciale. Valoarea fals
se reprezint prin zero. Orice valoare diferit de zero reprezint valoarea
adevrat.
Dac operatorul ! se aplic la un operand a crui valoare
este zero, atunci rezultatul este 1. Dac acelai operator se aplic la un
operand a crui valoare este diferit de zero, atunci rezultatul este 0.
Dm n continuare tabelele operatorilor logici binari aplicate
valorilor 0 i 1.
&& 0 1 || 0 1 sau exclusiv 0 1
0 0 0 0 0 1 0 0 1
1 0 1 1 1 1 1 1 0
Chiar dac pentru sau exclusiv nu exist operator el se poate
realiza prin expresia urmtoare aplicat operanzilor a i b: !a&&b||!b&&a
sau folosind parantezele rotunde ((!a) &&b)||((!b)&&a).
Operatorii logici se evalueaz de la stnga la dreapta. Dac la
evaluarea unei expresii se ajunge ntr-un punct n care se cunoate
valoarea ntregii expresii, atunci restul expresiei nu se mai evalueaz.
Dac a=0 i b=1 atunci expresia ! a||b are valoarea 1 pentru c !a
are deja valoarea 1.
3.3.5. Operatori logici pe bii
Lista operatorilor logici pe bii este redat mai jos n ordinea
descrectoare a prioritilor:
~ (operator unar; complement fa de 1)
>>
-
Operatorul >> realizeaz deplasarea la dreapta care este
echivalent cu o mprire ntreag cu puteri a lui 2; a >> 3 este
echivalent cu [a/23].
Operatorul > 6) & ~(~ 0 >6 are valoarea 1111 1110 1010 1110
Al doilea operand pregtete o masc astfel:
~0 1111 1111 1111 1111
~0
-
3.3.6. Operatori de atribuire
n forma cea mai simpl operatorul de atribuire se noteaz cu
= i se utilizeaz n construcii de forma:
v=expresie;
(v este fie o variabil simpl, fie variabil cu indici sau un
element de structur).
Aceast construcie se mai numete expresie de atribuire. Ea este
considerat ca fiind un caz particular de expresie. Tipul ei coincide cu
tipul lui v, iar valoarea ntregii expresii este chiar valoarea atribuit
lui v.
O expresie de forma:
v1=(v=expresie);
este i ea legal i se efectueaz n felul urmtor :
se evalueaz expresia expresie i valoarea ei se atribuie lui v;
valoarea lui v se atribuie apoi i lui v1.
Deoarece operatorii de atribuire se asociaz de la dreapta la stnga,
expresia de mai sus se poate scrie i fr paranteze:
v1=v=expresie;
n general, putem realiza atribuiri multiple printr-o expresie
de forma:
vn =. . . =v1=v=expresie
Dac expresia din dreapta semnului egal are un tip diferit de cel al
variabilei v, atunci nti valoarea ei se convertete spre tipul variabilei
v i pe urm se realizeaz atribuirea,
Pentru operaia de atribuire, n afara semnului egal se mai
poate folosi i succesiunea :
op=
unde prin op se nelege unul din operatorii binari aritmetici sau
logici pe bii, adic unul din urmtorii:
% / * - + & ^ | >
Acest mod de construcie se folosete pentru a compacta un anumit tip
de atribuire. Astfel expresia:
v op = expresie;
este identic cu expresia de atribuire:
v = op expresie;
Exemple:
int i, j; double x, y; int v[10]; i=5; j=10; x=y=10.01; i +=1; // echivalenta cu i=i+1 si cu i++ x*=3; // echivalenta cu x=x*3 j
-
3.3.7. Operatori de incrementare i decrementare
Aceti operatori sunt unari i au aceeai prioritate cu
ceilali operatori unari ai limbajului C. Operatorul de incrementare se
noteaz prin ++ i mrete valoarea operandului cu unu, iar operatorul de
decrementare se noteaz prin - - i micoreaz valoarea operandului cu
unu. Operatorii sunt folosii prefixat i postfixat. Astfel operatorii
prefixai au notaia:
++operand;
- - operand;
Ei se aplic mai nti i apoi se folosete valoarea lor.
Astfel operatorii postfixai au notaia:
operand++;
operand - -;
Se folosete valoarea operanzilor i apoi se aplic incrementarea sau
decrementarea.
Menionm c aceti operatori se pot aplica numai la urmtorii
operanzi:
variabil simpl;
variabil cu indici;
referire la elementul unei structuri.
Exemple:
int i,j; double x,y; int vector [5]; j=i++; // este echivalent cu j=i si i=i+1; y=--x; // este echivalent cu x=x-1 si y=x; i=++vector[j] // este echivalent cu vector[j]=vector[j]+1 si i=vector[j]
3.3.8. Operatorul de conversie explicit (expresie cast)
Pentru forarea tipului unui operand se folosete o construcie de
forma:
(tip) operand
Prin aceasta valoarea operandului se convertete spre tipul indicat
n paranteze.
Exemplu:
int i,j; double y; i=8; j=5; y=i/j; // y are valoarea 1, pentru ca se face impartirea intreaga i/j
Dac vom converti operanzii i i j spre tipul double se va obine
rezultatul corect adic 1.6.
Deci:
int i,j; double y; i=8; j=5; y=(double) i / (double) j; // y are valoarea 1.6,
Construcia (tip) este un operator unar prin care se expliciteaz
conversia dorit. Are aceeai prioritate ca restul operatorilor unari.
3.3.9. Operatorul dimensiune (sizeof)
Pentru a determina lungimea n octei a unei date se poate
folosi construcia:
-
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) // are valoarea 2; sizeof (l) // are valoarea 4; sizeof (f) // are valoarea 4; sizeof (d) // are valoarea 8; sizeof (c) // are valoarea 1; sizeof (itablou[1]) // are valoarea 2; sizeof (dtablou[1]) // are valoarea 8; sizeof (itablou) // are valoarea 10; sizeof (dtablou) // are valoarea 40;
Regula conversiilor implicite
n general o expresie C conine operanzi de tipuri diferite.
Pentru operatorii binari exist situaii cnd operanzii nu sunt de acelai
tip i trebuie executate conversii astfel nct operatorii s se aplice
pentru operanzi de acelai tip. Aceste conversii le face automat
compilatorul. Exist o regul a conversiilor implicite care are urmtorii
pai:
fiecare operand de tip char se convertete spre tipul int i fiecare
operand de tipul float se convertete spre double;
dac unul dintre operanzi este de tip double atunci i cellalt se
convertete spre tipul double i rezultatul va avea tipul double;
dac unul dintre operanzi este de tip long, atunci i cellalt se
convertete spre tipul long i rezultatul va avea tipul long;
dac unul dintre operanzi este de tip unsigned, atunci i cellalt se
convertete spre tipul unsigned i rezultatul va fi de tipul unsigned;
la acest pas se ajunge numai dac ambii operanzi sunt de tip int i
deci operaia se execut cu operanzii respectivi, iar rezultatul va fi de
tip int.
Aplicnd regula de mai sus pas cu pas (la fiecare operator n
momentul efecturii lui), se ajunge n final la evaluarea ntregii expresii
i prin acesta se determin tipul expresiei. Regula conversiilor implicite
nu se aplic pentru operatorul de atribuire (valoarea expresiei din partea
dreapt a semnului de atribuire se convertete spre tipul variabilei din
stnga semnului egal).
Exemple:
int i, j, k; float a, b; double x, y; unsigned p; long r;
-
char c; expresii conversii tipul expresiei i-j/k nu int a/b a spre double b spre double double x+y nu double i+a a spre double i spre double double i-3.14 i spre double double i+3 nu int i+x i spre double double i-c c spre int int x+10 10 spre double double p-10 10 spre unsigned unsigned r*5 5 spre long long (double)(i/j) se realizeaz mprirea ntreag ntre i i j i rezultatul se convertete spre double double
Dac rezultatul unei operaii depete domeniul de valori ce
corespunde tipului rezultatului, valoarea respectiv se trunchiaz i
rezultatul este eronat.
3.3.11. Operatori condiionali
Operatorii condiionali sunt ? i : i se folosesc mpreun n
construcii de forma:
exp1 ? exp2 : exp3 Evaluarea se face astfel:
se evalueaz expresia exp1; dac exp1 este diferit de zero, atunci valoarea i tipul expresiei
condiionale sunt egale cu valoarea i tipul expresiei exp2; altfel cu
expresia exp3.
Exemplu: procesul de determinare a maximului a dou numere a i b
este:
dac a>b 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 ntr-
una 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 intrare standard;
- stdout ieire standard;
- stderr ieire standard pentru erori;
- stdprn ieire pe imprimant;
- stdaux intrare / ieire serial.
4.1. FUNCIA STANDARD printf
Funcia printf realizeaz ieiri cu format la ieirea standard
stdout, deci afiare la terminalul la care care s-a lansat programul.
Funcia printf se apeleaz printr-o instruciune cu formatul:
int printf (control, lista_expresii);
unde control este un ir de caractere care conine:
texte de scris;
specificatori de format pentru datele care se scriu din
lista_expresii.
lista_expresii conine expresii; valoarea fiecrei expresii se scrie
conform unui specificator de format corespondent din parametrul control.
Parametrul control este inclus ntre ghilimele, iar numrul
specificatorilor de format coincide cu numrul expresiilor din
lista_expresii. Dac dorim s scriem numai un text atunci parametrul de
control nu conine nici un specificator de format iar lista_expresii este
vid (practic este absent).
Un specificator de format are formatul BNF urmtor:
%[-][d..d][.d..d][l1]l2
Dup cum se observ un specificator de format ncepe ntotdeauna cu
caracterul procent (%). Dup acest caracter poate urma una din
construciile urmtoare:
- un caracter - opional; prezena acestui caracter indic cadrarea
la stnga a datei n cmpul n care se scrie (implicit data se scrie
cadrat la dreapta);
-un ir de cifre zecimale opional, care definete lungimea minim a
cmpului n care se scrie data corespunztoare din lista_expresii; data se
scrie astfel:
n cazul n care necesit o lungime mai mic se scrie cadrat la
dreapta sau stnga (n funcie de absena sau prezena semnului -)
n cazul n care necesit o lungime mai mare se va scrie pe attea
poziii cte i sunt necesare;
-un punct urmat de un ir de cifre zecimale (dup cum se observ
opional); acest element indic precizia datei care se scrie:
dac data se scrie n virgul flotant, precizia definete numrul de
cifre aflate dup marca zecimal (deci cte zecimale);
dac data este un ir de caractere atunci indic cte caractere se
scriu.
-
-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 tipul de conversie realizat
d - din int intern n zecimal extern
o - din int intern n octal extern
x - din int intern n hexazecimal extern (litere mici
pentru cifrele mai mari ca 9 deci a,b,c,d,e,f,)
X - din int intern n hexazecimal extern (litere mici
pentru cifrele mai mari ca 9 deci A,B,C,D,E,F)
u - din unsigned intern n zecimal extern fr semn
c - din binar intern (cod ASCII) n caracterul
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
Literele d, o, x, u pot fi precedate de litera l conversia
realizndu-se din formatul intern long n loc de int.
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 #include 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);
-
printf ("\ni*j = %5.5d",i*j); printf ("\ni*j = %05d",i*j); printf ("\na*b = %10.1f",a*b); printf ("\nA*B = %10.5lf",A*B); printf ("\nradical(a*b) = %lf",sqrt((double) a*b)); printf ("\nradical(A*B) = %15.10lf",sqrt(A*B)); printf ("\nradical(A*B) = %25.17lf",sqrt(A*B)); printf ("\nradical(A*B) = %25.19lf",sqrt(A*B)); getche(); // asteapta citirea unui caracter de la terminal }
Rezultatele execuiei programului sunt: i*j = 110 i*j = 110 i*j = 110 i*j = 00110 i*j = 00110 a*b = 1.6 A*B = 2.10000 radical(a*b) = 1.249000 radical(A*B) = 1.4491376746 radical(A*B) = 1.44913767461894372 radical(A*B) = 1.4491376746189437200 2) #define sir PC WORLD void main (void) { printf(*%10s*,sir); printf(*%-10s*,sir); printf(*%10.5s*,sir); printf(*%-10.5s*,sir); } Rezultatele execuiei programului sunt:
* 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.
-
Condiia c) este absent n definirea cmpului dac n specificatorul
de format nu este indicat lungimea maxim a cmpului.
Literele care termin un specificator de format sunt
asemntoare cu cele utilizate la funcia printf. n acest caz este
realizat conversia invers fa de cea realizat de funcia printf.
Litera Tipul conversiei realizate
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
-
valida formal intrarea datelor (atenie nu e o validare calitativ) se va
folosi o construcie de forma:
nr=scanf(...)
Prin construcia de mai sus se poate pune n eviden sfritul
de fiier, deoarece n acest caz scanf returneaz valoarea EOF. Sfritul
de fiier se poate genera de la tastatur acionnd n acelai timp tastele
CTRL i Z (deci CTRL / Z). Deorece funcia scanf citete datele de la
intrarea standard prin intermediul unei zone de memorie intermediare
(numit zon tampon sau buffer), ea are acces la caracterele din zona
tampon numai dup acionarea tastei ENTER (RETURN). De aceea dup
acionarea combinaiei CTRL / Z se va tasta i ENTER. Totodat aceast
intermediere face posibil eventuale corecturi nainte de a aciona tasta
ENTER.
Exemplu:
Vom citi un ntreg de cinci cifre de la intrarea standard i vom
afia cifrele respective precedate fiecare de dou spaii.
void main (void) { int c1,c2,c3,c4,c5; // c1,c2,c3,c4,c5 sunt cifrele intregului citit scanf(%1d %1d %1d %1d %1d, &c1,&c2,&c3,&c4,&c5); // se citesc cifrele intregului in cele 5 variabile cu %1d printf(%3d%3d%3d%3d%3d,c1,c2,c3,c4,c5); }
Pentru a citi iruri de caractere se va folosi funcia scanf
fr a mai pune operatorul de adres n faa numelui irului de caractere,
deoarece numele unui tablou reprezint un pointer (deci conine o adres i
anume adresa primului element de tablou).
Exemplu:
Vom citi numele i prenumele unei persoane i le afim pe
ecran.
#define MAX 20 void main(void) { char nume[MAX+1], prenume[MAX+1]; //declararea tablourilor de caractere scanf (%20s %20s,nume, prenume); //nu s-a mai pus operatorul de adresa printf (\nnumele: %s, prenumele: %s,nume,prenume); }
4.3. FUNCIA STANDARD putchar
Funcia standard putchar se poate utiliza pentru a scrie un
caracter n fiierul standard de ieire stdout, n poziia curent a
cursorului. Ea se apeleaz folosind o instruciune de apel de forma:
putchar (expresie);
unde expresie este codul ASCII al caracterului care se scrie la
ieirea standard.
Practic putchar nu este o funcie n sensul definiiei ce am
dat-o n lecia 1, ci este un macrou definit n fiierul header stdio.h,
care folosete o funcie special destinat prelucrrii fiierelor, funcia
putc, astfel:
#define putchar(c) putc(c,stdout)
Exemplu:
void main (void)
{ putchar (A); // scrie caracterul A in fisierul de iesire in poziia curenta a cursorului putchar (A+2) // scrie caracterul de cod ASCII A+2=65+2=67, adica litera C putchar (\n); // scrie caracterul newline; deci inceput de linie nou }
-
4.4. FUNCIA STANDARD getchar
Aceast funcie citete de la intrarea standard, stdin,
caracterul curent i returneaz codul ASCII al caracterului citit. Tipul
valorii returnate este int. La ntlnirea sfritului de fiier (CTRL/Z) se
returneaz valoarea EOF (adic -1). Ca i putchar, getchar este un macrou
definit n fiierul header stdio.h, cu ajutorul unei funcii speciale, getc
destinate prelucrrii fiierelor, astfel:
#define getchar() getc(stdin)
De obicei getchar se folosete n expresii de atribuire de
forma:
c=getchar();
Dup citirea caracterului curent de la intrarea standard se atribuie
variabilei c codul ASCII al caracterului cititi sau EOF la ntlnirea
sfritului de fiier.
Exemple:
1)
#include void main (void) { putchar(getchar() A + a); // citeste o litera mare si o rescrie ca litera mica } 2) exemplul urmtor testeaz dac s-a citit o liter mare i numai n
acest caz aplic transformarea ei n liter mic. n cazul n care la
intrare nu se afl o liter mare se rescrie caracterul respectiv.
#include void main (void) { intc c; putchar(((c = getchar() )>= A && c
-
Aceast metod de fapt nu este o metod propriu-zis ci este prima
modalitate de programare odat cu apariia calculatoarelor. Intuiia i
experiena programatorului joac un rol important. Fiecare programator i
are propriile reguli de programare. Programele sunt monolitice (un singur
corp de instruciuni), lungi i greu de neles de alt programator. nsui
cel ce a elaborat un astfel de program ntmpin dificulti de nelegere
a propriului program dup un timp oarecare.
5.1.2. Programare procedural
Odat cu apariia primelor limbaje de nalt nivel se utilizeaz
programarea procedural. Necesitatea ca anumite secvene de program s fie
folosite de mai multe ori duce la organizarea acestora n uniti distincte
de program numite n diverse limbaje subprograme, subrutine, proceduri,
etc. De multe ori procedurile trebuie s fie generale deci procesarea s
fac abstractizare de valorile datelor. De exemplu o procedur de calcul al
radicalului de ordinul 2 trebuie s calculeze acest lucru din orice numr
real pozitiv iar pentru cele negative s semnaleze eroare. Procedurile
trebuie deci parametrizate cu anumite variabile numite parametri formali.
Valorile de la apel ale parametrilor formali se numesc parametri efectivi.
Programarea procedural are la baz deci utilizarea procedurilor, iar
acestea realizeaz o abstractizare prin parametri. La apelare o procedur
funcioneaz dup principiul cutiei negre (black box): se cunosc intrrile
i ieirile rezultate din acestea dar nu i modul de transformare care nu e
important n acest moment.
n majoritatea limbajelor procedurale de programare se
consider 2 categorii de proceduri:
proceduri care definesc o valoare de revenire (denumite i funcii);
proceduri care nu definesc o valoare de revenire.
n limbajele C i C++ procedurile de ambele categorii se numesc
funcii.
5.1.3. Programarea modular
Pe msur ce complexitatea aplicaiilor a crescut, a aprut
ideea de a descompune problemele n subprobleme mai simple care la rndul
lor pot fi descompuse n altele mai simple i aa mai departe. n felul
acesta se ajunge la o descompunere arborescent a problemei date n
subprobleme mai simple. Programarea subproblemelor devine o problem mai
simpl i fiecare subproblem are o anumit independen fa de celelalte
subprobleme. De asemenea, interfaa ei cu celelalte subprobleme este
limitat i bine precizat prin procesul de descompunere a problemei
iniiale. De obicei, programarea unei subprobleme, component a
descompunerii arborescente a problemei iniiale, conduce la realizarea unui
numr relativ mic de proceduri (funcii). Aceste funcii pot prelucra n
comun anumite date. Unele dintre ele sunt independente de funciile
realizate pentru alte subprobleme componente ale descompunerii
arborescente. Altele realizeaz chiar interfaa cu subproblemele
nvecinate.
Despre funciile obinute n urma programrii unei subprobleme
se obinuiete s se spun c sunt nrudite. De obicei, aceste funcii,
mpreun cu datele pe care le prelucreaz, se pstreaz ntr-un fiier i
se compileaz independent.
O colecie de funcii nrudite, mpreun cu datele pe care le
prelucreaz n comun formeaz un modul. n felul acesta, problema iniial
se realizeaz printr-un program alctuit din module.
Programarea modular are la baz elaborarea programelor pe
module.
O parte din datele utilizate n comun de funciile modulului,
sau chiar toate datele modulului, nu sunt necesare i n alte module.
Aceste date pot fi protejate sau cum se mai spune, ascunse n modul.
Limbajul C i C++, permite ascunderea datelor n modul folosind
date care au clasa de memorie static. Mai mult, pot fi declarate i
-
funciile ca statice i atunci ele vor fi ascunse n modul (nu pot fi
apelate din afara modului). Ascunderea funciilor n modul se face pentru
acele funcii care nu se utilizeaz la realizarea interfeei modulului cu
celelalte module. Ascunderea datelor i funciilor n module permite
protejarea datelor i prentmpin utilizarea eronat a funciilor.
5.1.4. Programarea structurat
Descompunerea unei probleme n subprobleme mai simple se poate
face succesiv n mai multe etape, pn cnd subproblemele sunt direct
programabile sub forma unor proceduri sau module. Aceast descompunere
succesiv se mai numete rafinare pas cu pas (stepwise refinement)..
Evident c se obine o descompunere arborescent. Procedurile se pot
organiza sau nu n module. n cadrul procedurilor se folosesc anumite
structuri de control a execuiei. Aceasta impune o anumit disciplin a
programrii. Structurile de control de sunt:
secvena;
iteraia (pretestat, posttestat, cu numr prestabilit de ciclri);
alternativa (simpl, complet, generalizat).
Instruciunea de baz (primitiv) n cadrul acestor structuri de
control este instruciunea de atribuire.
Aceast abordare a programrii s-a nscut din necesitatea eliminrii
instruciunii de control GO TO care face saltul necondiionat la o
instruciune precizat, alta dect instruciunea urmtoare ei. Profesorul
Dijsktra de la Universitatea din Eindhoven spunea, prin anul 1965,
calitatea unui programator este invers proporional cu numrul de
instruciuni GO TO folosite i a impus D-structurile de control:
secvena;
iteraia pretestat;
alternativa simpl.
D-structurile se regsesc n toate limbajele procedurale.
Corespondena ar fi:
secvena este echivalent cu execuia instruciunilor n ordinea
scrierii lor n programul surs;
b) iteraia pretestat echivalent cu WHILE ... DO;
c) alternativa simpl echivalent cu IF ... THEN.
O ilustrare grafic a celor trei D-structuri se d n
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.
-
5.1.5. Programarea prin abstractizarea datelor
n toate aceste tehnologii anterioare se urmrete mai mult
organizarea programului i mai puin rezolvarea ct mai natural a
problemei. Programarea prin abstractizarea datelor i programarea orientat
spre obiecte propun metodologii n care conceptele deduse din analiza
problemei s poat fi reflectate ct mai fidel n program i s se poat
manevra cu instanieri ale acestor concepte ct mai natural. Se realizeaz
o mai mare fidelitate a programului fa de problem. De exemplu dac ntr-
o problem n care se proceseaz numere complexe e nevoie s se lucreze
ntr-o form ct mai apropiat cu forma matematic se poate introduce tipul
COMPLEX (tip care nu exist n limbajele de programare) i apoi se pot
declara variabile de acest tip. Mai mult ar trebui s se poat face toate
operaiile matematice asupra datelor de tip COMPLEX. n general un TAD (Tip
Abstract de Date) are dou componente fundamentale:
datele membru (reflect reprezentarea tipului);
funciile membru (reflect comportamentul tipului).
5.1.6. Programarea orientat spre obiecte
Un neajuns al programrii prin abstractizarea datelor este
faptul c nu permite exprimarea legturilor dintre diferite concepte (TAD-
uri). Singura legtur dintre concepte care se poate exprima, este aceea c
datele membru ale unei clase pot fi obiecte ale unei alte clase. Acest
lucru nu este suficient n cazul n care conceptele sunt strns dependente
ntre ele formnd structuri ierarhice. Exprimarea ierarhiilor conduce la
atribute suplimentare cum sunt cele de motenire. Aceste atribute conduc la
un nou model de programare pe care l numim programare orientat obiect.
n vrful unei ierarhii se afl fenomenul sau forma de
existen care are trsturi comune pentru toate celelalte componente ale
ierarhiei respective. Pe nivelul urmtor al ierarhiei se afl componentele
care pe lng trsturile comune de pe nivelul superior, mai au i
trsturi suplimentare, specifice. O ierarhie, de obicei, are mai multe
nivele, iar situarea unui element pe un nivel sau altul al ierarhiei este
uneori o problem deosebit de complex. Dm n exemplul urmtor o ierarhie
arborescent pentru conceptele de paralelogram, dreptunghi, romb i ptrat.
Paralelogram
Dreptunghi Romb
Ptrat
Dac paralelogramul se afl n vrful ierarhiei atunci pe nivelul
imediat inferior se aeaz dreptunghiul (paralelogramul cu un unghi drept)
dar i rombul (paralelgramul cu 2 laturi alturate congruente). Apoi
ptratul se poate defini fie ca un dreptunghi cu laturile congruente fie ca
un romb cu un unghi drept. Conceptul de pe fiecare nivel se observ c
motenete proprietile conceptului imediat superior din care este
derivat.
La ora actual, toate ramurile cunoaterii tiinfice sunt
pline de ierarhii rezultate n urma clasificrii cunotinelor acumulate n
perioada lung de observare a fenomenelor i formelor de existen a lumii
materiale i spirituale. Clasificrile ierarhice ale cunotinelor pot fi
-
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; // instructiune de atribuire i++; // i se mareste cu 1 f=i; // instructiune de atribuire (valoarea lui i se converteste in float) d=++f; // incrementare lui f si atribuirea valorii lui d putchar(a); // instructiune de apel } 5.4. INSTRUCIUNEA COMPUS
Instruciunea compus este o succesiune de declaraii urmate de
instruciuni, succesiune inclus ntre acolade:
{
declaraii
instruciuni
}
Pot lipsi declaraiile sau instruciunle dar nu n acelai timp. Dac
delaraiile sunt prezente, atunci ele definesc variabile care sunt valabile
numai n instruciunea compus respectiv.
Exemplu:
. . . { int i=100; // variabila i este definita in aceasta instructiune compusa i++; // i are valabilitate doar intre acolade; dupa acolada inchisa i isi printf (i=%d\n,i); // pierde valabilitatea }
Observaii:
1o. Dup acolada inchis a unei instruciuni compuse nu se pune ;.
2o. Corpul unei funcii are aceeai structur ca i instruciunea
compus, deci o funcie are formatul:
antetul funciei
instruciune compus
5.5. INSTRUCIUNEA if
Instruciunea if permite s realizm o ramificare a execuiei n
funcie de valoarea unei expresii. Ea are dou formate ce permit aplicarea
structurii de alternativ simpl i compus.
Formatul 1:
if (expresie) instructiune;
Efectul:
se evalueaz expresia din paranteze;
dac valoarea expresiei este diferit de zero (deci conform
conveniei are valoarea adevrat), atunci se execut instructiune, altfel
se trece la instruciunea urmtoare.
Formatul 2:
if (expresie) 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:
-
1o. Se pot folosi instruciuni if imbricate, nivelul de imbricare
fiind oarecare (deci nu exist o limitare a numrului de imbricri).
2o. Pentru mai multe imbricri se folosete regula asocierii if-lui
cu else astfel:
un else se pune n coresponden cu primul if care se afl naintea
lui n textul surs i nu este inclus n instruciunea care l precede pe
el i nici nu i corespunde deja un else.
Exemple
void main (void) { float x,y,a; x=-5; y=10; if (x
-
Citeste n
f=1
i=2
CtTimp i
-
}
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
-
clrscr(); // sterge ecranul printf(\ndati un numar real pozitiv a=); if (scanf(%lf,&a) !=1 || a= 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: sirn
break;
default: sir
}
unde: c1,. . . cn sunt constante sau constante simbolice;
sir1, . . . ,sirn, sir sunt iruri de instruciuni.
Efectul:
se evalueaz expresia din parantez;
se compar pe rnd valoarea expresiei cu valorile constantelor c1, .
. . , cn;
dac valoarea expresiei coincide cu valoarea lui ck, se execut
secvena de instruciuni definit prin sirk; n cazul n care valoarea
expresiei nu coincide cu nici una din constantele c1, . . . , cn, se execut
secvena de instruciuni definit prin sir;
dup execuia secvenei sirk sau sir se trece la instruciunea
urmtoare instruciunii switch, adic la prima instruciune aflat dup
acolada nchis care termin instruciunea switch respectiv; evident,
acest lucru are loc dac irul care se execut nu impune, el insui, un alt
mod de continuare a execuiei, de exemplu o revenire din funcia
respectiv, un salt la o anumit instruciune, etc.
Observaii:
1o. Ramura default nu este obligatorie. n lipsa ei, dac valoarea
expresiei nu coincide cu nici una din constantele c1,. . . , cn,
instruciunea switch respectiv nu are nici un efect.
2o.Construcia break reprezint o instruciune. Ea termin fiecare
ramur de instruciuni sir1, . . . , sirn, provocnd saltul la instruciunea
urmtoare instruciunii switch sau, cum se mai spune, realizeaz ieirea
din instruciunea switch.
3o. Instruciunea break nu este obligatorie. n cazul n care este
absent, se execut secvenial urmtoarea ramur. De exemplu dac avem
secvena:
switch (exp)
{ case c1: sir1
case c2: sir2 }
-
ea se execut n felul urmtor:
dac valoarea expresiei este egal cu c1 se execut sir1 i apoi sir2;
dac valoarea expresiei este egal cu c2 se execut sir2;
daca valoarea expresiei difera de valorile c1 i c2 instruciunea
switch de mai sus nu este efectiv, se trece la instruciunea urmtoare
care urmeaz dup switch.
secvena de mai sus se putea realiza i astfel:
if (exp = = c1)
{ sir1
sir2
}else if (exp = = c2) sir2
Exemplu:
Vom citi din fiierul de intrare construcii de forma: op1 operator
op2, unde op1 i op2 sunt numere ntregi (operanzi ntregi) iar operator
este un operator aritmetic {+, -, *, /}. La ieire se va scrie
valoarea expresiei citite. De exemplu dac se citete secvena 100/3 se va
afia rezultatul 33. Programul permite citirea i evaluarea mai multor
astfel de expresii, pn la ntlnirea sfritului de fiier.
#include void main (void) { int op1,op2,operator,rezultat,i; while (( i=scanf(%d %c %d, &op1,&operator, &op2)) != EOF) if (i = = 3 ) // ramura adevarat inseamna ca s-au citit 3 campuri corecte { switch (operator) { case +: rezultat = op1 + op2 ; // avem adunare break; case - : rezultat = op1 op2; // avem scadere break; case * : rezultat = op1 * op2; // avem inmultire break; case / : // avem impartire intreaga if (op2 = = 0) { printf (divizor nul\n); rezultat = 0; } else rezultat = op1 / op2; break; default : printf (operator eronat\n); rezultat = 0; } // sfarsit switch printf (%d %c %d %d\n, op1, operator, op2, rezultat); } else
printf (expresie eronat\n); // sfarsit if si while }
5.10. INSTRUCIUNEA break
Formatul instruciunii este urmtorul:
break;
De obicei instruciunea break se folosete pentru a iei dintr-un
ciclu. Dac exist mai multe cicluri imbricate instruciunea break va trece
controlul la ciclul de nivel imediat superior (deci imbricarea rmne, nu
se iese din toate ciclurile). O alt utilizare este n instruciunea
switch, dup cum am observat n paragraful anterior.
Un alt exemplu de utilizare frecvent este ieirea dintr-un
ciclu infinit de forma:
for ( ; ; )
{. . .
if (exp) break;
. . .
-
}
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 de funcia
respectiv, apelul se face printr-o instruciune de apel.
-
2o. Dac dorim s utilizm valoarea returnat de funcie, vom folosi
apelul funciei drept operand ntr-o expresie, operandul avnd formatul
(*).
Exemple de apeluri de funcii folosite pn acum sunt apelurile
funciilor standard printf, scanf, getchar i putchar. Funciile printf i
putchar au fost apelate prin instruciuni de apel, valorile returnate de
ele nefiind utilizate. n schimb funciile scanf i getchar au fost apelate
n ambele moduri, att prin instruciuni d