Programare Structurata

59
PROGRAMARE PROCEDURALĂ Limbajul în general este un mijloc de comunicare. Limbajul folosit între oameni pentru a comunica între ei este limbajul natural. Un limbaj artificial este utilizat atunci cand unul natural un poate fi folosit în mod adecvat ca şi în cazul comunicării om - maşină. Tipuri de limbaje artificiale: limbaje construite (în vederea simplificării comunicării interlingvistice: Esperanto, Lojban etc), limbaje formale (semantică şi sintaxă precis definite), limbaje de calcul (limbaj de comandă, limbaj de programare, limbaj de marcare). Limbajul de programare este un limbaj artificial care prin exprimări simbolice bine definite (instrucţiuni, directive, comenzi) descrie operaţiile de prelucrare automată a datelor necesare pentru rezolvarea unei anumite probleme a utilizatorului. Un limbaj de programare operează cu elemente concrete numite programe. Instrucţiunea face parte din program şi este o comandă care se dă calculatorului pentru a efectua o anumită operaţie de calcul, de transfer de date, de intrare\ieşire a datelor etc.

Transcript of Programare Structurata

Page 1: Programare Structurata

PROGRAMARE PROCEDURALĂ

Limbajul în general este un mijloc de comunicare. Limbajul folosit între oameni

pentru a comunica între ei este limbajul natural. Un limbaj artificial este utilizat atunci

cand unul natural un poate fi folosit în mod adecvat ca şi în cazul comunicării om - maşină.

Tipuri de limbaje artificiale: limbaje construite (în vederea simplificării

comunicării interlingvistice: Esperanto, Lojban etc), limbaje formale (semantică şi sintaxă

precis definite), limbaje de calcul (limbaj de comandă, limbaj de programare, limbaj de

marcare).

Limbajul de programare este un limbaj artificial care prin exprimări simbolice bine

definite (instrucţiuni, directive, comenzi) descrie operaţiile de prelucrare automată a datelor

necesare pentru rezolvarea unei anumite probleme a utilizatorului.

Un limbaj de programare operează cu elemente concrete numite programe.

Instrucţiunea face parte din program şi este o comandă care se dă calculatorului

pentru a efectua o anumită operaţie de calcul, de transfer de date, de intrare\ieşire a datelor

etc.

Calculatorul manevrează informaţia în formă binară. Codul în care este scrisă informaţia este

codul binar, iar limbajul este limbajul maşină sau limbajul procesorului.

Etapele creării unei aplicaţii (în C):

Figura 1. Paşii pentru construirea unei aplicaţii

(http://control.aut.utcluj.ro/iatr/lab3/cintro.htm, de completat cu mediu de programare)

Page 2: Programare Structurata

Editarea fişierului sursă (presupune existenţa unui editor de text)

Compilare.

Editare de legături (link edit)

Rezultă fişierul executabil

Etapa de depanare (debug)

O clasificare a limbajelor:

a) După tipul (paradigma) programării: ezoterice, ex. (Brainfuck), procedurale;

ex. C, Java, Perl, funcţionale: ex. ML, Haskell, pentru programarea logică ex. Prolog,

DATALOG, limbaje mixte: ex. LISP (programare imperativă şi programare functională).

Limbajele de programare care descriu algoritmul de rezolvare a unei probleme sub forma

unei secvenţe de instrucţiuni (care se vor executa în ordinea scrierii) se numesc limbaje

procedurale sau algoritmice. Replica acestor limbaje de programare procedurală sunt cele

neprocedurale gen LISP, Prolog etc.

b) După nivelul de abstractizare (exprima printre altele uşurinţa cu care programele

pot fi citite şi înţelese de către programatori):

limbaje de generaţia întâia: limbajele cod-maşină (limbaj maşină proprii fiecarui

tip de procesor)

limbaje de generaţia a doua: limbajele de asamblare (în locul codului maşină

folosesc o desemnare simbolică a elementelor programului, relativ uşor de citit şi

interpretat de către om). Limbajele din primele două generaţii = limbaje de nivel scăzut.

limbaje de generaţia a treia: cum ar fi C-ul (şi toate derivatele sale: C++, Java, ...),

Pascal, Fortran ş.a. Obs: C, C++ = limbaje de nivel mediu.

limbaje de generaţia a patra: limbajele neprocedurale, orientate pe rezolvarea unei

anumite clase de probleme: SQL ş.a. limbaje de generaţia a cincea: limbaje utilizate în

domenii precum logica fuzzy, inteligenţa artificială sau şi reţelele neuronale: Prolog, LISP.

Java, Pascal, SQL, Prolog sunt limbaje de nivel înalt întrucât necesită existenţa unuia sau

mai multor filtre de translare din limbaj înalt în limbaj cod maşină. Aceste programe se

numesc translatoare şi sunt de 2 tipuri: compilatoare şi interpretoare. Compilatoarele

traduc întreg programul, după care acesta se poate executa la nevoie; interpretoarele traduc

şi execută pe rând fiecare instrucţiune.

Page 3: Programare Structurata

Altă clasificare alimbajelor:

- limbaje tipizate: acestea sunt limbaje care impun anumite restricţii asupra

operaţiilor care se pot aplica anumitor date, funcţie de tipul datelor (numerice, siruri de

caractere, etc). Tipul datelor trebuie declarat înainte de introducerea acestora în program si

respectat pe tot parcursul programului. Majoritatea limbajelor compilate sunt şi tipizate: C,

C++, Pascal, Java.

- limbaje netipizate, care nu impun restrictii (spre exemplu, variabilele nu sunt

restricţionate la un anumit tip de dată şi nu trebuie declarate înainte de a fi folosite). Aceste

limbaje ofera o flexibilitate mai sporită, sunt mai puţin restrictive. Majoritatea limbajelor

specializate sunt netipizate, iar majoritatea limbajelor netipizate sunt interpretate: Php,

Matlab etc.

Obs: Limbajul de programare C a fost elaborat de Dennis Rithie şi Brian Kernighan

între 1969 şi 1973 la compania BELL Telephone pentru a permite realizarea sistemului de

operare Unix. În anii 1980 a fost adoptat şi de calculatoarele IBM PC, popularitatea

acestuia începând să crească semnificativ. În acest timp, Bjarne Stroustrup împreună cu alţi

colegi de la Bell Labs au început să adauge limbajului C caracteristici ale programării

orientate pe obiecte. Limbajul rezultat a fost denumit C++ şi este cel mai popular limbaj de

