Documente Academic
Documente Profesional
Documente Cultură
aLl_fisiere2019
Tema: Elaborarea programelor pentru prelucrarea funcţiilor cu diverse
structuri şi fişiere în limbajul C.
Sarcina şi obiectivele:
1. să se analizeze principiile organizării şi gestiunii fişierelor în sistemele de operare şi procesarea fişierelor în
limbajul C, apoi şi să se analizeze algoritmii şi programele (declarări, utilizări, parcurgeri, salvare şi ştergeri).
2. de studiat şi însuşit materialul teoretic prin lansarea exerciţiilor de antrenament (Comp.3) şi verificări ale
cunoştinţelor (din indicaţiile acestea) şi să se elaboreze algoritmii şi, totodată, să organizeze calculele de
verificare cu explicaţii pentru evidenţierea esenţialului prelucrării fişierelor cu structuri de date în elaborarea
modelelor soluţiei. Toate observaţiile se înregistrează în raport;
3. să se preia de la profesor varianta (Comp.4. Exemple de verificare a cunoştinţelor însuşite. Variante pentru
lucrul individual) şi să se elaboreze algoritmii şi şi programul unde să organizeze antetul functiilor şi
transmiterea functiei apelate adresele variabilelor cu calculele de verificare şi cu explicaţii la prelucrarea
fişierelor. Pentru aprofundarea şi rularea programelor în limbajul C să se elaboreze scenariile succinte de
soluţionare cu calculele de verificare şi explicaţii.
4. în baza funcţiilor de timp şi dată din fişierul header time.h apreciaţi timpul definit de sistem şi timpul
execuţiei programului în secunde pentru ambele cazuri (tradiţional şi cu pointeri) şi să se descrie scenariile şi
principiile de algoritmizare si rezolvare ale problemei în baza diferitor modele de SD complexe,
implementând subprograme în C;
5. în raport să se reflecte toate exemplele efectuate cu analize a tehnicii programării eficiente cu argumentări şi
comentarii, incluzând fişierele cu teste de verificare şi vizualizări ale rezultatelor.
Consideraţii teoretice:
1. Organizarea şi gestiunea fişierelor în sistemele de operare (SO).
Tratarea informaţiilor cere prezenţa lor în memorie în timpul execuţiei programului dat. Dar în majoritatea
cazurilor trebuie neapărat ca aceste informaţii să fie conservate de o manieră durabilă .Ca exemplu elementar , se
poate de citat informaţiile relative ale clienţilor unor întreprinderi. De aceleaşi date (cod, client, numele clientului,
adresa ,cifra de afaceri ), sunt cele mai des exploatate pe o perioadă lungă de timp. Ele trebuie să fie rechemate la
moment şi în particular. În acest scop ele sunt scrise într-un fişier, care este stocat pe o memorie masivă (discul
magnetic) şi accesibil programului, manipulând informaţiile.
Un fişier nu este altceva decât o mulţime mai mult sau mai puţin importante de date, conservate pe un
oarecare suport.
Fişierele pot fi cu acces direct (stocate pe disc) sau cu acces secvenţial (stocate pe bandă). Numele fişierelor
are structura: numefişer.extensia.
SO UNIX suportă aşa-numitele fişiere conductă ("pipes") care pot fi deschise de două procese pentru a
stabili un canal de comunicaţie interproces.
Fişierele sunt împărţite în tipuri diferite în funcţie de utilizarea lor. Diferenţierea tipurilor se face prin
extensii diferite a numelui fişierului. De exemplu:
FILE.C; FILE.CPP: program - sursă în C/C++;
FILE.PAS: program - sursă în Pascal;
FILE.FTN: program - sursă în Fortran;
FILE.OBJ: fişier - obiect, rezultat în urma compilării;
FILE.BIN: program executabil (în mod binar);
FILE.DAT: fişier de date, etc.
Uneori extensia este o simplă convenţie, sistemul de operare neţinând cont de aceasta.
1.1. ORGANIZAREA SISTEMELOR DE FIŞIERE
Organizarea fişierelor este specifică fiecărui sistem de operare.
În sistemul de operare UNIX, fişierele sunt organizate în arborele unic al fişierelor, existând o singura rădăcină.
Acest sistem de operare tratează egal fişiere sau dispozitive.
În sistemul de operare MS-DOS există nume de dispozitive (ex.: A,B,C). Dispozitivele de disc permit organizări
arborescente.
Simplificarea accesului a dus la apariţia conceptului de directoare. Un director este un fişier de indicare a localizării
celorlalte fişiere. Un director e organizat pe înregistrări (articole), câte una pentru fiecare fişier; fiecare articol conţine
informaţii despre fişier ca: nume, tip, dimensiune, timp etc. La CP/M directorul conţinea şi numerele de ordine ale blocurilor
alocate. Fişierul este localizat prin cale (path), care precizează locul în arbore.
1.2 GESTIUNEA SPAŢIULUI PE DISC
Gestiunea spaţiului pe disc nu se face pe sectoare fizice; există unităţi de alocare, fiecare unitate conţinând un
multiplu de sectoare fizice, oferind flexibilitate la schimbarea dispozitivului. Contabilizarea sectoarelor ocupate se
realizează in doua moduri:
1. lista înlănţuită, care conţine unităţi de 16 biţi pe care se înregistrează numărul de blocuri ocupate succesiv;
2. bit-map, în care primul bit are semnificaţia de ocupat / neocupat.
Sistemul MS-DOS foloseşte listele înlănţuite (fiecare bloc conţine doi octeţi ce reprezintă un pointer către
următorul bloc din lanţ), ceea ce permite întreţinerea rapidă la eliberare/alocare spaţii pentru fişiere. La ştergere,
dispar înregistrările de 16 biţi corespunzătoare blocurilor fişierelor. La alocare, se ocupa în măsura găsirii spaţiilor
neînregistrate în FAT.
Sistemul UNIX înlatură dezavantajul fişierelor mari cu unităţi multe de alocare, care necesită un FAT mare in
sistemul MS-DOS astfel: se utilizează gestiunea spaţiului pe disc cu I-noduri (Index-nod). Fiecare fişier are un I-nod
(indiferent de dimensiunea fişierului respectiv).
1.3 ORGANIZAREA FIŞIERELOR ÎN UNIX
Spaţiul de pe un disc cu sistem de operare UNIX este împărţit astfel:
- Boot
- Superbloc:-volumul;
- nr. blocuri libere;
- tabelul blocurilor libere;
- index la primul bloc liber din tabela blocurilor libere;
- dimensiunea zonei de I-noduri;
- număr de I-noduri libere;
- index la primul I-nod liber;
- câmpuri cheie.
- I-noduri
- Date
- Swap.
Superblocul este prezent în memorie.
1.3.1 FIŞIERE PARTAJATE
Mai mulţi utilizatori care lucrează împreună la o aplicaţie au nevoie să exploateze în comun fişiere comune; este
convenabil ca un astfel de fişier să apară simultan în directoare de lucru diferite aparţinând unor utilizatori diferiţi.
Director rădăcină
A B C
B B B C C
C C
Fişier partajat
Pentru un astfel de sistem de fişiere organizat sub forma unui arbore, există două metode de a identifica fişierele:
1. Fiecare fişier primeşte un nume de cale absolută (absolute path name) care constă într-o cale din directorul radacină.
2. Alt mod este precizarea numelui căii relative (relativ path name).
Acest procedeu este folosit în conjuncţie cu conceptul de director de lucru (director curent). Un utilizator poate desemna
un director curent şi în acest caz numele căilor nu încep de la rădăcină, ci sunt relative la directorul de lucru.
1.5 STOCAREA FIŞIERELOR
Un fişier este memorat pe un anumit mediu într-o secvenţă de blocuri care trebuie gestionată de sistem. Stocarea
consecutivă a acestor blocuri nu este un lucru fezabil.
O metodă realizabilă este stocarea blocurilor într-o listă înlănţuită. Există două dezavantaje:
1. Nmărul octeţilor de date nu mai este o putere a lui 2;
2. Accesul aleator este scump de implementat.
Totuşi ideea de reprezentare a fişierelor ca o listă înlînăuită s-a păstrat, însă pointerii sunt stocaţi în memorie. Se asociază
fiecărui disc o tabelă de alocare de fişiere (FAT). FAT-ul are o intrare pentru fiecare bloc de pe disc. Intrarea directorului
pentru fiecare fişier primeşte numărul primului bloc de pe disc al fişierului. Mai departe slotul din FAT corespunzător
fiecărui bloc conţine numărul blocului următor.
Acest model a fost utilizat pe discuri floppy pentru discuri floppy de 360 k cu dimensiunea blocului de 1 k.
Numărul de identificare al blocului este de 12 biţi existând deci 480 de octeţi în FAT.
Principala problemă a FAT-ului este că pointerii tuturor fişierelor de pe întreg discul sunt mixate aleator în
această tabelă. Deci e nevoie de întreg FAT-ul chiar dacă un singur fişier este deschis. O metodă mai bună ar fi păstrarea mai
multor liste de blocuri pentru fişiere diferite în locuri diferite. Această metodă este folosită de UNIX, unde fiecare fişier are
asociată o mică tabelă (pe disc) numită I-node. Fiecare I-nod conţine pointeri către 10 blocuri de date de pe disc plus încă 3
pointeri indirecţi.
Pentru primele 10 blocuri din fişier adresele sunt trecute chiar în i-nod, fiind foarte uşor de accesat. Pentru fişiere mai
lungi de 10 blocuri se alocă un bloc de pointeri pe disc ce va fi accesat prin intermediul primului pointer indirect. Pointerul
dublu către blocuri de pointeri ce pointează la blocuri de pointeri către blocuri de date. Pointerul triplu acţionează după un
raţionament similar. Doar cu ajutorul pointerului dublu pot fi accesaţi 64 kblocuri.
Esenţial la acest sistem este faptul că blocurile de pointeri indirecţi sunt utilizate (încărcate în memorie) doar dacă este
necesar, făcându-se cel mult trei referinţe la disc oricât de lung ar fi fişierul.
1.6 STRUCTURA DIRECTOARELOR
Înainte ca un fişier să poată fi citit el trebuie deschis de către sistemul de operare care preia de la utilizator numele căii
pentru a putea identifica blocurile de pe disc alocate fişierului.
În sistemul CP/M exista doar un singur director. Pointerii către blocurile de date de pe disc sunt stocaţi chiar în intrarea
directorului.
O intrare într-un director MS-DOS are lungimea de 32 de octeţi. Câmpul “first block number” este utilizat ca un index în
FAT pentru identificarea următorului bloc.
Structura de directoare utilizată în UNIX este mult mai simplă: fiecare intrare conţine doar un nume de fişier şi numărul i-
nodului său. Toată informaţia despre un fişier se află în
i-nod. Toate directoarele din UNIX sunt fişiere.
Când se deschide un fişier sistemul de gestiune trebuie să găsească numele fişierului şi blocurile de pe disc. Ex.:
Fie calea /usr/ast/mbox. Mai întâi se localizează directorul rădăcină, apoi se identifică prima componentă a căii căutând i-
nodul fişierului /usr. Din acest i-nod sistemul de fişiere localizează directorul pentru /usr şi caută în el componenta următoare
ast. Din acest i-nod şi identifică similar mbox. I-nodul acestui fişier este încărcat în memorie şi reţinut până când fişierul se
închide.
1 . mod 6 . mod 26 .
1 .. m\rime 1 .. m\rime 6 ..
4 bin data 26 ast data 17 src
6 usr 132 51 jim 406 60 mbox
14 lib
8 tmp
Identificarea fişierelor prin precizarea numelui căii relative se face similar, dar procesul de căutare începe din directorul
de lucru.
1.7 VERIFICAREA CORECTITUDINII GESTIONăRII FIŞIERELOR
Multe sisteme de operare citesc blocuri, le modifică iar apoi le scriu; dacă sistemul cade înainte ca toate blocurile
modificate să fie scrise, sistemul de gestiune a fişierelor poate rămâne într-o stare nedefinită. Această problemă este cu atât
mai gravă cu cât blocurile care nu au fost scrise sunt I-noduri, blocuri de directoare sau blocuri conţinând liste libere.
Pentru a rezolva această problemă multe calculatoare dispun de un program utilitar care verifică soliditatea gestiunii
fişierelor: programul este rulat ori de câte ori se execută secvenţa de boot, mai ales după o cădere a sistemului respectiv.
Probleme ce pot apare: blocuri lipsă, caz în care programul de verificare doar le adaugă în lista blocurilor libere; blocuri
alocate dublu în lista de blocuri libere (această problemă apare doar dacă se lucrează cu lista; cu bit-map este imposibil), în
acest caz programul de verificare reconstruind lista blocurilor libere; sau acelaşi bloc de date este prezent în două sau mai
multe fişiere. Dacă oricare din aceste fişiere este şters, blocul respectiv va fi pus în lista blocurilor libere, ajungându-se la
situaţia în care un acelaşi bloc este simultan şi liber şi ocupat; dacă ambele fişiere sunt şterse, blocul va fi trecut de două ori
în lista blocurilor libere.Verificarea se poate face în două moduri: pe blocuri şi pe fişiere.
La verificarea pe bloc programul construieşte o tabelă cu doi contori per bloc, fiecare contor fiind iniţializat cu 0. Primul
contor urmăreşte de câte ori un bloc este prezent într-un fişier; al doilea înregistrează cât de adesea este prezent în lista
blocurilor libere (sau în bit-map-ul blocurilor libere). După aceasta, programul citeşte toate I-nodurile; pornind de la un
I-nod programul poate construi o listă cu toate numerele blocurilor utilizate ce corespund fişierului. Pe măsură ce fiecare
număr de bloc este citit, primul contor este incrementat; programul examinează apoi lista blocurilor libere sau bit-map-ul
pentru a găsi toate blocurile care nu sunt utilizate. Fiecare apariţie a blocului în lista blocurilor libere sau bit-map este
contorizată în cel de-al doilea contor.
1.8 PERFORMANŢE ALE SISTEMULUI DE GESTIUNE A FIŞIERELOR
Accesul la disc este mult mai lent decât accesul la memorie, fapt pentru care multe sisteme de gestiune a fişierelor sunt
proiectate pentru a reduce numărul de accesuri la disc necesare.
Cea mai utilizata metodă pentru reducerea timpului de acces la disc este utilizarea unui bloc cache sau a unui buffer
cache. În acest context, cache-ul este o colecţie de blocuri care logic aparţin discului dar care, din motive de performanţă
sunt păstrate în memorie.
Pentru managementul cache-ului cea mai folosită metodă este de a verifica toate cererile de citire pentru a vedea dacă
blocul respectiv este în cache. Dacă este, cererea de citire este satisfăcută fără a mai accesa discul; în caz contrar, blocul este
mai întîi citit în cache şi apoi copiat oriunde este necesar.
Când un bloc urmează a fi încărcat într-un cache care este deja plin, unele blocuri trebuiesc şterse şi rescrise pe disc dacă
au fost modificate după ce au fost aduse în cache. Această situaţie seamănă foarte mult cu procesul de paginare astfel că toţi
algoritmii uzuali de paginare ca FIFO, a doua şansă (second chance) sau LRU sunt utilizabili. Diferenţa dintre paginare şi
cache este ca cache-ul face referiri relativ rare, astfel încât este posibil să se păstreze toate blocurile în ordinea strictă LRU cu
liste înlănţuite.
Problemele ce pot apare sunt asemănătoare cu cele ce apar la corectitudinea gestionarii fişierelor, prezentată în paragraful
precedent; dacă un bloc important (cum ar fi un I-nod) este scris în cache şi apoi modificat, dar nu este rescris pe disc, o
cădere a sistemului va părăsi sistemul de gestiune a fişierelor într-o stare nedefinită.
Dacă blocul este esenţial pentru corectitudinea gestionării fişierelor (de fapt, orice exceptând blocurile de date) şi a fost
modificat, acesta trebuie scris pe disc imediat, indiferent de sfârşitul listei LRU în care este pus.
Sistemul MS-DOS utilizează metoda de a scrie fiecare bloc modificat pe disc imediat ce a fost modificat: metoda este
numită write-through caches (implică, în schimb, mai multe operaţii de I/O cu discul).
La UNIX, toate modificările sunt stocate în cache şi sunt scrise pe disc la fiecare 30 de secunde sau ori de câte ori un bloc
este şters din cache.
1.9 SERVERE DE FIŞIERE
Sistemele de distribuţie dispun adesea de mecanisme prin care oferă servicii de fişiere altor mecanisme; ele sunt numite
servere de fişiere.
O metodă uzuală de a păstra un cost scăzut al sistemelor de distribuţie este de a permite existenţa unor utilizatori cu staţii
de lucru fără disc, permiţându-le accesul la fişiere prin trimiterea unor cereri READ şi WRITE prin intermediul unei reţele la
un server de fişiere comun.
Servere-le de fişiere pot prezenta o interfaţă către utilizator la oricare din următoarele trei nivele:
disc la distanţă: în acest model, fiecare utilizator are alocat un disc virtual care este o porţiune privată din
discul serverului de fişiere. Utilizatorii pot folosi discul virtual în acelaşi mod ca şi un disc local; serverul de
fişiere furnizează comenzi READ BLOCK şi WRITE BLOCK exact ca şi un disc local. Ca urmare, reţeaua este
utilizată pentru a simula un controler de disc; toate codurile de gestiune a fişierelor în calculatoarele
utilizatorilor rulează exact ca în cazul unui disc local.
sisteme de gestiune la distanţă fără servicii de directoare (serviciile de directoare se fac local): comenzile
sunt disponibile pentru a crea şi şterge fişiere, citire, scriere, căutare de fişiere şi alte operaţii specifice lucrului
cu fişiere. Când utilizatorul creează un fişier, serverul de fişiere returneaza, în general, un identificator care
poate fi utilizat pentru operaţiile viitoare cu fişierul respectiv. Identificatorul poate fi, spre exemplu, un număr
aleator de lungime mare pentru a împiedica aflarea lui de către utilizatori neautorizaţi (aceşti identificatori sunt
analogi cu numerele I-nodurilor stocate în directoarele UNIX). O problemă care apare în acest caz este: dacă un
utilizator creează un fişier pe un server de fişiere şi apoi sistemul cade înainte de înregistrarea identificatorului
într-un director, fişierul este ”pierdut”. Fişierul va continua să existe dar nu va putea să fie accesat niciodată,
deoarece identificatorul său nu este cunoscut; singura cale de a ieşi din această situaţie este de a avea
posibilitatea ca serverul de fişiere să furnizeze o comandă prin care utilizatorul poate cere o listă completă cu
toate fişierele sale.
sisteme de gestiune completă la distanţă: în acest caz, comenzile disponibile permit nu numai manipularea
fişierelor, ci şi crearea şi ştergerea directoarelor, schimbarea directorului de lucru, realizarea şi distrugerea legaturilor la
fişierele existente şi alte operaţii similare. Sistemul apare ca fiind local.
1.10 BACKUP ATOMIC
Dacă se face actualizarea unei înregistrări fie că operaţia se execută complet (se verifică şi totul este corect), fie că nu (şi
în acest caz utilizatorului îi revine sarcina să reia operaţia de modificare), părăsirea sistemului are loc în starea sa originală.
În cazul serverelor care oferă toleranţă la erori, backup-ul atomic implementează, de obicei, un driver de disc logic ca drivere
fizice; când informaţia este scrisă în blocul logic n serverul mai întîi scrie informaţia la blocul fizic n de pe driverul 1. Apoi îl
citeşte pentru a verifică că ceea ce a scris este corect; dacă totul este corect serverul scrie apoi aceeaşi informaţie în blocul
fizic n de pe driverul 2 şi verifică de asemenea. Această tehnică se numeşte depozit stabil (stable storage). Dacă apare o
cădere în timpul scrierii la oricare din drivere, blocul în curs de scriere va da o eroare de sumă de control; atâta timp cât
aceasta poate fi detectată blocul bun poate fi utilizat pentru a suprascrie blocul defect. Dacă serverul cade în timp ce se scrie
pe driverul 1 sistemul va fi readus la starea lui originală; oricum sistemul nu rămâne într-o stare intermediară ambiguă.
O idee derivată din update-ul atomic este cea a fişirelor multiversiune (multiversion files); în acest caz un fişier nu este
niciodată modificat după ce a fost creat. Schimbările sunt înregistrate prin cererea unei copii temporare a fişierului,
modificarea copiei, iar schimbările devin permanente prin ”îngheţarea” copiei temporare printr-un update atomic (se verifică,
că noua versiune este corectă şi abia apoi se şterge vechea versiune).
1.11 SECURITATEA FIŞIERELOR
Fişierele conţin informaţii foarte importante pentru utilizatori. Implementarea mecanismelor de securitate a fişierelor este,
din această cauză, o cerinţă majoră a sistemelor de operare. Acestea conţin mecanisme de protecţie date de politica de
protecţie adoptată. Prin securitatea fişierelor se înţelege starea lor protejată la accesul utilizatorilor neautorizaţi precum şi la
orice pierdere de date.
Cele mai importante cauze ale pierderilor de date sunt:
- cazuri de forţă majoră (incendii, calamităţi, deteriorări ale aparaturii);
- erori hard/soft (dischete, erori CPU, erori de comunicaţii, greşeli de programare);
- erori umane (tastări greşite, rulări incorecte de programe).
Aceste pierderi pot fi prevenite în general prin păstrarea de copii în locuri protejate, chiar departe de locul datelor
originale.
Accesele neautorizate la date strict confidenţiale pot fi:
- întîmplătoare (utilizatori cărora nu li s-a interzis accesul la unele date);
- conştiente, fără intenţii rele (programatori buni care "sparg" sistemele);
- conştiente, cu intenţii rele (pentru bani, furt de informaţii, eludarea taxelor);
- spionaj militar, comercial, terorism (între state adverse, corporaţii concurente).
De asemenea trebuie asigurată confidenţialitatea, privită ca respectarea drepturilor individuale de acces la date,
împiedicînd folosirea datelor proprii de alte persoane fizice sau juridice, chiar şi de stat sau justiţie, inclusiv de proiectantul
sistemului.
2.Noţiuni, exemple şi importanţa implementării funcţiilor predefinite în procesarea
fişierelor în limbajul C
În ceea ce priveşte limbajul C , se poate de reprezentat un fişier ca un tablou gigantic permanent , în care un
program poate să scrie sau să citească datele. Un fişier trebuie să conţină elemente de aceeaşi natură , de un
conţinut omogen . Contrar altor limbaje, conţinutul unui fişier C nu este structurat la timp. Din contra aceste
donaţii sunt simplu aranjate sub forma unui şir de caractere(octeţi). Iată de ce un fişier este câteodată denumit flux
de donaţii. Fiecare caracter (octet conţinând caracterul ) luat individual poate fi localizat în fişier printr-un index.
Mai mult ca atât ca un fişier să fie considerat ca un şir nonstructurat de octeţi , îi încredinţează programatorului să
creeze o structură de fişiere aşa ca datele să fie administrate cum îl aud. Pentru aceasta dispune de o serie de
funcţii adaptate , care îi permit să manipuleze datele de toate dimensiunile şi toate tipurile.
În C se poate de lucrat pe două fişiere cu două niveluri : nivelul inferior; nivelul superior
La nivelul inferior se folosesc metode de acces elementar , fondat pe funcţiuni, care se bazează pe rutinele
corespondente ale sistemului de exploatare , relative . Funcţiile nivelului inferior depind direct de sistemul de
exploatare, şi nu fac parte din standardul ANSI. Accesele la fişierele nivelului superior se fac într-o manieră puţin
mai elementară şi mai facilă Ele sunt fondate pe funcţii predefinite relativ complexe , independente de sistem de
exploatare, si implementate pe funcţii de nivel înalt.
Operaţiile neelementare. Deoarece un program trebuie să citească sau să scrie datele într-un fişier , printr-o
metodă de acces de un nivel mai înalt, informaţiile trec pentru a ajunge la destinaţia lor printr-un bufer (tampon).
Acest bufer este o zonă de memorie RAM în care sunt temporar stocate, înainte de a fi transferate la destinaţie ,
informaţii citite sau scrise în fişier . Avantajul constă: că nu este necesar de a declanşa o operaţie de intrare / ieşire
specific pentru fiecare informaţie citită sau scrisă . Din contra o singură operaţie în program permite de a scrie un
bloc de informaţii în bufer.
Structurile FILE. Dislocarea memoriei din bufer de tip intare /ieşire de un oarecare fişier este furnizat de
variabile de tip FILE. Acesta e dotat cu valori când un program deschide un fişier pentru a-l manipula . Tipul
FILE este definit ca o structură, header <stdio.h>. Câmpurile sale conţin adresa tamponu-lui: un pointer spre
caracterul lui următor în bufer, numărul de carctere, starea fişierului (dreptul de acces, natura operaţiei efectuate
asupra fişierului ) şi descriptor . Descriptorul este un număr întreg care identifica fişierul dat .
După cum defineşte limbajul C noţiunea de fişier, el se poate referi la un fişier disc, ecran, tastatură, port, fişier
bandă, etc. Deşi fişierele diferă ca formă stream-urile sunt aceleaşi. În C un stream este o interfaţă logică între
computer şi unul din diferitele perifericele sale dar, în general între computer şi un fişier . Un stream este asociat
unui fişier cu ajutorul comenzii ‘open’ şi eliberat de el prin intermediul ‘close’. Există două tipuri de stream-uri:
binar şi text. Stream-ul text se utilizează pentru lucrul cu caractere ASCII. Trebuie de remarcat însă, că atunci
când lucrăm cu un stream text apare translatorul de caractere, astfel întâlnindu-se cu un caracter ‘newline’, de
exemplu, el este convertit într-un cod ‘caricatură’, de acea nu întotdeauna ceea ce vom tasta la monitor va fi salvat
în fişerul text. În cazul celor binare translatorul nu apare, în fişier înscriindu-se fiecare bit
Un fisier este o structura dinamica, situata in memoria secundara ( pe suporturi optice sau pe harddisk );
numarul de elemente ale unui fisier este variabil, chiar nul.. Limbajul C permite operarea cu fisiere:
de tip text - un astfel de fisier contine o succesiune de linii, separate prin NL ('\n')
de tip binar - un astfel de fisier contine o succesiune de octeti, fara nici o structura.
Definiţia structurii FILE în < stdio.h> poate să varieze de la un sistem la altul , în ceea ce priveşte numărul
tipul, şi numărul câmpurilor . Ea conţine întotdeauna informaţii precedent descrise .
Typedef struct { char buffer; /* pointerul spre adresa tamponului */
char */ pointerrul spre caracterul următor în tampon */
int cnt; /* numărul de caractere în tampon */
int flags ; /* biţi dând starea fişierului */
int fd ; /* descriptorul */ } FILE;
Fişierul <stdio.h> conţine declaraţia unui tablou de oarecare structuri FILE. Fiecare element din acest tablou
este o variabilă structurată, care poate să stocheze informaţii relative la un fişier, sub forma precedent descrisă.
Pentru a acceda concret la un fişier în programul dat, trebuie de utilizat un pointer spre o variabilă de tip FILE.
Trebuie de definit pointerul: FILE * fp ; /* pointer spre variabila structurată FILE
Definiţia precedentă crează un pointer fp de tip pointer spre FILE, capabil de a memoriza adresa unei
variabile structurate FILE. Deoarece un fişier este deschis pentru a fi manipulat, funcţia competentă caută o
structură FILE disponibilă în tabloul precedent evocat. Adresa acestei variabile structurate este afectată la un
pointer ad.hoc, aşa ca fp. Toate accesele ulterioare se vor face prin intermediul acestui pointer.
Imaginea următoare ilustrează conexiunea între un program şi un fişier la care accedează programul:
Structurile
FILE
Pointer spre tampon
Scierea
Pointer
FILE Citirea
Program tampon
se deschide fisierul pentru un anumit mod de acces, folosind functia de biblioteca fopen, care realizeaza si
asocierea intre variabila fisier si numele extern al fisierului
2.2.2 Fişierele binare în comparaţie cu fişierele text . Practic, fişierele text conţin informaţia stocată sub forma
unui şir de caractere (eventual, pe mai multe linii, dar ştim deja că sfârşitul de linie este şi el tot un caracter).
Spre deosebire de ele, fişierele binare stochează informaţia brut, fără prelucrări exact aşa cum apare ea în memorie
(puteţi să va imaginaţi că se face fotografia unei porţiuni din memoria RAM, şi se scrie în fişier Byte cu Byte, astfel încât
poate fi restaurată mai târziu printr-o simplă copiere înapoi în RAM).
Ca de obicei, ambele metode de stocare au avantaje şi dezavantaje care indică folosirea uneia sau a celeilalte în funcţie de
aplicaţie:
Stocarea sub formă text are ca principal avantaj formatul human readable al informaţiei. Asta înseamnă că oricând
putem să deschidem fişierul într-un editor şi putem interpreta ce scrie în el direct, fără a mai avea nevoie de o altă aplicaţie.
(Exemplu: sursele de C). Dezavantajul este că informaţia text ocupă mai mult decât în formă binară, şi este greu de prelucrat
de către programe.
Stocarea sub formă binară are ca avantaje faptul că datele ocupă în medie (nu mereu) mai puţină memorie decât
cele în format text, au structură previzibilă, dar cel mai important, pot fi încărcate direct în memorie. (Exemplu: un binar
executabil, care este de fapt imaginea din care este lansat un proces în execuţie). Dezavantajul constă în faptul că ele devin
complet neinteligibile pentru oameni (trebuie să le interpretăm cu o altă aplicaţie pentru a le înţelege).
Crearea si modificarea unor articole dintr-un fisier de articole.
typedef struct Elev{ short int nota1; short int nota2; char nume[10];
float medie; } Elev;
[ ... main() şi alte funcţii ...]
Elev elev;
elev.nota1 = 7;
elev.nota2 = 10;
elev.medie = (elev.nota1 + elev.nota2) / 2.0;
strcpy(elev.nume, "Cartman");
Exemplul 1: Sa se scrie un program pentru creerea unui fisier binar, avand articole structuri cu urmatoarele campuri:
-nume depunator (sir de maxim 30 de caractere)
-data depunerii (o structura avand campurile intregi: zi,luna,an)
-suma depusa (o valoare reala).
Articolele sunt grupate pe zile in ordine cronologica.
Datele se introduc de la consola, fiecare pe 3 linii. */
#include<stdio.h>
#include<conio.h>
#include<dos.h>
#include<stdlib.h>
#define MAX 3
typedef struct { int zi; int luna; int an; } DATA;
typedef struct { unsigned char nume[30]; DATA dat; int sum;} CLIENT;
void main()
{ CLIENT bd[MAX]; int i; FILE *baza; printf("\n Introduceti datele persoanelor ");
for(i=0;i<MAX;i++) { printf("\n====================================");
printf("\n Nume : "); scanf("%s",&bd[i].nume);
printf("\n Data : "); scanf("%d-%d-%d",&bd[i].dat.zi,&bd[i].dat.luna,&bd[i].dat.an);
printf("\n Suma : "); scanf("%d",&bd[i].sum); };
baza=fopen("date.dat","w"); fwrite( bd, sizeof( CLIENT ), MAX, baza ); fclose( baza ); }
Exemplul 2: Sa se ecrie un program care, folosind fisierul creat in problema 1, calculeaza si afiseaza:
-suma maxima depusa, impreuna cu data si numele depunatorului
-numarul depunerilor din fiecare zi, si suma totala depusa in fiecare zi, tinand cont ca tranzactiile dintr-o zi sunt contigue in
fisier. */
#include<stdio.h>
#include<conio.h>
#include<dos.h>
#include<stdlib.h>
#define MAX 3
typedef struct { int zi; int luna; int an; } DATA;
typedef struct { unsigned char nume[30]; DATA dat; int sum; } CLIENT;
void main() { CLIENT bd[MAX]; int j,sm,i,smax,ni; FILE *baza;
baza=fopen("date.dat","r"); fread( bd, sizeof( CLIENT ), MAX, baza ); fclose( baza ); smax=0;
for(i=0;i<MAX;i++) { if (smax<bd[i].sum) { smax=bd[i].sum; ni=i; } }
printf("\n %s , %d-%d-%d , %d \n",bd[ni].nume, bd[ni].dat.zi, bd[ni].dat.luna, bd[ni].dat.an, bd[ni].sum);
j=1; sm=bd[0].sum;
for (i=1;i<MAX;i++) { if (bd[i].dat.zi==bd[i-1].dat.zi && bd[i].dat.luna==bd[i-1].dat.luna && bd[i].dat.an==bd[i-1].dat.an)
{ j=j+1; sm=sm+bd[i].sum; } else {
printf(" \n Nr. depuneri din data %d-%d-%d = %d ; Suma depusa = %d ",bd[i-1].dat.zi,bd[i-1].dat.luna,bd[i-
1].dat.an,j,sm); j=1; sm=bd[i].sum; } }
printf(" \n Nr. depuneri din data %d-%d-%d = %d ; Suma depusa = %d ",bd[i-1].dat.zi,bd[i-1].dat.luna,bd[i-
1].dat.an,j,sm); printf("\n \n"); }
FILE* b = fopen("binar.out","rb");, în care scriem conţinutul acestei structuri în format binar astfel:
fwrite(&elev, sizeof(Elev), 1, b);
În realitate, fişierul arată în memorie astfel:
În acest caz, datele se reprezintă pe un număr cunoscut de Bytes (mai exact, dimensiunea tipului de dată). După cum se
vede din exemplu, asta nu înseamnă mereu că se ocupă mai puţină memorie. Cu toate acestea, în mod statistic, datele binare
ocupă mai puţină memorie!
O problemă este că dacă am vrea să deschidem fişierul pentru a citi aceste date, nu s-ar înţelege mai nimic, pentru că
orice editor ar încerca să transforme fiecare Byte într-un caracter pe care să îl afişeze pe ecran. Evident, nu se obţine ceea ce
ne-am dori noi sa vedem. Avem nevoie de un program care să interpreteze fişierul şi să ne arate conţinutul din el.
Din nou, cel mai important este că dacă am vrea să citim aceste date din fişier, le putem încărca direct la adresa unei
structuri de tip Elev. În realitate, aceste date nu sunt cu nimic mai mult decât o "fotografie" a unei porţiuni din RAM, astfel
încât citirea este de fapt o simplă copiere.
Funcţii de citire şi scriere la nivel de octet:
Primul lucru pe care trebuie să îl facem pentru a putea folosi un fişier este să îl deschidem. În acest sens, lucrurile stau
foarte simplu: trebuie doar să adaugăm "b" la şirul care specifică modul de deschidere al unui fişier în funcţia fopen().
Câteva exemple:
Semnificaţi Fişiere Fişiere
e binare text
citire "rb" "r"
scriere "wb" "w"
adăugare "ab" "a"
Pentru citire la nivel de octet se foloseşte funcţia fread() definită în headerul <stdio.h>, care are următoarea sintaxă:
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
Semnificaţia argumentelor este următoarea:
void* ptr este un pointer către o zonă de memorie unde se va face citirea
size_t size reprezintă dimensiunea în octeţi a unui element citit
size_t count reprezintă numărul de elemente citite. Elementele vor fi depuse în locaţii consecutive începând de la adresa
ptr din memorie
FILE* stream reprezintă fluxul (fişierul) din care se face citirea
Pentru scriere la nivel de octet se foloseşte funcţia fwrite() definită în headerul <stdio.h>, care are următoarea sintaxă:
size_t fwrite ( void * ptr, size_t size, size_t count, FILE * stream );
Semnificaţia argumentelor este următoarea:
void* ptr este un pointer către o zonă de memorie unde se vor prelua datele ce trebuie scrise
size_t size reprezintă dimensiunea în octeţi a unui element scris
size_t count reprezintă numărul de elemente scrise. Elementele vor fi preluate pentru scriere din locaţii consecutive
începând de la adresa ptr din memorie
FILE* stream reprezintă fluxul (fişierul) în care se face scrierea
Nu în ultimul rând, fişierele binare au o proprietate interesantă: Am spus că spaţiul ocupat de diverse articole depinde
exclusiv de tipul lor de dată. Cu alte cuvinte, dacă am vrea să citim al 101-lea număr întreg dintr-un fişier binar care conţine
doar numere întregi, ştim sigur că acest număr ocupă Bytes-ii cu numerele 400, 401, 402 şi 403 din fişier. (Presupunând că
sizeof(int)==4. Numerele se schimbă dacă avem alte arhitecturi cu alte tipuri de date.)
Ar fi foarte convenabil dacă am putea sări peste restul fişierului direct la acea locaţie de memorie. În realitate, acest lucru
este posibil. Pentru a rezolva această problemă, C-ul pune la dispoziţie două funcţii:
long int ftell ( FILE * fisier ), întoarce o valoare care reprezintă poziţia curentă în fişier.
int fseek ( FILE * fisier, long int deplasament, long int fata_de_acest_punct ), sare în fişierul fisier la poziţia obţinută prin
suma celor doi parametri întregi. Deplasamentul reprezintă un număr de Bytes peste care se sare, iar punctul faţa de care se
sare poate fi una din constantele:
SEEK_SET, începutul fişierului
SEEK_CUR, poziţia curentă în fişier (salt autorelativ)
SEEK_END, poziţia finală din fişier (nu adunaţi valori pozitive :D)
Exemplul: Funcţie care determină numărul de octeţi ai unui fişier
#include <stdio.h>
long FileSize(FILE *pf) { long pozv, noct;
pozv = ftell(pf); /* salveaza pozitia curenta */
fseek(pf, 0L, SEEK_END); /* pozitionare la sfarsit */
noct = ftell(pf); /* numar de octeti din fisier */
fseek(pf, pozv, SEEK_SET); /*revenirea la pozitia veche*/
return noct; }
tratarea erorilor
- int feof(FILE *pf); întoarce o valoare diferită de 0, dacă s-a detectat marcajul de sfârşit de fişier
- int ferror(FILE *pf); întoarce o valoare diferită de 0, dacă s-a detectat o eroare în cursul operaţiei de intrare /
ieşire
Includerea fişierelor. Gărzi de includere multiplă.
În aplicaţiile mari, în mod normal modulele diferite de program se implementează în fişiere separate, urmând a fi
necesară compilarea executabilului final din mai multe surse. Includerea unui fişier sursă în alt fişier sursă se face cu ajutorul
directivei de preprocesare # include care este urmată de numele fişierului ce trebuie inclus. Distingem două cazuri:
<nume_header> specifică un fişier header standard. Compilatorul se aşteaptă să găsească un astfel de fişier într-un
director anume care conţine biblioteci standard
"nume_header" specifică un fişier header definit de utilizator. Compilatorul se aşteaptă să găasească un astfel de fişier în
directorul curent al proiectului
Trebuie să mai specificăm aici următoarea problemă. Este posibil să implementăm de exemplu definiţia unei structuri de
date într-un fişier header, şi apoi să scriem în fişiere separate funcţii ce operează pe acea structură de date. Evident, funcţiile
definite vor trebui să includă la rândul lor fişierul de definire al structurii de date. Dar fişierul care conţine funcţia main(), de
exemplu, trebuie să includă toate fişierele care implementează funcţii, ceea ce ar însemna că fişierul de definire al structurii
de date este inclus de mai multe ori. Acest lucru trebuie întotdeauna evitat prin protejarea clauzelor de includere astfel:
#ifndef __STDLIB__
#define __STDLIB__
#include <stdlib.h>
#endif /* __STDLIB__ */
Înainte de a se include pentru prima dată <stdlib.h>, numele __STDLIB__ nu este definit, ceea ce permite includerea
headerului. Încercările ulterioare de a include fişierul header vor eşua (ne dorim acest lucru deoarece per ansamblu nu dorim
să includem headerul decât o singură dată în program).
2.2.1 Închiderea fişierelor
Când un fişier nu mai serveşte , el se poate închide. Legătura sa cu pointerul FILE corespunzător este
întrerupt. Funcţia nivelului înalt competent pentru a închide un fişier este fclose .Teoretic s-ar putea de renunţat să
apeleze explicit fclose în program . Fclose este chemat automatic la sfârşitul programului , pentru a închide toate
fişierele încă deschise.
Funcţia predefinită fclose admite prototipul:
int fclose (FILE *pointer_fişier);
Ea posedă ca parametru un pointer spre tipul FILE . Fclose returnează valoarea 0 dacă a putut să deschidă
fişierul ataşat la pointer_fiţier .
Următorul exemplu de program încearcă să deschidă un fişier a cărui nume e trecut pe linia de
comandă .Dacă va reuşi , fişierul este reînchis cu ajutorul funcţiei fclose
/* openclose arată cum se deschide şi se închide un fişier a cărui nume a dat pe linia de comandă. */
#include stdio.h /* printf , fopen , close */
#include stdlib.h /* exit */
#define READ “r”
main(int argc, char *argv )
FI LE *fp;
if (argc! =2) /* un singur parametru admis */
printf(?*=(“nsintaxa: opnclose fişier .exit/n”); exit(0);
if ((fp=fopen (argv1, READ ))==NULL) /*deschiderea fişierului în citire */
printf(“EROARE:imposibil de deschis fişierul %s./n”, argv 1 );
else fclose (fp); /* deschiderea fişierului */
printf (“fişierul %s a fost închis. /n”, argv 1 );
2.3. Operaţiile de citire şi de scriere
Pentru a citi sau a scrie datele unui fişier , se dispun de funcţii analogice a celor care servesc la prinderea
datelor la clavir şi la afişarea lor la ecran . Poziţia la care se citeşte sau se scrie într-un fişier este dat de un pointer
specific (seek pointer ), utilizat pentru operaţiile de lectură şi scriere. Acest pointer este condus de un sistem de
exploatare : el semnalează poziţia de tratare a mişcării într-un fişier. După fiecare lectură şi scriere acest pointer
este deplasat. Acest deplasament este efectuat prin sistem. Să presupunem că se citesc trei caractere (pe imaginea
următoare : A ,B, C) de un fişier X
SEEK pointer(citirea /scrierea )
A B C D E F G H
3.4. /* Problema 1 set 4 : Program pentru crearea unui fisier binar, avand articole structuri cu urmatoarele campuri:
-nume depunator (sir de maxim 30 de caractere)
-data depunerii (o structura avand campurile intregi: zi,luna,an)
-suma depusa (o valoare reala).
Articolele sunt grupate pe zile in ordine cronologica.
Datele se introduc de la consola, fiecare pe 3 linii. */
#include<stdio.h>
#include<conio.h>
#include<dos.h>
#include<stdlib.h>
#define MAX 3
typedef struct { int zi; int luna; int an; } DATA;
typedef struct { unsigned char nume[30]; DATA dat; int sum; } CLIENT;
void main()
{ CLIENT bd[MAX]; int i; FILE *baza; printf("\n Introduceti datele persoanelor ");
for(i=0;i<MAX;i++) { printf("\n====================================");
printf("\n Nume : "); scanf("%s",&bd[i].nume);
printf("\n Data : "); scanf("%d-%d-%d",&bd[i].dat.zi,&bd[i].dat.luna,&bd[i].dat.an);
printf("\n Suma : "); scanf("%d",&bd[i].sum); };
baza=fopen("date.dat","w"); fwrite( bd, sizeof( CLIENT ), MAX, baza ); fclose( baza ); }
3.5. /* Program care, folosind fisierul creat in problema 1, calculeaza si afiseaza:
- -suma maxima depusa, impreuna cu data si numele depunatorului
- -numarul depunerilor din fiecare zi, si suma totala depusa in fiecare zi, tinand cont ca tranzactiile dintr-o zi sunt contigue
in fisier. */
#include<stdio.h>
#include<conio.h>
#include<dos.h>
#include<stdlib.h>
#define MAX 3
typedef struct { int zi; int luna; int an; } DATA;
typedef struct { unsigned char nume[30]; DATA dat; int sum; } CLIENT;
void main() { CLIENT bd[MAX]; int j,sm,i,smax,ni; FILE *baza;
baza=fopen("date.dat","r"); fread( bd, sizeof( CLIENT ), MAX, baza ); fclose( baza ); smax=0;
for(i=0;i<MAX;i++) { if (smax<bd[i].sum) { smax=bd[i].sum; ni=i; } }
printf("\n %s , %d-%d-%d , %d \n",bd[ni].nume, bd[ni].dat.zi, bd[ni].dat.luna, bd[ni].dat.an, bd[ni].sum);
j=1; sm=bd[0].sum;
for (i=1;i<MAX;i++) {
if (bd[i].dat.zi==bd[i-1].dat.zi && bd[i].dat.luna==bd[i-1].dat.luna && bd[i].dat.an==bd[i-1].dat.an)
{ j=j+1; sm=sm+bd[i].sum; } else {
printf(" \n Nr. depuneri din data %d-%d-%d = %d ; Suma depusa = %d ",bd[i-1].dat.zi,bd[i-1].dat.luna,bd[i-1].dat.an,j,sm);
j=1; sm=bd[i].sum; } }
printf(" \n Nr. depuneri din data %d-%d-%d = %d ; Suma depusa = %d ",bd[i-1].dat.zi,bd[i-1].dat.luna,bd[i-1].dat.an,j,sm);
printf("\n \n"); }
3.6. / Program, care folosind fisierul creat in problema 5, actualizeaza acest fisier prin adaugarea dobanzii, la data
curenta. Se precizeaza urmatoarele date: -data curenta la care se calculeaza dobanda (an,luna,zi) -dobanda anuala.
Se va folosi o functie care determina numarul de zile dintre data depunerii si data curenta, pentru a calcula dobanda cuvenita.
*/
#include<stdio.h>
#include<conio.h>
#include<dos.h>
#include<stdlib.h>
#define MAX 3
typedef struct { int zi; int luna; int an; } DATA;
typedef struct { unsigned char nume[30]; DATA dat; int sum; } CLIENT;
int nrzile(int a1,int a2,int a3) { int y,nr; nr=0;
for(y=1;y<a3;y++) if (y % 4==0) nr=nr+365; else nr=nr+364;
for(y=1;y<a2;y++); if (y%2==0) if (y!=2) nr=nr+30;
else nr=nr+28; else nr=nr+31; nr=nr+a1; return(nr); }
void main() { CLIENT bd[MAX]; int i,n1,n2,n3,dobanda; FILE *baza;
baza=fopen("date.dat","r"); fread( bd, sizeof( CLIENT ), MAX, baza ); fclose( baza );
printf(" Introduceti data curenta : "); scanf("%d-%d-%d",&n1,&n2,&n3);
printf("\n Introduceti dobanda : "); scanf("%d",&dobanda);
for (i=0;i<MAX;i++) { bd[i].sum=bd[i].sum+(nrzile(n1,n2,n3)-nrzile(bd[i].dat.zi,bd[i].dat.luna,bd[i].dat.an))*dobanda; }
baza=fopen("date.dat","w"); fwrite( bd, sizeof( CLIENT ), MAX, baza ); fclose( baza );}
3.7. //Se da o matrice, sa se calculeze numarul de elemente pozitive de pe fiecare rinduri.
#include <stdio.h>
#include <conio.h>
#include <math.h>
main() { int n,m,sum,i,j,k; int a[50][50]; clrscr(); printf(" Introduceti numarul de linii si coloane (n,m): \n");
scanf("%d%d",&n,&m); printf("Introduceti elementele matricei A: \n");
for(i=0; i<n; i++) for(j=0; j<m; j++) { scanf("%d",&a[i][j]); fflush(stdin); }
printf("____________________________________________________________________\n\n ");
for(i=0; i<n; i++) { for(j=0; j<m; j++) printf("%3d",a[i][j]); printf("\n "); }
printf("\n____________________________________________________________________\n");
for(i=0; i<n; i++) {k=0; for(j=0; j<m; j++) { if (a[i][j]>=0) {k=k+1;}} printf("\n");
printf("In rindul N=%d sunt %d elemente pozitive",i+1,k); } }
3.8 /*programul dat cauta un anumit cuvint specificat in doua fisiere. Este important de a plasa fisierele pentru
prelucrare in radacina catalogului al discului C,dupa cum este indicat in program*/
#include<stdio.h>
#include<iostream.h>
#include<conio.h>
#include<string.h>
#define size 20
char basic_w[size]; FILE *p1,*p2;int iden, contor;
search() { int i,m; char c,word[size];FILE *p;
switch(iden) { case 1:*p=*p1;break; case 2:*p=*p2;break; }
for(i=0;i<size;i++) word[i]=0;m=0; while(!feof(p)) { c=fgetc(p);
if(c!=' '&&c!='.'&&c!='\n') {word[m]=c;m++;} else {if(strcmp(word,basic_w)==0)
{printf("\nCuvintul a fost gasit in fisierul nr.%d\n",iden);contor++;}
for(i=0;i<size;i++) word[i]=0; m=0; } }return 0; }
main() { int n1,n2; char y; Again:clrscr();
printf("UN MOTOR DE CAUTARE A INFORMATIEI\n\n"); n1=0;p1=fopen("\\p1.txt","r++");
if(p1!=NULL) n1=1; n2=0;p2=fopen("\\p2.txt","r++");
if(p2!=NULL) n2=1; if(n1==0&&n2==0){printf("Fisierele nu pot fi acesate;verificati path-ul.\n");
getch();goto End;}
printf("Introduceti cuvintul ce doriti sa-l cautati:"); gets(basic_w);contor=0;
if(n1==1){iden=1;search();} if(n2==1){iden=2;search();}
if(contor==0)printf("\nCuvintul da repetati procedura(d/n)?"); y=getche();
if(y=='d'||y=='D'){fclose(p1);fclose(p2); goto Again;}
else goto End; End: fclose(p1);fclose(p2); return 0; }
3.9. /*frecventa de tranzitie a tranzistoarelor bipolare*/
# include<stdio.h>
#include<conio.h>
#include <dos.h>
void main() {int t1,ts,t2,tsec; clrscr(); FILE *tranz;
tranz=fopen("c:\\tranzistor.txt","r+"); printf ("indicati de pe ce segment [t1,t2] se iau valorile timpului de intirziere\n");
printf("t1=");scanf("%d",&t1); printf("t2=");scanf("%d",&t2);
printf("fregventa tranzistoarelor bipolare peste fiecare 5 sec in intervalul [t1,t2]\n");
struct time t; gettime(&t); tsec=t.ti_sec; printf("ora: %2d:%02d:%02d.%02d", t.ti_hour, t.ti_min, t.ti_sec, t.ti_hund);
printf(" fregventa tranzistorului:%d\n",0); ts=t1;
while(t1<t2) { gettime(&t); if ((t.ti_sec-tsec)==5) { t1=t1+5; ts=ts+t1;
printf("ora: %2d:%02d:%02d.%02d", t.ti_hour, t.ti_min, t.ti_sec, t.ti_hund);
printf(" fregventa tranzistorului:%d\n",ts*2*3); fprintf(tranz,"%d",ts*6); fprintf(tranz,"\n"); tsec=t.ti_sec; } }}
3.10. //Scrieti un program care va tipari in ordine inversa subconsecutivitatea de numere dintre valoarea minima si
maxima al consecutivitati de numere citita din fisier*/
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void main() { clrscr(); FILE *fin; int x,w,d,y,max=0,min=0; int k,p,s;
fin=fopen("ts.txt","r"); if (fin==NULL) { printf(" Eroare"); exit(1); } int a[20]; int i=0;
while(!feof(fin)) { fscanf(fin,"%d",&y); a[++i]=y; printf("%d ",y); } fclose(fin); max=a[1];
{ for (k=1;k<=i;k++) if (max<a[k]) { max=a[k]; w=k;} } min=a[1];
{ for ( k=1;k<=i;k++) if (min>a[k]) { min=a[k]; s=k;} }
printf("\n Numarul maxim %d si num minim %d \n",max,min); printf("\n Locul num maxim %d si num minim %d\n ",w,s);
for (k=w;k>=s;k--) printf("%d ",a[k]); getch(); }
3.11. Program pentru numararea liniilor si cuvintelor dintr-un fisier text, al carui nume se da in linia de comanda.
Cuvintele sunt siruri de orice caractere separate intre ele prin (oricate) spatii albe. Se va folosi functia de biblioteca "strtok".
#include <stdio.h>
#include <string.h>
// numarare linii si cuvinte dintr-un fisier text
void main ( int argc, char *argv[] ) {
char linie [200], *p, *sep="\t \r\n" ;
FILE * f;
int nl=0, nc=0; // nr linii, nr cuvinte
if (argc < 2) { printf("Lipseste numele fisierului din comanda \n"); return; }
if( (f = fopen (argv[1],"r")) == NULL) { printf(" fisier negasit \n"); return ; }
while ( fgets (linie,200,f) != NULL) { nl++; p=linie;
while ( (p= strtok (p,sep)) != NULL) {++nc; p=p+strlen(p)+1; } }
printf ("\n %d linii %d cuvinte",nl,nc); // si alte operatii cu linia citita
fclose(f); }
3.12. Program pentru numararea liniilor si cuvintelor dintr-un fisier text, al carui nume se da in linia de comanda.
Cuvintele sunt siruri de orice caractere separate intre ele prin (oricate) spatii albe. Nu se vor folosi functii pe siruri de
caractere din <string.h>.
#include <stdio.h>
#include <ctype.h>
// numarare linii si cuvinte dintr-un fisier text
void main ( int argc, char *argv[] ) {
char linie [200], *p ; FILE * f;
int nl=0, nc=0; // nr linii, nr cuvinte aici se pot face verificari asupra datelor primite
f=fopen(argv[1],"r");
while ( fgets (linie,200,f) != NULL) { nl++; p=linie;
while (*p) { while ( *p && isspace(*p) ) // ignora spatii dintre cuvinte
p++; if (*p =='\0') // daca s-a terminat linia curenta
break; // citeste alta linie
nc ++; while (*p && ! isspace(*p) ) // cauta sfarsit de cuvant
p++; } } printf ("%d linii %d cuvinte",nl,nc); // si alte operatii cu linia citita
fclose(f); }
3.13. Program pentru citirea unui fisier de numere (reprezentate prin siruri de caractere separate prin spatii albe)
si crearea unui alt fisier cu aceleasi numere ordonate crescator. Numele celor doua fisiere se dau in linia de comanda.
// ordonare fisier de numere
#include <stdio.h>
#include <stdlib.h>
// compara doi intregi (ptr qsort)]
int intcmp (const void* a , const void * b) { return *(int*)a - *(int*)b; }
// program de ordonare fisier de numere
int main (int na, char ** arg) { int num[1000]; // vector pentru numere citite din fisier
int n,i,j; FILE * f1, * f2; if (na < 3) { printf ("Eroare! Utilizare corecta: nume infile outfile \n");
return -1; } // citire fisier de date
if ( (f1=fopen (arg[1],"rt"))==0) { printf ("Eroare: Fisier de date negasit! \n");
return -2; } i=0;
while ( fscanf(f1,"%d",&num[i]) != EOF) i++; n=i; // lungime vector
// ordonare vector cu functia "qsort"
qsort (num,n,sizeof(int), intcmp); // scrie vector ordonat in fisier
f2=fopen(arg[2],"wt");
for (i=0;i<n;i++) fprintf(f2,"%d ",num[i]); fclose(f2); }
Obs: Nu era posibila ordonarea numerelor ca siruri de caractere (fara conversie in binar), deoarece sirul "7" este superior
sirului "123", dar numarul 7 este inferior numarului 123.
3.14. // compara doua siruri dupa cuvantul k din sir (k=0,1,..)
int compar ( char * a, char * b, int k) { char w1[80], w2[80]; while (k>=0) { sscanf(a,"%s",w1);
sscanf(b,"%s",w2); a=strstr(a,w1)+strlen(w1); b=strstr(b,w2)+strlen(w2); k=k-1; } return strcmp(w1,w2); }
// ordonare linii din fisier text dupa orice cuvant din linie
void main ( int argc, char * argv[]) {
FILE * f; char line[132]; int k,n, gata; char * aux; char * tlin[1000]; // vector de pointeri la linii (max 1000)
f= fopen(argv[1],"r"); // nume fisier in argv[1]
int nc = atoi(argv[2]); // numar cuvant in linie (0,1,..)
// citire fisier si creare vector de pointeri
k=0; // k= indice in vectorul tlin
while ( fgets (line,132,f) ) tlin[k++]=strdup(line); n=k; // ordonare vector de pointeri
do { gata =1;
for (k=0;k<n-1;k++) if ( compar(tlin[k],tlin[k+1],nc) > 0) { aux=tlin[k+1]; tlin[k+1]=tlin[k]; tlin[k]=aux;
gata=0; } } while (!gata); // afisare fisier ordonat
puts(""); for (k=0;k<n;k++) printf("%s",tlin[k]); }
3.15. Program pentru numararea liniilor si cuvintelor dintr-un fisier text, al carui nume se da in linia de comanda.
Cuvintele sunt siruri de orice caractere separate intre ele prin (oricate) spatii albe. Se va folosi functia de biblioteca
"strtok".
#include <stdio.h>
#include <string.h>
// numarare linii si cuvinte dintr-un fisier text
void main ( int argc, char *argv[] ) {
char linie [200], *p, *sep="\t \r\n" ;
FILE * f; int nl=0, nc=0; // nr linii, nr cuvinte
if (argc < 2) { printf("Lipseste numele fisierului din comanda \n"); return; }
if( (f = fopen (argv[1],"r")) == NULL) { printf(" fisier negasit \n"); return ; }
while ( fgets (linie,200,f) != NULL) { nl++; p=linie;
while ( (p= strtok (p,sep)) != NULL) { ++nc; p=p+strlen(p)+1; }
}
printf ("\n %d linii %d cuvinte",nl,nc); // si alte operatii cu linia citita
fclose(f);
}
3.16. Program pentru numararea liniilor si cuvintelor dintr-un fisier text, al carui nume se da in linia de comanda.
Cuvintele sunt siruri de orice caractere separate intre ele prin (oricate) spatii albe. Nu se vor folosi functii pe siruri de
caractere din <string.h>.
#include <stdio.h>
#include <ctype.h>
// numarare linii si cuvinte dintr-un fisier text
void main ( int argc, char *argv[] ) {
char linie [200], *p ; FILE * f;
int nl=0, nc=0; // nr linii, nr cuvinte
// aici se pot face verificari asupra datelor primite
f=fopen(argv[1],"r");
while ( fgets (linie,200,f) != NULL) { nl++; p=linie;
while (*p) { while ( *p && isspace(*p) ) // ignora spatii dintre cuvinte
p++; if (*p =='\0') // daca s-a terminat linia curenta
break; // citeste alta linie
nc ++;
while (*p && ! isspace(*p) ) // cauta sfarsit de cuvant
p++; } }
printf ("%d linii %d cuvinte",nl,nc); // si alte operatii cu linia citita
fclose(f);
3.17. Program pentru citirea unui fisier text creat in Unix (in care fiecare linie se termina cu un singur caracter '\n' ) si
crearea unui alt fisier cu acelasi continut, dar in care liniile se termina cu doua caractere: "\r\n". In final se sterge fisierul
initial si se schimba numele noului fisier in numele fisierului initial. Functia "fputs" adauga caracterul '\r' inaintea
caracterului '\n'.
#include <stdio.h>
#include <string.h>
void main () {
char nume1[80], nume2[80]; // nume fisiere
char line[200]; // aici se citeste o linie
char *point ;
FILE * f1, * f2; puts("Nume fisier text:"); gets(nume1);
if( (f1 = fopen (nume1,"r")) == NULL) { printf(" fisier negasit \n"); return ; }
strcpy(nume2,nume1); point = strchr (nume2,'.');
if (point==0) point=nume2+strlen(nume2); strcpy(point+1,"$$$"); f2 =fopen (nume2,"w");
while ( fgets (line,200,f1) != 0) fputs (line,f2);
if (fclose(f1)<0 || fclose(f2)<0) { puts("Erori la fisiere \n"); return; }
remove(nume1); rename(nume2,nume1); // schimba nume1.$$$ in nume1.*
}
}
3.18. Vizualizaţi listingul programului, verificaţi corectitudinea, scopul şi organizaţi afişarea rezultatelor
#include<stdio.h>
int nrart(FILE *f, int l) {long p; int n; p=ftell(f); fseek(f,0,2); n=ftell(f)/l; fseek(f,0,p); return n;}
void main() {FILE *f,*g,*h; float x,y,z; char s1[20],s2[20]; printf("\nPrimul fisier: ");gets(s1);
printf("Al doilea fis: ");gets(s2);
if(!(f=fopen(s1,"rb")))printf("Fisierul %s nu poate fi deschis.", s1);
else if(!(g=fopen(s2,"rb")))printf("Fisierul %s nu poate fi deschis", s2);
else {if(nrart(f,sizeof(float))!=nrart(g,sizeof(float))) printf("Numar diferit de articole.");
else {printf("Fisier rezultat: "); gets(s1); h=fopen(s1,"wb"); fread(&x,sizeof(float),1,f);
fread(&y,sizeof(float),1,g);
while(!feof(f)) {z=x*y; fwrite(&z,sizeof(float),1,h); fread(&x,sizeof(float),1,f); fread(&y,sizeof(float),1,g);}
fclose(h);} fclose(f); fclose(g);} }
3.19. Vizualizaţi listingul programului, verificaţi corectitudinea, scopul şi organizaţi afişarea rezultatelor
#include<stdio.h>
int nrart(FILE *f, int l) {long p; int n; p=ftell(f); fseek(f,0,2); n=ftell(f)/l; fseek(f,0,p); return n;}
void main() {FILE *f,*g; float x,y,z; char s1[20],s2[20]; printf("\nPrimul fisier: ");gets(s1);
printf("Al doilea fis: ");gets(s2);
if(!(f=fopen(s1,"rb")))printf("Fisierul %s nu poate fi deschis.",s1);
else if(!(g=fopen(s2,"rb")))printf("Fisierul %s nu poate fi deschis.", s2);
else {if(nrart(f,sizeof(float))!=nrart(g,sizeof(float))) printf("Numar diferit de articole.");
else {z=0; fread(&x,sizeof(float),1,f); fread(&y,sizeof(float),1,g);
while(!feof(f)) {z+=x*y; fread(&x,sizeof(float),1,f); fread(&y,sizeof(float),1,g);} printf("Rezultat: %7.2f",z);}
fclose(f); fclose(g);} }
3.20. Vizualizaţi listingul programului, verificaţi corectitudinea, scopul şi organizaţi afişarea rezultatelor
#include<stdio.h>
#include<conio.h>
void main(void) {FILE *f; float x,y; int i,m,n; char nume[20];
printf("\nFisier="); gets(nume);
if(f=fopen(nume,"rb+")) {fseek(f,0,SEEK_END); n=ftell(f)/sizeof(float); m=1;
while(m) {rewind(f); m=0;
for(i=0;i<n;i++) {fseek(f,i*sizeof(float),SEEK_SET); fread(&x,sizeof(float),1,f); fread(&y,sizeof(float),1,f);
if(x>y) {fseek(f,ftell(f)-2*sizeof(float),SEEK_SET); fwrite(&y,sizeof(float),1,f); fwrite(&x,sizeof(float),1,f);
m=1;} } } fclose(f);} else printf("Fisierul %s nu poate fi deschis.", nume);}
3.21. Vizualizaţi listingul programului, verificaţi corectitudinea, scopul şi organizaţi afişarea rezultatelor
#include<stdio.h>
int nrart(FILE *f, int l) {long p; int n; p=ftell(f); fseek(f,0,2); n=ftell(f)/l; fseek(f,0,p); return n;}
void main() {FILE *f; char s[20]; int n,i,p,j; float x,y,z; printf("\nFisier: "); gets(s);
if(!(f=fopen(s,"rb+")))printf("\nFisierul %s nu poate fi deschis.",s); else{n=nrart(f,sizeof(float));
for(i=0;i<n-1;i++) {p=i; fseek(f,p*sizeof(float),SEEK_SET); fread(&x,sizeof(float),1,f); z=x;
for(j=i+1;j<n;j++) {fseek(f,j*sizeof(float),SEEK_SET); fread(&y,sizeof(float),1,f); if(x>y){p=j;x=y;} }
fseek(f,p*sizeof(float),SEEK_SET); fwrite(&z,sizeof(float),1,f); fseek(f,i*sizeof(float),SEEK_SET);
fwrite(&x,sizeof(float),1,f);} fclose(f);} }
3.22. Vizualizaţi listingul programului, verificaţi corectitudinea, scopul şi organizaţi afişarea rezultatelor
#include<stdio.h>
void main() {FILE *f,*g,*h; float x,y,z; int m,n,p,q,i,j,k; char s1[20],s2[20],s3[20];
printf("\nNume fisier1="); gets(s1);
if(!(f=fopen(s1,"rb")))printf("\nFisierul %s nu poate fi deschis.",s1); else{printf("Nume
fisier1="); gets(s2);
if(!(g=fopen(s2,"rb")))printf("\nFisierul %s nu poate fi deschis", s2);
else{printf("Rezultat: ");gets(s3);
h=fopen(s3,"wb"); fseek(f,0,SEEK_END); n=ftell(f)-sizeof(int); rewind(f);
fread(&m,sizeof(int),1,f);
n=n/(m*sizeof(float)); fseek(g,0,SEEK_END); q=ftell(g)-sizeof(int); rewind(g);
fread(&p,sizeof(int),1,g);
q=q/(p*sizeof(float));
if(n!=p)printf("\nMatricele nu se pot inmulti."); else{fwrite(&m,sizeof(int),1,h);
for(i=0;i<m;i++)
for(j=0;j<q;j++) {z=0;
for(k=0;k<n;k++) {fseek(f,(i*n+k)*sizeof(float)+sizeof(int),0);
fread(&x,sizeof(float),1,f);
fseek(g,(k*q+j)*sizeof(float)+sizeof(int),0); fread(&y,sizeof(float),1,g); z+=x*y;}
fwrite(&z,sizeof(float),1,h);} }
fclose(h); fclose(g);} fclose(f);} }
3.23. Vizualizaţi listingul programului, verificaţi corectitudinea, scopul şi organizaţi afişarea rezultatelor
#include<stdio.h>
#define POZ(i,j,n) sizeof(int)+((i)*(n)+j)*sizeof(float),SEEK_SET
void main() {FILE *f; int m,n,i,j; float x; char s[20]; printf("\nFisier: ");gets(s);
if(!(f=fopen(s,"rb")))printf("\nFisierul %s nu poate fi deschis",s);
else{fseek(f,0,SEEK_END);
n=ftell(f)-sizeof(int); rewind(f); fread(&m,sizeof(int),1,f); n=n/(m*sizeof(float));
if(m!=n) printf("\nFisierul nu contine o matrice patrata."); else{n=0;
for(i=0;i<m;i++)
for(j=0;j<i-1;j++) {fseek(f,POZ(i,j,m)); fread(&x,sizeof(float),1,f); if(!x)n++;}
printf("\n Sub d.p. sint %d zerouri.",n);} fclose(f);} }
3.24. Vizualizaţi listingul programului, verificaţi corectitudinea, scopul şi organizaţi afişarea rezultatelor
#include<stdio.h>
void main() {FILE *f; int m,n,p,q,i,j,k;
float x,a[20][20],b[20][20]; char s[20]; printf("Nume fisier: ");gets(s);
if(!(f=fopen(s,"r"))) printf("\nFisierul nu poate fi deschis."); else{fscanf(f,"%d %d",&m,&n);
for(i=0;i<m;i++)
for(j=0;j<n;j++) fscanf(f,"%f",&a[i][j]); fscanf(f,"%d %d",&p,&q);
for(i=0;i<p;i++)
for(j=0;j<q;j++) fscanf(f,"%f",&b[i][j]);
if(n!=p) printf("\nNu se pot inmulti."); else{f=fopen(s,"a"); fprintf(f,"%d %d\n", m,p);
for(i=0;i<m;i++)
{for(j=0;j<q;j++) {x=0; for(k=0;k<n;k++) x+=a[i][k]*b[k][j]; fprintf(f,"%5.2f ",x);} fprintf(f,"\n");} }
fclose(f);} }
3.25. Vizualizaţi listingul programului, verificaţi corectitudinea, scopul şi organizaţi afişarea rezultatelor
#include<stdio.h>
#define MANY 1000
void main() {FILE *f; int m,n,i,j; float x; char s[20]; printf("Nume fisier: ");gets(s);
if(!(f=fopen(s,"r"))) printf("\nFisierul nu poate fi deschis."); else{fscanf(f,"%d %d",&m,&n); fgets(s,MANY,f);
for(i=0;i<m;i++) fgets(s,MANY,f); fscanf(f,"%d %d",&m,&n); fgets(s,MANY,f);
for(i=0;i<m;i++) fgets(s,MANY,f); fscanf(f,"%d %d",&m,&n);
for(i=0;i<m;i++) {for(j=0;j<n;j++) {fscanf(f,"%f",&x); printf("\t%5.2f",x);}
printf("\n");} fclose(f);} }
4. Exemple de verificare a cunoştinţelor însuşite: în listingul programelor de mai jos verificaţi
corectitudinea, scopul şi rezultatele afişate:
4.1. Listingul programului:
#include<conio.h>
#include<stdio.h>
#include<string.h>
void main() {clrscr(); int i,n;
FILE *f;
f=fopen("d:\\input.txt","r");
char *s,**s1,*aux;
fgets(s,1000,f);
for(i=0,n=0;i<strlen(s);i++) if((s[i]=='.')||(s[i]=='!')) n++;
s1[0]=strtok(s,".!");
for(i=1;i<n;i++) s1[i]=strtok(NULL,".!");
aux=s1[0]; s1[0]=s1[2]; s1[2]=aux;
for(i=0;i<n;i++)printf("%s. ",s1[i]);
fclose(f);
getch();
}
4.2. Listingul programului:
#include<stdio.h>
#include<conio.h>
void main() {clrscr();
FILE *f;
int i,x;
f=fopen("e:\\numbers.txt","a");
printf("\n Introduceti 5 numere:\n");
for(i=0;i<5;i++)
{scanf("%d",&x);
fprintf(f,"%d\n",x);
}
fclose(f);
getch();
}
4.3. Listingul programului:
#include<conio.h>
#include<stdio.h>
void main() {clrscr();
FILE *f;
int i,x,S=0;
f=fopen("file.txt","w+");
printf("\n introduceti zece numere intregi \n");
for(i=0;i<10;i++) { scanf("%d",&x); fprintf(f,"%d ",x); } rewind(f);
while(!feof(f)) {
fscanf(f,"%d",&x);
if(!feof(f))
S+=x; }
printf("S=%i",S); getch(); fclose(f); }
4.4. Listingul programului:
#include<iostream.h>
#include<stdio.h>
#include<conio.h>
#include<dos.h>
void main() {clrscr();
struct dosdate_t d;
struct dostime_t t; printf(" \n De la inceputul erei noastre au trecut: \n "); _dos_getdate(&d);
printf("\n %d veacuri %d ani %d luni %d zile ",d.year/100,d.year,d.month,d.day); _dos_gettime(&t);
printf(" %2d:%02d:%02d.%02d\n", t.hour, t.minute,t.second, t.hsecond); getch(); }
4.5. Listingul programului:
#include <string.h>
#include <stdio.h>
int main(void){ FILE *fp;
char buf[11] = "0123456789"; /* create a file containing 10 bytes */
fp = fopen("DUMMY.FIL", "w"); fwrite(&buf, strlen(buf), 1, fp);
/* close the file */ fclose(fp); getchar(); return 0; }
4.6. Listingul programului:
#include <stdio.h>
#include <ctype.h>
#include <mem.h>
char q[250]; int g[26]; int k[26]; int len=0;
int main()
{ FILE *f; int ch,i; long kol; f=fopen("input.txt","r");
while((ch=fgetc(f))!='\n') { if(isalpha(ch)) { g[ch-'A']++; len++; } }
i=0; kol=0; if(len>0)
while((ch=fgetc(f))!=EOF) { if(isalpha(ch))
{ if(q[i]) k[q[i]-'A']--; q[i]=ch; k[ch-'A']++; i=(i+1)%len; if(memcmp(g,k,sizeof(g))==0) kol++; } }
fclose(f); f=fopen("output.txt","w"); fprintf(f,"%ld\n",kol); fclose(f); return 0; }
4.7. Listingul programului:
#include<stdio.h>
#include<conio.h>
main()
{ int acc; char nume[10]; float balanta;
FILE *cfPtr; clrscr();
if ((cfPtr= fopen("clientii.txt","w"))==NULL) printf("Failul nu poate fi deschis\n");
else {printf("introdu banii,numele,si balanta\n"); printf("introdu sf. daca m.\n"); printf("?");
scanf("%d%s%f",&acc,nume,&balanta);
while(!feof(stdin)){ fprintf(cfPtr,"%d%s%.2f\n", acc,nume,balanta); printf("?");
scanf("%d%s%f",&acc,nume,&balanta); } fclose(cfPtr); } return 0;
}
4.8. Listingul programului:
#include <conio.h>
#include <stdio.h>
#include <string.h>
struct regest{ char name[20]; int ani; }; regest cat[2]; FILE *f1,*f2;
void init_f()
{int num=sizeof(cat)/sizeof(cat[0]); f1 = fopen("f1","w"); f2 = fopen("f2","w"); clrscr();
printf(" Introduceti %d de inregistrari.\n",num+1);
for(int i=0;i<=num;i++) { printf("Inregistr. nr.%d \n",i); scanf("%s %d", &cat[i].name, &cat[i].ani);
fprintf(f1,"%s ",cat[i].name); fprintf(f2,"%d ",cat[i].ani); };
// fflush(f1); fflush(f2);
fclose(f1); fclose(f2); }
void init(){ int i=0;
while (!feof(f1)) { fscanf(f1,"%s ",&cat[i].name); fscanf(f2,"%d ",&cat[i].ani); i++; } }
void afish(){ int num=sizeof(cat)/sizeof(cat[0]); printf("Afisarea continutului catalogului\n");
for (int i=0;i<=num;i++) printf("%s %d\n",cat[i].name,cat[i].ani); }
int num_lit(){ int num=sizeof(cat)/sizeof(cat[0]); int len,min=strlen(cat[0].name);
for (int i=1; i<=num; i++) { len=strlen(cat[i].name); if (len<min) min=len; } return (min); }
void afish_min(int l)
{ int num=sizeof(cat)/sizeof(cat[0]);
for (int i=0;i<=num;i++) { if (strlen(cat[i].name)==l) printf("%s %d \n",cat[i].name,cat[i].ani); } }
void main(){ int lungimea; clrscr(); f1 = fopen("f1","r"); f2 = fopen("f2","r");
if (f1==NULL) {init_f();} else{init();}; lungimea = num_lit(); afish(); afish_min(lungimea);
fclose(f1); fclose(f2); getch(); }
4.9. Listingul programului:
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void main(){ clrscr(); FILE *fin; int x,w,d,y,max=0,min=0; int k,p,s; fin=fopen("ts.txt","r"); int a[20]; int i=0;
if (fin==NULL) { printf(" Eroare"); exit(1); }
while(!feof(fin)) { fscanf(fin,"%d",&y); a[++i]=y; printf("%d ",y); } fclose(fin); max=a[1];
{ for (k=1;k<=i;k++) if (max<a[k]) { max=a[k]; w=k;} } min=a[1];
{ for ( k=1;k<=i;k++) if (min>a[k]) { min=a[k]; s=k;} }
printf("\n Numarul maxim %d si num minim %d \n",max,min);
printf("\n Locul num maxim %d si num minim %d\n ",w,s);
for (k=w;k>=s; k--) printf("%d ",a[k]); getch(); }
4.10. Listingul programului:
#include <stdio.h>
#include <conio.h>
#define MIN_DISCOUNT .97
#define MAX_DISCOUNT .95
void main()
{ float frPrice, fbPrice; FILE *fin, *fout; fin = fopen("customer.dat", "r"); fout = fopen("billing.dat", "w");
if (fin == NULL) { printf("Fisierul CUSTOMER.DAT nu exista!"); getch(); return; }
while (fscanf(fin, "%f", &frPrice) != EOF) { if (frPrice < 100) fbPrice = frPrice * MIN_DISCOUNT;
else fbPrice = frPrice * MAX_DISCOUNT;
fprintf(fout, "Suma $%8.2f ", frPrice); printf("Suma $%8.2f ",frPrice); fprintf(fout, "cu rabat e $%8.2f\n", fbPrice);
printf("cu rabat e $%8.2f\n", fbPrice); } printf("\nDatele de mai sus au fost salvate");
printf(" in fisierul BILLING.DAT!"); getch(); }
4.11. Listingul programului:
#include<stdio.h>
#include<conio.h>
#include<alloc.h>
typedef struct articol{ int camp1; char camp2[80]; unsigned char camp3; float camp4; };
int *p_int; int **p_mat; articol *p_art; int mat[3][3]={{1,2,3},{4,5,6},{7,8,9}};
articol art[1]={{100,"sir1",’a’,12.3},};
void main(){ clrscr(); p_int=(int *)malloc(sizeof(int)); *p_int=10; p_mat=(int**)malloc(3*sizeof(int*));
for(int i=0;i<3;i++) p_mat[i]=(int*)malloc(sizeof(int));
for(i=0;i<3;i++) for(int j=0;j<3;j++) p_mat[i][j]=mat[i][j]; p_art=(articol *)malloc(sizeof(articol));
p_art=art; printf("\nintregul este:...%d", *p_int); printf("\nmat[1][1] este:...%d",p_mat[1][1]);
printf("\ncamp 3 este:...%c",p_art->camp3); getch(); }
4.12. Listingul programului:
#include<stdio.h>
void main(void) { char nompoint; int x,y; char nomfich[10];
FILE * donnes; printf("Donnez le nom du fichier a creer\n"); scanf("%s",nomfich);
donnes=fopen(nomfich,"w"); printf("Introdu numele si coordonatele punctului\n");
printf("Pentru terminare - caracterul #\n");
while(1) { scanf(" %c%d%d",&nompoint,&x,&y); // notez l'espace avant %c
if (nompoint=='#') break; fprintf(donnes,"%c %d %d\n",nompoint,x,y); } fclose(donnes);
donnes=fopen(nomfich,"r"); printf("Contenu du fichier grafic\n");
while(1) {fscanf(donnes," %c%d%d",&nompoint,&x,&y); // attention : espace avant %c
if (feof(donnes)) break; printf("%c %d %d\n",nompoint,x,y); } printf(" *** Fin de fichier ***\n");
fclose(donnes); }
4.13. Listingul programului:
#include<stdio.h>
#include<alloc.h>
main() { int i,j,ni,x,m;char a='n';int d,n; struct std{int nr;char nm[10],pr[10];int a1,a2;}s,*l,l1[1];
FILE *f1,*f2; if((f1=fopen("f1.doc","r"))==NULL) {puts("Fisierul f1.doc nu exista.");exit(1);}
for(ni=0;fscanf(f1,"%d %s %s %d %d",&s.nr,s.nm,s.pr,&s.a1,&s.a2)!=EOF;ni++){}
fclose(f1);f1=fopen("f1.doc","r"); l=malloc(ni*sizeof(s)); puts("Elementele listei neordonate.");
for(i=0;i<ni;i++) {fscanf(f1,"%d %s %s %d %d",&l[i].nr,l[i].nm,l[i].pr,&l[i].a1,&l[i].a2);
printf("%d %s %s %d %d \n",l[i].nr,l[i].nm,l[i].pr,l[i].a1,l[i].a2);} puts("Introduceti numarul metodei de sortare.");
puts("1.Metoda inserectiei."); puts("2.Metoda selectiei."); puts("3.Metoda bulelor."); puts("4.Metoda Shell");
printf("N=");scanf("%d",&n); if(n==1) goto si; if(n==2) goto ss; if(n==3) goto mb; if(n==4) goto ms; goto m;
si: for(i=1;i<ni;i++) {l1[0]=l[i];j=i-1;
while(j>=0 && l[j].a2<l1[0].a2) {l[j+1]=l[j];j--;} l[j+1]=l1[0];} goto m;
ss: for(x=0;x<ni;x++) {l1[0]=l[x]; for(i=x;i<ni;i++) if(l[i].a2>l1[0].a2) {l1[0]=l[i];j=i;} l[j]=l[x]; l[x]=l1[0];} goto m;
mb: for(x=0;x<ni-1;x++) for(i=0;i<ni-1;i++) if(l[i].a2<l[i+1].a2) {l1[0]=l[i];l[i]=l[i+1]; l[i+1]=l1[0];} goto m;
ms: d=ni/n; while(a=='n') {if(d==1) a='d'; for(j=0;j<ni-d;j++) if(l[j+d].a2>l[j].a2) {l1[0]=l[j+d];l[j+d]=l[j];l[j]=l1[0];a='n';}
d=(d+1)/2;}
m: f2=fopen("f2.doc","w"); puts("Lista ordonata.");
for(i=0;i<ni;i++) {printf("%d %s %s %d %d\n",l[i].nr,l[i].nm,l[i].pr,l[i].a1,l[i].a2);
fprintf(f2,"%d %s %s %d %d\n",l[i].nr,l[i].nm,l[i].pr,l[i].a1,l[i].a2); } fcloseall(); return(0); }
4.14. Listingul programului:
#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
void main() {int i,n,s=0,a[100]; FILE *in; clrscr();
if(in=fopen("ser.dat","w")==NULL) fprintf(stderr,"Nu poate deschide fisierul \n"); printf("Introdu numarul de elemente
\n"); scanf("%d",&n); printf(" elementele cele pozitive si negative sint \n"); randomize();
for(i=0;i<n;i++) {scanf("%d",&a[i]); fprintf(in,"%d",a[i]);} fclose(in);
if(in=fopen("ser.dat","rt")==NULL) fprintf(stderr,"Nu poate deschide fisierul \n"); printf("\n");
printf("Elementele extrase din fisier sint \n"); for(i=0;i<n;i++) {fscanf(in,"%d",a[i]); s=s+a[i]; printf(" %d ",a[i]);}
printf("\n"); printf("Suma este egala cu S=%d\n",s); fclose(in); getch(); }
4.15. Listingul programului:
#include <stdio.h>
#include <conio.h>
main(){ FILE *f,*f1; int a[10]; int i; int j; f=fopen ("aaa","w+"); f1=fopen ("aaa1","w+"); clrscr();
printf("Introduceti valoarile functiei: \n");
for (i=1;i<=10;i++) { scanf("%d", &a[i]); fwrite(&a[i],sizeof(a[i]),1,f); }
for (i=1;i<=10;i++) if (a[i]<0) a[i]=-10; else a[i]=10;
for (i=1;i<=10;i++) fwrite(&a[i],sizeof(a[i]),1,f1); fseek(f,0,0);fseek(f1,0,0); printf("\n");
for (i=1;i<=10;i++) { fread(&j,sizeof(j),1,f); printf("%d ",j); } printf("\n");
for (i=1;i<=10;i++) { fread(&j,sizeof(j),1,f1); printf("%d ",j); } printf("\n"); getch();}
4.16. Listingul programului:
#include <process.h>
#include <iostream.h>
#include <errno.h>
#include <time.h>
#include <stdio.h>
int main(int argc,char *argv[]) { clock_t start,end; FILE *fp; int j; char bb = 'f'; float var;
char aa[45]="The time that complies the program is : "; cout << "Command line arguments:\n\n";
for (int i = 0; i < argc; ++i) { cout << "Argument [" << i << "] : " << argv[i] << '\n'; }
cout << "Measuring the time that needs to comply program [" << argv[i-1] << ".cpp" << ']' << "\n\n";
for(j=0;j<argc;++j) { if((argv[j][0]=='-') && (argv[j][1]=='o')) { fp=fopen(argv[j+1],"w"); bb = 't'; }
if((argv[j][0]=='b') && (argv[j][1]=='c') && (argv[j][2]=='c')) argv=argv+j; }
start = clock(); int result = spawnvp(P_WAIT,"bcc",argv); end = clock(); var = (end - start) / CLK_TCK;
if (bb == 't') { fprintf(fp,"%s",aa); fprintf(fp,"%8.3f %s",var,"second(s)"); fclose(fp); }
if ((result != -1) && (bb != 't')) { cout << "The time that complies the program is : " << var << " second(s)" << '\n'; }
if (result == -1) { perror("execution error"); } return result; }
4.17. Vizualizaţi listingul programului, verificaţi corectitudinea, scopul şi organizaţi afişarea rezultatelor:
#include <process.h>
#include <iostream.h>
#include <errno.h>
#include <time.h>
#include <stdio.h>
int main(int argc,char *argv[])
{ clock_t start,end; FILE *fp; int j; char bb = 'f'; float var;
char aa[45]="The time that complies the program is : ";
cout << "Command line arguments:\n\n";
for (int i = 0; i < argc; ++i)
{ cout << "Argument [" << i << "] : " << argv[i] << '\n'; }
cout << "Measuring the time that needs to comply program [" << argv[i-1] << ".cpp" << ']' << "\n\n";
for(j=0;j<argc;++j)
{ if((argv[j][0]=='-') && (argv[j][1]=='o')) { fp=fopen(argv[j+1],"w"); bb = 't'; }
if((argv[j][0]=='b') && (argv[j][1]=='c') && (argv[j][2]=='c')) argv=argv+j; }
start = clock();
int result = spawnvp(P_WAIT,"bcc",argv);
end = clock();
var = (end - start) / CLK_TCK;
if (bb == 't') { fprintf(fp,"%s",aa); fprintf(fp,"%8.3f %s",var,"second(s)"); fclose(fp); }
if ((result != -1) && (bb != 't')) { cout << "The time that complies the program is : " << var << " second(s)" << '\n';}
if (result == -1) { perror("execution error"); } return result; }
4.18. Vizualizaţi listingul programului, verificaţi corectitudinea, scopul şi organizaţi afişarea rezultatelor:
#include<stdio.h>
#include<conio.h>
#include<dos.h>
#include<stdlib.h>
#define MAX 3
typedef struct { int zi; int luna; int an; } DATA;
typedef struct { unsigned char nume[30]; DATA dat; int sum;} CLIENT;
int nrzile(int a1,int a2,int a3) { int y,nr; nr=0;
for(y=1;y<a3;y++) if (y % 4==0) nr=nr+365; else nr=nr+364;
for(y=1;y<a2;y++); if (y%2==0) if (y!=2) nr=nr+30;
else nr=nr+28; else nr=nr+31; nr=nr+a1; return(nr); }
void main() { CLIENT bd[MAX]; int i,n1,n2,n3,dobanda; FILE *baza;
baza=fopen("date.dat","r"); fread( bd, sizeof( CLIENT ), MAX, baza ); fclose( baza );
printf(" Introduceti data curenta : "); scanf("%d-%d-%d",&n1,&n2,&n3);
printf("\n Introduceti dobanda : "); scanf("%d",&dobanda);
for (i=0;i<MAX;i++) { bd[i].sum=bd[i].sum+(nrzile(n1,n2,n3)-
nrzile(bd[i].dat.zi,bd[i].dat.luna,bd[i].dat.an))*dobanda; }
baza=fopen("date.dat","w"); fwrite( bd, sizeof( CLIENT ), MAX, baza ); fclose( baza );
4.19. Vizualizaţi listingul programului, verificaţi corectitudinea, scopul şi organizaţi afişarea rezultatelor:
# include <stdio.h>
# include <stdlib.h>
void main (void)
{ FILE *fp; float bal [10];
if ((fp=fopen (’’test’’, ’’rb’’)) = = NULL) { printf (’’Nu pot deschide fisierul.\n’’); exit (1); }
if (fread (bal,sizeof (float), 10, fp)!=10) { if (feof (fp)) printf (’’Sfarsit prematur fisier.’’);
else printf (’’Eroare de citire fisier.’’); } fclose (fp); }
4.20. Vizualizaţi listingul programului, verificaţi corectitudinea, scopul şi organizaţi afişarea rezultatelor:
#include<stdio.h>
#include<stdlib.h>
void main(int argc, char argv [])
{ FILE *f1, *f2; long pozitie ;
typedef unsigned char byte; byte octet;
/* verificarea argumentelor din linia de comanda */
if(argc != 3){ printf ("\nEroare. Numarul parametrilor incorect!"); exit (1); }
/* deschide fisier sursa in citire binara */
if((f1=fopen(argv[1], "rb")) == NULL ){ printf ("\n Eroare deschidere fisier sursa ih"); exit (1); }
/* deschide in scriere fisier destinatie */
if((f2=fopen(argv[2], "wb")) == NULL ){ printf ("\nEroare deschidere fis destinatie \n"); exit (1); }
/* pozitionare la sfarsitul fisierului sursa */
fseek(f1, OL, SEEK_END); pozitie = ftell(f1)-1;
/* copiere in ordine inversa */
while (pozitie>=OL){ fseek(f1, pozitie, SEEK_SET); fread (&octet, 1, 1, f1); fwrite( octet, 1, 1, f2); pozitie--; }
/* inchidem fisierele */
fclose(f1); fclose(f2);
}
4.21. Vizualizaţi listingul programului, verificaţi corectitudinea, scopul şi organizaţi afişarea rezultatelor:
#include <process.h>
#include <iostream.h>
#include <errno.h>
#include <time.h>
#include <stdio.h>
int main(int argc,char *argv[]) { clock_t start,end; FILE *fp; int j; char bb = 'f'; float var;
char aa[45]="The time that complies the program is : ";
cout << "Command line arguments:\n\n";
for (int i = 0; i < argc; ++i) { cout << "Argument [" << i << "] : " << argv[i] << '\n'; }
cout << "Measuring the time that needs to comply program [" << argv[i-1] << ".cpp" << ']' << "\n\n";
for(j=0;j<argc;++j) if((argv[j][0]=='-') && (argv[j][1]=='o')) { fp=fopen(argv[j+1],"w"); bb = 't'; } if((argv[j][0]=='b')
&& (argv[j][1]=='c') && (argv[j][2]=='c')) argv=argv+j; }
start = clock(); int result = spawnvp(P_WAIT,"bcc",argv); end = clock(); var = (end - start) / CLK_TCK;
if (bb == 't') { fprintf(fp,"%s",aa); fprintf(fp,"%8.3f %s",var,"second(s)"); fclose(fp); }
if ((result != -1) && (bb != 't')) { cout << "The time that complies the program is : " << var << " second(s)" << '\n'; }
if (result == -1) { perror("execution error"); } return result; }
4.22. /* Conditia problemei:Sa se alcatuiasca un program care sa formeze un fisier cu datele de baza despre carti:
-completarea initiala; -adaugarea inregistrarilor; -cautarea dupa denumirea cartii;*/
#include<stdio.h>
#include<conio.h>
#include<string.h>
#include<stdlib.h>
#define MAX 100
struct Tip_Carte { int Numar; /*Numarul de ordine*/
char Denumirea[30]; /*Denumirea cartii*/
char Familia[15]; /*Numele de familie a autorului*/
char Numele[10]; /*Numele autorului*/
char Locul_Ed[15]; /*Locul editiei*/
int Anul_Ed; /*Anul de editie*/
float Costul; /*Costul cartii*/
}Carte[MAX];
int ND; int meniu(void); void Introducere(void); void Incarcare(void); void Salvare(void); void Cautare(void);
void main(void) { int Alegerea; clrscr();
while(Alegerea!=5) { Alegerea=meniu();
switch(Alegerea) { case 1:Incarcare();break;
case 2:Introducere();break;
case 3:Cautare();break;
case 4:Salvare();break;
}
}
}
meniu(void) { int i; printf("\nAlegeti una din variantele propuse:\n");
printf("1.Incarcarea datelor de pe disc.\n");
printf("2.Introducerea datelor.\n");
printf("3.Cautarea cartii dupa denumire.\n");
printf("4.Salvarea datelor pe disc.\n");
printf("5.Iesire din program\n\n");
do { printf("Introduceti alegerea dumneavoastra: \n"); i=getche(); printf("\n"); } while((i<'1')||(i>'5'));
return i-'0'; }
void Incarcare(void) {
FILE *fp;
if((fp=fopen("Nicu.txt","r"))==NULL)
{ printf("Nu pot deschide fisierul la incarcare."); exit(1); }
ND=0;
while(!feof(fp)) { fscanf(fp,"%d%s%s%s%s%d%f",
Carte[ND].Numar,
Carte[ND].Denumirea,
Carte[ND].Familia,
Carte[ND].Numele,
Carte[ND].Locul_Ed,
Carte[ND].Anul_Ed,
Carte[ND].Costul);
ND++;
}
printf("Fisierul a fost incarcat de pe disc!\n"); fclose(fp); }
void Introducere(void) { char temp[100],a;
while(ND<MAX) { if(ND<MAX) { Carte[ND].Numar=ND+1;
printf("\rIntroduceti denumirea cartii: \n"); fflush(stdin);
gets(Carte[ND].Denumirea); printf("Introduceti numele de familie a autorului: \n");
gets(Carte[ND].Familia); printf("Introduceti numele autorului: \n");
gets(Carte[ND].Numele);
printf("Introduceti locul editiei cartii: \n"); gets(Carte[ND].Locul_Ed);
printf("Introduceti anul de editie a cartii: \n"); gets(temp);
Carte[ND].Anul_Ed=atoi(temp); printf("Introduceti costul cartii: \n"); gets(temp);
Carte[ND].Costul=atof(temp); printf("Doriti sa continuati? (y/n)\n"); a=getche();
if(a!='y') goto A1; ND++; } }
A1:; }
void Salvare(void) { FILE *fp; int i;
if((fp=fopen("Nicu.txt","w"))==NULL) { printf("Nu pot deschide fisierul la salvare."); exit(1); }
for(i=0;i<=ND;i++) { fprintf(fp,"%d %s %s %s %s %d %f\n",
Carte[i].Numar,
Carte[i].Denumirea,
Carte[i].Familia,
Carte[i].Numele,
Carte[i].Locul_Ed,
Carte[i].Anul_Ed,
Carte[i].Costul);
}
printf("\nFisierul a fost salvat pe disc!\n"); fclose(fp); }
void Cautare(void) { char nume[30]; int i,a=0;
printf("\nIntroduceti denumirea cartii pe care o cautati:\n"); fflush(stdin); gets(nume);
for(i=0;i<=ND;i++) if(!strcmp(nume,Carte[i].Denumirea)) {
printf("Cartea cautata este:\n%d.'%s',%s %s,%s,%d - %f lei\n",
Carte[i].Numar,
Carte[i].Denumirea,
Carte[i].Familia,
Carte[i].Numele,
Carte[i].Locul_Ed,
Carte[i].Anul_Ed,
Carte[i].Costul);
a++; }
if(a==0) printf("Nu dispunem de asa carte.\n"); }
Bibliografie:
1. ."Limbajul de programare C". Brian W.Kernighan. Dennis M.Ritchie.
2. Liviu Negrescu. ”Limbajul de programare C şi C++” V.1-4. Buc. 1999
3. Bacivarov, A.; Nastac, I. - "Limbajul C. Indrumar de laborator", Tipografia UPB, Bucuresti, 1997.
4. BibliogrШилдт, Герберт. Полный справочник по С, 4-е издание. : Пер. с англ. - М,: Издательский дом "Вильямс",
2002. - 704 с. : ил. - Парал.т ит. англ.
5. Павловская Т.А. С/C++. Программирование на языке высокого уровня. / Т.А. Павловская. - СПб.: Питер, 2002. -
464 с.: ил.
6. Культин Н.Б. C/C++ в задачах и примерах. - СПб.:БХВ-Петербург, 2001. - 288 с.: ил.
7. Першиков В.И., Савинков В.М. Толковый словарь по информатике.-М.: Финансы и статистика, 1991. - 543 с.