PRELEGERE XIII PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE Noţiunea de funcţie - continuare VI. Funcţii recursive O funcţie se poate activa n

Documente similare
Microsoft Word - CarteC.doc

Limbaje de Programare Curs 6 – Functii de intrare-iesire

Limbaje de Programare Curs 8 – Fisiere

SUBPROGRAME

Microsoft Word - CarteC.doc

Microsoft Word - PCLP2_Curs_4_2019.doc

E_d_Informatica_sp_SN_2014_bar_10_LRO

L7

Programarea şi utilizarea calculatoarelor

Limbaje de programare Pointeri. Alocare dinamică (continuare) 26 noiembrie 2012

LUCRAREA NR

Limbaje de Programare Curs 5 – Siruri de caractere

Logică și structuri discrete Limbaje regulate și automate Marius Minea marius/curs/lsd/ 24 noiembrie 2014

E_d_Informatica_sp_MI_2015_bar_02_LRO

Laborator 2 Incompatibilităţi/Diferenţe între C şi C++ Completări C++ Supraîncărcarea (redefinirea) numelui de funcţii În C nu este permisă existenţa

Slide 1

Microsoft PowerPoint - ImplementareLimbaj [Read-Only] [Compatibility Mode]

Paradigme de programare

ALGORITMII ŞI REPREZENTAREA LOR Noţiunea de algoritm Noţiunea de algoritm este foarte veche. Ea a fost introdusă în secolele VIII-IX de către Abu Ja f

Microsoft PowerPoint - Curs_SDA_4_RO_2019_v2.pptx

Operatorii in C Expresii Operatori aritmetici Operatori de asignare Operatori de incrementare si decrementare Operatori relationali Operatori logici O

Microsoft Word - Lab1a.doc

Object Oriented Programming

Programarea calculatoarelor. Note de curs Marius Minea 1 Introducere în programarea în C 1.1 Funcţii în limbajul C Calcule şi funcţii La origine, rolu

Lab6LCD

Slide 1

Microsoft PowerPoint - Curs_SDA_3_RO_2019_v2.pptx

tehnologii web

Programarea şi utilizarea calculatoarelor

Adresarea memoriei Modurile de adresare constituie un instrument principal pentru reprezentarea în memorie a imaginii datelor, aşa cum este ace

Subiectul 1

Microsoft PowerPoint - Curs_SDA_9_RO_2019_v2.pptx

Slide 1

Preprocesorul C Funcţii cu numǎr variabil de argumente 6 decembrie 2005 Programarea calculatoarelor 2. Curs 10 Marius Minea

Microsoft Word _POO_Lab_1_Modificari_v01.htm

Microsoft Word - CarteC.doc

1. Operatii cu matrici 1 Cerinte: Sa se realizeze functii pentru operatii cu matrici patratice (de dimensiune maxima 10x10). Operatiile cerute sunt: A

Microsoft Word - O problema cu bits.doc

proiectarea bazelor de date

Top

Procesarea Imaginilor - Laborator 1: Introducere în utilizarea bibliotecii OpenCV 1 1. Introducere în utilizarea bibliotecii OpenCV 1.1. Introducere S

Interfețe și Protocoale de Comunicații Arduino-Port Paralel Arduino. Laborator 1- Portul Paralel 1 Caracteristici generale Arduino UNO este o placă de

GHERCĂ MAGDA CASA CORPULUI DIDACTIC BRĂILA PORTOFOLIU EVALUARE INFORMATICĂ ȘI TIC PENTRU GIMNAZIU CLASA A V-A Neamț SERIA 1 GRUPA 1 CURSANT: GHERCĂ G

-

Microsoft Word - c6.doc

Microsoft Word - Curs1.docx

ALGORITMICĂ. Seminar 3: Analiza eficienţei algoritmilor - estimarea timpului de execuţie şi notaţii asimptotice. Problema 1 (L) Să se determine număru

Propunator: Morar Florin Colegiul National Silvania Zalau Discipina: Informatica Nivel liceal, cls. XII 1.Să se scrie în limbajul C/C++ definiţia comp

PROGRAMA DE EXAMEN

Laborator 3

Microsoft PowerPoint - Curs_SDA_10_RO_2019_v1.pptx

PROGRAMARE ORIENTATA PE OBIECTE

Diapositive 1

SIRURI DE CARACTERE in C++ O constanta de tip sir de caractere de declara intre doua caractere. In memoria interna, o constanta de acest tip este reti

Tipuri de date abstracte 30 noiembrie 2005 Programarea calculatoarelor 2. Curs 9 Marius Minea

Microsoft Word - 2 ES RO.doc

Microsoft Word - Curs_08.doc

Laborator 2: Instrucţiuni Java şi lucru cu şiruri de caractere Întocmit de: Adina Neculai Îndrumător: Asist. Drd. Gabriel Danciu 18 octombrie 2011

Secţiunea 7-8 începători Concurs online de informatică Categoria PROGRAMARE PROBLEMA 1 ID 100 puncte Calculatoarele trebuie să se recunoască în rețeau

Lucrarea 10

Fişiere 11 ianuarie 2004 Utilizarea şi programarea calculatoarelor. Curs 13 Marius Minea

Aggregating Data

PPSD

Paradigme de Programare

PHP (II)

Slide 1

Modul Modbus ASCII SISTEME DE COMUNICATIE CURS 5 - Constantinescu Catalin Atunci cand se foloseste modul MODBUS ASCII fiecare octet din mesaj

Capitole Speciale de Informatică Curs 4: Calculul scorurilor în un sistem complet de extragere a informaţiilor 18 octombrie 2018 Reamintim că în cursu

PowerPoint Presentation

Nr. 932 din Avizat ISJ Vâlcea, Inspector școlar informatică, Ciochină Luisa EXAMEN DE ATESTARE A COMPETENȚELOR PROFESIONALE A ABSOLVENȚILOR

LUMINIŢA SCRIPCARIU

Logică și structuri discrete Relații. Funcții parțiale Marius Minea marius/curs/lsd/ 20 octombrie 2014

Microsoft Word - unitati de invatare 11liceu-12 sam

Fâciu N. Maria-Ema CASA CORPULUI DIDACTIC BRĂILA PROGRAM DE FORMARE INFORMATICĂ ȘI TIC PENTRU GIMNAZIU CLASA A V-A SERIA 1 GRUPA 2 CURSANT: Fâciu N. M

Microsoft Word - Curs_10.doc

Microsoft Word - Curs_07.doc

B

Microsoft Word - Cuprins_LP.doc

Informație și comunicare

Facultatea de Științe Politice, Administrative și ale Comunicării Str. Traian Moșoiu nr. 71 Cluj-Napoca, RO Tel.: Fax:

PCLPII-C16(9)

Baze de date - Anul 2 Laborator 8 Limbajul de definire a datelor (LDD) (partea I) În general, instrucţiunile LDD sunt utilizate pentru definirea struc