programare pe sistemele de operare Microsoft Windows (http://ro.wikipedia.org/wiki/C_

%28limbaj_de_programare%29#.C3.8Enceputurile_limbajului_de_programare_C)

Prezentare generală a limbajului C

În cadrul C se foloseşte setul de caractere ASCII, care asociază fiecărui caracter un

număr întreg din intervalul [1; 127].

Caracterul 0 ASCII corespunde caracterului impropriu nul şi acesta se foloseşte

pentru a marca sfârşitul unui şir arbitrar de caractere.

Mulţimea caracterelor poate fi impărţită în 3 grupe:

1. caractere negrafice, care au caracterele ASCII corespunzătoare mai mici decât

32; face excepţie de la această regulă caracterul Delete căruia îi corespunde 127;

Page 4: Programare Structurata

2. Spaţiul, care are ca şi corespondent ASCII valoarea 32;

3. caracterele grafice, care au codurile ASCII mai mari decât 32 (litere mari, mici,

cifre).

Literele mari au în ordine codul ASCII de la 65 la 90, literele mici de la 97 la 122,

iar cifrele de la 48 la 57.

Specificaţii de limbaj C

Vocabular:

setul de caractere: a - z , A - Z , 0 - 9;

semne de punctuaţie: ‘ . ‘ , ‘ , ‘ , ‘ ; ‘ ;

caractere speciale : % , & , $ etc.;

cuvinte rezervate: while, if, for, else, void, char, int, float, double, unsigned,

include, main, getch etc.

Constante şi expresii

O constantă nu îşi modifică valoarea pe parcursul rulării unui program.

Pot fi constante predefinite (gen MAX INT) sau constante propriu-zise. Declararea

se face prin CONST.

OBS. Înţelegem prin identificator un nume (denumire) ce se poate atribui (şi care

defineşte de regulă în mod unic) unei constante, variabile, funcţii.

Regulă de construcţie identificatori valizi

Un identificator conţine doar litere, cifre şi “_” (underline). Nu poate conţine

spaţii şi nu poate începe cu o cifră.

Definiţie: O expresie este o construcţie validă în C din punct de vedere sintactic şi

semantic.

Exemplu: ( a||b ) sau ( a&&c ).

Separatori

Definiţie: Un separator separă uzual atomi–lexicali (cuvinte rezervate). Cel mai

uzual separator este “spaţiul ” iar “ ; “ separă două instrucţiuni. Alţi separatori: ( ) , [ ] ,

{ } , virgulă, ‘, “ “.

Page 5: Programare Structurata

Comentarii : “ // “ pe o singură linie şi “ / * a……b */ “ pe mai multe linii.

TIPURI DE DATE

Un tip de date constă într-o mulţime de valori pentru care există un mod de

reprezentare în memoria calculatorului, cât şi o mulţime de operatori, care pot fi aplicate

acestor valori.

OBS. Tipul de date determină lungimea zonei de memorie ocupată de acea dată.

Tipuri de date: char, int, float, double.

OBS. Tipurile de date pot avea calificatori gen: short, long, sign, etc .

OBS. Constantele simbolice (max long etc) sunt definite în biblioteca <values.h>.

TIP Memorie uzuală

DescriereMS-DOS Linux

Char 8 8

unsigned char 8 8

signed char 8 8

int 16 32

Long 32 64

long long int 32 64

short int 16 32

unsigned int 16 32 Fără semn

unsigned long 32 64 valoarea întreagă fără semn

float 32 32valoare numar zecimale,

simplă “precizie”

Double 64 64 “dublă precizie” (10)

long double 80 128 “dublă precizie”

Page 6: Programare Structurata

Observaţii:

Secvenţele ESCAPE sunt folosite pentru reprezentarea caracterelor invizibile sau greu de

obţinut. Cele mai uzuale sunt:

Constanta char Cod ASCII Denumire

‘ \n ’ 10 LF(line feel) Enter

‘ \t ’HT(horizonter

Tabulator)Tab

‘ \r ‘CR

(carriage return)

mă întoarce la

capăt de rand

‘ \f ‘ FFsalt la pagina

din imprimantă

‘ \a ‘ BELse activează un

sunet

VARIABILE

O variabilă spre deosebire de o constantă îşi poate modifica valoarea în cadrul unui

program. Ea este caracterizată de:

1. Identificator (nume);

2. Domeniul de vizibilitate (zona de program în care variabila are influenţă/efect )

<engleză: scope >;

OBS. Din acest punct de vedere pot exista într-un program 2 variabile cu acelaşi

identificator ( int a , A = 2 ).

3. Valoare;

4. Tipul de date (indică spaţial de memorie alocat/ocupat);

5. Adresă.

O variabilă poate primi drept valoare:

Page 7: Programare Structurata

─ o valoare constantă;

Exemplu: A = 2 .

─ valoarea unei constante predefinite sau nu;

Exemplu: PI = 3.14;

float X = PI;

float X = MAXINTEGER;

─ valoarea întoarsă de o funcţie;

─ valoarea unei alte variabile;

Exemplu: a = A.

─ valoarea unei expresii;

Exemplu: x = (a+b)&&(!c)||1

INSTRUCŢIUNI DE CONTROL

Instrucţiunile de control descriu structurile de control şi fluxul circulaţiei datelor.

Structura decizională (alternativă):

1. alternativă binară (instrucţiunea IF);

Sintaxă: if <conditie> then A

[else] B

OBS. În cazul în care A şi B lipsesc obţinem o structură decizională cu ramură vidă.

2. alternativă generalizată (corespunde instrucţiunii SWITCH)

Sintaxa: switch(expresie)

{case const1:<i1>; break;

case const2:<i2>; break;

…………………………..

case constn:<in>; break;

[default: < B >]

}

Page 8: Programare Structurata

Semantica: se evaluează expresia şi se compară rezultatul evaluării cu valorile

constante specificate; se execută secvenţa de instrucţiune asociată k, dacă evaluarea

expresiei coincide cu valoarea constantei din cazul k. Default este opţional.

OBS. Pot exista maxim 257 cazuri (case ).

Exemplu: int i;

cin>>i ;

swich(i)

{case 1: cout<<”Introduceti date“ >>; break;

case 2: cout<<”Afisare date”; break;

default: cin<<”Iesire” ;

}

OBS. Prezenţa instrucţiunii break face ca atunci când se evaluează cazul respectiv,

la întâlnirea lui break să se părăsească switch pentru a nu evalua inutil restul cazurilor.

INSTRUCŢIUNI DE SALT ŞI ÎNTRERUPERE

Instrucţiunile de salt sunt:

GO TO – este o intrucţiune de salt la o altă instrucţiune din acelaşi program ce a fost în

prealabil etichetată. O etichetă este un identificator urmat de 2 puncte.

Exemplu: i=1;

if(k==i) go to unu;

unu: i=2;

OBS. GO TO se evită a fi folosită întrucât încalcă principiile programării

structurale. GO TO trebuie să fie în aceeaşi funcţie cu eticheta (în C nu există proceduri)

pentru că nu se poate face salt peste funcţii.

RETURN – este folosită pentru reîntoarcerea dintr-o funcţie. Este de salt întrucât la

intalnirea ei se face salt la intrucţiunea imediat următoare celei care a determinat apelul

funcţiei. În general sintaxa este RETURN.

Sintaxă: return [<expresie>]

Page 9: Programare Structurata

Observaţii:

1. Dacă return are o valoare, aceasta devine valoarea întoarsă de funcţii.

2. În C++ o funcţie care nu are tipul void trebuie să întoarcă o valoare.

3. Acolada care încheie o funcţie determină ieşirea din funcţie şi echivalează cu

RETURN, însoţită sau nu de valoare.

Instrucţiuni de întrerupere

BREAK – determină ieşirea dintr-o instrucţiune alternativă (de obicei la switch şi

câteodată la if ) sau determină părăsirea unei bucle (a unei instrucţiuni repetitive),

controlul programului fiind cedat instrucţiunii ce urmează imediat după buclă.

Funcţia EXIT

OBS. Nu este o instrucţiune de control ci o funcţie ce determină părăsirea

programului. Exit poate fi apelată oriunde în program, de regulă atunci când nu sunt

indeplinite condiţii obligatorii pentru program.

Sintaxă: exit();

CONTINUE – este o funcţie similară cu break , cu deosebirea că nu forţează

părăsirea buclei ci trecerea la următoarea interaţie.

OBS. Aflată în interiorul instrucţiunilor repetitive continuă transferul controlului

programului expresiei de testare (condiţiei) ignorând instrucţiunile care o succed în buclă.

Exemplu: v = (10, 2, 6, 1, 8, 7, 5)

for( i = 1; i<=7; i++)

if(v[i]%2==0) // v[i]=nr par

S = S+v[i];

else continue ;

p = S+2v[i];

INSTRUCŢIUNI REPETITIVE

Page 10: Programare Structurata

Clasificare:

A. Instrucţiuni repetitive cu număr necunoscut de paşi:

1. Repetiţia cu test iniţial (while);

2. Repetiţia cu test final (do…while).

B. Instruncţiuni repetitive cu număr cunoscut de paşi:

1. Structura repetitivă cu contor (for):

a. cu contor în creştere ;

b. cu contor în descreştere.

A1. Repetiţia cu test iniţial

Intrucţiune: while…do

Sintaxa: while(<cond>)

[do]

Set instruct <A>

Semantica: se evaluează expresia <cond>; dacă valoarea obţinută în urma evaluării

expresiei este nenulă se execută setul de instrucţiuni A şi se revine la pasul 1, în caz

contrar se trece la instrucţiunea imediat următoare.

Exemplu: Afişarea unui şir de numere naturale de la 1 la n (dat).

Presupunem ca în i se depun valorile 1,2,….,n . Iniţial i=1

int i=1;

int n=10;

while(i<=n)

{cout<<i<<” “ ;

i++;

}

OBS. Setul de instrucţiuni A trebuie să conţină minim o instrucţiune care să

afecteze valoarea restului astfel încât să devină la un moment dat fals (ies din buclă astfel -

ciclare infinită).

Page 11: Programare Structurata

A2. Repetiţia cu test final

Exemplu: do

{cout<<i<<” “;

i++;

}

while(i<=n)

Instrucţiunea: do…while

Sintaxă: do

set instruct B;

while(<cond>)

instrc_urm;

Semantică:

─se execută setul de instrucţiuni B (1);

─se evaluează expresia <cond>. Dacă e adevarată se revine la (1), în caz contrar se

execută instrucţiunea următoare;

─se execută B până când <cond> devine falsă (cât timp cond rămâne adevarată).

Observaţii:

1.Spre deosebire de while, do…while presupune execuţia cel puţin odată a setului

de instrucţiuni B.

2. Similar cu while şi pentru do...while trebuie să existe în setul B minim o

instrucţiune care să afecteze valoarea testului, altfel se ciclează la infinit.

Exemplu: S = 1 + 2 + …. + n

int i=1; s=0;

int n=10;

while (i <= n)

{cout<<i<<” “;

S = S + i; i++;

}

cout <<”suma este : ”<<S;

Page 12: Programare Structurata

B. Repetiţia cu număr cunoscut de paşi

Instrucţiunea FOR

Sintaxă: for(<expr1> ; <expr2> ; <expr3>)

set instr A;

instr_urm;

Semantică:

- <expr1> se numeşte expresie de iniţializare; se stabileşte valoarea iniţială a

contorului.

- <expr2> se numeşte expresie de test. Dacă valoarea rezultată a evaluării expr2

este nenulă, se execută set instr A. În caz contrar se execută instrucţiunea următoare

( instr_urm ).

- <expr3> se numeşte expresie de incrementare/decrementare folosită pentru

creşterea/descreşterea contorului.

OBS. Dacă vi<vf atunci rezultă for cu contor în creştere, în caz contrar for cu

contor în descreştere.

Principiul de execuţie:

- se evaluează expr1;

- se evaluează expr2; dacă s-a produs o valoare diferită de 0 se execută A, altfel se trece

la instrucţiunea următoare;

- se evaluează expr3 şi se revine la pasul 2.

Exemplu: for(i=1;i<=n;i++)

cout<<i<<” “;

S=0;

for (i=1;i<=n;i++)

S=S+i;

cout<<”Suma primelor”<<n<<” numere naturale”<<S;

Un exemplu complet: algoritmul lui Euclid

Page 13: Programare Structurata

Pentru a obţine c.m.m.d.c. a două numere a şi b, folosim:

-împărţim a la b ( b≠0);

-dacă restul împărţirii este 0 (r1=0) atunci c.m.m.d.c. este b;

-dacă nu, împărţim pe b la restul împărţirii anterioare (r1) şi obţinem r2;

-împărţim r1 la r2 si obţinem r3 etc.;

-ultimul rest nul este c.m.m.d.c. a lui a şi b.

c.m.m.d.c.(a,b)=c.m.m.d.c.(b,a mod b)

Program:

#include <iostream>

using namespace std;

int a, b, deimp, imp, cmmdc, rest;

int main()//void pentru medii

do

{

cout<<”Dati a şi b”<<endl;

cout<<”a= “;cin>>a;

cout<<endl;

cout<<”b= “;cin>>b;

cout<<endl;

deimp=a;imp=b;

do

{rest=deimp%imp;

deimp=imp;

imp=rest;

}

while(imp!=0)

cmmdc=deimp;

cout<<”continuati (d/n)”<<endl;

cin>>ok;

Page 14: Programare Structurata

while(ok=”n”)

cout<<”c.m.m.d.c.”<<cmmdc;

system(“Pause”);

getchar();

return 0;

}

Determinarea cmmdc prin scăderi repetate:

# include <iostream.h>

# include<conio.h>

int main(){

int a,b,u,v,cmmdc,cmmmc;

cout<<”dati a: “; cin>>a;

cout<<endl;

cout<<”dati b: “; cin>>b;

cout<<endl;

if(a*b==0 ) \\ a sau b sunt 0

{if(a + b != 0)

{cout<<”cmmdc este: “<<a+b;

cout<<endl; }

else

cout<<”nu exista cmmdc”;

cout<<”cmmmc=0“;

}

else {

u=a;

v=b;

while(a*b)

if(u > v)

u=u-v;

else

Page 15: Programare Structurata

v=v–u;

cmmdc=u;

cmmmc=(u*v)/cmmdc;

cout <<”cmmdc= “<<cmmdc<<”cmmmc= “<<cmmmc;

}

system(“pause”);

getch();

}

TIPURI STRUCTURATE

1. TABLOURI

Cel mai uzual tip stucturat de date.

Un tip de date este structurat dacă este format din tipuri de date elementare.

Alte tipuri structurate:

- matrici, masive;

- înregistrări, uniuni, fişiere etc.

Observaţii:

1. Generalizarea conceptului de vector poartă denumirea de tablou

(unidimensional=vector, bidimensional=matrice, tridimensional=masiv)

Declarare:

<tip_v>.<nume_v>[<dim>]

Exemple: int vector[20]; char alfabet_RO[31];

2. Indexarea elementelor unui vector începe în C/C++ de la 0.

3. C/C++ nu face “check boundaries”(nu verifică dacă s-a depăşit dimensiunea

vectorului).

Parcurgere:

Presupunem cunoscută dimensiunea.

Exemplu: for(i=0;i<n;i++)

<prelucrare elemente>

Page 16: Programare Structurata

Unde <prelucrare elemente> poate fi:

a) citire:

cin>>vector[i];

b) afişare:

cout<<vector[i];

c) mixt a) şi b).

{cout<<”vector[“<<i<<”]=”;

cin>>vector[i];

cout<<endl;

d) alte prelucrări

Prelucrări pe vectori (operaţii):

aritmetice: sumă, produs scalar, norma unui vector etc.

sortări: boublesort, sortare cu pivotare, quick sort etc.

Metoda bulelor:

int bule=1;

while(bule = = 1) {

bule=0;

for (i=1; i<=n; i++)

if (v[i] > v[i+1]) {

aux= v[i]; // interschimb

v[i]= v[i+1];

v[i+1]= aux;

bule=1;

}

}

regăsirea unuia sau a mai multor elemente ale tabloului ce satisfac o sumă

de proprietaţi: determinarea minimului, a maximului, verificare dacă elementele vectorului

determină o progresie, calcul număr apariţii elemente, determinare elemente impare, a

Page 17: Programare Structurata

celor divizibile printr-un număr dat, a acelor elemente care sunt palindroame, care conţin

un anumit număr de vocale etc.

gasit=1;

for (i=1; i<=7&&gasit; i++)

if (v[i]= = 5) {

cout<<”gasit”;

gasit=0;

}

interclasarea: presupune obţinerea din 2 sau mai mulţi vectori sortaţi, un al