Curs de formare Informatică și TIC pentru clasa a V-a Portofoliu pentru evaluarea finală Tema: ELEMENTE DE INTERFAŢĂ ALE UNUI SISTEM DE OPERARE (DESKT

Microsoft PowerPoint - Curs_TPI_22_v01.ppt

Laborator 1-Teoria probabilitatilor si statistica matematica Sef lucrari dr.mat. Daniel N.Pop Departamentul de calculatoare si inginerie electrica 1 P

Scrieţi pe foaia de examen răspunsul pentru fiecare dintre cerinţele următoare

Microsoft Word - Laborator 6 - Expresii Regulate IV.doc

Cursul 12 (plan de curs) Integrale prime 1 Sisteme diferenţiale autonome. Spaţiul fazelor. Fie Ω R n o mulţime deschisă şi f : Ω R n R n o funcţie de

Facultatea de Științe Politice, Administrative și ale Comunicării Str. Traian Moșoiu nr. 71 Cluj-Napoca, RO Tel.: Fax:

Înregistrator de temperatură şi umiditate AX-DT100 Instrucţiuni de utilizare

Programarea şi utilizarea calculatoarelor

Microsoft Word - Curs_09.doc

Secţiunea 5-6 începători Concurs online de informatică Categoria PROGRAMARE PROBLEMA puncte PERIODIC Se citește un număr natural nenul N. Se ump

ANEXĂ

Microsoft Word - 4-Interfete paralele.doc

Secţiunea 5-6 avansaţi PROBLEMA 1 Concurs online de informatică Categoria PROGRAMARE 100 puncte NR Un număr natural nenul V care se plictisea singur,

1. Găsiți k numerele cele mai apropiate într-un şir nesortat Dându-se un şir nesortat și două numere x și k, găsiți k cele mai apropiate valori de x.

Managementul Resurselor Umane

Gestionarea I/E

Transcriere:

PRELEGERE XIII PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE Noţiunea de funcţie - continuare VI. Funcţii recursive O funcţie se poate activa nemijlocit pe ea însăşi de un număr nedeterminat de ori. În această situaţie, funcţia se numeşte recursivă. O condiţie de oprire a acestui proces trebuie prevăzută şi programată. În caz contrar, spaţiul afectat în stivă pentru depozitarea adresei de retur, a valorilor parametrilor transmişi prin valoare, a informaţiilor despre parametrii transmişi prin adresă, a rezultatelor ermediare şi al apelului de funcţie va creşte rapid, riscînd depăşirea acestuia. Etapele care apar în desfăşurarea fiecărui proces de activare a unei funcţii recursive sînt acelaşi ca la activarea unei funcţii obişnuite, chiar dacă apelul de funcţie este situat în definiţia unui bloc de funcţie şi nu în funcţia apelantă. Aici, funcţia fact() realizează calculul factorialului conform formulei n! = nx(n-1)!, care permite organizarea acesteia ca o funcţie recursivă. /* Functie recursiva */ fact( n) { if (n == 0) return 1; else return n*fact(n-1); } Funcţia 12.6.1 De fapt, determinarea expresiei n! cu ajutorul unei funcţii recursive fact() se face pe baza formulei n! = fact(n)*fact(n-1)* fact(1)*fact(0). Se observă că, sînt necesare n apeluri ale funcţiei fact(), urmate de secvenţele corespunzătoare de reveniri. Terminarea apelurilor recursive are loc atunci cînd se întîlneşte apelul fact(0). Calculul factorialilor se face acum de la dreapta către stînga. Dacă n este foarte mare, atunci este posibil depăşirea spaţiului din stivă cu semnalarea unei erori corespunzătoare şi oprirea programului. În consecinţă, simplitatea şi eleganţa funcţiilor recursive nu sînt motivaţii suficiente în recomandarea utilizării lor în rezolvarea unor probleme. Şi funcţia predefinită main() poate primi atributul de recursiv, după cum se observă în exemplu de mai jos: main(void) { prf("\n Acest mesaj se tipareste la infinit"); main(); return 0; } Funcţia 12.6.2 1

VI. Funcţii predefinite Biblioteca limbajului oferă un sortiment bogat de funcţii predefinite, care sînt un instrument eficace la doispoziţia utilizatorului în scrierea unor programe rapide, elegante, uşor de urmărit şi de întreţinut. Acestea sînt destinate în utilizarea funcţiilor matematice, prelucrarea valorilor ordinale, tratarea şirurilor de caractere, definirea, actualizarea şi exploatarea fişierelor, folosirea poerilor, alocarea dinamică a memoriei, eficientizarea folosirii display-ului, dezvoltarea unei grafici diverse, etc. În această secţiune vom prezenta contextul general de apelare a unor funcţii predefinite care rezolvă operaţii privitoare la şirurile de caractere, la alocarea dinamică a memoriei, la construirea de funcţii cu număr variabil de parametri şi la descrierea modulului principal de program. 1) Cîteva funcţii din string.h Declaraţiile de date împreună cu macrodefiniţiile şi prototipurile funcţiilor cu referire la şiruri de caractere sînt grupate în fişierul antet string.h (extensia h provine de la cuvîntul header) existent în directorul include. La începutul programelor, care utilizează funcţiile enumerate mai jos şi nu numai, trebuie să se prevadă directiva #include <string.h>. a) Întoarcerea numărului de caractere (lungimea) dr-un şir de caractere se obţine prin apelarea funcţiei predefinite strlen(). Antetul acestei funcţii are următorul format general: unsigned long strlen(const char *sir). De exemplu, lungimea şirului evidenţiat în figura 12.6.1.1 este 3, adică, strlen(şir)=3. abc sir Figura 12.6.1.1 b) Duplicarea unui şir de caractere se realizează prin ermediul funcţiei predefinite strdup(), al cărui antet de definiţie este următorul: char *strdup(const char *sir1). Atribuirea sir2 = strdup(sir1); poate fi reprezentată schematic ca în figura 12.6.1.2: aabb11cc sir1 sir2 aabb11c Figura 12.6.1.2 c c) Concatenarea (suma) a două şiruri de caractere este efectul apelului funcţiei predefinite strat(). Linia de definiţie a acestei funcţii este următoarea: char *strat(char *sir1, const char *sir2). Şirul al doilea de caractere se memorează în spaţiul alocat lui sir1, după valoarea acestuia, aşa cum se preză în figura 12.6.1.3. sir1 sir2 sir1 sir2 sir2 Figura 12.6.1.3 2

d) Compararea a două şiruri de caractere se rezolvă, prin apelul fucţiei predefinite strcmp(), după schema: - dacă sir1 < sir2, atunci funcţia întoarce 1; - dacă sir1 > sir2, atunci funcţia întoarce 1; în caz contrar se întoarce 0. Antetul de definiţie al funcţiei strcmp() este următorul: strcmp(const char *sir1, const char *sir2). e) Prin apelul funcţiei predefinită strcpy(), care are linia de definiţie char *strcpy(char *sir1, const char *sir2), se realizează copierea şirului al doilea de caractere în zona de memorie afectată lui sir1. Operaţia de copiere poate fi urmărită în reprezentarea grafică din figura 12.6.1.2, schimbînd doar sensul săgeţii verticale. f) Funcţia strchr() caută într-un şir de caractere prima apariţie a unui caracter dat şi întoarce poer la acea apariţie, după cum se observă în figura 12.6.1.4. Saxa generală a antetului de definiţie este următoarea: char *strchr(const char *sir1, c). sir1 c c Figura 12.6.1.4 În programul 12.6.1.1 ervin funcţiile strlen() şi strcat(). Prin apelul funcţiei strlen() se află lungimea tuturor şirurilor de caractere manipulate în program, iar rezultatul returnat prin apelarea funcţiei strcat() este sir3, care repreză concatenarea şirurilor de caractere sir1 cu sir2. /*Utilizarea functiilor strlen() si strcat() */ #include <stdio.h> #include <conio.h> #include <string.h> void main(void) { clrscr(); char *sir1 = Programare ; char *sir2 = in Turbo C++ ; char *sir3; prf("\n Sirul %s are lungimea de %d caractere ", sir1, strlen(sir1)); prf("\n Sirul %s are lungimea de %d caractere ", sir2, strlen(sir2)); sir3 = strcat(sir1, sir2); prf("\n Sirul %s are lungimea de %d caractere ", sir3, strlen(sir3)); getch(); } Sirul Programare are 10 caractere Sirul in Turbo C++ are 13 caractere Sirul Programare in Turbo C++ are 23 caractere Programul 12.6.1.1 Pentru a stîrni mai mult curiozitatea cititorilor, textul definiţiilor funcţiilor strlen() şi strcat() se preză în cele ce urmează. /* Functia strlen() */ unsigned long strlen(const char * sir) 3

{ register n; for(n=0; *sir!= \0 ; ++sir) ++n; return n; } Funcţia 12.6.1.1 După cum se observă, se utilizează registrele de memorie pentru alocarea numărătorului de paşi, în vederea optimizării procesării structurii repetitive for. De cîte ori se găseşte un caracter diferit de caracterul terminator de şir de caractere (\0) se incrementează valoarea contorului n. /* Functia strcat() */ char*strcat(char * sir1, const char *sir2) { register char *p = sir1; while(*p) ++p; while(*p++ = *sir2++); return sir1; } Funcţia 12.6.1.2 Cu prima instrucţiune while se localizează terminatorul de sfîrşit de şir de caractere pentru sir1, apoi cu a doua instrucţiune while se memorează, în continuare, caracter după caracter, conţinutul lui sir2. Zona de memorie afectată lui sir2 nu suportă nici o modificare. 2. Funcţii de alocare dinamică Alocarea dinamică a variabililor, care nu au dimensiunea cunoscută sau la care dimensiunea variază înte limite largi, prin ermediul funcţiilor predefinite din fişierul antet stdlib.h. a) Cele mai des folosite funcţii predefinite de alocare dinamică în limbajul C++ sînt malloc() şi free(), care se aplică variabililor de tip static şi automatic. Prin apelul funcţiei malloc(), necesarul de memorie pentru o astfel de variabilă se afectează în momentul execuţiei programului, în zona Heap, după care se eliberează prin funcţia free(), în vederea realocării lui în alt scop. Formatul general al antetului de definiţie pentru funcţia malloc() este următorul: void *malloc(unsigned numar_octeti);. Argumentul numar_octeti indică dimensiunea în octeţi rezervată în zona de memorie Heap. Rezultatul funcţiei este un poer de tip void, care conţine adresa primului octet din zona Heap afectată. În situaţia cînd memoria este insuficientă, funcţia întoarce un rezultat NULL. Se reameşte că un poer de tip void poate fi asignat oricărui alt tip de poer. De exemplu, pentru alocare dinamică de memorie unui tablou unidimensional, raţional în simplă precizie şi cu dimensiune precizată se pot utiliza următoarele două linii de program: float *x; x = (float ) malloc(5*sizeof(float)); x[0], x[1], x[2], x[3] şi x[4] sînt componentele tabloului x, care vor fi memorate în zona Heap la adesele x, x+1, x+2, x+3 şi respectiv x+4. Precizarea spaţiului de memorie pentru un anume tip de dată prin operatorul sizeof() şi utilizarea operatorului cast pentru conversie de tip la atribuire sînt recomandate în asigurarea portabilităţii programelor. Dezafectarea unei alocării dinamice de memorie se face prin apelul funcţiei free(), care are următorul format general: void free(void * nume_poer);. 4

După prelucrarea tabloului x, din exemplul de mai sus, se impune eliberarea memorie afectate acestuia, prin free(x);. Prin programul 12.6.2.1 se citeşte, de la tastatura computerului, un număr nedeterminat de valori reale nenule şi diferite între ele, a căror sumă se află şi se tipăreşte pe ecranul monitorului în modulul principal de program. /* Functii de alocare dinamica */ #include <stdio.h> #include <conio.h> #include <stdlib.h> float *cit_nr( ); void main(void) { clrscr(); k, i = 0 ; float suma, *t; prf("\n Introduceti numarul valorilor regi : "); scanf("%d", &k); t = cit_nr(k); for ( suma =0., i = 0; i < k; ++i) suma +=*t+i; //Aflarea sumei prf("\nsuma =%f", suma); //Tiparirea sumei free(t); //Eliberarea memoriei getch(); } /* Functia de citire numere regi */ float *cit_nr( k) { i; float *p; if(!(p = (float *) malloc(k*sizeof(float)))) //Alocare dinamica { puts("memorie insuficienta"); return NULL; } prf("\n Nr. s : "); for (i = 0; i < k; ++i) //Citirea sirului de valori { scanf("%f", p+i); prf(" \n ");} return p; } Introduceti numarul valorilor regi : 2 Nr. s: 4 5 Suma = 9.000000 Programul 12.6.2.1 Absenţa funcţiei free(t); în modulul principal are ca efect neeliberarea variabilei dinamice t şi în consecinţă, zona de memorie Heap rămîne alocată şi neadresată pînă la încheierea execuţiei programului. Absenţa argumentului local p în cadrul instrucţiunii return are de asemenea efecte nedorite. Domeniul de vizibilitate al lui p este blocul funcţiei cit_nr() şi dispariţia ei nu implică eliberarea zonei de memorie Heap alocate dinamic şi adresată dinamic pînă la terminarea execuţiei acesteia. În modulul principal, variabila dinamică t nu mai poate fi accesată deşi ea există în memorie şi nici eliberată pentru că poerul p dispare odată cu revenirea în funcţia main(). 5