treilea format din elementele primilor, în aceeaşi ordine

(crescătoare sau descrescătoare).

while (( i<n) && (j<m))

if (a[i]<b [j])

c[k++]=a [i++];

else c[k++]=b[j++];

tablou bidimensional: este un tip de dată corespunzător unei matrici <nr

linii>][<nr coloane>].

for (i=0;i<n;i++)

for (j=0;j<n;j++)

{cout << “ a[“ << i << “][“ << j << “]“;

cin>>a[i][j];}

cout<<endl;

OBS. Aplicaţiile cu matrici sunt similare cu cele de la vectori.

masive;

Declarare: tip nume_masiv[<dim1>][<dim2>]….[<dimn>]

Structuri. Uniuni

OBS. Spre deosebire de tablouri care conţin elemente de acelaşi tip, structurile/uniunile pot

conţine variabile diferite reunite sub acelaşi nume.

Page 18: Programare Structurata

Structurile sau uniunile sunt tipuri structurate de date. Variabilele ce alcătuiesc structura se

numesc membrii structurii sau câmpuri. Pentru accesul la un câmp a unei structuri se

foloseşte operatorul “ . “ . Declararea unei structuri se încheie cu “;“ deoarece e considerată

o singură instrucţiune.

Sintaxa:

struct<nume_structura>

{ <tip_camp_1><lista_var_1>;

<tip_camp_2><lista_var_2>;

.

.

.

<tip_camp_n><lista_var_n>; }

<lista_var_tip_struct>;

Structurile implicate în situaţii în care se declară o structură în interiorul unei alte

structuri.

Exemplu:

struct student {

char nume[30], prenume[30];

struct {

char specializare[20];

float note[14];

} Situatie;

}S1,S2;

OBS. În interiorul structurii “student” se află o structura anonimă ce poate fi

apelată prin intermediul variabilei “Situatie“:

cout<<S1.Situatie.specializare;

cout<<S2.Situatie.note[0];

Definiţie. Uniunile sunt un tip de dată structurată prin care se rezervă o locaţie de

memorie pentru două sau mai multe variabile. Deci uniunea este o structură în care

Page 19: Programare Structurata

componentele sale de tip diferit, ocupă la momente de timp diferite aceeaşi locaţie de

memorie.

Sintaxa:

union <nume_uniune>

Uniunile sunt în general declarate dacă există înregistrări cu structură variabilă. O uniune

poate fi declarată atât în afara unei structuri cât şi în interiorul ei.

Exemplu:

struct persoana {

char nume[20],prenume[20];

union {

int clase;

struct {

char denumire[20];

char oras[20]

} liceu;

struct {

char denumire[20], oras[20]

} facultate;

} studii;

} p;

p.studii.liceu.denumire sau p.studii.clase sau p.studii.facultate.oras

POINTERI

Numim pointer o variabilă al cărei atribut valoare poate conţine doar o adresă.

Sintaxa: < tip >*< identificator_pointer >

Exemple: int *a,*b; //a şi b pointer către întreg

float *pointer_to_float;

int a1; int *p;

p=&a1; // p primeşte ca valoare adresa lui a1

Page 20: Programare Structurata

OBS. Afişarea valorii lui p, cât şi a adresei lui a dau evident acelaşi rezultat.

Avantaj: reutilizarea spaţiului de memorie.

OBS. Pointerii au o aritmetică proprie. O variabilă poate ocupa unul sau mai mulţi octeţi,

în funcţie de tipul său. Un pointer va conţine adresa unei variabile, în fond adresa primului

octet ocupat de aceasta. Dacă pentru o variabilă ştim adresa şi numărul de octeţi ocupaţi,

putem face un calcul prin care, de exemplu, să aflăm adresa următoare. Procedeu dificil

întrucât variabilele pot avea tipuri diferite. Aritmetica pointerilor simplifică acest calcul:

pointer + 1 → înseamnă adresa următoarei variabile de tipul celei conţinute de

pointer;

pointer + 2 → înseamnă adresa următoare de acelaşi tip.

Legătura pointeri–tablouri:

OBS. C/C++ furnizează două metode de acces la elemenetele unui tablou:

a) specificând indicele elementelor;

b) cu ajutorul pointerilor.

Exemplu: char sir[20];*p;

a) sir[3];

b) p=sir;

c) *(p+3).

OBS. p=sir ≡ p=&sir[20].

int *x[ 10 ] → vector de 10 pointeri către întreg.

OBS. Pentru a declara pointeri constanţi folosim:

int b=5;

int *const p=&b;

- p este o constantă de tip integer ce conţine adresa variabilei b (conţinutul său, adică

conţinutul de la adresa &b, nu mai poate fi modificat).

Operaţii cu pointeri

1.Atribuirea

Page 21: Programare Structurata

Exemplu: int *a ,*b;

char *a ;

a = b ;

Atribuirea se realizează dacă cei doi pointeri reţin adrese către variabile de acelaşi

tip, în caz contrar, atribuirea nu se poate realiza, implicit se foloseşte operatorul de

conversie explicită.

Exemplu: int a=5;

*adresa=&a;

float b=5.2;

*adresb=&b;

adresa = (int *) adresb;

2.Compararea variabilelor de tip pointer

Fiind date două adrese de memorie, acestea pot fi comparate folosind operatorii

relaţionali.

3.Incrementarea/Decrementarea pointerilor

Dacă a este pointer de tip x si n număr natural, atunci a+n reprezintă adresa ce se

obţine ca sumă între adresa reţinută în “a“ şi produsul dintre n şi numărul de octeţi rezervat

de compilator pentru a memora o variabilă de tipul celei a cărei adresă se află în a .

4.Pointeri către funcţii

OBS. Deşi o funcţie nu este o variabilă, ea are o localizare în memorie, ce poate fi

atribuită unui pointer.

OBS. Pointeri speciali (POO):

- this – intervine în cazul apelului unei funcţii membre a unei clase;

- near si far – gestionează reprezentarea fizică a memoriei în pointeri, respectiv zona de

memorie, respectiv numele cu semnificaţie de adresă. Funcţiile de dimensiunea de