b) În plus, pentru limbajul C++ există mai multe variante de organizare a spaţiului de memorie afectat variabililor dinamice, numite modele de memorie. Acestea necesită cunoştinţe de programare avansată. 3. Funcţii cu număr variabil de parametri Funcţiile cu un număr variabil de parametri ridică probleme legate atît de cunoaşterea dimensiunii zonei de memorie afectată şi de tipul de dată utilizat în fixarea modului de reprezentare a valorii de memorare, cît şi de referirea valorilor parametrilor actuali care se transferă parametrilor actuali, în absenţa indentificatorilor acestora. Dre funcţiile predefinite cu un număr variabil de parametri des utilizate în programele prezentate pînă în prezent se amesc scanf() şi prf Fişierul antet stdarg.h oferă un set de funcţii predefinite, care permite scrierea şi folosirea funcţiilor utilizator cu un număr variabil de parametri. Astfel, cu funcţiile va_start(), va_arg() şi va_end() se pot prelucra liste de parametri formali, pentru care nu se cunoaşte numărul şi tipurile acestora. Funcţia va_start() iniţializează variabila nume_var cu adresa primului parametru formal din sublista variabilă. Formatul general al acestei funcţii este următorul: void va_start(va_list nume_var, par_ultim_fix);, unde va_list este un tip de poer predefinit şi precizat în fişierul antet stdarg.h, către lista variabilă de parametri formali, nume_var este numele simbolic al variabilei prin ermediul căreia se adresează parametri formali, iar par_ultim_fix este indentificatorul ultimului parametru din sublista fixă. Funcţia va_arg() returnează valoarea parametrului indicat de variabila nume_var şi atribuie acesteia adresa următorului parametru formal din sublista variabilă. Saxa generală a funcţiei va_arg() este următoarea: tip_par va_arg(va_list nume_var, tip_var);, unde tip_par este tipul următorului parametru formal din sublista variabilă, care va preciza dimensiunea zonei de memorie alocată variabilei nume_var. Valorile transferate sînt extinse după caz la tipurile şi double. Funcţia va_end() încheie operaţia de extragere a parametrilor din sublista variabilă. Formatul ei general este următorul: void va_end(va_list nume_var);. Orice reluare a operaţiei de extragere a valorilor parametrilor din lista de variabile respectivă trebuie să recurgă din nou, în ordinea precizată mai sus, la cele trei funcţii. În programul 12.6.3.1 ervine funcţia suma(), care află suma unui număr variabil de valori cu tipul double cu ajutorul funcţiilor va_start(), va_arg() şi va_end(). Lista de valori poate să conţină numai constante reale, variabile şi elemente de tablou, cu restricţia că ultimul element al listei este zero. Deci, expresiile chiar cu rezultat de tip double nu sînt admise în lista de valori. Prima neconcordanţă de tip, fără să fie semnalată, generează oprirea prelucrărilor cu afişarea unui rezultat greşit. /* Functii cu numar variabil de parametri */ #include <stdarg.h> #include <stdio.h> typedef double dbl; void suma(char *msg,...) { dbl arg, total =0.; va_list v; 6

va_start(v, msg); /*initializarea variabilei v */ while(( arg = va_arg(v, dbl))!= 0.) {total += arg;} prf (msg, total); va_end(v); } /*incheie citirea parametrilor */ void main(void) { dbl x = 7., t[] ={4,5, 6,9, 0}; suma("suma =%lf\n", t[1], 4., t[3], 1., 3., 3., x, t[2], 0.) } Suma = 38.000000 Programul 12.6.3.1 4. Funcţia main() Funcţia main() determină modulul principal de program. Deci, cu ea se începe şi se încheie execuţia oricărui program. Prin funcţia main() se pot transmite informaţii necesare lansării în execuţie a programului, cum ar fi: indentificatorul de recunoaştere al programului, opţiuni de compilare şi date iniţiale. Aceste informaţii se numesc argumente din linia de comandă, deoarece sînt editate de sistemul de operare în cadrul comenzii de lansare în execuţie a programului respectiv. Funcţia main() are următoarea structură: [tip_de_dată] main([ argc, char *argv[]],[char *env[]]) {..} Atît tipul funcţiei cît şi lista de argumente sînt opţionale. În general, tipul de date care precede cuvîntul rezervat main este void. Dacă funcţia main() întoarce un rezultat, prin utilizarea instrucţiunii return, către programul apelant (adică, sistemul de operare), atunci acesta este 0, care indică terminarea normală a execuţiei funcţiei, sau un cod de eroare în caz de eşec. Argumentele argv[] şi env[] sînt tablouri de poeri. Parametrul argc fixează dimensiunea tabloului argv[] şi trebuie să verifice condiţia argc 1. Linia de comandă cuprinde şiruri de caractere delimitate de spaţiu sau Tab. Adresele acestora se memorează, în ordine, în tablourile de poeri argv[] şi env[]. La adresa argv[0] se înscrie numele programului. Numărul de adrese conţinute de tabloul argv[] depinde de valoarea argumentului argc. În figura 12.6.4.1 se repreză grafic conţinutul următoarei linii de comandă: nume_program o lista de sase argumente, unde argc = 6. argv[0] argv[1] nume_progra m o argv[2] lista argv[3] argv[4] de sase argumente 7

argv[5] Figura 12.6.4.1 Următoarele şiruri de caractere vor fi înregistrate la adrese succesive în tabloul de poeri env[]. Aceste şiruri de caractere pot constitui valori pentru unii parametri ai sistemului de operare, cum ar fi tipul prompt-ului tipărit la începutul unei linii de comandă sau căi implicite de căutare în directoare. La ultima adresă din env[] se înscrie valoarea NULL, care marchează sfîrşitul listei de opţiuni. Programul următor vizualizează numele autorului în conformitate cu informaţiile luate din linia de comandă: C:> Test Popescu I. Gheorghe <Enter> /* Functia main() #include <stdio.h> #include <conio.h> main(argc, char* argv[]) { i; prf("\nautor :"); for (i = 1; i < argc; i++) prf(" %s ", argv[i]); return 0; getch(); } Autor: Popescu I. Ghoerghe Programul 12.6.4.1 II. Noţiunea de structură Definirea şi prelucrarea unui grup organizat de date neomogen se realizează prin ermediul noţiunii de structură. Acelaşi lucru se denumeşte în alte limbaje de programare cu articol sau înregistrare logică. Unitatea elementară de informaţie din cadrul unei structuri se numeşte cîmp sau membru. Atît natura cît şi ordinea unui cîmp într-o structură se fixează, de către utilizator, după necesităţi. Numărul de cîmpuri care ră în componenţa unei structuri este nedeterminat. Declararea şi iniţializarea structurilor şi tablourilor de structuri vor fi prezentate în următoarele două secţiuni, iar diverse tipuri de structuri recursive, inclusiv exemple adecvate, vor constitui esenţa secţiuni 3.7.5. 1. Declararea şi iniţializarea unei structuri Un ansamblu format dr-un număr nedeterminat de cîmpuri cu diverse tipuri defineşte o structură. Referirea structurii se face prr-un nume simbolic stabilit de programator. Saxa generală de declarare a unei structuri este următoarea: struct nume_tip_structura { tip_cîmp_1 nume_cîmp_1; tip_cîmp_2 nume_cîmp_2;.. tip_cîmp_n nume_cîmp_n; } lista_nume_var_tip_struct; unde, struct este cuvînt cheie. Nume_tip_structura şi nume_cîmp_i, cu i= 1, n, sînt identificatorii de recunoaştere pentru structură şi cîmpurilor componente structurii. Identificatorii de cîmpuri trebuie să fie unici numai în tipul de structură în care au fost definiţi. Tip_cîmp_i, cu i= 1, n, sînt tipuri de date, din cele descrise pînă în prezent, în concordanţă cu natura cîmpurilor corespunzătoare. La rândul lui, tipul unui cîmp poate 8

să fie un tip de structură descris anterior, existînd astfel posibilitatea reprezentării şi organizării a unor structuri de date complexe şi imbricate. Lista de variabile de tip structură încheie construcţia sactică de declarare a unei structuri. Ca separator de variabile în cadrul listei se admite doar virgula.. Este posibil să absenteze, fie numele simbolic al structurii, fie lista de variabile. Prima situaţie este mai rară, permiţînd declararea unei structuri anonime. Lista de variabile de tip structură poate fi precizată ulterior, numai cînd identificatorul de recunoaştere al structurii este cunoscut, prr-o construcţie de forma: struct nume_tip_structura lista_var_tip_struct;. O declarare mai simplă a variabililor de tip structură se poate obţine prin utilizarea specificatorului typedef (vezi, secţiunea 2.4.2). Referirea unui cîmp dr-o variabilă de tip structură se realizează, prin calificare, cu operatorul de selectare punct (.), astfel: nume_variabila. nume_cîmp_i, unde i= 1, n. O astfel de referire poate să ervină ca operand în expresii de atribuire sau ca parametru actual în funcţii de citire/scriere. Menţionăm doar că operatorul utilizat în aces caz este cel de selectare indirectă, notat prin săgeată ( ). Iniţializarea unei variabile de tip structură se obţine prin indicarea, în ordine, pentru fiecare cîmp component cîte o valoare corespunzătoare, după cum urmează: struct nume_tip_structura nume_variabila = (lista_valori);. Separatorul de valori în lista_valori este tot virgula. Ulterior, aceste valori pot fi afişate, modificate sau utilizate în diverse operaţii matematice. În programul de mai jos se descrie o structură, de tip catalog şcolar, cu următoarele cîmpuri componente: nume_prenume, adresa, discipline şi medie. A doua linie din programul principal precizează valorea iniţială pentru variabila student de tip structură catalog. Ulterior, o parte din aceste valori sînt schimbate prin instrucţiuni de atribuire, şi anume notele de la a treia disciplină şi a patra şi media. Tipărirea valorii variabilei student se face prin ermediul primelor trei funcţii de scriere prf() şi succede un text de tip comentariu. Alte amănunte despre structura programului sînt date la sfîrşitul secţiunii. /* Declarare structura catalog */ #include <stdio.h> #include <conio.h> struct catalog { char nume_prenume[25]; char adresa[35]; discipline[5]; float medie; }; void main(void) { clrscr(); struct catalog student={"popescu Ioan","M Eminescu 30 Iasi", 10, 9, 9, 8, 10, 9.2}; student.discipline[2] = 10; student.discipline[3] = 10;student.medie=9.80; prf("\n Variabila student este: "); prf("\n%s %s", student.nume_prenume, student.adresa); 9

prf("\n %d %d %d %d %d %5.2f\n", student.discipline[0], student.discipline[1], student.discipline[2], student.discipline[3], student.discipline[4], student.medie); struct catalog elev; elev = student; prf("\n Introduceti nume elev: \n"); gets(elev.nume_prenume); elev.discipline[1]=10; elev.medie=(elev.discipline[0]+elev.discipline[1]+elev.discipline[2] + elev.discipline[3]+elev.discipline[4])/5.; prf("\n Variabila elev este: "); prf("\n%s %s",elev.nume_prenume,elev.adresa); prf("\n %d %d %d %d %d %5.2f", elev.discipline[0], elev.discipline[1], elev.discipline[2], elev.discipline[3], elev.discipline[4], elev.medie); getch(); } Variabila student este: Popescu Ioan M Eminescu 30 Iasi 10 9 10 10 10 9.80 Introduceti nume elev: Ionescu Mihai Variabila elev este: Ionescu Mihai M Eminescu 30 Iasi 10 10 10 10 10 10.00 Programul 13.3.1.1 Variabilele, cu tipul structură identic, pot să apară în expresii de atribuire. Asignările se realizează în ordinea apariţiei cîmpurilor din componenţa structurii respective. În cazul programului de mai sus, atribuirea student = elev; este corectă şi se întinde asupra tuturor cîmpurilor componente, adică: nume şi prenume, adresă, discipline şi medie aritmetică. Numele şi prenumele elevului s-au citit de la tastatura calculatorului cu ajutorul funcţiei gets(). După schimbarea notei la a doua disciplină, se recalculează media aritmetică generală. Ultimele trei funcţii de scriere prf() afişează valoarea variabilei elev. III. FIŞIERE ŞI OPERAŢII DE INTRARE/IEŞIRE 1. Consideraţii generale Transferul informaţiilor între calculator şi utilizator se face prin ermediul dispozitivelor de rare/ieşire. Prre acestea se pot enumera tastatura, monitorul, imprimanta şi diverse unităţi de disc. De aceea, noţiunea de fişier trebuie discutată din două puncte de vedere: fizic şi logic. Pentru simplitate, dispozitivele fizice se denumesc prin vocabula fişier. Modul de organizare, de consultare şi de tratare al fişierelor logice depinde de limbajul de programare utilizat, de volumul informaţiilor prelucrate şi nu în ultimul rînd de configuraţia sistemului de calcul. În limbajul C++ s-au gîndit două categorii de fişiere logice (dispozitive de rare/ieşire) logice: predefinite şi de tip utilizator. 10