memorie alocată unui pointer, numele reţinute pot fi mai mici sau mai mari. Un pointer

near poate adresa un bloc de memorie de 64 Kb.

Page 22: Programare Structurata

O referinţă este un nume alternativ al unui obiect. Sunt utilizate în principal în

specificarea argumentelor şi a valorilor returnate de funcţie, cât şi pentru supraîncărcarea

operatorilor (POO).

Notaţie: &x înseamnă referinţă la obiectul x.

Exemplu: int i=1;

int &r=i; //r şi i se referă la aceeaşi entitate

int x=r;

x++; // i are aceeaşi valoare

r++; // i işi schimbă valoarea

OBS. Deşi pentru declararea unei referinţe folosim operatorul &, tipul construcţiei în care

este folosit diferă.

Exemplu: int a=5;

int *pi=&a; // pi = adresa lui a

int &r=a; // r = alt nume pentru a

OBS. O referinţă este utilizată ca argument pentru o funcţie care poate să modifice

valoarea acestui argument.

Exemplu: void incr(int &x)

{x++;

}

void f ()

{int i=1;

incr(i);

}

Conversii de tip

Atunci când într-o expresie sunt amestecate constante şi variabile de diferite tipuri,

ele sunt convertite (la tipul cel mai mare) de către compilator.

Exemplu: int i;char c;float f; double d;

expresie = (c/i)+(f*d)-(f+I)

Page 23: Programare Structurata

c ← int

f ← double

i ← float

int+double ← double

double - float ← double

Conversia forţată se face specificând tipul dorit între paranteze, în faţa variabilei

sau expresiei ce se converteşte .

FUNCŢII ÎN C/C++

Subprograme

Limbajele de programare permit construirea programelor pe baza tehnicii

programelor structurate, ce presupune o metodologie de proiectare organizată cât şi

folosirea adecvată a instrucţiunilor de control.

Divizarea algoritmilor de mari dimensiuni în module mai uşor de controlat,

prezintă o serie de avantaje precum:

- rezolvarea unei probleme printr-un program monoid nu evidenţiază legatura naturală între

algoritmul folosit şi unitatea de program destinată implementării acestuia;

- programe extrem de mari sunt dificil de înţeles, în special după trecerea unei perioade mari

de timp sau dacă se impune transferul dezvoltării ulterioare a acestuia unor terţe persoane;

- se impune ca o unitate de program (subprogram) să aibă o funcţie bine definită care să

implementeze un singur algoritm având bine precizate intrările şi ieşirile.

Concluzie: În general un subprogram este un modul scris independent de programul

principal, dar legat de acesta printr-un proces de transfer şi revenire.

Definiţie. Procesul de transfer al controlului se numeşte apelare subprogram. Modulul care

solicită execuţia subprogramului se numeşte modul apelant, subprogramul numindu-se

modul apelat.

Un subprogram uzual este format din:

- nume;

Page 24: Programare Structurata

- definire subprogram, care poate avea o zonă declarativă (variabile locale) şi zonă

executivă.

OBS. În general entităţile (uzual variabile) declarate în interiorul unui subprogram sunt

entităţi locale – pot fi utilizate doar în interiorul subprogramului respectiv. În cazul în care

unele entităţi trebuie folosite în comun de toate modulele (sau numai de o parte) unui

program, acestea se vor numi entităţi globale.

OBS. Utilizarea entităţilor globale este contraindicată.

Apelul subprogramelor:

<tip_rezultat><nume_subprog>(<lista_param_formali>)

Exemplu: int maxim(int a,int b)

bool este_in_sir(double sir[], double x )

void aria(float lung, float latime)

OBS. Spre deosebire de Pascal unde există chiar cuvântul rezervat procedure, în C/C++ nu

există proceduri, ci doar funcţii către void (funcţii care nu întorc nici un rezultat). Spre

deosebire de funcţii, procedurile (în sens clasic) nu întorc în modulul apelant nici o valoare

(rezultat).

OBS. Funcţiile pot conţine minim o singură dată o instrucţiune return.

Exemplu: subprogram maxim(int x, int y, int z)

Apel: maxim(a, b, max)

a) a şi b sunt transferate în x, respectiv y;

b) subprogramul plasează valoarea mai mare în z;

c) valoarea din z este transmisă modulului apelant.

Modalităţi de transfer a parametrilor:

1) Datele sunt copiate efectiv din locaţiile respective, din programul principal, în

celulele de memorie asociate subprogramului, caz în care se spune că transferul se

realizează prin valoare (ineficient dacă dimensiunea datelor asociate parametrilor

sunt mari, întrucât, lucrându-se cu copii ale parametrilor reali, stiva alocată

subprogramului se încarcă).

OBS. La apel, parametrii formali sunt substituiţi cu cei reali, cele două liste trebuie să

coincidă ca tip şi număr de parametri.

Page 25: Programare Structurata

2) Se pot transfera doar adresele celulelor de memorie ce conţin datele respective,

fapt ce oferă subprogramului acces direct la date fără a genera o copie a acestora.

Se spune că transferul se realizează prin adresă sau referinţă. Parametrii transmişi

prin referinţă vor avea în faţa numelui un & (et).

Exemplu: void unu(int a)

{a = a + 2;

cout<<”unu”<<a;}

void doi(int &b)

b = b + 5;

unu(b); cout<<”doi1”<<b;

unu(b); cout<<”doi2”<<b;

}

void main()

{int c = 10;

doi(c); cout<<”afara”<<c;}

OBS. În cazul în care apelul unu(b)←unu(a), valoarea lui a trebuie precizată înaintea

apelului. În această situaţie a devine variabilă globală pentru “unu“ ca funcţie şi “doi“.

Exemplu: int x, y, z;

void P(int x, int &y)

{z = x + y;

x++;

y = y + x;

cout<< x<<y<<z<<endl;}

void main()

{x = 3; z = 4; int t = 10;

P(t,x);

cout<<x<<y<<z;}

Page 26: Programare Structurata

void p(int x, int &y)

{x++; y = x;}

void pa(int &x, int &y)

{x++; y = x;}

void main()

{int x = 0, y;

while(x<3)

{p(x ,y); x++; cout<<x<<y<<endl;}

x=0 ;

while(x<3)

{pa(x ,y); x++; cout<<x<<y<<endl;}

OBS. Dacă mediul nu acceptă tipul logic (bool), bool se înlocuieşte cu integer, true←1,

false←0.

Problemă. Să se scrie un program care să conţină procedura citeşte elementele unui

vector, dimensiunea şi numele lui, o procedură care afişează vectorul, o funcţie care

validează dacă un element aparţine unui vector (mulţimii), o procedură mulţime care

transferă vectorul într-o mulţime, cât şi procedurile reuniune, intersecţie, diferenţă, care să

fie apelate într-un program ce transferă vectorul în mulţimi şi operează cu acestea.

#include<stdio.h>

#include<stdlib.h>

void citeste(int x[], int &n, char nume[])

{int i;

printf(“Dati numarul de elemente pentru vectorul %s”,

nume);

scanf(“%d”, &n);

for(i=1; i<=n; i++)

{printf(“Dati %s[%d]= “, nume, i);

scanf(“%d”, &(x[i]));

}

Page 27: Programare Structurata

}

void afiseaza(int x[], int n, char nume[])

{int i;

printf(“Vectorul este %s: “, nume)

for(i=1; i<=n; i++)

{printf(“%d”, x[i]);

printf(“\n”);

}

}

bool estein(int a ,int x[], int n)

{int i;

for(i=1; i<=n; i++)

if(x[i] == a)

return true;

return false;

}

void multime(int x[i], int n, int y[], int &n)

{int i;

m = 0;

for(i=1; i<=n; i++)

if(!estein(x[i], y, m)

{m++;

y[m] = x[i];

}

}

void reuniune(int x1[], intn1, int x[], int n2, int

r[], int &nr)

{int i;

for(i=1; i<=n1; i++)

r[i] = x1[i];

Page 28: Programare Structurata

nr = n1;

for(i=1; i<=n2; i++)

if(!estein(x2[i], x1, n1)

{nr++;

r[nr] = x2[i];

}

}

void intersectie(int x1[], intn1, int x2[], int n2, int

s[], int &ns)

{int i; ns = 0;

for(i=1; i<=n1; i++)

if(estein(x1[i], x2, n2)

{ns++;

s[ns] = x1[i]; }}

int main()

{int a[20], b[20], am[20], bm[20], reun[40], inters[20],

difer[20];

int na, nb, nam, nbm, nr, ns, nd;

citeste(a , na, “a“);

afiseaza(a, na, “a”);

citeste(b, nb, “b“);

afiseaza(b, nb, “b“);

multime(a, na, am, nam);

afiseaza(am ,nam, “Multime a“);

multime(b ,nb ,bm ,nbm);

afiseaza(bm ,nbm, “Multime b“);

reuniune(am ,nam ,bm , nbm, reun, nr);

afiseaza(reun , nr, “Reuniunea: “);

intersectie(am, nam, bm, nbm, inters, ns);

Page 29: Programare Structurata

afiseaza(inters, ns, “Intersectia: “);

diferenta(am, nam, bm, nbm, difer, nd);

afiseaza(difer, nd, “Diferenta: “);

………………

}

OBS. Transferul prin adresă se poate face şi prin intermediul pointerilor.

Exemplu: void cuPointer(int x, int *y)

{x++;

*y = x;}

int main()

{int x, y;

x = 1;

while(x<=5)

cuPointer(x, &y);

}

OBS. Pointeri la structuri: când structurile sunt mai mari, este mai eficient să se transmită

un pointer către acea structură, iar în interiorul funcţiei să se folosească accesul prin

pointer. Când un pointer al unei structuri e transmis unei funcţii, în stivă se reţine doar

adresa structurii. Acest lucru garantează apeluri de funcţii rapide, funcţiile putând totodată

să modifice conţinutul structurii folosite la apelare.

Exemplu: struct timp

{int ora;

int minute;

int secunde;

}*t;

- apel câmp structură prin pointer

if(t→minute == 60)

{t→minute = 0;

t→ora++;

Page 30: Programare Structurata

}

- funcţie simulare potrivire oră la ceas

void potrivire(timp *t) {

if(t→minute == 60)

{t→minute = 0;

t→ora++;

}

if(t→ora == 24)

t→ora = 0;

}

Pointeri către o funcţie

Deşi funcţia nu este o variabilă, ea are localizare în memorie; aceasta poate fi

atribuită unui pointer. Altfel spus, adresa unei funcţii este punct de intrare în funcţie, deci

se poate folosi un pointer către o funcţie pentru a o apela.

OBS! Adresa unei funcţii se obţine specificând numele funcţiei fără paranteze sau

argumente.

Exemplu: float mult(float x, float y)

{return x*y;}

float add(float x, float y)

{return x+y;}

float scad(float x, float y)

{return x-y;}

float operatie(float(*f)( float , float ),

float x, float y)

{return (*f)( x, y )*1000;}

void main()

{float a = 2, b = 3, c;

float(*t[3])(float, float);

t[0] = mult;

Page 31: Programare Structurata

t[1] = add;

t[2] = scad;

c = (*t[1])(a, b);

c = operatie(scad, a, b);

Funcţii standard în C++

double abs(double x) → calculează modulul;

double ceil(double x) → calculează partea întreagă (în minus);

double floor(double x) → calculează partea întreagă (în plus);

double exp(double x) → calculează ex

double log(double x) → calculează ln x;

double log10(double x) → calculează lg x;

double pow(double x, double y) → calculează xy;

int rand() → generează aleatoriu un număr întreg cuprins între 0 şi

32687.

OBS! Pentru setarea generatorului de numere aleatorii într-un anumit punct se foloseşte

void strand(unsigned n). Dacă n=1 se reiniţializează generatorul.

RECURSIVITATE

Pentru a putea rezolva o problemă în mod recursiv, ea trebuie formulată recursiv,

fapt ce presupune că:

- este specificat un set de situaţii în care soluţia problemei este cunoscută (aceste situaţii

descriu încetarea apelurilor recursive; pot fi situaţii nemijlocite sau rezultate prin apelul

unei alte metode).

- sunt definite o sumă de situaţii admisibile (A ≠ Ǿ) pentru care problema se poate

rezolva.

Page 32: Programare Structurata

Exemplu: În problema determinării lui n! situaţiile admisibile A sunt date de N, nu

şi de Z de exemplu. Orice situaţie din A este reductibilă la o situaţie iniţială (din I ≠ Ǿ).

OBS. Posibilitatea de a rezolva o problema recursiv este o caracteristică a limbajului de

programare şi nu ţine doar de formularea problemei.

Un subprogram recursiv se comportă ca şi cum am avea definite în acelaşi program un

număr de copii identice ale subprogramului.

I. Mod iterativ:

unsigned long facti(int n)

{int i, unsigned long f=1;

for(i=1; i<=n; i++)

f = f*i;

return f;}

II. Mod recursiv:

unsigned long factr(int n)

{if(n == 0)

return 1;

else

return n*factr(n-1);}

În urma apelurilor recursive, valorile întoarse se refac în ordinea inversă a apelului.

Exemplu:

#include<iostream>

using namespace std;

void frec(int n)

{if(n == 0)

{cout<<”GATA”<<endl;

return;}

cout<<”#n”<<n<<” “<<$n<<endl;

frec(n-1);

cout<<”*n”<<n<<” “<<$n<<endl;

return;}

Page 33: Programare Structurata

void main()

{frec(5);…}

Se afişează : #n 5 0012FE98

#n 4 0031DE45

#n 3 00120AB20

#n 2 0011AB19

#n 1 0011AB15

GATA

*n 1 0011AB15

*n 2 0011AB19

. . . . . . .

*n 5 0012FE98

Restricţii specifice recursivitaţii:

Exemplu: int Peano(int n)

{if(n == 1)

return 1;

else

return (1+Peano(n-1));

}

OBS. Reamintim: f(1)=1 (funcţia identitate)

f(n)=f(n-1)+1

a) Dacă renunţ la if(n = = 1) return 1; obţin: “stack overflow error “, deci toate

valorile admise la apelul unei funcţii recursive trebuie să conducă la condiţia de oprire.

b) Dacă în loc de secvenţa if(n == 1) return 1; avem:

if(n == 5)

return 5;

atunci funcţia va funcţiona corect pentru apeluri cu n≥5;

în caz contrar nu se va opri.

c) Dacă apelăm funcţia cu o valoare foarte mare putem obţine eroare generată de

depăşirea spaţiului de memorie.

Page 34: Programare Structurata

Exemplu: Peano(214748364) //OK

Peano(412400012) //eroare

Exemple de programe rezolvate recursiv:

1) Aranjamente ( I)=iterativ, R)=recursiv)