Conţinutul logic al fişierelor de tip utilizator este determinat de noţiunea de structură, în care se precizează numărul şi tipurile cîmpurilor componente structurii. Astfel, fişierul logic de tip utilizator este un ansamblu organizat de un număr nedeterminat de structuri. De fapt, fişierul logic de tip utilizator poate fi considerat un tablou multidimensional de lungime variabilă, în care coloanele au diferite tipuri de date. O situaţie specială o constituie fişierele predefinite (dispozitivele logice predefinite), care sînt gestionate automat la lansarea în execuţie a programului de tip C. Fişierele predefinite asociate claviaturii stdin şi stderr permit numai operaţii de citire, iar fişierele predefinite asociate ecranului şi imprimantei stdout şi respectiv stdprn permit numai operaţii de scriere. Fişierul predefinit auxiliar stdaux este de rare/ieşire. Cele 5 cuve cheie sînt constante poer de tip file declarate în stdio.h. Operaţiile de rare/ieşire suportate de un fişier se efectuează cu ajutorul funcţiilor predefinite care formează conţinutul fişierelor antet stdio.h şi conio.h. Aceste fişiere nu fac parte egrantă din structura limbajelor de tip C, aşa cum se întîmplă cu toate celelalte fişere cu extensia.h. De aceea, este necesar să se prevadă roducerea lor, în antetul programului C++, prin directiva #include <nume_fişier_antet>. Cînd apare o cerere de citire/scriere, sistemul de operare iniţiază o procedură de control şi execuţie cu privire la transferul de informaţii, între dispozitivul fizic de rare/ieşire (ecran, tastatură, imprimantă, unitate de disc) şi dispozitivul logic de rare/ ieşire similar, numit stream (flux). Deschiderea stream-ului asociat unui anumit dispozitiv logic de rare/ieşire presupune, pe de o parte crearea indicatorilor standard de stare (variabile de tip File) corespunzători şi poziţionarea acestora pe valorile iniţiale iar pe de alta, alocarea necesarului de memorie zonei tampon (buffer-ului) prin ermediul căreia se realizează efectiv transferul de informaţie. Rezultatul controlului transferului de informaţie de către sistemul de operare se va reflecta în valorile actualizate ale indicatorilor de stare, care pot fi aflate prr-o serie de funcţii standard, aşa cum vom vedea mai tîrziu. Închiderea stream-ului va permite eliberarea memoriei afectate zonei tampon după golirea acesteia. Stream-urile pot fi de tip text sau de tip binar. Un stream de tip text transferă şiruri de texte organizate în linii de lungime variabilă, în concordanţă cu numărul maxim de caractere gestionat de dispozitivul logic de rare/ieşire. Separarea liniilor se face prin caracterele de control sfîrşit de linie (0DH) şi salt la linia următoare (0AH). Un astfel de stream se poate asocia cu stdin, stderr şi stdout, din care numai stdin necesită o zonă tampon de memorie, cu dimensiunea egală cu lungimea maximă a linei de text transferată. Un stream de tip binar transferă o secvenţă de cifre binare fără o structură anume. Completarea zonei tampon se face automat dacă şirul binar este mai scurt, avînd în vedere că dimensiunea standard a zonei tampon este de 256 octeţi. Un stream de tip binar se poate asocia cu stdprn şi stdaux. În paragraful următor se preză prototipul funcţiilor predefinite care permit operaţii de citire/scriere direct legate de dispozitivele logice predefinite de rare/ieşire şi care sînt mai des utilizate în structura programelor de tip C. 2. Funcţii predefinite pentru dispozitivele standard de rare/ieşire Funcţiile predefinite pentru tastatură permit realizarea operaţiei de citire a unor caractere sub anumite condiţii: cu sau fără afişarea caracterelor cititite pe ecran şi cu sau fără 11

formatare lor. Funcţiile getch(), getche(), getchar() şi gets() permit o citire cu afişare, cu excepţia lui getche() şi fără formatare. Atît tipărirea pe ecran, cît şi formatarea datelor citite se realizează cu funcţia scanf(). Corespunzător, pentru operaţia de scriere fără formatare pe ecranul monitorului s- au conceput funcţiile putchar() şi puts(), iar pentru cea cu formatare prf(). Lungimea şirului de rare/ieşire diferă la ambele categorii de funcţii astfel getch(), getche(), getchar() şi putchar() prelucrează un singur caracter şi nu are importanţă în rest. 2.1 Operaţia de citire fără formatare Introducerea unor caractere de la tastatură (dispozitivul de rare standard stdin) poate fi cu sau fără ecou (cu sau fără afişare pe ecran), iar funcţiile predefinite uzuale folosite în acest scop se preză după cum urmează: - getch(void); Această funcţie aşteaptă apăsarea unei taste, după care afişează pe ecran caracterul citit. Prototipul ei se află în fişierul conio.h. Aproape în toate programele C prezentate în capitolele anterioare s-a utilizat această funcţie ca un subterfugiu pentru obţinerea accesului nelimitat de către programator la pagina cu rezultatele programului (pagina de ecran utilizator). - getche(void); Funcţia getche() este analoagă cu getch(), atît ca localizare, cît şi ca efect, doar că returnarea caracterului furnizat de la tastatură este fără ecou; - getchar(void); Această funcţie transformă caracterul citit în întreg fără semn numai după apăsarea tastei Enter (CR). În caz de eroare sau condiţie de sfîrşit de fişier (EOF) furnizează valoarea 1 (deoarece caracterul EOF are valoarea în hexazecimal 0xff = -1); - char *gets(char *s); Cu funcţia gets() se poate roduce de la claviatura calculatorului un şir de caractere de lungime variabilă. Caracterele tastate succesiv sînt memorate, pe rînd, în tabloul de la adresa s, iar după apăsarea tastei Enter se adaugă terminatorul de şir de caractere \0. În caz de eroare funcţia gets() întoarce NULL, altfel adresa şirului de caractere. Exemplul 1. char sir[15]; gets(sir); puts(sir);.. Cu gets() se citeşte din stdin un şir de caractere de lungime maximă 15, care se tipăreşte apoi la stdout prin ermediul funcţiei predefinite puts(). 2.2 Operaţia de citire cu formatare Operaţia de citire cu formatare permite pe lîngă roducerea de date de diverse tipuri de la suportul de rare, conversia acestora de la reprezentarea externă la reprezentarea binară, cu respectarea restricţiilor impuse (numărul total de caractere alocate, numărul de zecimale, caractere de spaţiere, etc.). Prototipul funcţiei scanf() de citire cu formatare este următorul: scanf(const char *şir_de_formatare [, lista_adrese_variabile]); Lista cu adresele variabililor de rare este opţională. Există o corespondenţă strictă de tip, de număr şi de poziţie între descriptorii de format (specificatorii de format) 12