R) int aranjamente(int n, int k)

{if(k == 0)

return 1;

else

return n*aranjamente(n-1, k-1);}

I) int aranjamente(int n, int k)

{int i; float a = 1;

for(i=n; i>=n-k+1; i--)

a = a*i;

return a;}

2) Combinări

R) int combr(int n, int k)

{if((n == k)||(k == 0))

return 1;

else

return (combr(n-1, k-1) + combr(n-1, k ));}

3) Minimul într-un vector – metoda DIVIDE ET IMPERA

#include<iostream.h>

int n, i, x[20];

int minim(int x[], int inceput, int sfarsit) {

int m1, m2, mij, m;

if((sfarsit-inceput) == 1)

{if (x[inceput]>x[sfarsit])

m = x[sfarsit];

else

Page 35: Programare Structurata

m = x[inceput];}

else

{mij = (inceput + sfarsit)/2;

m1= minim(x,inceput,mij);

m2 = minim(x,mij,sfarsit);

if(m1<m2)

m = m1;

else

m = m2;}

return m;

}

FIŞIERE

OBS. În C nu există instrucţiuni de intrare/ieşire (în sens clasic). Operaţiile de intrare/ieşire

sunt realizate prin apelul unor funcţii ale sistemului de operare. Aceste operaţii sunt

implementate prin funcţii sub o formă compatibilă cu diverse sisteme de operare.

Un fişier e o colecţie ordonată de articole (înregistrări) păstrate pe un suport de memorie şi

identificate printr-un nume.

OBS! Pentru fişierul standard de intrare datele sunt introduse de la tastatură, iar pentru cel

standard de ieşire sunt afişate pe aşa numitul terminal de ieşire. Erorile se afişează în

fişierul standard de eroare. Există un articol ce marchează sfârşitul fişierului, care pentru

fişierul standard de intrare, pentru DOS şi WINDOWS, se generează cu Ctrl+Z.

Operaţii specifice cu fişiere: deschiderea / închiderea, crearea, citirea, actualizarea

(modificarea), adăugarea la sfarşit, poziţionarea în fişier, schimbarea numelui fişierului,

ştergerea.

Prelucrarea se poate face pe două niveluri:

a. inferior (se apelează direct la sistemul de operare);

b. superior (utilizând structuri speciale tip FILE);

Page 36: Programare Structurata

OBS! Funcţiile standard de intrare / ieşire au prototipurile în fişierul antet < stdio.h >.

Clasificare:

- fişiere text;

- fişiere binare.

În orice fişier text datele sunt memorate ca şiruri de caractere, linii separate prin Enter.

Într-un fişier text spaţiul de memorare pe disc nu e folosit eficient. Într-un fişier binar

datele sunt păstrate în formatul lor intern.

Pentru fişiere text EOF (end of file), caracterul OX1A există fizic în fişier. La întâlnirea

lui, funcţia fgetcc întoarce EOF (-1). Pentru fişierele binare, marcajul de sfârşit de fişier e

generat de fgetc (nu există fizic).

OBS. În DOS (Unix) intrările / ieşirile standard pot fi redirectate în fişiere disc la

nivelul liniei de comandă, gen: ”<” redirectează intrarea spre fişierul specificat ,”>”

redirectează ieşirea spre fişierul specificat.

Accesul la fişiere: atât fişierele standard cât şi la cele de pe disc sunt gestionate prin

pointeri la structuri specializate tip FILE ce se asociază acestora pe durata prelucrarii.

Declararea unui pointer într-un fişier în C se face prin *pf.

Deschiderea unui fişier:

a) înainte de prelucrare;

b) se asociază unui nume de fişier un pointer la acesta;

c) se stabileşte un mod de acces la fişier;

Prototipul funcţiei FILE *fopen(char *nume_fisier, *mod_acces).

Deschiderea presupune crearea unei conexiuni între fişier şi variabila pointer şi

alocarea unei zone de memorie.

Funcţia întoarce un pointer la fişier dacă deschiderea e corectă sau NULL în caz

contrar.

Moduri de acces:

a) citirea ”R” (citirea din fişier inexistent dă eroare);

b) scrierea ”W” (dacă fişierul există deja, el va fi şters).

OBS! Fişierele standard nu trebuie deschise. Redirectarea unui fişier deschis se poate face

cu FILE *freopen(char *nume, char *mod, FILE *fisier).

Page 37: Programare Structurata

Fişierul deschis este închis, se deschide unul nou avand ca sursa fluxul

(fişier), de nume (nume) şi modul de acces specificat (mod): instrucţiunea fclose.

Închiderea unui fişier se face după terminarea prelucrărilor.

OBS: La apelul ”exit” toate fişierele se închid automat.

int fclose(FILE *pf )

Întoarce 0 la închiderea normală şi EOF la eroare.

OBS: Fişierele standard nu se închid.

Pentru un fişier de ieşire se scriu datele nescrise din buffer în fişier. Închiderea e

obligatorie pentru un fişier de intrare.

Operaţii de intrare / ieşire la nivel de caracter

int fputc(char c, FILE *pf)

OBS. Funcţia întoarce primul parametru sau EOF în caz de eroare.

int fgetc(FILE *pf) – citeşte un caracter dintr-un fişier. Întoarce ca rezultat următorul

caracter citit din fişier. EOF dacă s-a citit sfârşitul sau s-a produs o eroare.

Operaţii de intrare / ieşire pentru şiruri de caractere

char fgets(char *s, integer, FILE *pf) – citeşte caractere din ”pf ”(fişierul considerat),

cel mult (n-1), în tabloul ”s”; pune la sfârşit ’\n’ (Enter) şi marcajul de sfârşit de şir ’\

o’; (citirea se face pâna la întâlnirea unui Enter) intoarce ’s’ sau NULL la întâlnirea lui

EOF sau eroare.

char *fputs(char *s ,FILE *pf ) – un string în FILE; copiază şirul în fişierul de ieşire,

nu copiază terminarea de şir ’\o’. Întoarce numărul de caractere scrise în fişier sau EOF

la eroare.

Moduri de acces

Situaţii :

1. fişierul nu există: dorim să-l creăm şi să punem informaţii în el - ” W ” ;

2. fişierul există: dorim să extragem informaţii din el - ” R ” si ” R+ ” ( citire şi scriere);

Page 38: Programare Structurata

3. fişierul există: dorim să adăugăm pastrând informaţiile existente

a: deschiderea spre adăugare la sfarşit ;

a+: citire şi adăugare. Dacă nu există el va fi creat;

4. fişierul există: dorim să punem alte informaţii ştergându-le pe cele existente - ” w+ ”

(citire şi scriere) .

OBS. Modul de acces binar se specifică cu ” b ” . Avem : ” Rb ” , ” W+b”. Modul text

este considerat implicit, dar se poate specifica prin ” t ” .

Intrări / ieşiri cu format

1. Scrierea cu format