din şirul de formatare şi variabilile a căror adrese sînt precizate în lista_adrese_variabile. Orice neconcordanţă va fi sancţionată cu un mesaj de eroare. Şirul de formatare poate să conţină: - descriptori de format, care sînt şiruri de caractere precedate de % conforme cu tipurile de date atribuite variabililor a căror adrese ervin în lista_adrese_variabile. Lista acestora se precizează în figura 5.2.2.1. - secvenţele escape \n (linie nouă) şi \t (tab); - blancul (spaţiul liber); - orice alt caracter ASCII. Funcţia scanf() citeşte în ordine caracterele tastate de la claviatura calculatorului, care constituie valoarea unei variabile de rare, le erpretează conform precizărilor furnizate de descriptorul de format corespunzător şi le depune la adresa alocată în memorie variabilei respective. După satisfacerea întregii liste de variabile, funcţia returnează numărul de valori citite. Dacă lista de adrese de variabile este vidă, atunci rezultatul întors este nul. Ultimile două categorii de caractere din şirul de formatare declanşează citirea fără memorare a caracterului citit din stdin, dacă există identitate între ele. Saxa generală a unui descriptor de format se preză astfel: %[*][n1[.n2]][c1][c2]indentificator_descriptor, unde singurile argumente obligatorii sînt % şi indentificator_descriptor. Lista descriptorilor de fomat se preză în tabelul 5.2.2.1. Celelelalte argumente sînt cu următoarele semnificaţii: - * precizează că următoarea valoare citită nu se mai atribuie variabilei care urmează în lista de adrese; - n1 repreză numărul maxim de caractere alocate unei valori; - n2 este numărul de cifre situate după punctul zecimal în cazul unei valori raţionale; - c1 repreză un modificator de adresă pentru variabila de rare corespunzătoare, şi anume: F pentru far (modelul depărtat) sau N pentru near (modelul apropiat); - c2 repreză un modificator de tip pentru argumentul de rare respectiv, după cum urmează: h (short ) pentru descriptorii de format d, i, o, u şi x; b) l (long ) pentru descriptorii de format d, i, o, u şi x sau în situaţia tipului double pentru descriptorii de format e, f şi g; c) L (long double) pentru descriptorii de format e, f şi g. Dacă n1 este precizat în componenţa descriptorului de format, atunci citirea valorii respective se termină după preluarea din stdin a unui număr de caractere egal cu n1 sau la întîlnirea unui caracter incompatibil cu formatul precizat. Dacă n1 este absent, atunci citirea valorii respective se încheie după întîlnirea unui blanc, a unui tab, a unui caracter incompatibil cu formatul precizat sau după tastarea unui sfîrşit de linie (Enter). c s d D Indentificator descriptor Valoarea de rare caracter şir de caractere întreg zecimal întreg zecimal Tip variabilă * char char 13

u U e, f, g, E, G o O x X i I n p întreg zecimal fără semn întreg zecimal fără semn număr raţional întreg octal întreg octal întreg hexazecimal fără semn întreg hexazecimal fără semn întreg (d, o sau x) întreg (D, O sau X) - adresa în hexazecimal: far: YYYY:ZZZZ near: ZZZZ unsigned unsigned long float long long long poer Tabelul 13.2.2.1 Se precizează că descriptorul de format n specifică lungimea şirului de rare în citirea curentă. Dacă şirul de rare este prea lung, ultimele caractere sînt ignorate la citirea curentă, dar rămînînd în dispozitivul de rare pot afecta următoarea citire. Cu funcţia predefinită fflush() se înlătură, prin program, balastul rămas în dispozitivul de rare. Dacă lista adreselor de variabile nu se satisface complet, şirul de rare fiind prea scurt, atunci computerul ră într-o stare de aşteptare. Indiferent de lungimea şirului de rare, execuţia funcţiei scanf() se încheie la citirea unui caracter incompatibil cu specificaţia de format erpretată, cu afişarea unui mesaj de eroare corespunzător. Cîteva exemple. 1.. char c1,s1; i; long j; float x; double y; scanf ( %c%s, c1, s1); scanf( %3d%4D%f%lf, &i, &j, &x, &y);.. Pentru şirul de rare aabcd12312347.5-16.35 se produc următoarele atribuiri: c1 = a, s1 = ABCD, i = 123, j = 1234, x = 7.5 şi termină normal. 2.. float z[10]; y = -16.35 şi funcţiile scanf se i; for ( i = 0; i<10; ++i) scanf( %f, z[i]); fflush(stdin);.. În situaţia şirului de rare 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 1.10 1.11 1.12 instrucţiunea for se încheie normal, dar este necesar să se prevadă funcţia fflush() pentru 14

golirea dispozitivului de rare, altfel ultimile două valori din şir pot afecta citirea următoarea din program. 3... a, b; scanf ( %d%d, a, b);.. Funcţia scanf() se termină cu eroare în cazul şirului de rare 15 1x3y, deoarece a doua valoare conţine litere în locul a două cifre zecimale. 2.3 Operaţia de scriere fără formatare Scrierea unui caracter pe ecranul monitorului se realizează prin ermediul funcţiei predefinite putchar(). Prototipul acestei funcţii este următorul: putchar( c);. În situaţia cînd operaţia de scriere decurge normal, funcţia putchar() întoarce ca rezultat caracterul afişat pe ecran. Altfel, rezultatul ei se consideră EOF (-1). Cu funcţia predefinită puts() se poate tipări la stdout un şir de caractere. Aceasta are următorul prototip: puts(const char *s);. Funcţia puts() scrie pe ecran şirul de caractere memorat la adresa s şi sare la linie nouă. În caz de eroare rezultatul ei este EOF (adică, -1). 2.4 Operaţia de scriere cu formatare Operaţia de scriere cu formatare presupune conversia unei secvenţe binare din reprezentarea ernă într-un şir de caractere ASCII şi afişarea acestui şir la stdout, conform specificaţiilor de formatare precizate în componenţa funcţiei predefinită prf. Formatul general al prototipului funcţiei prf() este următorul: prf(const char * şir_de_formatare, listă_valori_ieşire);. Şirul de formatare cuprinde: - descriptori de format, care sînt şiruri de caractere precedate de % conforme cu tipurile valorilor de ieşire. Lista descriptorilor de format se precizează în figura 5.2.4.1; - caractere ASCII, care se tipăresc ca atare la dispozitivul de ieşire; - secvenţe escape de spaţiere de tipul \n (linie nouă) şi \t (tab); - blancul. Indentificator Format de scriere Tip variabilă c s d, i u f e E g G o x ( sau X) descriptor caracter şir de caractere întreg zecimal cu semn întreg zecimal fără semn [-]n1.dddddd [-]n1.dddde[+/-]ddd [-]n1.dddde[+/-]ddd similar cu f sau e, în funcţie de precizie similar cu E întreg octal fără semn întreg hexazecimal fără semn char char * float float float float float 15

% n p cu a,, f (sau A,, F) caracterul % la adresa indicată afişează numărul de caractere transferate curent adresa în hexazecimal: far: YYYY:ZZZZ near: ZZZZ - * poer Tabelul 5.2.4.1 În această situaţie, spre deosebire de operaţia de citire cu formatare, structura descriptorilor de format poate fi completată cu o serie de precizări privitoare la alinierea valorilor în limitele spaţiului alocat, la semn, la punctul zecimal sau la prefixul datelor octale şi hexazecimale, după cum urmează: %[a][n1[.n2]][c1][c2]indentificator_descriptor, unde singurile argumente obligatorii, după cum se ştie, sînt % şi indentificator_descriptor. Majoritatea argumentelor sînt cu semnificaţii similare celor prezentate în paragraful 5.2.2. Urmează să discutăm doar semnificaţia lui a. Alinierea valorilor în spaţiul precizat prin descriptorul de format se face ţinînd cont de regulile de mai jos: - alinierea implicită (în absenţa lui a) a valorilor numerice se face la dreapta, iar a şirurilor de caractere la stînga şi completare cu spaţii sau 0 în rest. Precizia implicită pentru valorilor de tip raţional este de 6 cifre zecimale (adică, după punctul zecimal se afişează 6 cifre, eventual cu adăugare de zerouri); - dacă a este, atunci alinierea valorilor numerice se face la stînga şi completare cu spaţii în dreapta; - dacă a este +, atunci valorilor numerice sînt precedate de + sau -; - dacă a este spaţiu liber, numai valorile negative sînte precedate de semnul minus; - dacă a este #, atunci se produc inserări de caractere distinctive, astfel: se adaugă prefixul 0 la valorile octale (pentru o); 2) se adaugă prefixul 0x sau 0X la valorile hexazecimale (pentru x sau X); 3) se înscrie punctul zecimal pentru e, E, f, g sau G, iar în cazul descriptorilor g şi G nu se elimină digiţii 0 finali. Cîteva exemple. 1. În tabelul 13.2.4.2 se descriu cîteva formate de scriere pentru tipuri de date întregi şi raţionale în simplă precizie: Tip de dată Descriptor de format Format de scriere întregi 153 153 153 153 raţoinale 7.52 7.52 7.5 7.5 17.52 %d %3d %2d (se ignoră) %5d %f %f4.2 %f4.2 %f6.2 %f3.1 (se ignoră) Tabelul 13.2.4.2 153 153 153 153 7.520000 7.52 7.50 7.50 17.52 16

. k = 14; double z = -335.3; prf( \nk=%3d\tz=%9.2lf, k, z); Şirul de formatare cuprinde secvenţe de evitare, caractere ASCII şi descriptorii de format d şi lf. Valorile variabililor k şi z vor fi tipărite în clar, la linie nouă, iar spaţiul liber între ele este egal cu o tabulare standard. 3 Operaţii aplicabile fişierelor utilizator Fişierele de tip utilizator pot suporta operaţiile de creare, exploatare şi actualizare. Operaţia de creare constă în scrierea structurilor componente una după alta pe suportul magnetic afectat fişierului sau în directorul precizat în calea fişierului. Indicatorul care fixează poziţia curentă în fişier se iniţializează cu 0. Valoarea acestuia va fi actualizată la fiecare transfer. Fişierul se încheie cu un caracter special EOF (end of file - sfîrşit de fişier). Operaţia de exploatare permite citirea parţială sau totală a unui fişier în vederea inventarierii, prelucrării sau tipăririi informaţiilor conţinute de către acesta. Operaţia de actualizare constă în modificare de cîmpuri componente unor structuri, în adăugare de noi structuri, nu neapărat la sfîrşitul fişierului, sau în şteregere de structuri cu un conţinut perimat. Actualizare presupune în anumite situaţii crearea unui nou fişier de acelaşi tip sau nu cu cel iniţial, cu luare de măsuri referitoare la indentificarea corectă a fişierului nou (în general, se utilizează un nume simblic diferit de cel al fişierului iniţial). Indiferent de operaţia de rare/ieşire executată asupra fişierului, progresarea în fişier se face prin funcţii predefinite de citire/scriere de un tip corespunzător. Accesul la informaţiile unui fişier poate fi secvenţial sau aleator (direct). Accesul secvenţial presupune citirea/scrierea structurilor una după alta, începînd cu prima şi terminînd la ultima. Valoarea variabilei poziţie în fişier se incrementează automat cu un anumit număr de octeţi după fiecare operaţie scanf()/prf(). Pe baza informaţiilor furnizate prin program, accesul aleator permite direct depistarea unei anumite structuri din componenţa fişierului prin ermediul funcţiei predefinită fseek(), fără a se mai trece prin toate structurile dinaea acesteia. Cu alte cuve, valorea indicatorului poziţie în fişier este gestionată prin program, realizîndu-se astfel operaţii de rare/ieşire în diverse zone ale fişierului. Este util de remarcat că în fişierele memorate pe disc se pot combina cele două tipuri de accese, în sensul că o anumită porţiune din fişier poate fi procesată în totalitate. Orice ervenţie într-un fişier este precedată de operaţia de deschidere a fişierului prin funcţia predefinită fopen(), care pregăteşte fişierul pentru acest lucru şi succedată de operaţia de închidere a fişierului prin fclose(). Aşa cum s-a mai spus, nu acelaşi lucru se întîmplă în cazul fişierelor predefinite, unde cele două operaţii se realizează automat. Indentificarea unui fişier se face prr-un şir de caractere ce include numele unităţii de disc, calea, numele simbolic al fişierului şi extensia acestuia. Şirul de caractere poate să conţină litere, cifre, liniuţa de subliniere, blancul, :, şi \ (backslash-ul se repreză prin secvenţa \\). Sistemul de operare nu face distincţie înte majuscule şi minuscule. Se recomandă ca fixarea numelui simbolic al fişierului să se facă în aşa fel încît să sugereze funcţia lui, deoarece acesta rămîne o caracteristică permanentă şi independentă de programul care îl va utiliza de acum înae. Dacă numele unităţii de disc absentează, atunci se consideră unitatea de disc implicită. Fişierul va fi căutat în directorul de lucru în cazul cînd lipseşte calea. 17

În concluzie, pentru a se lucra corect cu fişiere utilizator trebuie să se parcurgă următoarele etape: - să se precizeze numele formal al fişierului prr-o variabilă de tip FILE în partea de declaraţii a unităţii de program corespunzătoare. Trebuie să existe concordanţă de nume între fişierul formal (declarat ca o variabilă FILE) şi numele unui fişier ce există sau va exista pe un suprt magnetic; - să se deschidă fişierul prin fopen(), cu precizarea tipurilor operaţiei de citire/scriere şi stream-ului (text sau binar) executate; - să se scrie/citească în fişier cu funcţia predefinită fwrite()/fread(); - să se închidă fişierul cu fclose(). Indentificatorii declaraţi în domeniul fişierului cu caracter global au, în mod implicit, legătură de tip extern. Cu specificatorul static ultimul atribut poate fi schimbat în unul de tip ern. Indentificatorii neglobali au legătură identică cu cea rezultată din declaraţia indentificatorilor globali, dacă există şi este cu vizibilitate. În mod similar, specificatorul static poate determina o legătură ernă, iar specificatorul extern una externă. Urmărirea reperelor anunţate mai sus se poate face în exemplu prezentat în ultima secţiune. 18