int printf( FILE *pf , char *format , lista_expresii ; –

transferă în fişierul specificat valorile expresiei convertite conform formatului. Întoarce

numărul de caractere scrise dacă am eroare .

OBS. Un descriptor de conversie pentru format are sintaxa:

%[ indicator ][ latime ].[ precizie ][ spec.lung];

Unde ” indicator ” poate lua ca valori : ”-” pentru aliniere la stânga, ”+” pentru afişare cu

semn, ”0” pentru completarea la stânga cu zerouri, adăugare spaţiu înaintea cifrei dacă

numarul este pozitiv. ”lăţimea” indică lăţimea maximă în care se face scrierea. ”precizia”

este un număr interpretat în funcţie de descriptorul găsit, astfel, dacă descriptorul este :

%a , %E , %f atunci precizia este egală cu numărul de cifre zecimale. Dacă descriptorul

este string ( %s ) atunci precizia este numărul de caractere din şir. Dacă descriptorul este :

%d , %i atunci precizia este numărul minim de cifre cu zerouri în faţă . Specificarea

lungimii se face prin: M( short ), l( long ), L (long double).

2. Citirea cu format

int fcanf( FILE *pf , char *format , lista_var ) ; - se citesc date din ”pf” cu format,

iniţializându-se variabilele din listă . Se întoarce numărul de câmpuri citite sau EOF la

întâlnirea lui EOF sau eroare .

Page 39: Programare Structurata

Intrările/ieşirile în modul de acces binar sunt citiri/scrieri fără conversii la nivel de articol,

iar poziţia fiecărui fişier este actualizată după fiecare citire/ scriere.

unsigned fread( void *zona unsigned la unsigned na , FILE *pf ) ; - se citesc

cel mult ”na” articole, de lungime ”la”, din fişierul ”pf ” în ”zona” . Întoarce numărul de

înregistrări citite (na) sau 0 în caz de eroare sau EOF .

unsigned fwrite( void *zona , unsigned la , unsigned na , FILE *pf ) ; - se scriu

”na” articole, de lungime ”la” , din fişierul ”pf ” în ”zona”. Întoarce numărul de articole

scrise sau 0 în caz de eroare sau EOF .

Operaţii pentru fişiere cu acces direct

a) Poziţionarea în fişier

int fseek ( FILE *pf , long depl , int orig ) ;

- modifică poziţia curentă în fişierul pf cu depl octeţi relativ la cel de-al 3-lea

parametru orig ;

- astfel: *faţă de începutul fişierului: orig = 0 (SEEK_SET)

*faţă de poziţia curentă: orig = 1 (SEEK_CUR)

*faţă de sfârşitul fişierului: orig = 2 (SEEK_END);

- întoarce 0 pentru poziţionare corectă şi diferit de 0 în caz de eroare; OBS.

Procedura void rewind ( FILE *pf ); realizează o poziţionare la începutul fişierului, fiind

echivalentă cu fseek ( pf 0L , SEEK_SET ); .

b) Poziţia curentă în fişier

long ftell ( FILE *pf );

- întoarce poziţia curentă în fişier dată prin numărul de octeţi faţă de începutul

fişierului;

c) Tratarea erorilor

- int feof ( FILE *pf ) ;

- întoarce o valoare nenulă dacă s-a găsit eof;

- int ferror ( FILE *pf ) ;

- întoarce o valoare nenulă dacă s-a detectat o eroare în timpul operaţiei de I/O.

Page 40: Programare Structurata

Fluxuri de I/O in C++:

OBS. Prin flux înţelegem o clasa. Astfel putem clasifica fluxurile în:

- fluxuri de I / O standard (pentru monitor , tastatură );

- fluxuri de I / O folosind fişiere;

- fluxuri de I / O în memorie .

OBS. cout<<x – cout este un obiect de tip flux de ieşire standard iar transferul informaţiei

în fişier se realizează prin operatorul << supraîncărcat .

- similar , cin este obiectul flux de intrare standard;

- ambele obiecte sunt declarate uzual în iostream.h;

Utilizatorul îşi poate defini propriile fluxuri ca obiecte în clasele:

- ofstream pentru operaţii de scriere;

- ifstream pentru operaţii de citire;

- fstream pentru operaţii mixte.

OBS. La folosirea acestor clase se include antetul fstream.h .

- asocierea fişier-flux (deschidere fişier) se face cu funcţia membru open() cu

sintaxa:

void open(char *nume_fisier int mod , int acces )

- modul în care poate fi deschis un fişier este precizat în clasa ios prin

enumeratorii:

*in – fişierul se deschide pentru citire şi trebuie să existe;

*out – fişierul se deschide pentru scriere. Dacă există deja se suprascrie;

*ate – fişierul se deschide pentru adăugare la sfarşit. Dacă nu există se creează

automat;

*app – fişierul se deschide pentru adăugare la sfarşit, dar trebuie să existe;

*trunc – dacă fişierul există va fi şters şi se va crea unul nou pentru scriere;

*nocreate – fişierul trebuie să existe;

*noreplace – fişierul este deschis însă conţinutul lui nu-i poate fi înlocuit;

*binary – fişierul deschis va fi prelucrat ca un fişier binar.

Exemple: fstream f;

f.open (“situatie.dat” ios: in) ;

Page 41: Programare Structurata

Modul de acces acces poate fi 0 (fişier fără restricţii de acces), 1 (fişier protejat la

scriere) , 2 (fişier ascuns) , 4 (fişier sistem) , 8 (fişier arhivă).

Desfacerea legăturii fişier–stream se face cu close() .

OBS. Dacă în urma deschiderii variabila stream = null atunci operaţia de deschidere a

eşuat.

Exemple: fstreamf g ;

if (!g.open (“note.in ios: in )

{cerr<<” eroare la deschidere !\n “ ;

exit(1) ; }

Operatorii de inserţie şi extracţie pot fi folosiţi pentru a scrie/citi din/în fişier.

Funcţia Explicaţie

void open (char *nume, int mod, int acces);

void close ();

istream &get (char &c);

int peek ();

istream &putback ();

istream &get (char *sir, int n, char sep=’\n’);

istream &getline (char *sir, int n, char sep=’\

0’);

istream &read (char *sir, int n);

int gcount ();

int tellg ();

istream &seekg (long depl, int orig = ios ::

beg);

deschide fişierul;

închide fişierul;

citeşte un caracter din fluxul de intrare; la

întâlnirea lui eof întoarce null;

preia următorul caracter din fluxul de

intrare, fără a-l extrage;

pune înapoi în fişier un caracter;

se citesc cel mult n-1 caractere sau până la

întâlnirea lui set, care este pus în şir;

se citesc n-1 caractere până la întâlnirea lui

set, în locul căruia este pus acest terminator

‘\o’ (sfarşit de şir de caractere);

citeşte cel mult n caractere binare;

determină câte caractere s-au citit în ultima

operaţie de citire;

determină poziţia curentă a citirii;

deplasare cu depl octeţi faţă de început /

poziţie curentă / sfarşit;

Page 42: Programare Structurata

ios ::

cur

ios ::

end

ostream &put (char c);

ostream &write (char *c, int n);

long tellp ();

ostream &seekp (long depl, int orig = ios ::

leg);

introduce ‘c’ în fluxul de ieşire;

scrie cel mult n caractere în fluxul de ieşire;

determină poziţia curentă la scriere;

deplasare cu depl octeţi faţă de început.

Exemplu:

void main ()

{ofstream out;

ifstream in;

out.open (“ iesire.dat ”);

out<<” Vasilica invata C ”;

out.close();

in.open (“ intrare.dat ” );

char linie[80];

in>> linie;

cout<<linie; }