Sunteți pe pagina 1din 78

UNIVERSITATEA DE STAT DIN MOLDOVA

Eleonora Seiciuc

Lucia Bitcovschi

Programarea n limbajul C

Instruciunu metodice, probleme rezolvate, lucrri de laborator

Chiinu 2010
1

Cuprins
Introducere ......................................................................................................................................3 Lucrare de laborator N1..................................................................................................................4 Lucrare de laborator N2..................................................................................................................9 Lucrare de laborator N3................................................................................................................15 Lucrare de laborator N4................................................................................................................21 Lucrare de laborator N5................................................................................................................26 Lucrare de laborator N6................................................................................................................34 Lucrare de laborator N7................................................................................................................43 Lucrare de laborator N8................................................................................................................50 Lucrare de laborator N9................................................................................................................58 Lucrare de laborator N10..............................................................................................................67 Bibliografie...............................................................................................................................................................78

Introducere
Disciplina Fundamentele programrii se studiaz de studenii facultii Matematic i Informatic n semestrele 1 i 2 i prevede studierea limbajului de programare C. Broura dat se dorete a fi un supliment la manualele de C/C++ existente pe piaa lucrrilor de informatic. Ea este o culegere de lucrri de laborator, dar nu se limiteaz doar la asta. Fiecare lucrare de laborator este precedat de un set de sugestii i indicaii teoretice de lucru care au ca scop oferirea n mod succint a funciilor i instruciunilor limbajului referitor la tema lucrrii. La fel fiecare lucrare de laborator conine mai multe probleme rezolvate, fiind prezentate programele respective (cu explicaiile necesare), i un set de probleme propuse spre rezolvare. La fiecare lucrare sunt propuse i un ir de de ntrebri de control pentru testarea cunotinelor. Sunt propuse 10 lucrri de laborator: lucr. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Denumirea lucrrii Funcii de intrare/ieire, tipuri de baz. Operatori, operanzi, expresii i funcii matematice n limbajul C. Instruciuni ciclice. Pointeri i tablouri. Prelucrarea irurilor de caractere. Lucrul cu tablourile unidimensionale. Lucrul cu tablourile bidimensionale. Subprograme. Tipuri de date definite de utilizator, redenumirea tipurilor. Prelucrarea fiierelor. ore 6-8 4-6 6-8 6-8 4-6 4-6 4-6 6-8 6-8 4-6

Toate lucrrile de laborator i exemplele respective pot fi rulate pe un calculator PC, cu compilatorul Borland C++ 3.1. Astfel, majoritatea exemplelor din lucrare, chiar dac sunt scrise n limbajul C standard (deci neobiectual), folosesc un minim de faciliti aduse de limbajul C++, cum ar fi comentariile cu simbolurile // i declararea variabilelor simultan cu iniializarea lor, n cadrul unor instruciuni repetitive. Studenii efectueaz fiecare lucrare de laborator, o salveaz pe calculator i susin lucrarea. Susinerea lucrri se face, de regul, n mod practic la calculator prin prezentarea lucrrii i testarea asistat de calculator pe ntrebrile de control venite din partea profesorului.

Lucrare de laborator N1
Tema: Funcii de intrare/ieire, tipuri de baz. Scopul lucrrii: nsuirea funciilor de intrare/ieire, utilizarea lor la introducerea i extragerea datelor sub controlul unor formate i fr aceasta. Indicaii i sugestii de lucru: Funcia clrscr() terge ecranul. Are prototipul void clrscr(void) i se afl n fiierul <conio.h>. Funcia getch() citete fr ecou un caracter de la intrarea standard direct n memorie, fr acionarea tastei Enter. La citirea unui caracter ASCII funcia returneaz codul caracterului citit. La citirea unui caracter ne ASCII funcia se apeleaz de dou ori: la primul apel ea returneaz valoarea 0, iar la cel de al doilea apel ea returneaz o valoare specific tastei acionate. Are prototipul int getch(void), n fiierul <conio.h>. Funcia getche() citete cu ecou un caracter de la intrarea standard direct n memorie, fr acionarea tastei Enter. La citirea unui caracter ASCII funcia se apeleaz de dou ori: la primul apel ea returneaz valoarea 0, iar la cel de al doilea apel ea returneaz o valoare specific tastei acionate. Are prototipul int getche(void), n fiierul <conio.h>. Funcia putch(e) scrie un caracter la ieirea standard. Ea are un singur parametru. Funcia returneaz codul imaginei extrase, adic valoarea lui e. De exemplu, putch(\n), trece cursorul pe linia urmtoare n aceeai coloan. Funcia getchar() citete cu ecou caractere ASCII de la intrarea standard ntr-un tampon special pn la acionarea tastei Enter. La acionarea tastei Enter, ea returneaz codul caracterului curent din tampon. La urmtorul apel funcia returneaz codul caracterului urmtor din tampon. Dac n tampon nu mai sunt caractere, atunci apelul funciei impune citirea unui nou set de caractere de la intrarea standard n tampon. Prototipul este: int putchar(int c), n fiierul <stdio.h>. Funcia getc() citete din flux un caracter. Funcia gets() citete cu ecou un ir de caractere ASCII de la intrarea standard care se termin cu <Enter>. Ea are un parametru valoarea cruia este adresa de nceput a zonei de memorie unde se pstreaz irul de caractere citit. De obicei acest parametru este numele unui tablou unidimensional de tip char. La apsarea tastei Enter funcia nu scrie caracterul newline (\n) n memorie, ci caracterul NUL (\0), care semnific sfritul irului. Deci, \n se substitute prin \0. Fiecare caracter ocup un octet n memorie. Rezult c un ir de n caractere ocup n+1 octei. Funcia puts(s) scrie la ieirea standard un ir de caractere ASCII, care n memorie se termin cu caracterul NUL (\0), Ea are un parametru, valoarea cruia este adresa de nceput a irului de extras. De obicei, acest parametru este numele unui tablou unidimensional de tip char. La ntlnirea caracterului NUL, funcia nu scrie acest caracter, ci trece cursorul la nceputul liniei urmtoare, adic se substituie caracterul \0 prin \n. Funcia returneaz adresa de nceput a zonei de memorie unde se pstreaz irul citit, adic adresa primului caracter. Dac ntlnete caracterul EOF, funcia returneaz valoarea 0. Are prototipul n fiierul <stdio.h>. Funcia putchar(e) scrie un caracter ASCII la ieirea standard. Ea returneaz codul caracterului extras sau -1 n caz de eroare. Aici putchar(\n), ca i putchar(10), trece cursorul la nceputul liniei urmtoare. Funcia are prototipul int putchar(int e), n fiierul <stdio.h>. Funcia printf(c, p1, p2, p3, ...) scrie la ieirea standard date sub controlul unor formate. Are unul sau mai muli parametri. De obicei, parametrul c este un ir de caractere scris n 4

ghilimele, care conine textele eventuale de extras i specificatorii de format eventuali pentru datele de extras. Textele din parametrul c sunt extrase fr schimbare. Secvenele escape, cum ar fi \n, \t, \0 .a., nu sunt extrase ci sunt executate. Parametrii p1, p2, p3, ... sunt expresii, valorile crora vor fi extrase. La fiecare din aceti parametri, n irul de caractere c, i corespunde un specificator de format, care indic cum se va extrage valoarea respectiv. Un specificator de format ncepe cu % i se termin cu una sau dou litere anumite. El determin conversia valorii de extras din formatul intern n formatul extern. Parametrii p1, p2, p3, pot lipsi. Atunci vor fi extrase numai textele din parametrul c. Funcia returneaz numrul de octei (caracter) extrai la ieirea standard sau -1 n caz de eroare. Ea are prototipul n fiierul <stdio.h>. Funcia scanf(c, p1, p2, p3, ...) citete de la intrarea standard date sub controlul unor formate. Are mai muli parametri. De obicei, parametrul c este un ir de caractere scris n ghilimele, care conine specificatori de format pentru datele de la intrare. El poate conine i caractere albe care sunt neglijate. Parametrii p1, p2, p3, ... sunt adresele zonelor de memorie unde se vor pstra datele citite. De obicei, adresa unei zone de memorie se exprim prin operatorul & n faa numelui unei variabile simple sau cu indice. La fiecare dintre aceti parametri, n irul de caractere c, i corespunde un specificator de format, care indic cum se va citi data respectiv de la intrare. Un specificator de format ncepe cu % i se termin cu una sau dou litere anumite. El determin conversia datei de citit din formatul extern n formatul intern. Se cunosc urmtorii specificatori: %d, %i - ntreg, %f - real, %lf - real lung, %ld - ntreg lung, %u-ntreg fr semn, %c - citete caracterul curent, %s - citete irul, %e - real n format exponenial, %p - pointer. Funcia citete toate datele ce corespund specificatorilor de format din parametrul c. Dac o dat de la intrare nu corespunde specificatorului de format, atunci citirea se ntrerupe. Funcia returneaz numrul datelor citite corect. Ea are prototipul n fiierul <stdio.h>. Funcia fflush(stdin) golete stream-ul intrrii standard (terge coninutul buferului tastaturii). Ea are prototipul n fiierul <process.h>. Funcia exit(c) ntrerupe execuia programului. Parametrul c definete starea programului n momentul apelului funciei. De obicei, valoarea 0 a parametrului c definete o stare normal de terminare a execuiei programului, iar o valoare diferit de 0 semnific prezena unei erori. Se folosete pentru a termina execuia unui program. Funcia are prototipul n fiierul <stdlib.h> . sizeof este un operator care determin dimensiunea n octei a unei date sau a unui tip de date. De exemplu, sizeof(int) returneaz numrul de octei necesari pentru a pstra o valoare de tipul int, iar sizeof d returneaz numrul de octei alocai datei cu numele d.

Tipuri de date
ntregi reale s imple caracter enum erativ s tatice logic m asiv ir s tructurate m ulim e articol dinamice fi ier

Tipuri simple de date


Grupa Grupa de dat de dat Tipul Tipul [signed] char un signed char ntreg un signed [int] [short] [in t] un signed long long [int] float Real double long double Lungime Lungime (octe i ) (octe i ) 1 1 2 2 4 4 4 8 10 Domeniu de valori Domeniu de valori -128..127 (-27..27-1) 0..255 (0..28-1) 0..65535 -32768..32767 0..232-1 -231..231-1 3.4*10-38..3.4*1038 1.7*10-308.. 1.7*10308 3.4*10-4932.. 3.4*104932

Exemple de programe: Exemplul 1.1. Programul citete o liter minuscul i extrage caracterul precedent acestei litere din setul de caractere al calculatorului.
#include<conio.h> #include<stdio.h> void main(void) { char c; clrscr(); c=getchar(); putchar(c-1); getch(); }

Exemplul 1.2. Programul citete un ir de caractere i extrage lungimea irului citit.


#include<conio.h> #include<stdio.h> #include<string.h> void main(void) { char s[256]; clrscr(); gets(s); printf(irul are %d caractere,strlen(s)); getch(); }

Exemplul 1.3. Programul definete i citete 4 numere de la tastatur de tip int, float, long double, char i le afieaz la ecran.
#include<conio.h> #include<stdio.h> void main(void) { char c=a; int k=3; float f=5.9; double d=9.999; clrscr(); printf(%c\t%d\t%f\t%lf,c,k,f,d); getch();

Exemplul 1.4. Programul afieaz ntre dou caractere * constanta 123.456f (definit prin directiva #define) cu diferii specificatori de format pentru date de tip float.
#include<conio.h> #include<stdio.h> #define a 123.456f void main(void) { clrscr(); printf(*%f*\n,a); printf(*%2f*\n,a); printf(*%20f*\n,a); printf(*%-20f*\n,a); printf(*%020f*\n,a); printf(*%.2f*\n,a); printf(*%.10f*\n,a); printf(*%2.2f*\n,a); printf(*%2.10f*\n,a); printf(*%20.10f*\n,a); printf(*%-20.10f*\n,a); printf(*%020.10f*\n,a); getch(); }

Exemplul 1.5. Programul citete cu getch() caractere ne ASCII i apoi extrage codul fiecruia cu printf().
#include<conio.h> #include<stdio.h> void main(void) { char a; clrscr(); getch(); // primul apel printf("al doilea apel:%d\n",getch()); getch(); // primul apel a=getch(); // al doilea apel printf("al doilea apel:%d\n",a); getch(); // primul apel printf("al doilea apel:%d\n",a=getch()); getch(); }

Exemplul 1.6. Este dat numrul ntreg a. Folosind numai operaia de nmulire s se calculeze a8 prin trei operaii.
#include<conio.h> #include<stdio.h> void main(void) { int a,k,l,f; clrscr(); printf("introducei valoarea lui a); scanf(%d,&a); k=a*a; //a2 l=k*k; //a4 f=l*l; //a8 printf("rezultat=%d",f); getch(); }

Probleme propuse spre rezolvare: 1. Programul citete dou numere ntregi i afieaz media lor aritmetic.

2. Programul afieaz ntre dou caractere * constanta 123.456 (definit prin directiva #define) cu urmtorii specificatori de format: %f, %2f, %10f, %-10f, %010f, %.2f, %.10f, %2.2f. 3. Programul afieaz n zecimal, octal i hexazecimal constanta 123456789 definit prin directiva #define. 4. Programul citete un caracter ne ASCII (cu getchar()) i apoi afieaz (cu printf()) codul caracterului citit i caracterul. 5. Programul citete (cu scanf()) un numr ntreg zecimal format din cel mult nou cifre i apoi afieaz (cu printf()) numrul citit n zecimal, octal i hexazecimal. 6. Sunt date trei numere de tipul: int, float, double. Calculai suma lor, produsul i diferena lor i afiai rezultatele la ecran. 7. Programul citete (cu scanf()) o dat calendaristic sub forma ddmmyy (o succesiune de 6 cifre) i apoi o afieaz (cu printf()) sub forma 20yy/mm/dd. Aici dd, mm i yy sunt numere din dou cifre care reprezint respectiv ziua, luna i anul. 8. Programul citete (cu scanf()) numele i prenumele unei persoane separate prin spaii albe, apoi afieaz (cu printf()) numele pe un rnd i prenumele pe alt rnd. 9. Sunt date numere ntregi x i y. S se obin: x y .
1 + xy

10. Dat a ntreg. Folosind doar operaia de nmulire s se calculeze a2, a5, a17 prin ase operaii. 11. Dat a ntreg. Folosind doar operaia de nmulire s se calculeze a4, a12, a28 prin ase operaii. 12. S - au amestecat v1 litri de ap de temperatura t1 cu v2 litri de ap de temperatura t2. S se calculeze volumul i temperatura compoziiei obinute. 13. Sunt date x i y numere ntregi. S se gseasc media aritmetic i media geometric a modulului lor. 14. Este dat x ntreg. Folosind numai operaia de nmulire, adunare i scdere, s se calculeze expresia: 2x4-3x3+4x2-5x+6. Se permit nu mai mult de 4 operaii de nmulire, 4 operaii de adunare i scdere. 15. Sunt date lungimile catetelor triunghiului drept. S se gseasc ipotenuza i aria lui. 16. Sunt date numerele ntregi x i y. Folosind numai operaiile de nmulire, adunare i scdere, s se calculeze: 3x2y2-2xy2-7x2y-4y2+15xy+2x2-3x+10y+6. Se permite folosirea nu mai mult de opt operaii de nmulire, de adunare i scdere. 17. Programul citete (cu scanf()) o majuscul i apoi afieaz (cu printf()) minusculele corespunztoare. 18. Folosind operatorul sizeof afiai ct memorie se rezerv pentru fiecare tip de date (char, signed char, unsigned char, short, signed short, unsigned short, int, signed int, unsigned int, long int, long signed int, long unsiged int, float, double, long double). ntrebri de control: 1. 2. 3. 4. 5. 6. 7. 8. 9. Cum se lanseaz un program la execuie n Turbo C++ ? n care fiiere se afl prototipurile funciilor standard ? Cum se afieaz Help-ul pentru o funcie standard, de exemplu clrscr() ? Care sunt deosebirile dintre funciile getche() i getchar() ? Ce valori returneaz funciile de intrare ? Ce valori returneaz funciile de ieire ? Cum i pentru ce se utilizeaz funcia exit() ? Care sunt funciile de citire cu ecou ? Care funcii de intrare cer acionarea tastei Enter ?

10. char a; unsigned char b; a=200; b=200; printf(ntreg %d\t caracter %c,a, a); printf(\n ntreg %d\t caracter %c,b, b);

Ce se va extrage la ecran? Explicai. 8

Lucrare de laborator N2
Tema: Operatori, operanzi, expresii i funcii matematice n limbajul C. Scopul lucrrii: .Utilizarea corect a operatorilor, alctuirea corect a expresiilor cu respectarea regulilor de conversie implicit i conversia forat a datelor. Suport teoretic: O expresie este o secven de caractere care specific o regul pentru calculul unei valori. Aceast valoare poate fi: numeric, alfanumeric, boolean sau de tip structurat. Trebuie s v mrturisim c acum a sosit momentul s definim acest termen mult mai precis. O expresie poate fi foarte simpl. Cifra 7 singura (o constant) i litera M (o variabila) sunt expresii valide. Dar, o expresie poate fi de asemenea foarte complicat. Observai membrul drept al enunului de mai jos: m:=7*a+b*(j+sqrt(x)) unde: 7, a, j si x sunt toate expresii; 7*a este o expresie; Funcia sqrt(x) este o expresie; j+sqrt(x), cu sau fr paranteze exterioare, este o expresie; Tot membrul drept este o expresie. O expresie are sens, n timpul compilrii, dac toate elementele componente au fost n prealabil declarate i au fost respectate regulile de sintax a limbajului. O expresie se calculeaz n timpul execuiei dac, dup momentul cnd s-a ajuns la codul obiect, tuturor identificatorilor li s-au atribuit valori (specifice) care permit s fie evaluai. Fiecare din cei trei operatori (+,-, | |) care pot fi folosii pentru conectarea termenilor unor expresii simple se numesc operatori de adugare (adding operators). Fiecare din cei patru operatori (*, /, % i &&) care pot fi folosii pentru conectarea factorilor se numesc operatori de multiplicare (multiplying operator). Pentru micarea biilor spre stnga i spre dreapta, se folosesc operaiile << i >>. Deoarece biii sunt mutai ctre un capt, la cellalt capt se adaug zerouri. (n cazul unui ntreg negativ cu semn o deplasare la dreapta va determina introducerea unui 1, astfel nct bitul de semn se va pstra.) Biii deplasai dincolo de capt nu se ntorc la captul cellalt, ci sunt pierdui. Operaiile de deplasare a biilor pot fi foarte utile atunci cnd decodificai intrarea de la un dispozitiv extern. O deplasare la dreapta mparte efectiv un numr cu 2, iar o deplasare la stnga l nmulete cu 2. Funciile matematice: pow(x,y), poly(x, n, c[]), sin(x), sqrt(x), cos(x), exp(x), log(x), log10(x), asin(x), acos(x), atan(x) au prototipul n fiierul <math.h>. Toate funciile trigonometrice presupun argumentul exprimat n radiani. Pentru a transforma gradele n radiani se nmulesc gradele cu / 180 , unde constanta = 3.14 .
Tabela 2.1: Funcii matematice din fiierul math.h
Prototipul funciei double acos(double x); double asin(double x); double atan(double x); double atan2(double y, double x); Efect arccosinus de x arcsinus de x arctangenta de x arctangenta de y/x

double ceil(double x); double cos(double x); double exp(double x); double fabs(double x); double floor(double x); double log(double x); double log10(double x); double pow(double x, double y); double sin(double x); double sqrt(double x); double tan(double x); double poly(x, n, c[])

cel mai mic intreg mai mare sau egal cu x cosinus de x exponeniala valoarea absoluta a lui x cel mai mare intreg mai mic sau egal cu x ln de x lg de x x la puterea y calculeaz valoarea funciei sinus de unghiul x exprimat n radiani. radicalul lui x tangenta lui x calculeaz valoarea polinomului p=cnxn+cn-1xn-1+...+c2x2+c1x+c0

Media geometric a numerelor a1, a2,...,an este (a1*a2*...*an)(1/n).


Tabela 2.2: Operatori i descrierea lor.
Operatorul < <= > >= != == && ! || ~ << >> ^ += ++ -/ %= ?: Descrierea mai mic mai mic i egal mai mare mai mare i egal diferit egal a&&b are valoarea 1, atunci i numai atunci, cnd i a i b au valori diferite de 0. negarea logic, !a are valoarea 0 (false), dac a are valoarea diferit de 0 i 1 (true), dac a are valoarea 0. sau complement fa de 1 deplasare la stnga deplasare la dreapta sau logic pe bii suma cu atribuire increment decrementul mprire restul mpririi egal condiie

10

Tabela 2.3: Codurile ASCII.


0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 Ctrl | Ctrl A Ctrl B Ctrl C Ctrl D Ctrl E Ctrl F Ctrl G Ctrl H Ctrl I \n Ctrl K Ctrl L Return Ctrl N Ctrl O Ctrl P Ctrl Q Ctrl R Ctrl S Ctrl T Ctrl U Ctrl V Ctrl W Ctrl X 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 . / 0 1 Ctrl Y Ctrl Z ESCAPE Ctrl < Ctrl / Ctrl = Ctrl BLANK ! " # $ % & ' ( ) * + , 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 92 97 98 99 100 101 102 103 104 K L M N O P Q R S T U V W X Y Z \ a b c d e f g h 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 I J K L M n o p q r s t u v w x y z { | } ~

Exemple de programe: Exemplul 2.1. Sunt date 2 variabile de tip real. S se efectueze operaiile suma, produs i mprire.
#include<stdio.h> #include<conio.h> void main() { float k,l; clrscr(); printf("dati k si l:"); scanf("%f%f",&k,&l); printf("suma=%.2f",k+l); printf("\nimpartirea=%.2f",k/l); printf("\nprodus=%.2f",k*l); getch();}

11

Exemplul 2.2. Este dat un numr ntreg. Programul verific dac numrul introdus este pozitiv, negativ sau zero.
#include <stdio.h> void main() { int nr; printf("Numar="); scanf("%d",&nr); (nr<0)?printf("negativ\n"):((nr>0)?printf("pozitiv\n") : printf("zero\n")); }

Exemplul 2.3. Programul citete dou numere ntregi i testeaz operatorii >> i <<. Tastai programul pentru: x=1, u=4; x=2, u=8; x=3, u=5; x=-1, u=-1; x=-5, u=-5.
#include<stdio.h> #include<conio.h> void main() { long x,y; int u,v; clrscr(); printf("dati x,u:"); scanf("%ld%d",&x,&u); //deplasare la stnga a lui u, nseamn nmulirea lui cu 2 v=u<<2; printf("\nu=%d\t%d<<2=%d\n",u,u,v); //deplasare la dreapta a lui x, nseamn mprirea lui cu 2 y=x>>2; printf("\nx=%ld\t%ld>>2=%ld\n",x,x,y); getch(); }

Exemplul 2.4. Programul determine maximul i minimul dintre dou numere ntregi date.
#define max(x,y) x>y?x:y #define min(x,y) x<y?x:y #include <stdio.h> void main() { int x,y; printf(dai x i y); scanf(%d%d,&x,&y); printf(maximul=%d,max(x,y)); printf(\nminimul=%d,min(x,y)); getch(); }

Exemplul 2.5. S se determine aria unui triunghi n funcie de lungimile laturilor sale.
#include<stdio.h> #include<conio.h> #include<math.h> void main() { float a,b,c,p,aria; printf(Dai lungimile laturilor:\n); scanf(%f%f%f,&a,&b,&c); p=(a+b+c)/2; aria=sqrt(p*(p-a)*(p-b)*(p-c)); printf(Aria este: %7.3f,aria); getch(); }

Exemplul 2.5. Este dat n ntreg. S se afle ultima cifr a lui n.


#include<stdio.h> #include<conio.h> void main() { int n,c;

12

clrscr(); printf("n="); scanf("%d",&n); n=n%10; printf("c=%d",c); getch(); }

Probleme propuse spre rezolvare: 1. S se calculeze puterea a n-a a lui 2, unde n este un ntreg dat de la tastatur, folosind operatorul de deplasare la stnga. 2. S se gseasc lungimea dintre dou puncte cu coordonatele x1, y1 i x2, y2. 3. Fie a, b, c trei numere reale. S se verifice dac a, b pot reprezenta lungimile laturilor unui dreptunghi, respectiv c s fie diagonala n acel dreptunghi. 4. Sunt date a, b, c numere ntregi. S se verifice, dac se execut expresia: a < b < c. 5. Sunt date x, y, z. S se calculeze: a. max(x, y, z); b. max(x+y+z, xyz); c. min2(x+y+z/2, xyz)+1. 6. Sunt date c,d. S se calculeze:
2 sin 2 cx13 + dx2 cd

(cx + dx x1 ) + 3.14

3 1

2 2

2 + tg (cx13 + dx2 x1 ) , unde x1- rdcina

mare, iar x2 - rdcina mic a ecuaiei x 2 3x cd = 0. 7. Sunt date a, b. S se calculeze s: a. s =


2a(a + 2b + a 2 + 4ab) a + (a + 4ab )(a + 4b + a + 4ab)
2 2 2
2 2

b b 2 + 1/ b

1 1 b. s = (ab + 1) 1

c.

a3b3 1 a3b3 + 1 ; / 1 1 ab a b a b + ab + 1 ab + a 1b 1 a + a 3 / 4b1 / 2 + a1 / 4b3 / 2 + b 2 4 3 b (a1 / 2 b) 1 / 3 4 s=( ( a ) + b ) + 1 / 4 1 / 4 ) /( a + b ) 1; a1 / 2 + 2a1 / 4b1 / 2 + b a (a b )


ba + a a b a 2b 2 b2 9

3 4 3 23 2 d. s = (3 b2 + a3 b + a 2 ) b a + a b ba + 2b + 2 b 9 ; 1 4 1 2

2b 5/3 5/ 4 3/ 4 2/ 3 2 e. s = (a b 6a b +12ab a2 8ab ) . 3/ 4 /3 3

ab a 4ab

+ 4a

8. Sunt date x, y. S se calculeze a, b, dac: a. a = x 1 3 y , b = x(arctgz + e ( x + 3) ) ; 2 2


1+ x y + 2 4

b. a =

( y x) 2 y x ; 3 + e y 1 , b =1+ y x + + 2 3 1 + x 2 y tgz
x y2 + x2 y + x3 / 3

c. a = y +

z , b = (1 + tg 2 ) ; 2

2 5 y , b= x x + x ; 2 z + x /4 3! 5! 2 + e. a = (1 + y) xx 2 y /( x + 4) , b = 1 + cos( y 22) ; x 4 / 2 + sin z e + 1/( x 2 + 4) 2 f. a = 2 cos( x 2 / 6) , b = 1 + z 2 ; 3+ z /5 1/ 2 + sin y

d. a = ln ( y x )( x

13

g. a =

1 1 + sin 2 ( x + y ) 2 + x , b = cos (arctg ) ; 2 2 z 2 + x 2 x /(1 + x y )

2 2 1 3 3 h. a = ( ( y + 2 xy )(2 y + 4 x y ) (2 x)1 / 3 ) 6 , b = 3 y 3 2x

x+ y x y x y x + y y xy + x ; x y x+ y 2 xy + x+ y x y

ntrebri de control: 1. Ce este o expresie, un operand, un operator. Ce operatori cunoatei? 2. Explicai cum se utilizeaz operatorul adres & ? 3. Explicai cum se utilizeaz operatorul condiionat ? :. 4. Ce specificatori de format se folosesc pentru a citi i a scrie date numerice flotante de tipul long double? 5. Fie int x=2, y; y=--x; x=y--; Care este valoarea lui x? 6. Fie int x=2, y; y=x++; x=++y; Care este valoarea lui x? 7. Fie char c; c=R+m-M; Care este tipul valorii lui c i ce va afia printf(%d,c)? 8. Explicai cum lucreaz funciile abs(), log10(), pow(x, z) i dai exemple? 9. Care sunt specificatorii pentru tipurile: int, float, char, double i care este diapazonul acestor tipuri? 10.Fie int x=1, y=2, n=3, m=4; n=x/y; m=x%y; Care sunt valorile lui n i m?

14

Lucrare de laborator N3
Tema: Instruciuni ciclice. Scopul lucrrii: nsuirea instruciunilor limbajului. Suport teoretic: Instruciunea compus este un bloc de instruciuni cu formatul:{declaraii; instruciuni;}. La nceputul blocului prin declaraii se pot defini i iniializa date de diferite tipuri. Prin instruciuni se realizeaz prelucrarea datelor. Instruciunea if este o instruciune de ramificare. Ea are dou formate: incomplet i complet. Formatul incomplete este: if (expresie) instruciune1. La ntlnirea acestei instruciuni se evalueaz expresia din paranteze. Dac expresia are valoarea adevr, adic o valoare diferit de 0, atunci se execut instruciune1 i apoi se trece la instruciunea imediat urmtoare dup instruciunea if. n caz contrar, se trece imediat la instruciunea urmtoare. Deci forma general a instruciunii if este: if (expresie) instruciune1; else instruciune2; Se evalueaz expresia din parantez i n caz de adevr se execut instruciune1, altfel se execut instruciune2. Dup aceasta se trece la instruciunea urmtoare dup if. Instruciunile instruciune1 i instruciune2 pot fi simple i compuse. Instruciunile if pot fi incluse una n alta. Instruciunea for este o instruciune de ciclu condiionat i are formatul: for(i1; i2; i3) instruciune; Aici i1, i2, i3 sunt expresii: i1 este expresia de iniializare a ciclului, i2 este expresia care determin condiia de repetare a ciclului, i3 este expresia de reiniializare a ciclului; instruciune este corpul ciclului i poate fi o instruciune simpl sau compus. Corpul ciclului sunt acele instruciuni de prelucrare a datelor care trebuie repetate. i corpul ciclului poate lipsi. n acest caz ciclul const numai din antet i instruciunea vid: for(i1; i2; i3); Instruciunea for se execut n felul urmtor: se efectueaz operaiile de iniializare ale ciclului i1, apoi se evalueaz expresia i2. Dac i2 are o valoare diferit de 0, adic valoarea adevr, atunci se execut instruciune corpul ciclului. n caz contrar, cnd i2 are valoarea 0, adic valoarea fals, se termin execuia ciclului for i se trece la instruciunea urmtoare dup ciclu. Dup execuia corpului, ciclul se reiniializeaz se execut operaiile definite de i3 i se revine iari la verificarea condiiei de repetare a ciclului i2. Instruciunea while este o instruciune de ciclul condiionat i are formatul: while(i1) instruciune; antetul ciclului este while(i1) i conine n paranteze expresia i1 care este condiia de repetare a ciclului. Corpul ciclului este instruciune i poate fi o instruciune simpl sau compus. Ea conine acele operaii care trebuie repetate n ciclu. Corpul ciclului poate lipsi. Se evalueaz i1 i corpul ciclului se execut de attea ori de cte ori i1 are valoarea adevr. Instruciunea do-while se execut astfel: mai nti se execut instruciune, adic corpul ciclului, apoi se evalueaz i1, care este condiia de repetare a ciclului. Dac i1 este adevr, atunci se repet execuia corpului ciclului. n caz contrar, adic dac i1 este 0, atunci se termin execuia ciclului i se trece la instruciunea urmtoare dup ciclu. Instruciunea continue se folosete n corpul unui ciclu i are formatul: continue; Instruciunea dat abandoneaz iteraia curent a ciclului i trece la iteraia urmtoare a lui. Instruciunea break se folosete numai n corpul unui ciclu sau n instruciunea switch. La ntlnirea instruciunii break n corpul unui ciclu se termin execuia ciclului i se trece la instruciunea urmtoare dup ciclu. La folosirea instruciunii break n instruciunea switch se iese din instruciunea switch i se trece la instruciunea urmtoare dup switch. Instruciunea switch este o instruciune care realizeaz o alternativ din mai multe alternative posibile i are formatul: 15

switch (expresie) { case valoare1: instructiune1; break; case valoare2: instructiune2; break; case valoaren: instructiunen; break; default: instructiune; } In limba engleza, switch nseamn comutator. Conform acestei forme generale, dup cuvntul cheie switch, exist o expresie de tip int sau compatibil cu aceasta (deci poate fi i de tip char, byte sau short, dar nu de tip long), a crei valoare servete drept

comutator. Se deschide apoi acolada corpului instruciunii, n care exist mai multe cazuri. Fiecare caz ncepe prin cuvntul cheie case, urmat de o valoare de tip ntreg, dup care apar una sau mai multe instruciuni (simple sau compuse) i opional intruciunea break. Dup ce sau epuizat toate cazurile, opional se poate scrie cuvntul cheie default urmat de una sau mai multe instruciuni i se nchide acolada corpului instruciunii switch. Executarea instruciunii switch decurge astfel: se evalueaz mai nti expresie i se obine o valoare, care servete drept comutator. Aceast valoare se compar, de sus n jos, cu fiecare din valorile indicate dup cuvintele cheie case, pn cnd se gsete prima valoare care coincide cu cea a comutatorului. Dac s-a gsit o astfel de valoare, se execut toate instruciunile care ncep cu cazul respectiv i se ncheie la prima instruciune break ntlnit sau, n lipsa acesteia, pn la acolad de nchidere a corpului instruciunii switch. dac ns nici unul din cazuri nu conine valoarea potrivit a comutatorului, atunci se execut instruciunile care urmeaz dup cuvntul cheie default sau, n lipsa acestuia, nu se execut nimic. Instruciunele case i default se folosesc numai n instruciunea switch. Instruciunea goto este o instruciune de salt necondiionat. Ea are formatul goto nume, unde nume este numele unei etichete. Eticheta este un identificator (un nume) care se scrie n faa unei instruciuni cu simbolul : dup el. De exemplu lab1: i++; Aici numele lab1 este o etichet. La ntlnirea instruciunii goto lab1; se trece imediat la execuia instruciunii cu eticheta lab1 n fa, adic la instruciunea i++. Instruciunea return se folosete pentru a reveni dintr-o funcie. Ea are formatul return; sau return expresie; n primul caz, funcia din care se revine nu returneaz nici o valoare. Al doilea caz se folosete cnd funcia returneaz o valoare i anume valoarea expresie definete valoarea de returnat. Tipul valorii pentru expresie trebuie s coincid cu tipul indicat n antetul funciei respective pentru valoarea returnat. Instruciunea return poate fi scris n orice punct al corpului unei funcii, ns nu este obligatorie. n corpul aceleai funcii pot fi scrise mai multe instruciuni return. Exemple de programe: Exemplul 3.1. Este dat n ntreg. S se afle prima cifra a lui n (n=123, prima cifr este 1).
#include<stdio.h> #include<conio.h> void main() { int n,c; clrscr(); printf("n="); scanf("%d",&n); //ct n este mai mare ca 9 se face mprirea lui n la 10, pn se ajunge la prima cifr while(n>9) n=n/10; printf("prima cifra este=%d",n); getch(); }

Exemplul 3.2.Este dat n ntreg. S se numere din cte cifre este compus n (n=345, c=3).
#include<stdio.h> #include<conio.h>

16

void main() { int n,c; //c este un contor, iniial are valoarea zero c=0; clrscr(); printf("n="); scanf("%d",&n); //att ct n este mai mare ca zero, n se mparte la zece i c crete while(n>0){ n=n/10; c=c+1; } printf("c=%d",c); getch(); }

Exemplul 3.3. Date a, b dou numere ntregi. S se afle cel mai mic multiplu comun al lor.
#include<stdio.h> #include<conio.h> void main() { int i,min,a,b,div; float mult; clrscr(); printf("a, b"); scanf("%d%d",&a,&b); if(a<b) min=a; else min=b; //mai nti gsim minimul dintre a i b //parcurgem ciclul pn la minim for(i=1;i<=min;i++) //gsim cel mai mare divizor comun a lui a i b if((a%i==0)&&(b%i==0)) div=i; //calculm multiplu comun mult=(a*b)/(float)div; //float n faa lui div-pentru conversie de tip printf("multiplu comun a 2 numere=%.2f", mult); getch(); }

Exemplul 3.4. S se calculeze expresia: produs = (1 + 1 )(1 + 12 )(1 + 12 )...(1 + 12 ) . 2


#include<stdio.h> #include<conio.h> void main() { int i,n; float produs; clrscr(); printf("n="); scanf("%d",&n); //notm iniial produsul cu valoarea 1 produs=1; for(i=1;i<n;i++) produs=produs*(1+(1/(float)(i*i))); printf("produs=%.2f",s); getch(); }

Exemplul 3.5. Este dat numrul n . S se verifice dac n este numr prim sau nu(numr prim se mparte la 1 i la el nsi (1, 2, 3, 5, 7, 11 etc.)).
#include<stdio.h> #include<conio.h> void main() { int i,n,prime; prime=1; clrscr(); printf("n="); scanf("%d",&n); //parcurgem ciclul de la 2 pn la jumtatea lui n

17

for(i=2; i<n/2; i++) if(n%i==0) prime=0; //dac n are divizori atunci if(prime==1) printf(n este numr prim); else printf(n nu este numr prim); getch(); }

Exemplul 3.6. Folosind instruciunea case i do while calculm: a. Este dat numrul n s se verifice dac este numr perfect(suma divizorilor este egal cu el nsi 6=1+2+3); b. S se calculeze expresia: 1i (i + 1) / i!;
i =1 n

c. S se calculeze expresia: s = 1 + x +

#include<stdio.h> #include<conio.h> #include<math.h> void main() { int i,n,f,s1,s2,x,y,n1; float s=0,s3,e; char c; clrscr(); s1=s2=0; s=0; x=y=1; f=1; printf("n="); scanf("%d",&n); do{ printf("\n1:se verifica daca este perfect"); printf("\n2:sa se calculeze expresia din punctual b"); printf("\n3:sa se calculeze suma din punctual c"); printf("\n4:esirea\n"); c=getch(); //ateapta alegerea unei operaii switch(c){ //c primete una din valorile (1- 4) case '1': for(i=1; i<n; i++){ // aflm divizorii lui n i calculm suma lor if(n%i==0) s1=s1+i;} if(s1==n) printf("numar perfect"); else printf("nu este numar perfect");break; case '2': for(i=1; i<n; i++) { f=f*i; //calculm factorialul s=s+(pow(-1,i)*(i+1))/f; } printf("factorial=%d\tsuma=%f\n",f,s); break; case '3': printf("dati x"); scanf("%d",&x); e=0,0001; s3=1; n1=1; y=x; while(abs(y)>e) { n1=n1+1; s3=s3+y; y=y*(float)(x/n1); } printf("\ns=%f\tn=%d\n",s3,n1); printf("\ny=%d\n",y); break; }} while(c!='4'); //ciclul lucreaz att timp pn[ c va primi valoarea 4 getch(); }

x 2 x3 xn + + + , e = 0.0001 , x / n! > e . 2! 3! n!

Exemplul 3.7. S se afieze toate numerele prime din intervalul [2;50].


#include<stdio.h> #include<conio.h> void main(){

18

int i,j; int prim=0; // for(i=2; i<50; i++) { for(j=2; j<i; j++) {// dac restul mpririi nu e zero, atunci are loc instruciunea //de continue, n caz contrar se trece la else if(i%j) continue; else { prim=1; break; //dac s-a gsit un numr prim se iese din ciclu } } if(!prim) printf("%3d",i); prim=0; } getch(); }

Probleme propuse spre rezolvare: 1. Este dat x numr ntreg. S se calculeze f(x): a. b.
x 2 , daca 2 x < 2, f ( x) = 4, in caz contrar;

c. 2. 3. 4. 5.

Programul citete valorile a, b, c de tip long, rezolv ecuaia ax2+bx+c=0 i afieaz rezultatul. Programul citete un numr ntreg din segmentul [1;7] i afieaz denumirea zilei din sptmn ce corespunde acestei cifre (1 luni, 2 mari,, 7 - duminic). Un numr natural n se numete perfect daca este egal cu suma divizorilor si naturali mai mici ca n. Sa se determine toate numerele perfecte pn la un numr dat. Pentru n i x numere ntregi date s se calculeze: a. b. c.

x 2 + 4 x + 5, x 2, f ( x) = 1 x 2 + 4 x + 5 , in ca z contrar; 0, x 0, 2 f ( x) = x x, 0 < x 1, x 2 sin x 2 , in caz contrar.

i! ;
i =1
n

xi

d.
x );

(1)i (i + 1) ; i! i =1
n

g. h.

(1)i (i 1) / 2 ; i! i =1
n
2i + x

1 ( i! + i =1
n

e. f.

(1 +
i =1

sin( ix) ; ) i!

1 x i!( x + i)! 2 i =1
[lg1]

;
[lg n]

6. 7.

(1) (1) (1) (1 x)i +1 + 1 ; i. . + + ... + ((i 1)!+1)2 1 2 n i =1 n Pentru n dat s se calculeze: xi , x1 = y1 = 1, xi = 0,3xi 1 , yi = xi 1 + yi 1 , i = 2,3,... i =1 1 + yi
x + cos(ix) 2i i =1
n

[lg 2 ]

Pentru a1 = b1 = 1; ak = 3bk 1 + 2ak 1; bk = 2ak 1 + bk 1; k = 2,3,... ; n dat, s se calculeze:


2k (1 + a 2 + b2 )k!. k =1 k k
n

8.

2 Pentru a1 = u; b1 = v; ak = 2bk 1 + ak 1; bk = 2ak 1 + bk 1 , k = 2,3,... Sunt date u, v, s se

calculeze: 9.

ak bk (k + 1)!. k =1
n

Sa se afle toate numerele ntregi pozitive formate din 3 cifre, egale cu media aritmetica a numerelor obinute din fiecare din aceste numere n urma efecturii tuturor permutrilor (inclusiv cea identica) din cifrele sale. 19

10. 11. 12. 13.

14. 15. 16. 17. 18. 19.

20.

Sa se scrie un program care s calculeze cel de-al n-lea numr al irului lui Fibonacci (Astfel, fiecare numr Fibonacci este suma celor dou numere Fibonacci anterioare, rezultnd secvena 0, 1, 1, 2, 3, 5, 8, 13,...). Sunt date a, b numere ntregi. S se determine toate numerele prime din intervalul [a, b]. Pentru un numr n dat s se determine dac n este numr polindrom (numr polindrom 6789876). Programul citete un numr pozitiv s cu cel mult dou cifre dup virgul care exprim o sum de bani n lei, determin i afieaz numrul minim de bancnote de 500, 200, 100, 50, 20, 10, 5,1 lei i monede de 50, 25, 10, 5, 1 bani necesare pentru a exprima suma s. Folosii instruciunea do-while. Sunt date a, b numere ntregi. S se afieze toate numerele perfecte din intervalul [a,b]. Pentru n ntreg dat s se gseasc toate perechile gemene mai mici ca n. Pereche gemene sunt numerele prime cu diferena 2(5 i 7, 11 i 13, 29 i 31 etc.). Pentru n ntreg dat. S se gseasc perechea maxim de numere gemene mai mici ca n. Scriei un program care determin numrul de zerouri n n! (n<=100). n!=1*2*3**(n1)*n. Numrul n este introdus de la tastatur. Exemplu: 12. Rezultat: 4. Din cifrele a dou numere naturale de alctuit cel mai mare numr, pstrnd ordinea iniial a cifrelor din numerele date. De la tastatur se introduc dou numere. Exemplu: 23 91662. Rezultat: 9231662. Numerele de la 1 la N sunt aezate n ordine cresctoare pe circumferina unui cerc astfel c N ajunge situate lng 1. ncepnd cu numrul S se marcheaz numerele din K n K, n ordine cresctoare a lor, pn cnd un numr este marcat de 2 ori. Cte numere au rmas ne marcate? Numerele N, S i K se citesc de la tastatur. S se afieze la ecran numerele n ordinea de marcare i numrul de valori, ce au rmas ne marcate. Exemplu: N=8, S=2, K=5. Rezultat: 2 7 4 1 6 3 8 5 2; 0. Se citesc cele N cifre ale unui numr natural, N dat, n ordine descresctoare a rangurilor. Pentru K dat, s se gseasc cel mai mare numr care rmne dup tergere a K cifre, pstrnd ordinea dat a cifrelor (N, K <255). Exemplu: N=12; K=7; 682395892161. Rezultat: 99261.

ntrebri de control: 1. Ce este o instruciune compus? 2. Care este formatul instruciunii if ? Explicai cum lucreaz, dai exemplu. 3. Care este formatul ciclului for, care este antetul i corpul ciclului? Explicai cum lucreaz, dai exemplu. 4. Care este deosebirea dintre ciclurile for, while i do-while? 5. Care este formatul instruciunii switch? Explicai cum lucreaz aceast instruciune. 6. Unde i cum se folosesc instruciunile continue i break? 7. De cte ori se vor executa ciclurile: for(;;); for(;;) continue; for (;;) break? Explicai. 8. De cte ori se vor executa ciclurile: do {;} while (3.14); do {continue;} while(-1); do {break;} while(0); do {continue;} while(0); do {break;} while(1); Explicai. 9. Fie char h; h=getch(); puts(ati introdus);
switch(h) { default: puts(greit); case 1: printf(%d\n,1); case 2: printf(%d\n,2); case 3: printf(%d\n,3); case 4: printf(%d\n,4); }

Ce se extrage la ecran? Explicai. 10. Fie long double w; printf(\nw=); while(scanf(%lf,&w)!=1) { clrscr();
printf(Greit! Repetai introducerea\n); printf(\nw=);}

De cte ori se va executa ciclul? Explicai. 20

Lucrare de laborator N4
Tema: Pointeri i tablouri. Scopul lucrrii: obinerea deprinderilor practice la utilizarea pointerilor, nsuiri aritmeticii pointerilor n limbajul C i a legturii dintre pointeri i tablouri. Suport teoretic: Un pointer este o variabil valorile creia sunt adrese de memorie. Pe adresele-valori ale unui pointer se pot pstra date de un anumit tip. Acest tip se indic n declaraia variabilei de tip pointer i se numete tipul de baz al pointerului sau tipul spre care pointeaz pointerul. Declaraia de pointer are formatul: tip *id1, *id2,_, *idn, unde tip este un tip de date care arat ce tip de date se vor pstra pe adresele-valori ale variabilelor id1, id2,_,idn. De exemplu: int *pi, i; Aici i este o variabil simpl de tip int, iar pi este un pointer ce indic spre tipul int, adic n pi se vor pstra adrese ale datelor de tip int. La fel char *c; c este pointer la un obiect de tipul char. Se pot declara i tablouri de pointeri: char *s[80]. Alocarea memoriei pentru pointeri. Unui pointer i se aloc, de obicei, un cuvnt al calculatorului, adic 2 octei. ns modificatorii near, far, huge pentru tipul pointer modific modul de alocare a pointerilor n memorie. Modificatorii far i huge aloc 2 cuvinte, adic 4 octei de memorie pentru pointeri, iar near sau lipsa oricrui modificator semnific alocarea pointerului pe un cuvnt, adic pe 2 octei de memorie. Operatori specifici pentru pointeri: * - se utilizeaz pentru accesul la coninutul variabilei adresate; & - se utilizeaz pentru aflarea adresei variabilei. Pentru tiprirea adreselor se folosete specificatorul de format %p. Pentru a atribui pointerului pi adresa variabilei i scriem pi=&i. Dac pi este un pointer, atunci *pi este data stocat pe adresa-valoare a lui pi. De exemplu, fie i=10 i pi=&i. Atunci pi are ca valoare adresa lui i, iar *pi este chiar valoarea 10 a lui i. La declaraie pointerii se pot iniializa: float w, *y=&w; sau char *pc=Informatica; Aici pc este un pointer de tipul char * i lui i se atribuie ca valoare adresa de nceput a irului de caractere Informatica, adic adresa primului caracter din ir. Se pot declara pointeri de tipul void *, adic pointeri la care nu se indic tipul de baz. n acest caz nu se tie n prealabil tipul datelor ce se vor pstra pe adresele-valori ale pointerului. De exemplu: int x=10, *pi; void *pv; Atribuirea pi=&x i pv=pi sunt corecte. Atribuirea pi=pv nu este corect. La atribuirea sau citirea datelor de pe adresele-valori ale unui pointer de tip void * trebuie explicit indicat tipul datelor respective, adic pi=(int*)pv. Operaii aritmetice cu pointeri: valorile a doi pointeri pot fi comparate folosind operatori relaionali. Operaia este folosit, de obicei, pentru pointerii care pointeaz spre elementele aceluiai tablou. Comparaia unui pointer cu NULL constant special definit n <stdio.h>, are rolul de a verifica dac s-a fcut alocarea unei zone pointerului respectiv. Este definit adunarea (scderea) unui scalar la un (dintr-un) pointer rezultatul fiind tot un pointer i diferena dintre doi pointeri, operaiile avnd sens doar dac pointerul pstreaz adresa unui element dintr-un tablou. Fie p i q doi pointeri la elemente ale aceluiai tablou. Expresia p+i indic elementul situat n vector cu i poziii la dreapta fa de p, iar expresia p-q are ca valoare numrul de elemente cuprinse ntre cele dou adrese. Operaia de incrementare (++) i decrementare (--) pentru pointeri mrete (micoreaz) adresa-valoare a pointerului cu numrul de octei necesari pentru a pstra o valoare de tipul spre care pointeaz pointerul. De exemplu, dac avem declarat int *p; atunci ++p, ca i p++, mrete valoarea lui p cu 2 octei, 21

deoarece o valoare de tipul int este alocat pe 2 octei. Analogic, dac avem declarat double *w; atunci w++, ca i ++w, mrete valoarea lui w cu 8, deoarece tipul double cere 8 octei. Legtura dintre pointeri i tablouri. Fie tab[n] un tablou unidimensional cu n elemente. Atunci numele tab este un pointer care are ca valoare adresa primului element al tabloului, adic are valoarea &tab[0]. Deci tab+1 este adresa elementului cu indicele 1, adic &tab[1], tab+2 este adresa elementului cu indicele 2, adic &tab[2] .a.m.d. Respectiv *(tab+0), adic *tab este elementul tab[0], *(tab+1) este elementul tab[1], *(tab+2) este elementul tab[2] .a.m.d. Fie acum tab[m][n] un tablou bidimensional cu m linii i n coloane. Atunci tab[0] este un pointer care are ca valoare adresa de nceput a liniei 0 a tabloului tab[m][n], adic &tab[0][0], tab[1] este un pointer care are ca valoare adresa de nceput a liniei 1 a tabloului tab[m][n], adic &tab[1][0] .a.m.d. Deci tab[0], tab[1],..., tab[m] este un tablou de pointeri. La rndul su, numele tab al tabloului tab[m][n] este un pointer ce pointeaz spre irul de pointeri tab[0], tab[1], tab[2],..., adic pointerul tab are ca valoare adresa pointerului tab[0]. Din toate acestea rezult c expresiile &tab[i][j], tab[i]+j, *tab+i*n+j sunt echivalente. La fel expresiile tab[i][j], *(tab[i]+j), *(*tab+i*n+j) sunt echivalente. Deci **tab este nu altceva dect elementul tab[0][0]. Exemple de programe: Exemplul 4.1. Programul determin elementul maxim dintr-un ir numeric; sunt demonstrate diferite moduri de adresare la elementele unui tablou unidimensional.
#include<conio.h> #include<stdio.h> void main() { int x[]={10,20,30,40,50}, *px,i,r,t; clrscr(); px=x; r=*px; for (i=0;i<5;i++) { t=*(px+i); if (r<t) r=x[i]; } printf(Elementul maxim al irului x este %i,r); }

Exemplul 4.2. Programul inverseaz un ir de caractere


#include<conio.h> #include<string.h> #include<stdio.h> void main() { char *s=programare,i,j,aux; clrscr(); puts(irul iniial:); puts(s); for (i=0, j=strlen(s)-1; i<j;i++,j--) { aux=*(s+i); *(s+i)=*(s+j); *(s+j)=aux; puts(irul inversat:); puts(s); getch(); }

Exemplul 4.3. Programul afieaz doar numerele prime dintr-un tablou de numere ntregi pozitive.
#include<conio.h> #include<stdio.h> void main()

22

{ unsigned a[]={10,7,9,40,5,7}, i=0,s=0,d,h; clrscr(); puts(irul iniial este:); while ( i<6) printf(%u\t, *(a+i++)); while (s<6) { d=0; for (h=1; h<=a[s];h++) if ( *(a+s)%h1==0) d++; if (d==2) printf(%u\t, *(a+s++)) ; } getch(); }

Exemplul 4.4. Programul determin caracterul de cod maxim ntr-un ir de caractere.


#include<conio.h> #include<string.h> #include<stdio.h> void main() { char *s=programare C++,i=-1,x; clrscr(); x=*s; for (;++i<strlen(s);) if (x<*(s+i)) x=*(s+i); puts(Caracterul de cod maxim n irul); printf(%s\neste %c,s,x) ; getch(); }

Exemplul 4.5. Programul ordoneaz cresctor un ir de caractere.


#include<conio.h> #include<stdio.h> void main() { char x[]=UNIVERSITATEA DE STAT A MOLDOVEI; int n=strlen(x),i,j,aux; clrscr(); puts(irul iniial:); puts(x); for (i=0; i<n-1; i++) for (j=i+1; j<n; j++) if (x[i]>x[j] ) { aux=x[i]; x[i]=x[j]; x[j]=aux; puts(\nirul ordonat cresctor:); puts(s); getch(); }

Exemplul 4.6. Programul formeaz din vectorul x de numere ntregi un vector y de numere ntregi, n care y[i] s fie restul mpririi lui x[i] la suma cifrelor lui. #include<conio.h>
#include<stdio.h> void main() { unsigned x[]={123,17,439,5146,5667}, i=0,y[5],s; clrscr(); puts(irul numeric iniial este:); while ( i<5) printf(%u\t, *(x+i++)); for (i=0; i<5; i++) { s=0; while (x[i]>0)

23

{ s+=x[i]%10; x[i]=x[i]/10; } *(y+i)=s; } puts(irul numeric format:); i=0; while (i<5) printf(%u\t, *(y+i++)) ; } getch(); }

Exemplul 4.7. Programul afieaz doar simbolurile cuprinse ntre simbolurile ( i ). Se presupune c nu exist mai multe paranteze.
#include<conio.h> #include<stdio.h> void main() { char *s=abcd(1,2,3,4,5)xzy; int k, *p, *q; clrscr(); puts(irul iniial:); puts(s); p=strchr(s,(); q=strchr(s,)); k=p-s; j=q-s; for (i=k+1; i<j; i++) printf(%c,*(s+i)); getch(); }

Exemplul 4.8. Programul afieaz doar simbolurile cuprinse ntre simbolurile ( i ). Se presupune c nu exist mai multe paranteze. (Alt variant)
#include<conio.h> #include<stdio.h> void main() { char *s=abcd(1,2,3,4,5)xzy; int k, *p, *q; clrscr(); puts(irul iniial:); puts(s); for (i=0; *(s+i++);) { if ( *(s+i)!=( ) continue; while ( *(s+ ++i)!=) ) printf(%c,*(s+i)); } getch(); }

Exemplul 4.9. Programul determin i afieaz elementul maxim pe liniile unui tablou bidimensional. Sunt demonstrate diferite moduri de adresare la elementele tabloului.
#include<conio.h> #include<stdio.h> void main() { unsigned v[5][5],i,j,max,n,m; puts(Introdu numrul de linii i de coloane:); scanf(%i%i,&n,&m); for (i=0;i<n;i++) for (j=0;j<m;j++) //accesul ctre elementele tabloului prin numele lui scanf(%i, *v+i*m+j); for (i=0;i<n;i++) { //accesul ctre elementele tabloului prin indicatorii v[0], v[1], max=*(v[i]+j); for (j=0;j<m;j++) if ( max<v[i][j] ) max=v[i][j]; //acces la elemente tabloului prin indici

24

printf(Elementul maxim pe linia %i este %i\n,i+1,max); } for (i=0; i<n*m;i++) printf(%i\t,*(*v+i)); // accesul ctre elementele tabloului prin v indicator la indicatorul v[0]

} Probleme propuse spre rezolvare: 1. Programul determin cel mai mic numr dintre elementele de indice par ale unui ir numeric. 2. Programul transcrie toate elementele nule ale unui ir numeric la nceputul tabelului, la sfrit transcrie toate elementele ne nule, pstrnd ordinea lor. 3. Programul deplaseaz elementele unui ir numeric a[10] astfel nct a[i] s se deplaseze n a[i1], iar a[0] n a[9]. 4. Programul deplaseaz spre stnga un tablou a[10] cu k poziii. Ultimele k poziii se completeaz cu 0. 5. Programul arunc din textul dat toate cuvintele de lungime mai mare ca 6 simboluri. Se va afia textul iniial i cel redactat. 6. Programul afieaz din irul S l simboluri ncepnd cu poziia k . 7. Programul realizeaz n tabloul a[10] cu numere sortate introducerea unui numr k astfel nct tabloul s rmn sortat. 8. Programul realizeaz inversarea elementelor matricei ptrate de ordin n n raport cu diagonala secundar. 11. S se bordeze o matrice A (avnd m linii i n coloane) cu linia m+1 i coloana n+1, unde A[m+1][j] s fie suma elementelor de pe coloana j (cu j de la 1 la n), iar A[i][n+1] s fie suma elementelor de pe linia i (cu i de la 1 la m). 12. Programul nmulete un vector din n elemente cu o matrice numeric de dimensiunea m n. ntrebri de control: 1. Ce este un pointer ? 2. Ct memorie se aloc unei variabile de tip pointer ? 3. Cum se extrage valoarea unui pointer la ecran ? dar valoarea de pe adresa pstrat n variabila de tip pointer ? 4. Fie int *p, *q, a=1, b=0; p=&a ; q=&b; if (*p<*q) *q=*p; else q=p; Ce va afia
printf( %i %i %i %i, a,b,*p,*q); ?

5. Care dintre expresiile urmtoare este eronat, tiind c variabilele p, q i a sunt declarate:
int a, *p, **q; a) a=*q=*p b) p=&(**q) c) *q=&a d) *p*=*(*q)+a ?

6. Care este numrul de bii necesari pentru memorarea tabloului declarat int a[20]; ? 7. Dac vectorul a este declarat char a[20]; atunci elementul al treilea este:
a) a[3] a) a[3] b) *a[3] b) *a[3] c) *(a+2) c) *(a+2) d) *(a+3) ? d) *(a+3) ?

8. Dac vectorul a este declarat char a[20]; atunci elementul al treilea este: 9. Ce este un pointer nul, ce reprezint constanta NULL i unde este definit ? 10. Fie char a=a, *pa; int x=10, *px; float y=2.8, *py; double z=12345.54321,
*pz; long double w=123456789.987654321, *pw ; pa=&a ; px=&x ; py=&y ; pz=&z ; pw=&w ; Ce va afia printf(%c\t%d\t%f\t%lf\t%Lf\n, *pa, *px, *py, *pz, *pw) ; ? Fie int x=2000, *p=&x, **q=&p, ***w=&q ; Ce va afia printf(%d %d %d %d, x, *p, **q, ***w) ; ? Fie int s[20]= {0,1,2,3,4,5}, *pi=s ; Ce va afia printf(%d %d %d %d %d %d, *pi, *++pi, *++pi, *++pi, *++pi, *++pi) ; ?

13. 14.

25

Lucrare de laborator N5
Tema: Prelucrarea irurilor de caractere. Scopul lucrrii: Utilizarea funciilor standarde de prelucrare a irurilor de caractere i operaii cu iruri. Suport teoretic: Cele mai des ntlnite utilizri ale tablourilor unidimensionale n limbajul C sunt irurile de caractere, deoarece n C nu este prevzut tipul de date ir de caractere. Pentru memorarea irurilor se utilizeaz tablouri cu tipul de baz char, care au pe ultima poziie caracterul \0. Pe lng necesitatea de a defini un ir de caractere ca i tablou de caractere, n prelucrarea irurilor se utilizeaz deseori tipul pointer la caracter. De exemplu: char sir[20]; // tablou de 20 de caractere char *psir; // pointer la caractere. Astfel, sir este o variabila de tipul tablou de caractere pentru care se rezerv un spaiu de memorie de 20 de octei, n timp ce psir este un pointer la caracter care poate primi ca valoare adresa unui caracter (n particular, adresa primului element dintr-un ir de caractere). Trebuie reinut c ori de cte ori se lucreaz cu variabile iruri de caractere ntr-un program, trebuie s existe fie o definiie de forma celei prezentate pentru variabila sir, prin care se rezerv static (n timpul compilrii), spaiul de memorie necesar variabilei, fie s se aloce dinamic memoria necesar. Funciile pentru prelucrarea irurilor sunt declarate n fiierul antet string.h. Ele primesc adresele irurilor prelucrate, prin intermediul parametrilor de tipul pointer la caracter. Denumirea funciilor de prelucrare a irurilor declarate n fiierul stdio.h funcia char * gets(char* s) explicaie Citete caracterele din intrarea standard pn la ntlnirea caracterului Enter, care nu se adaug la irul s; plaseaz '\0' la sfritul lui s; returneaz adresa primului caracter din ir. int puts(char* s) Tiprete irul s, trece apoi la rnd nou. printf("%s",s1) Tiprete irul s1. Denumirea funciilor de prelucrare a irurilor declarate n fiierul string.h funcia explicaie int strncmp(char* s1, char* s2, int n) Compar irurile s1 i s2 spre care pointeaz pointerii s1, s2. Funcia returneaz 1 dac s1>s2, valoarea -1 dac s1<s2, i valoarea 0 dac s1=s2. Dar se compar irurile pentru cel mult n caractere. char *strcpy(char* s1, char* s2) Copie irul surs s2 n irul destinaie s1 i returneaz adresa irului destinaie. char* strcat(char* s1, char* s2) Concatenarea irurilor i afiarea irului rezultat. char* strchr(char s, char c) Poziia primei apariii a caracterului c n irul s, respectiv NULL dac c nu este n s. strcspn(char* s1, char* s2) Afieaz prima apariie a caracterului care coincide n ambele iruri. char *strncpy(char* s1, char* s2, int Copie maxim n caractere de la irul surs s2 n irul n) destinaie s1 i returneaz adresa irului destinaie. 26

char *strtok(char *s1, const char *s2); Desparte irul s1 de irul s2. int strlen(char* s1) Returneaz lungimea irului fr a numra caracterul de sfrit \0. strlwr(char* s1) Convertete irul din litere mari (A la Z) n litere mici (a la z). strset(char* s1, char* s2) Caut prima intrare a irului s2 n irul s1. strrev(char* s) Inverseaz irul. strrchr(char* s, int c) Verific ultima intrare a simbolului c n irul s. Returneaz pointerul spre ultimul simbol ce coincide cu c a irului s. Dac nu-l gsete returneaz NULL. char*strpbrk(const char*s, const Cut n irul s orice simbol din irul s1 i afieaz pe char*s1) acel care mai naite se ntlnete n irul s. strrupr(s) Convertete irul din litere mici n litere mari . isalpha(s) Verific dac s este liter. isdigit(c) Verific dac c cifr. islower(s) Verific dac s este liter de la a la z. isspace(c) Verific dac c este spaiu.z int atoi(const char* s) Convertete irul s ntr-o valoare ntreag. int atol(const char* s) Convertete irul s ntr-o valoare ntreag lung. itoa(int n, char* s, int ) Convertete un ntreg n char. Double atof(char* s) Convertete sirul s ntr-o valoare real char*gcvt(double v,int n, char*buf) Convertete datele de tip double ntr-un ir de simboluri, inclusiv simbol cu virgul mobil. Mai des se folosete la convertirea numerelor introduse ca ir de simboluri, i efectuarea anumitor operaii asupra lor. Exemple de programe: Exemplul 5.1. Este dat irul s. S se tipreasc cte litere de a se ntlnesc in ultimul cuvnt din ir (de ex. Ana frate ada; rezulat: 2).
#include<stdio.h> #include<conio.h> #include<string.h> void main() { char s[256]; int i,j=0; clrscr(); gets(s); for(i=strlen(s)-1; s[i]!=' '; i--) //parcurgem irul de la sfrit if(s[i]=='a') j++; //dac gsim litera a, contorul j va crete printf(" Litere de a n ultimul cuvnt sunt: %d",j); getch(); }

Exemplul 5.2. Fiecare caracter se nlocuiete cu urmtorul caracter(de ex. abc se tiprete bcd) pn la apsarea tastei cifrei 9.
#include<stdio.h> #include<conio.h> #include<string.h> void main() { char g,c; int i,j,x,k; g=0; clrscr(); while(!g)

27

{ c=getchar(); // ct g=0, se citesc cu ecou caractere, pn c!=9 if ( c == '9' ) {g = 1; continue;} // dac c=9, atunci g=1 i se trece la urmtorul pas putchar (c+1); // tiprete urmtorul caracter } getch(); }

Exemplul 5.3. Este dat irul d. Se concateneaz irurile i se copie un ir n alt ir.
#include <string.h> #include <stdio.h> #include <conio.h> void main(void) { char d[25]; char *blank = " ", *c = "C++", *t = "Turbo"; clrscr(); gets(d); strcat(d, blank); // la concatenare se pstreaz textul din ambele iruri strcpy(d, t); // irul t se copie n d, i textul din irul d se terge strcat(d, c); //se concateneaz printf("%s\n", d); // se va afia: TurboC++ getch(); }

Exemplul 5.4. Este dat irul s. S se numere cte cuvinte are irul.
#include<stdio.h> #include<conio.h> #include<string.h> void main() { char s[20]; int i,k; k=1; clrscr(); printf("sir:\n"); gets(s); for(i=1;i<strlen(s);i++) //irul e parcurs din poziia 1 pn la sf.irului { if((s[i-1]==' ')&&s[i]!=' ') // verificm dac este cuvnt k++; //contor ce numr cuvintele } printf(" %d",k); getch(); }

Exemplul 5.5. Este dat irul s. De desprit fiecare propoziie din rnd nou. Propoziia se termin cu punct.
#include<stdio.h> #include<conio.h> #include<string.h> void main() { char s[256],*t; clrscr(); printf("sir:\n"); gets(s); t=strtok(s,"."); while(t!=NULL) { printf("%s\n",t); t=strtok(NULL,"."); } getch(); }

// atribuim lui t irul s pn la punct //att timp ct n t sunt propoziii //tiprim din rand nou

28

Exemplul 5.6. Este dat un cuvnt s de maxim 20 caractere. S se verifice dac cuvntul introdus este polidrom (care se citete i de la stnga i de la dreapta la fel; de exemplu cojoc).
#include<stdio.h> #include<conio.h> #include<string.h> #include<stdlib.h> void main() { char s[20]; int i,k,l,h=1; clrscr(); printf("sir\n"); gets(s); k=strlen(s); l=k/2; for(i=0;i<l;i++) { if(h) if(s[i]==s[k-i-1]) h=1; else {printf("nu\n"); getch(); exit(0);} } printf("polidrom=%s",s); getch(); }

Exemplul 5.7. Este dat irul s. S se tipreasc cuvintele ce au lungimea mai mare dect 6 caractere.
#include<stdio.h> #include<conio.h> #include<string.h> void main() { char s[256]; int i,j,x; j=0;x=0; clrscr(); printf("sir\n"); gets(s); for(i=0;i<strlen(s);i++) { j++; if(s[i]==' ') { if(j>6) for(k=x;k<i;k++) s[k]=' '; j=0;x=1; }} printf("=%s",s); getch(); }

Exemplul 5.8. Este dat irul s. De tiprit irul astfel nct, unde sunt mai mult de un spaiu de considerat numai unul (De exemplu: azi plou, rezultat: azi plou).
#include<stdio.h> #include<conio.h> #include<string.h> void main() { char s[256]; int i,j; clrscr(); printf("sir\n"); gets(s); for(i=0,j=0;i<strlen(s);i++) s[j++]=s[i]; s[j]='\0';

if((s[i]!=' ')||(s[i]==' ')&&(s[i+1]!=' '))

//se verific dac s[i] nu-i spaiu sau s[i] este spaiu i urmtoarea poziie nu-i //spaiu, atunci n irul s[j], unde j crete la fiecare simbol, se nscrie s[i]

//ultimul caracter zero

29

puts(s); getch(); }

//tiprim irul

Exemplul 5.9. S se tipreasc poziia caracterului ce se afl n ambele iruri.


#include<conio.h> #include<stdio.h> #include<string.h> void main() { char s[256]; int i,l; clrscr(); printf(irul:); gets(s); for(l=0;l<strlen(s);l++) i=strcspn(s,"nmn"); printf("%d\t",i); getch(); }

// de exemplu: abcdmh // atribuie poziia primului caracter din irul s //i=4 deoarece m se afl pe poziia 4

Exemplul 5.10. Este dat irul s i subirul cutat. S se caute un subir n irul s.
#include<conio.h> #include<stdio.h> #include<string.h> void main() { char s[256],s1[256],*p; int i; clrscr(); printf("dati irul s:"); gets(s); printf("dati subirul cutat:"); gets(s1); for(int l=0; l<strlen(s); l++) p=strstr(s,s1); printf("Subirul cutat: %s\t",p); getch(); }

//de exemplu: ada ion mihai //ion

//ion

Exemplul 5.11. Este dat irul s. S se tipreasc la ecran: irul pn la dou puncte; irul dup dou puncte.
#include<conio.h> #include<stdio.h> #include<stdlib.h> #include<string.h> void main() { char s[256],*p; int i,j; i=j=0; clrscr(); printf("dati irul:"); gets(s); // de exemplu: asfsd:fdfh:hjkl; p=s; printf("\nirul pna la dou puncte:"); while(p[i]!=':'){ putchar(p[i]); i++; } // afiarea irului (asfsd) i++; j++; printf("\nsirul dupa doua puncte:\n"); for(i; i<=strlen(p); i++) putchar(p[i]); // fdfh:hjkl; getch(); }

30

Exemplul 5.12. Este dat irul s. S se gseasc cuvintele ce conin litera s.


#include <string.h> #include <stdio.h> #include <conio.h> void main(void) { char s[256]; char *ptr, c='s'; clrscr(); printf("dai irul:\n"); gets(s); ptr = strchr(s,c); if (ptr) printf("caracterul %c se afl pe poziia: %s\n", c, ptr); else printf("nu este aa caracter\n"); getch(); }

Exemplul 5.13. Este dat irul s. S se afieze lungimea celui mai scurt cuvnt i numrul de cuvinte.
#include<stdio.h> #include<string.h> #include<conio.h> void main() { char s[256],*t,*p; int k,min; k=0; clrscr(); printf("dati sirul:"); gets(s); t=s; t=strtok(s," "); // lui t se atribuie cuvintele (desprite prin spaiu) min=strlen(t); // notm prin min lungimea irului t while(t!=NULL) // verificm att timp ct avem cuvinte { printf("%s\n",t); //tiprim fiecare cuvnt din rand nou if(min>strlen(t)) //dac se gsete un cuvnt cu lungimea mai mic ca min min=strlen(t); //atunci min primete lungimea acelui cuvnt t=strtok(NULL," "); k++; //contorizeaz numrul de cuvinte } printf("\nnr de cuvinte:%d\nlungimea celui mai scurt cuvant:%d",k,min); getch(); }

Exemplul 5.14. Folosind funcia gcvt(), s se efectueze unele operaii pentru convertirea irului.
#include<stdio.h> #include<string.h> #include<conio.h> #include<stdlib.h> void main() { char s[256]; double n; int k=4; n=2.897; gcvt(n, k. s); printf(%s ,s); // 2.897 // numr negativ n=-982.897; gcvt(n, k. s); printf(%s ,s); // -982.8 // numr n format tiinific n=0.897e3; gcvt(n, k. s);

31

printf(%s ,s); }

// 8970

Probleme propuse spre rezolvare: 1. Se citete un ir. S se numere cuvintele care ncep cu litera b. 2. S se afieze toate poziiile unui caracter intr-un ir dat. Caracterul se introduce de la tastatur(de exemplu: adelina; a are poziia 0 i 6). 3. Se citete un ir de caractere care nu conine caractere albe. S se decid dac irul este alctuit exclusiv din caractere numerice. 4. S se determine numrul de litere mari i mici dintr-un text dat. 5. Se citete un ir ce conine i dou puncte. S se afieze textul cuprins ntre dou puncte ( Ex: ada:hjk:vbnv, irul rezultat: hjk). 6. Se citete un ir. S se tipreasc la ecran cuvntul cu lungimea mai mic. 7. Se citete un ir. S se tipreasc la ecran caracterul de cod maxim i simbolurile cu codurile cuprinse ntre [100, 235]. 8. Se citete un ir. S se tipreasc la ecran irul dintre paranteze (Ex: asdf (ghdfhg ) fdhj,6g ghdfhg). 9. Se d o list de cuvinte separate prin spaiu, lista se ncheie prin dou rnduri goale succesive (dou enter-uri). S se tipreasc n ordine alfabetic toate polindroamele care apar n list. Un polindrom este un cuvnt care este identic citit att de la nceput spre sfrit ct i de la sfrit spre nceput (Ex: cazac, elevele, cojoc). 10. Se citete un text. Textul conine cuvinte separate printr-un spaiu. Dac textul conine *, atunci fiecare simbol / ce precede * s fie nlocuit cu ,. 11. Se citete un text. Textul conine cuvinte separate printr-un spaiu. S se scrie, pe linii separate, fiecare cuvnt care apare n text urmat de un numr care va reprezenta de cte ori apare cuvntul n text. S se determine cuvntul care apare de cele mai multe ori. 12. Se citete un text. Textul conine cuvinte separate printr-un spaiu. Se va genera un nou text care va conine cuvintele ordonate alfabetic. 13. Se citete un text. Textul conine cuvinte separate printr-un spaiu. S se determine numrul de apariii al fiecrui caracter. Informaia referitoare la un caracter se va afia o singur dat. 14. Se citete un text. Textul conine cuvinte separate printr-un spaiu. Se va genera un nou text care va conine cuvintele n ordine invers (asdf - fdsa). 15. S se sorteze alfabetic un ir de cuvinte (eventual, s se disting literele mici de cele mari). 16. Se d un text de maxim 30 de caractere. S se listeze toate cuvintele de dou caractere din acest text. 17. Se dau dou texte. S se stabileasc o vocal comun celor dou texte, care apare de cele mai puine ori. 18. Fie un ir de forma: cifr-liter, cifr liter etc.(Ex : 2a4b5c). S se genereze un astfel de ir: aabbbbccccc. 19. Se citete un ir de caractere alfanumerice. Considerm c literele sunt separatorii numerelor. Afiai datele de tip numeric preluate n ordine din irul citit. Numerele vor fi scrise cte unul pe o linie. Ex. in.txt out.txt a23sc345ss5e 23 345 5 20. Se citete un text de la tastatur astfel nct cuvintele s fie separate printr-un singur spaiu i imediat dup ultimul cuvnt se scrie punct. Textul va fi scris pe un singur rnd: a. S se determine dac textul are cuvinte distincte (se ignora diferena de cheie). b. S se tipreasc cuvintele cu lungimea mai mare ca 6. c. S se determine dac textul conine cifre 32

21. Este dat un ir de caractere (lungimea irului este <=100). De codificat acest ir n urmtorul mod: caracterele se plaseaz ntr-un ptrat de dimensiune minim pe spiral, ncepnd cu colul din dreapta jos n direcia acelor de ceasornic. Spaiul se codific prin *. Intrare: de la tastatur se va introduce irul de caractere. Ieire: se va afia la ecran dimensiunea aleas a ptratului i textului codificat. Exemplu: Bun dimineaa, Chiinu! Ieire: 5 ineatminaai!u,dihC**anuB i n e a t m i n a a i ! u , d i h C * * a n u B 22. Se consider dou iruri: a=a1an i b=b1bm formate din n i respectiv m litere. Asupra irului a se pot face urtoarele operaii. tergere: S(i) terge litera de pe poziia i. Inserare: I(j,c) insereaz litera c pe poziia j. Modificare:M(i,c) nlocuiete litera de pe poziia i cu c. S se transforme irul a n irul b cu numr minim de astfel de operaii. Exemplu: a= DANIELA, b=IOANA. Numrul minim de operaii este 5 i anume: M(1,1); I(2,O); S(5); S(6); S(5). Intrare: a i b se citesc de la tastatur. Restricii: m>0, n<80. ntrebri de control: 1. Ce returneaz funciile: strlen(ASEM), strlen(asem0), strlen(ASEM\N), strlen (0), strlen()? 2. Care va fi rezultatul returnat de funciile: strcat(Limbajul C, ++), strncat(Cibernetica, ,Informatica Aplicat, Management, Matematica, 21)? 3. Ce afieaz puts(strstr(Informatica Aplicat,scop));? Explicai. 4. Ce returneaz funciile: strcmp(asem,ASEM), stricmp(ASEM, asem), strncmp(Limbajul C, Limbajul C++, 10), strnicmp(INFORMATICA, informatica,1)? 5. Fie char *s=Costel, Vicu i Andrei merg la teatru, *q=Vicu; puts(strstr(s,q)); Cine merge la teatru? Explicai. 6. #define L 15
char sir[L]; strcpy(sir,"123\0456"); printf("irul copiat este:/%s/ i are lungimea:%d\n",sir, strlen(sir));

Ce se tiprete pe ecran?.
7. char s[]=70000; int i=atoi(s); long l=ato1(s); printf(%d\t%ld,i,l); Explicai. Ce se tiprete la ecran?. 8. char s[]=asdfghjert; int i; i=strcspn(s,fnm); Ce se tiprete la ecran, ce valoare primete 9. char s1[]=asdfghjert; char s2[]=esa; char *p; p=strpbrk(s1,s2); printf((%s, p); Explicai. Ce se tiprete la ecran?. 10. char s1[]=asdfghjert; char *p; p=strrchr(s1,j); printf((%s, p); Explicai. Ce se tiprete la ecran?.

variabila i?.

33

Lucrare de laborator N6
Tema: Lucrul cu tablourile unidimensionale. Scopul lucrrii: obinerea deprinderilor practice la utilizarea tablourilor unidimensionale i operaiile de prelucrare a lor. Suport teoretic: Definiie: Masivele sunt structuri de date omogene cu un numr finit i cunoscut de elemente, ce ocup un spaiu contiguu de memorie. Un masiv este caracterizat de urmtoarele elemente: numele; tipul de date asociat; numrul de dimensiuni; numrul de elemente pentru fiecare dimensiune. Definiie: Vectorii sunt masive unidimensionale. In C++ vectorii se declar folosind sintaxa: tip nume[n] unde: tip tipul de date folosit; poate fi unul din tipurile de baz (int, float, char, ) sau un tip definit de utilizator (articole, obiecte) nume numele prin care va fi referit vectorul n numrul de elemente ale vectorului Exemple de declaratii:
// vector de 100 valori ntregi int vanzari[100]; // vector de 15 valori reale float temperaturi[15];

Memorarea vectorilor se face ntr-un spaiu contiguu de memorie. Numele vectorului este de fapt un pointer ctre adresa primului element. Pentru o declaraie de forma int v[5]; reprezentarea n memoria intern este: v

v[0]

v[1]

v[2]

v[3]

v[4]

Dimensiunea total a vectorului este calculat ca produs ntre numrul de elemente i dimensiunea unui element. Iniializarea vectorului se poate face la declarare printr-o construcie de forma: tip nume[]={lista_valori}. Se observ c n acest caz nu este necesar precizarea numrului de elemente. Acesta va fi dedus automat de compilator din dimensiunea listei cu care se face initializarea. In cazul in care numrul de elemente precizat este mai mare dect numrul de elemente din list se va realiza o initializare partiala a vectorului. Exemple de initializri la declarare:
// iniializare fr precizarea explicit a numrului maxim de elemente int v1[] = {1, 2, 3, 4, 5}; // iniializare complet cu precizarea numrului maxim de elemente int v2[3] = {17, 19, 23};

34

// iniializare parial int v3[5] = {7, 6, 5};

Accesul la elementele vectorului se face direct; compilatorul calculeaz adresa elementului pe baza indexului i a dimensiunii unui element. Numerotarea elementelor se face incepnd cu zero. Pentru un vector v cu n elemente referirea elementelor se face folosind v[0], v[1], v[2], , v[n-1]. Operaii de baz: Citirea de la tastatur ;

printf("dai nr de elemente:"); scanf("%d",&nrelem); for (i = 0; i < nrelem; i++) { printf("vector[%d]=",i); scanf("%d",&vector[i]); } for (i = 0; i < nrelem; i++) printf("%3d",vector[i]);

Afiarea pe monitor;

Cutarea elementului dup valoare ;

// parcurgem vectorul for (i = 0; i < nrelem; i++) if (vector[i] == valoare) { f=1;// notm c am gsit valoarea cutat printf("elementul cautat %d e pe pozitia: d:",vector[i],i); } // element negsit if (f==0) printf("elementul cautat nu este in vector: ");

Inserarea elementului;

// se presupune c dimensiunea maxim a vectorului // este cel putin egala cu nrElemente + 1 int pozitia; printf("dati pozita pe care vreti sa inserati:"); scanf("%d",&pozitia); printf("dati valoarea pentru inserare:"); scanf("%d",&valoare); for (i = 0; i < nrelem; i++) if (pozitia == nrelem) // inserare la sfarsitul vectorului vector[nrelem] = valoare; else // inserare n interiorul vectorului { // se deplaseaz la dreapta a elementele aflate dup poziia de inserare for (int i = nrelem; i > pozitia; i--) vector[i] = vector[i-1]; // i se insereaz elementul vector[pozitia] = valoare; } printf("Dupa inserare:\n"); for (i = 0; i < nrelem+1; i++) printf("%3d",vector[i]);

tergerea elementului;

// deplasm la stanga elementele aflate dup poziia de stergere printf("dati pozita pe care vreti s o stergei:"); scanf("%d",&pozitia); for (i = pozitia; i < nrelem; i++) vector[i] = vector[i+1]; printf("Dupa stergere:\n"); for (i = 0; i < nrelem; i++) printf("%3d",vector[i]);

35

Exemple de programe: Exemplul 6.1. Dat un tablou de 10 elemente. Programul determin suma elementelor de pe poziiile pare.
#include<stdio.h> #include<conio.h> void main() { int a[10], i, s; s=0; printf(Introducem elementele vectorului:\n); for(i=0; i<10; i++){ printf(a[%d]=, i); scanf(%d, &a[i]); } for(i=0; i<10; i++) if(i%2==0) s=s+a[i]; // se verific dac poziia elementului este par printf(\nSuma elementelor de pe poziiile pare este=%d, s); }

Exemplul 6.2. Se d un tablou de n elemente, toate elementele sunt diferite. S se afieze pe primele locuri elementele egale cu zero, apoi restul elementelor pstrnd ordinea lor( Ex.: 1 2 0 4 0 0 0 1 2 4 ).
#include<stdio.h> #include<conio.h> void main() { int a[100], n, i, j, x[100]; clrscr(); printf("\ndimensiunea vectorului:"); scanf("%d",&n); for(i=0; i<n; i++) { printf("a[%d]=", i); scanf("%d", &a[i]); } j=0; for(i=0; i<n; i++) if(a[i]==0) { j++; x[j-1]=a[i]; } // se verific dac elementul este zero, atunci j crete i nscriem n x for(i=0; i<n; i++) if(a[i]!=0) { j++; x[j-1]=a[i]; } printf("vectorul final\n"); for(i=0; i<n; i++) printf("%d%c", x[i],';'); getch(); }

Exemplul 6.3. Se d un tablou de n elemente. S se deplasare la stnga cu x poziii i pozitiile eliberate se nlocuiesc cu zero ( Ex.: 1 2 3 4 5 6; x=2; 3 4 5 6 0 0 ).
#include<stdio.h> #include<conio.h> void main() { int a[100], n, i, j, x; clrscr(); printf("\ndimensiunea vectorului:"); scanf("%d", &n); printf("\nnumrul de poziii de deplasare:"); scanf("%d", &x); printf("\nIntrodu elementele:\n"); for(i=0; i<n; i++) {

36

printf("a[%d]=", i); scanf("%d", &a[i]); } for(i=0; i<x; i++) { for(j=0; j<n; j++) a[j]=a[j+1]; // se face deplasarea la stnga a[j-1]=0; // i nscrierea lui zero pe poziiile eliberate } printf("vectorul final\n"); for(i=0; i<n; i++) printf("%3d", a[i]); getch(); }

Exemplul 6.4. Se d un tablou de n elemente. S se gseasc elementul maxim din acest tablou.
#include<stdio.h> #include<conio.h> void main() { int a[100], n, i, j, max; clrscr(); printf("\ndimensiunea vectorului:"); scanf("%d", &n); printf("\nIntrodu elementele:\n"); for(i=0; i<n; i++) { printf("a[%d]=", i); scanf("%d", &a[i]); } max=a[0]; //iniial elementul maxim este elementul de pe poziia zero for(i=0; i<n; i++) if (a[i]>max) max=a[i]; // gsim elementul maxim printf("%3d", max); getch(); }

#include<stdio.h> #include<conio.h> #include<alloc.h> void main() { int k,*a, n, i, j,*b, l; clrscr(); printf("\ndimensiunea vectorului:"); scanf("%d", &n); /* se aloc memorie pentru vectorul a: dimensiunea vectorului se nmulete cu dimensiunea tipului int(2 octei) */ a=(int*)malloc(n*sizeof(int)); b=(int*)malloc(n*sizeof(int)); // se aloc memorie pentru vectorul b printf("elementele vectorului a:\n"); for(i=0; i<n; i++) { printf("a[%d]=", i); scanf("%d", a+i); } printf("elementele vectorului b:\n"); for(i=0; i<n; i++) { printf("\nb[%d]=", i);

Exemplul 6.5. Sunt dai doi vectori de aceeai dimensiune a i b. S se gseasc: poziiile pentru care elementele din vectorul a sunt mai mari ca elementele din vectorul b; poziiile pentru care elementele din vectorul a sunt egale cu elementele din vectorul b

37

scanf("%d", b+i); } printf("a:"); for(i=0; i<n; i++) printf("%3d", a[i]); printf("\nb:"); for(i=0; i<n; i++) printf("%3d", b[i]); k=0; printf("\npoziiile pentru care elementele din vectorul a sunt mai mari ca din b\n"); for(i=0; i<n; i++) /* dac mcar un element din a este mai mare ca un element din b, atunci k pstreaz poziia elementului mai mare */ if(*(a+i)>*(b+i)) { k=i; printf("%3d", k); } l=0; printf("\npoziiile elementele corespunztoare primului vector egale cu elementele din al doilea vector\n"); for(i=0; i<n; i++) if(*(a+i) ==*(b+i)) { l=i; // dac elemental sunt egale, atunci l pstreaz poziia elementelor egale printf("%3d", l); } free(a); // se elibereaz memoria alocat vectorului a free(b); // se elibereaz memoria alocat vectorului b getch(); }

Exemplul 6.6. Se d un tablou de n elemente. S se gseasc cel mai mic element pozitiv
#include<stdio.h> #include<conio.h> #include<alloc.h> void main() { int k,*a, n, i, min; clrscr(); printf("\ndimen vec:"); scanf("%d", &n); a=(int*)malloc(n*sizeof(int)); printf("elementele vectorului a:\n"); for(i=0; i<n; i++) { printf("a[%d]=", i); scanf("%d", a+i); } printf("a:"); for(i=0; i<n; i++) printf("%3d", a[i]); min=a[0]; k=0; printf("\n"); for(i=0; i<n; i++) if((*(a+i)<0)&&*(a+i)<min) { min=*(a+i); k=i;} printf("pozitia elementului negativ %d are minimul %d", k, min); free(a); getch(); }

Exemplul 6.7. Se d un tablou de n elemente. S se sorteze descresctor folosind metoda bulelor (adic se compar primul cu al doilea, 2 cu 3,etc. Ex: 6 2 4 3 1 5; prima parcugere: 2 4 3 1 5 6; a doua parcurgere: 2 3 1 4 5 6; 38

#include<stdio.h> #include<conio.h> #include<alloc.h> //biblioteca pentru funcia malocc void main() { int k,*a, n, i, aux, j; clrscr(); printf("\ndimen vec:"); scanf("%d", &n); a=(int*)malloc(n*sizeof(int)); printf("elementele vectorului a:\n"); for(i=0; i<n; i++) { printf("a[%d]=", i); scanf("%d", a+i); } printf("a:"); for(i=0; i<n; i++) printf("%3d", *(a+i)); printf("\n"); for(i=0; i<n-1; i++) //se parcurge de la 0 pn la n-1 for(j=i+1; j<n; j++) // se parcurge de la i+1 pn la n { if(*(a+i) <*(a+j)) //comparm elementele { aux=*(a+i); // pstrm elemntul (a[0]) *(a+i)=*(a+j); // se inverseaz (a[0]=a[1]) *(a+j)=aux; // (a[1]= a[0]) i etc. } } printf("vectorul sortate\n"); for(i=0; i<n; i++) printf("%3d", *(a+i)); free(a); getch(); }

a treia parcurgere: 2 1 3 4 5 6; a patra parcurgere: 1 2 3 4 5 6;

Exemplul 6.8. Este dat vectorul a de lungimea n. S se mite ciclic la drapta cu x poziii.
#include<stdio.h> #include<conio.h> void main() { int a[100], n, i, j, x, k; clrscr(); printf("\ndimen vec:"); scanf("%d", &n); printf("\nnumarul de pozitii de deplasare:"); scanf("%d", &x); printf("\nIntrodu numarul de elemente:\n"); for(i=0; i<n; i++) { printf("a[%d]=", i); scanf("%d", &a[i]); } for(i=0; i<x; i++) { k=a[n-1]; for(j=n-1;j>=0;j--) a[j]=a[j-1]; a[0]=k; } printf("irul final\n");

39

for(i=0; i<n; i++) printf("%3d", a[i]); getch(); }

Exemplul 6.9. Este dat vectorul a de lungimea n. S se schimbe cu locurile elementul maximal cu cel minimal.
#include<stdio.h> #include<conio.h> void main() { int a[10], n, i, j, max, min, k; clrscr(); printf("\ndimen vec:"); scanf("%d", &n); for(i=0; i<n; i++) { printf("a[%d]=", i); scanf("%d", &a[i]); } printf("\nsirul initial\n\n"); for(i=0; i<n; i++) printf("%d ", a[i]); max=min=a[0]; for(i=0;i<n;i++) if(a[i]<min) {min=a[i]; k=i;} for(i=0; i<n; i++) if(a[i]>max){max=a[i]; j=i;} a[k]=a[j]; a[j]=min; printf("\nirul final\n\n"); for(i=0;i<n;i++) printf("%d ",a[i]); getch(); }

Probleme propuse spre rezolvare: 1. Se d un tablou de 10 elemente. S se determine suma elementelor pare. 2. Se d un tablou de 10 elemente. S se determine cte elementelor pare i cte impare sunt. 3. Se d un tablou de n elemente. S se determine produsul elementelor divizibile la 3. 4. Se d un tablou de n elemente. S se tipreasc elementele care se repet cel mai des. Dac sunt mai multe de acelai fel, atunci s se indice unul din ele. 5. Se d un vector din n elemente. S gseasc poziia ultimului element pozitiv. 6. Se d un tablou de 10 elemente nici un element nu este nul. S se determine de cte ori se schimb semnul numerelor scrise n tablou (trebuie verificate cte dou, ca s le vedem semnul mai bine le nmulim). 7. Se d un tablou de 10 elemente ntregi pozitive formate din 2 cifre(10 - 99). S se determine cte elemente sunt distincte (elementul se numr numai odat). 8. Se d un tablou de 10 elemente. S se determine de cte ori se ntlnete elementul maxim n tablou. 9. Se d un vector de n elemente. S construiasc un nou vector ce conine acelea elemente ca tabloul iniial cu condiia c toate elementele negative preced pe cele pozitive. 10. Se d un tablou de n elemente, toate elementele sunt diferite. S se afieze pe primele locuri elementele diferite de zero, apoi elementele egale cu zero pstrnd ordinea lor (Ex: 1 2 0 4 0 1 2 4 0 0). 11. Se d un tablou de n elemente. S se deplaseze ciclic la stnga cu x poziii (Ex: 1 2 3 4 5 ; x=3 4 5 1 2 3). 40

12. Se d tablou a de n elemente. S se alctuiasc algoritmul de numrare a elementelor maxime i minime din tablouul a de n. 13. Se d tablou a de n elemente. S se construiasc un nou vector de lungimea n, pentru care elementul i este media aritmetic ale primelor i elemente din vectorul iniial. 14. Sunt dai doi vectori de lungimea n cu elementele n ordine descresctoare. S se construiasc un alt vector de lungimea n+n elemente, n ordine cresctoare i conine elementele vectorilor iniiali. 15. Se d tabloul a de n elemente. Au fost introduse meciurile cu participarea echipei ZIMBRU. Elementele tabloului sunt egale cu zero (ZIMBRU a suferit nfrngere), 1 (meciul s-a terminat la egalitate) cu 2 (nvingtoare). S se stabileasc n cte meciuri echipa a suferit nfrngere, n cte a ctigat i n cte a fost la egalitate. 16. n tabloul t[31] a fost nscris temperatura zilnic a lunii ianuarie. S se numere n cte zile a fost nregistrat temperatura sub zero grade i n cte mai sus de zero grade. S se stabileasc numrul de zile z, n care a fost nregistrat o temperatur mai mic dect temperatura medie a lunii i numrul de zile z1 n care temperatura a depit mrimea medie. 17. Se d un vector din n elemente. S se determine numrul elementelor pentru care elementele precedente sunt mai mari. 18. Statu-Palm-Barb-Cot a ngropat patru comori n vrfurile unui dreptunghi, scriindu-i coordonatele comorilor pe un pergament. n timpul unei lupte cu Ft-Frumos pergamentul s-a pierdut. Din fericire, Statu-Palm-Barb-Cot a memorat coordonatele a trei puncte n care se afl comorile. Scriei un program, care va determina coordonatele celei de a patra comori. Punctele n care au fost ngropate comorile au coordonate ntregi (x1,y1), |x1|<100, |y1|<100. Coordonatele a trei vrfuri ale dreptunghiului se introduc de la tastatur n ordinea (x1,y1), ( x2,y2), ( x3,y3). Coordonatele celui de a patra vrf se afieaz la ecran n ordinea (x4,y4). Exemplu: 1 1 5 1 1 7. Rezultat: 5 7. 19. Se dau N(N+1)/2 numere ntregi strict pozitive, mai mici sau egale ca 10000. S se aeze aceste numere, dac este posibil, ntr-o piramid cu urmtoarele proprieti: piramida are N nivele, pe fiecare nivel 1 sunt 1 numere; fiecare numr din piramid, n afar de cele de pe ultimul nivel, este egal cu suma celor dou numere pe care se sprijin. Exemplu: 1 1 2 3 3 4 5 8 9 17 Rezultat: 17 8 9 3 5 4 1 2 3 1. 20. Se d tabloul a de n elemente, unde este introdus informaia despre ndeplinirea planului de producere a strungurilor de ctre 10 uzine de profil ce aparin ministerului respectiv. Valorile .a[i] (i=0,..,n) au urmtoarea semnificaie: a[i]>0 numrul de strunguri produs supraplan de ctre uzin cu numrul de ordine i; a[i]=0 arat c uzina a produs att ct prevede planul; a[i]<0 indic cte strunguri nu ajung pentru a ndeplini planul. S se compun algoritmul de numrare a uzinelor ce au ndeplinit planul sau au depit. S se stabileasc dac ministerul respectiv a ndeplinit planul, rspunsul da sau nu. S se calculeze cu ct n-au realizat planul unele uzine (a[i]<0). ntrebri de control: 1. Ce nseamn tablou. Cum se definete? 2. Poate tabloul(vectorul) include diferite tipuri. Dac da sau nu explicai. Dai exemplu. 3. int i, a[100], k=0;
for(i=0; i<6; i++) if(a[i]<0) k=k*i; printf(k=%d,k);

Ce se tiprete la ecran? Explicai. 41

4. Ce se tiprete? Explicai.
int i, a[100], k=0; for(i=0; i<6; i++) if(a[i]%2==1) k++; printf(k=%d,k);

5. Ct memorie se aloc pentru un vector de lungimea n i de tipul: int, double, char, float. ? 6. Cnd se folosesc funcile free() i malloc(), i ce fac ele? n care fiier se includ ele? 7. Ce se tiprete? Explicai.
int i, a[100], k=1; for(i=0; i<6; i++) if(a[i]!=0) k=k*a[i]; else k=0; printf(k=%d,k);

8. Sunt dai doi vectori. Cum se face nscrierea ambilor vectori n al treilea vector? i ce dimensiune va avea al treilea vector?

42

Lucrare de laborator N7
Tema: Lucrul cu tablourile bidimensionale. Scopul lucrrii: obinerea deprinderilor practice la utilizarea tablourilor bidimensionale i operaiile de prelucrare a lor. Suport teoretic: Matricele sunt masive unidimensionale. Sintaxa de declarare este: tip nume[m][n] unde: tip tipul de data folosit; poate fi unul din tipurile de baza (int, float, char, ) sau un tip definit de utilizator (articole, obiecte); nume numele prin care va fi referita matricea; n numarul de linii din matrice; m numarul de coloane din matrice. Exemple de declaratii:
// matrice de intregi cu 10 linii si 10 coloane int vanzari[10][10]; // vector de valori reale float temperature[3][15];

Memorarea matricelor se face, ca i n cazul vectorilor, ntr-un spaiu continuu de memorie. Numele matricei un pointer ctre adresa primului element. Elementele matricei sunt stocate n memorie linie dup linie. Pentru o declaraie de forma float m[2][3] reprezentarea n memoria interna este: m

m[0][0] m[0][1] m[0][2] m[1][0] m[1][1] m[1][2]

Dimensiunea total a matricei este calculat ca produs ntre numrul de linii, numrul de coloane i dimensiunea unui element. Iniializarea matricei se poate face la declarare printr-o construcie de forma: tip nume[][n]={{lista_valori1}, {lista_valori2}, , {lista_valorim}}. Se observ c n acest caz nu este necesar precizarea numrului de elemente asociat primei dimensiuni. Acesta va fi dedus automat de compilator din dimensiunea listei cu care se face initializarea. n cazul n care numrul de linii precizat este mai mare dect numrul de elemente din list se va realiza o iniializare parial a matricei. Exemple de iniializri la declarare:
// iniializare fr precizarea explicit a numrului de linii int m1[][2] = {{1, 2}, {3, 4}, {5, 6}}; // iniializare complet cu precizarea numrului de linii i coloane int m2[2][3] = {{17, 19, 23}, {29, 31, 37}}; // iniializare parial int m3[2][5] = {{7, 6}, {5}};

Accesul la elementele matricei se face direct; compilatorul calculeaz adresa elementului pe baza liniei, a coloanei, a numrului de elemente pe linie i a dimensiunii unui element. Formula folosit este: 43

adr(m[i][j]) = adr(m[0][0]) + (i * nr_max_elemente_linie + j) * dim_element. Numerotarea liniilor i a coloanelor se face ncepnd cu zero. Exemple de accesare elemente:
// citeste al doilea element de int a = m2[1][1]; // modifica primul element m2[0][0] = 7; pe a doua linie din matrice

Transmiterea ca parametri se face ca i in cazul vectorilor prin numele masivului. Problema care apare n cazul matricelor este aceea c numrul de coloane trebuie fixat pentru a permite calcularea de ctre compilator a adresei elementelor. n cazul n care se dorete lucrul cu matrice oarecare, transmiterea se va face prin pointeri iar adresa elementelor se va calcula dupa formula prezentat anterior. n acest caz va trebui trimis ca parametru att dimensiunea maxim a matricei ct i dimensiunea minim a acesteia. In practic apar cazuri n care matricele au anumite caracteristici care permit o stocare mai eficienta dect cea standard. Exemple de asemenea matrice sunt: matricele diagonale, matricele simetrice. Matricele diagonale sunt matrice ptratice de dimensiune n care conin elemente nenule numai pe diagonala principal: 7 0 0 0 2 0 0 0 11 In acest caz memorarea se va face folosind un vector de dimensiune n care va memora elementele de pe diagonala principala. Exemplu de utilizare:
// declarare si initializare int matDiag[3] = {7, 2, 11}; // citire valoare int val1 = CitireValoare(matDiag, 3, 1, 2); // scriere valoare (1, 1); ScriereValoare(matDiag, 3, 1, 1, 5);

Matricele simetrice sunt matrice patratice in care corespondente de sub i de peste diagonala principala sunt egale (adica m[i][j] = m[j][i] pentru oricare i si j). n acest caz se va folosi un vector care va conine numai elementele de peste i de pe diagonala principal. Matricea 1 2 3 4 2 5 6 7 3 4 8 9 7 8 9 10 va fi liniarizata sub forma: 1 2 3 4 5 6 7 8 9 10 Calculul pozitiei elementului i,j dintr-o matrice de dimensiune n se face dupa formula:
p = (n 1) + (n 2) + ... + (n i) + j = i n (1 + 2 + ... + i ) + j = i n i (i 1) +j 2 pentru j <= i. Daca j > i,

atunci se interschimb i cu j. Funcia de acces la elemente este:


int& Valoare(int* matrice, int n, int i, int j)

44

{ // interschimbm elementele daca este cazul if (j > i) { int t = j; j = i; i = t; } // calculam pozitia int pozitia = i*n + (i*(i-1))/2 + j; return matrice[pozitia]; }

Exemplu de utilizare:
// declarare si initializare int matSim[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // citire valoare int val1 = Valoare(matSim, 4, 1, 2); // scriere valoare (1, 1);

Valoare(matSim, 4, 1, 1) = 7; Aceeai tehnica se poate aplica i n cazul matricelor triunghiulare. Matricele rare sunt matrice care au majoritatea elementelor nule (mai mult doua treimi). n acest caz este mai eficient s memorm matricea sub forma a trei vactori care s conin linia, coloana i valoarea pentru elementele nenule. Pentru matricea: 0 0 0 0 0 0 0 23 0 7 0 0 0 0 0 0 vom avea vectorii: Linii: 1 2 Coloane: 3 1 Valori: 23 7 Alternativ, putem stoca elementele intr-un singur vector de articole care s conin linia, coloana i valoarea pentru fiecare element nenul. Exemple de programe: Exemplu 7.1. Este dat matricea de dimensiunea n*m. S se afieze cte elementele sunt pare pe fiecare linie.
#include<stdio.h> #include<conio.h> #include<malloc.h> void main() { int i,j,n,m,a[5][5],pare; clrscr(); printf("\nintroduceti numrul de linii"); scanf("%d",&n); printf("\nintroducei numrul de coloane"); scanf("%d",&m); printf("\nintroducei elementele matricei:\n"); for(i=0;i<n;i++) for(j=0;j<m;j++) { printf("a[%d][%d]=",i,j); scanf("%d",&a[i][j]); }

45

printf("\nAfim elementele matricei:\n"); for(i=0;i<n;i++) { for(j=0;j<n;j++) printf("%3d",a[i][j]); printf("\n"); } printf("\nAfisam cate elementele sunt pare si impare pe fiecare nie:\n"); for(i=0;i<n;i++) { pare=0; // notam prin k numrul de elemente pare for(j=0;j<n;j++) if(a[i][j]%2==0) //daca se mparte la 2 si restul este zero pare++; printf("%3d",pare); } getch(); }

Exemplul 7.2. Este dat matricea de dimensiunea n*n. S se calculeze produsul unui vector de dimensiunea n cu matricea de dimensiunea n*n, Rezultatul va fi un vector de dimensiunea n.
#include<stdio.h> #include<conio.h> #include<malloc.h> void main() { int i,j,n,m,a[10][10],k=0,s,c[10],b[10]; clrscr(); printf("\nintroduceti numarul de linii"); scanf("%d",&n); printf("\nintroducei elementele matricei:\n"); for(i=0;i<n;i++) for(j=0;j<n;j++) { printf("a[%d][%d]=",i,j); scanf("%d",&a[i][j]); } printf("\nintroducei elementele vectorului:\n"); for(i=0;i<n;i++) { printf("b[%d]=",i); scanf("%d",&b[i]); } printf("\nprodusul unui vector cu o matrice:\n"); for(j=0;j<n;j++) { s=0; for(i=0;i<n;i++) s=s+b[i]*a[i][j]; c[k]=s; k++; } for(i=0;i<n;i++)
printf("%3d",c[i]); getch(); }

Exemplul 7.3. Este dat matricea de dimensiunea n*m. S se afieze maximul pe fiecare coloan dintre elementele pozitive.
#include<stdio.h> #include<conio.h> #include<malloc.h> void main() { int i,j,n,m,*a,max;

46

clrscr(); printf("\nintroducei numarul de linii"); scanf("%d",&n); printf("\nintroducei numarul de coloane"); scanf("%d",&m); a=(int*)malloc(n*m*sizeof(int)); // alocm memorie printf("\nintroducei elementele matricei:\n"); for(i=0;i<n;i++) for(j=0;j<m;j++) { printf("a[%d][%d]=",i,j); scanf("%d",a+i*m+j); } printf("\nAfim elementele matricei:\n"); for(i=0;i<n;i++) { for(j=0;j<n;j++) printf("%3d",*(a+i*m+j)); printf("\n"); } printf("\nAfim maximul pe fiecare coloan:\n"); for(j=0;j<m;j++) { // notm prin max primul element din fiecare coloan max=*(a+0*m+j); for(i=0;i<n;i++) // verificm dac elementul este mai mare ca zero if dac este mai mare dect max if(*(a+i*m+j)>0 && *(a+i*m+j)>max) max=*(a+i*m+j); printf("%3d",max); } free(a); // eliberm memoria ocupat getch(); }

Exemplul 7.4. Este dat matricea de dimensiunea n*m. S se calculeze suma elementelor mai sus de diagonala principal i suma elementelor mai jos de diagonala principal. #include<stdio.h>
#include<conio.h> #include<malloc.h> void main() { int i,j,n,m,*a,sum=0,suma=0; clrscr(); printf("\n introducei numrul de linii"); scanf("%d",&n); a=(int*)malloc(n*n*sizeof(int)); printf("\n introducei elementele matricei:\n"); for(i=0;i<n;i++) for(j=0;j<n;j++) { printf("a[%d][%d]=",i,j); scanf("%d",a+i*n+j); } printf("\nAfim elementele matricei:\n"); for(i=0;i<n;i++) { for(j=0;j<n;j++) printf("%3d",*(a+i*n+j)); printf("\n"); } printf("\nAfisam suma elementelor mai sus de diagonala principal:\n"); for(i=0;i<n;i++) for(j=0;j<n;j++)

47

if(i<j) suma=suma+*(a+i*n+j); printf("%3d",suma); printf("\nAfisam suma elementelor mai jos de diagonala principala:\n"); for(i=0;i<n;i++) for(j=0;j<n;j++) if(i>j) sum=sum+*(a+i*n+j); printf("%3d",sum); free(a); getch(); }

Probleme propuse spre rezolvare: 1. Se d un vector numeric de n elemente i o matrice numeric de dimensiunea m*n. S se nmuleasc matricea cu vectorul. 2. S se determine poziia i elementul maxim dintre elementele maxime de pe fiecare linie a unei matrice de dimensiunea m*n. 3. S se afieze toate elementele pare din matricea dat m*n. 4. Este dat matricea n*n. S se afieze numrul elementelor negative de pe diagonala secundar. i numrul elementelor pozitive de pe diagonala principal. 5. Este dat matricea m*n. S se afieze numrul elementelor negative de pe fiecare linie. i numrul elementelor pozitive de pe fiecare coloan. 6. Determinai de cte ori se ntlnete elementul minimal n matricea de dimensiunea m*n i afiai poziiile unde se gsete. 7. Dintr-o matrice dat M, s se listeze valorile tuturor punctelor a i poziia lor. M[i, j] este considerat punct a dac este minim pe linia i i maxim pe coloana j. 8. S se elimene dintr-o matrice A (cu m linii i n coloane) linia 1 i coloana k i s se listeze matricea rmas. (Nu se va folosi o alt matrice). 9. S se afieze matricea A (cu m linii i n coloane) cu linia m+1 i coloana n+1, unde A[m+1, j] s fie suma elementelor de pe coloana j, cu j de la 1 la m, iar A[i, n+1] s fie suma elementelor de pe linia i, cu i de la 1 la n. 10. Se d o fotografie specificat printr-o matrice ptratic, care conine 0 i 1 (0 pentru punctele albe, 1 pentru punctele negre). Se consider fonul alb, obiectele negre. Iar dac dou puncte negre sunt vecine pe linie, coloan sau diagonal, atunci aparin aceluiai obiect. S se numere cte obiecte distincte apar n fotografie. Exemplu: 1 0 1 0 1010 0010 0 1 0 1. Rezultat: 2. 11. Se numete ptrat magic ptratul N*N, n care sunt nscrise numerele 1,2, .., N2 astfel nct suma numerelor fiecrei linii este egal cu suma elementelor fiecrei coloane i, n plus, cu suma elementelor situate pe cele dou diagonale ale ptratului. Scriei un program, care construiete ptratul magic pentru N dat (2<N<=25). Exemplu: 3 Rezultat: 4 3 8 951 2 7 6. 12. Se consider o matrice ptratic de dimensiune N*N (N<=50), ale crei elemente sunt cifre de la 0 la 9. S se afieze toate elementele situate de asupra diagonalei principale (inclusiv pe diagonal) sub forma unui triunghi, ca n exemplul de mai jos. Datele se citesc de la tastatur. 13. Se d matricea A[N, N] de numere ntregi (N<=10). De parcurs matricea n urtoarea ordine: primul se va afia A[N, 1] A[1, N]. 14. S se verifice dac o matrice A(3,3) de tip ntreg, este sau nu o matrice simetric.

48

15. Se consider un grup format din N2 (N<50) copii de nlimi diferite. Se cere s se aeze n spiral copiii n ordinea cresctoare a nlimilor. Copilul cu nlimea cea mai mic va fi plasat n centrul spiralei. Exemplu: 3 1.80 1.90 1.75 1.65 1.70 1.55 1.68 1.78 1.95. Rezultat: 1.95 1.90 1.80 1.65 1.55 1.78 1.68 1.70 1.75. ntrebri de control: 1. 2. 3. 4. Cum se definete o matrice ? Cte feluri de matrice cunoatei ? Poate matricea include diferite tipuri. Dac da sau nu explicai. Dai exemplu.
int i, j, b[3][3]; for(i=0; i++<3;) for(j=0;j<3;j++) { b[i][j]=8>>(i+j)%3; printf((%4d,*(*(b+i)+j));} printf(\n); Ce se tiprete la ecran? Explicai.

5. Ce nseamn matrice simetric? Explicai. 6. Care este funcia de alocare a memoriei ntr-o matrice. Explicai cum vom aloca memorie pentru matricea *a de dimensiunea n*m. 7. Ce se tiprete la ecran? Explicai.
for(i=0;i<n;i++) for(j=0;j<n;j++) { printf("a[%d][%d]=",i,j); scanf("%d",a+i*n+j); }

49

Lucrare de laborator N8
Tema: Subprograme. Scopul lucrrii: Definirea subprogramelor-utilizator, apelarea i aplicarea lor. Suport teoretic: Subprogramele snt uniti de program care: au un algoritm propriu, pot fi proiectate independent, pot fi scrise independent, pot fi compilate independent, nu se pot executa independent ci numai n cadrul unui program (apel). Avantajele utilizrii lor: evitarea scrierii repetate a aceluiai set de instruciuni, creterea eficienei, prin reutilizarea subprogramelor (biblioteci de subprograme). Programele se pot descompune n subprobleme (module), adic n grupe de aciuni care se pot repeta de un numr de ori i care se execut numai n funcie de anumite condiii. Acest lucru determin existena unui modul principal pentru prelucrrile principale i pentru activarea subordonailor. Cnd se apeleaz un subprogram, executarea continu cu prima instruciune din respectivul subprogram. Cnd se termin executarea instruciunilor din subprogram, se continu cu instruciunea urmtoare apelului, din blocul apelant. Subprogramele in limbajul C++ se numesc funcii. Subprogramele pot fi: standard (predefinite) sau nestandard (utilizator) Exemple de funcii sdandard utilizate frecvent: Funcii de i/o: gets (), fgets (), puts (), scanf (), printf (), getch (), getchar (), fscanf (), Funcii de lucru cu iruri de caractere: strlen (), strcat (), strchr (), strcmp (), atoi (), Funcii matematice: exp(), log(), sin(), cos(), ceil(), floor(), pow(), sqrt(), abs(), Ce trebuie s tim despre funcii? cum le putem defini, cum s le apelm, cum s stabilim legtura dintre funcie i programul apelant. Definiia conine antetul funciei i corpul acesteia. Nu este admis definirea unei funcii n corpul altei funcii. Sintaxa antetului: tip_rezultat nume (lista parametrilor formali); Aici tip_rezultat poate fi : un tip standard, o adres a unui tip definit anterior, o structur de tip articol. Dac este omis se consider ca fiind tipul int. sau void nume (lista parametrilor formali) Dac are tipul void , apelul la funcie se face dintr-o linie de program aparte. n celelalte cazuri poate fi parte component a unor expresii. Lista parametrilor formali este o list separat prin virgule de nume de variabile i tipurile asociate lor, care primesc valorile argumentelor atunci cnd este apelat funcia. O funcie poate s nu aib parametri. Totui, parantezele sunt necesare, chiar dac nu exist parametri. Toi parametrii funciei trebuie declarai individual, fiecare coninnd att tipul ct i 50

numele. Ei snt creai la intrarea n funcie i distrui la ieirea din ea. Parametrilor formali li se pot aplica atribuiri sau folosii n expresii. Aceste variabile ndeplinesc sarcina de primire a valorilor argumentelor transmise funciei. Corpul funciei este un bloc, care implementeaz algoritmul de calcul folosit de ctre funcie. n corpul funciei apar (n orice ordine) declaraii pentru variabilele locale i instruciuni. Dac funcia ntoarce o valoare, se folosete instruciunea return valoare. La execuie, la ntlnirea acestei instruciuni, se revine n funcia apelant. Sfera de influen a funciilor. Fiecare funcie este un bloc de cod discret. Nici o instruciune din alt funcie nu poate avea acces la el dect printr-un apel al funciei. De exemplu nu putem folosi goto pentru a sri n mijlocul altei funcii. Codul i datele definite ntr-o funcie nu pot s interacioneze cu codul sau cu datele definite n alta, deoarece cele dou funcii au diferite sfere de influen. Variabilele definite ntr-o funcie se numesc variabile locale. Clasa de memorare este segmentul de stiv. Ele snt vizibile doar la nivelul blocului n care au fost declarate. Durata de via este egal cu durata execuiei blocului respectiv. Adic variabilele locale nu-i pstreaz valoarea ntre apelrile funciei. Excepie este atunci cnd variabila se declar cu specificatorul de clas de memorie static. Variabilele globale se declar n afara oricrei funcii i pot fi utilizate de toate funciile care urmeaz declaraiei respective. La declarare acestea snt iniializate automat cu 0. Ele au alocat spaiu n tot timpul execuiei programului. Sunt utile atunci cnd mai multe funcii ale aceluiai program folosesc aceleai date. Observaie: n C++ toate funciile au acelai nivel de influen. Asta nseamn c nu pot fi definite ntr-o funcie alte funcii. Funcia se utilizeaz prin apelare la ea. Apelul funciei este o construcie urmat de punct i virgul, numit instruciune de apel, de forma: nume_funcie (lista_parametrilor_efectivi); Parametrii efectivi trebuie s corespund cu cei formali ca ordine i tip. La apel, se atribuie parametrilor formali valorile parametrilor efectivi, dup care se execut instruciunile din corpul funciei. La revenirea din funcie, controlul este redat funciei apelante, i execuia continu cu instruciunea urmtoare instruciunii de apel, din funcia apelant. O alt posibilitate de a apela o funcie este aceea n care apelul funciei constituie operandul unei expresii (apelul funciei intervine intr-o expresie). Acest lucru este posibil doar n cazul n care funcia returneaz o valoare, folosit n calculul expresiei(doar pentru funciile cu tip). La ntlnirea instruciunii return, dup atribuirea valorii, execuia funciei se ncheie i se revine la funcia care a apelat-o. n absena instruciunii return, execuia funciei se ncheie dup execuia ultimei instruciuni. n acest caz nu se ntoarce nici o valoare. Parametrii declarai n antetul unei funcii sunt numii formali, pentru a sublinia faptul c ei nu reprezint valori concrete, ci numai in locul acestora pentru a putea exprima procesul de calcul realizat prin funcie. Ei se concretizeaz la execuie prin apelurile funciei. Parametrii folosii la apelul unei funcii sunt parametri reali, efectivi, concrei, actuali iar valorile lor vor fi atribuite parametrilor formali, la execuie. Utilizarea parametrilor formali la implementarea funciilor i atribuirea de valori concrete pentru ei, la execuie, reprezint un prim nivel de abstractizare n programare. Acest mod de programare se numete programare procedural i realizeaz un proces de abstractizare prin parametri. Funciile comunic prin argumente: ele primesc ca parametri (argumente) datele de intrare, efectueaz prelucrrile descrise n corpul funciei asupra acestora i pot returna o valoare (rezultatul, datele de ieire). Transmiterea parametrilor se poate realiza: prin valoare. Aceast metod copiaz valoarea unui argument ntr-un parametru formal al subprogramului. n acest caz modificrile efectuate asupra parametrului nu au efect asupra argumentului; 51

prin referin (adres). Prin aceast metod n parametru se copiaz adresa unui argument. Aceasta nseamn c modificrile efectuate asupra parametrului afecteaz argumentul. Se utilizeaz dac e necesar a transmite n programul apelant mai mult dect o valoare. Cu puine excepii, C++ folosete apelarea funciilor prin valoare. Cnd o matrice este folosit ca un argument al unei funcii, acesteia i este pasat adresa matricei. Astfel, codul funciei opereaz asupra coninutului efectiv al matricei i poate s-l modifice.

Funciile pot fi descrise n cadrul aceluiai fiier, sau n fiiere diferite, care sunt testate i compilate separat, asamblarea lor realizndu-se cu ajutorul linkeditorului de legturi. Funcii recursive se folosesc la programarea proceselor de calcul recursive. Recursivitatea este procesul de definire a unui lucru prin el nsui. Se spune despre o funcie c este recursiv, dac o instruciune din corpul ei apeleaz chiar acea funcie. Funcia de calcul al factorialului e un exemplu simplu de funcie recursiv. n limbajul C funcia recursiv fact(n) poate fi realizat astfel:
double fact(int n) { if(n==0) return 1.0; else return n*fact(n-1); }

Exemple de programe: Exemplul 8.1. Funcia afisare afieaz 65 de simboluri * consecutive.


#include<stdio.h> #define NAME Vasilache Andrei #define ADDRESS Cogalniceanu, 65 #define LIM 40 void afisare(void); void main() { afisare(); printf(\t%s\t,NAME); printf(%s\n,ADDRESS); afisare(); } void afisare() { int n; for(n=1; n<=LIM; n++) putchar(*); putchar(\n); }

// prototipul funciei //apelul funciei // al doilea apel al funciei

n urma execuiei programului vom avea afiat p ecran: **************************************** Vasilache Andrei Cogalniceanu,65 **************************************** Exemplul 8.2. Programul efectueaz acelai lucru; dar funcia are doi parametri : un caracter i un ntreg.
#include<stdio.h> #define NAME Vasilache Andrei #define ADDRESS Cogalniceanu, 65 #define LIM 65 #define SPACE void show_n_char(char ch, int n); // prototipul funciei void main() { int spaces; show_n_char(*,LIM); // apelul funciei putchar(\n);

52

show_n_char(SPACE,20); printf(%s,NAME); spaces=(60-strlen(ADDRESS))/2; show_n_char(SPACE, spaces); printf(%s\n,ADDRESS); show_n_char(*,LIM); // al doilea apel al funciei } void show_n_char(char ch,int n) { int i; for(i=1; i<=n; i++) putchar(ch); }

Exemplul 8.3. Programul nmulete dou valori ntregi, utiliznd o funcie.


#include<stdio.h> int prod(int a, int b) { return a*b; } void main() { int x,y,z; x=10; y=20; z=prod(x,y); // funcia e atribuit folosit ntr-o expresie printf(%i, prod(x,y)); // funcia nu e atribuit, dar e folosit prod(x,y); // valoarea returnat se pierde }

Exemplul 8.4. Programul calculeaz factorialul pentru numerele din intervalul 0 170, utiliznd o funcie.
#include<stdio.h> #include<stdlib.h> double fact(int n); // prototipul funciei void main() { for (int m=0;m<171;m++) {printf(m=%d \t m!=%g \n,m, fact(m)); if((m+1)%23==0) { puts(actionati o tasta); getch(); } } double fact(int n) { double f; int i; if(n<0 || n>170) return -1.0; for(i=2, f=1.0; i<=n; i++) f*=i; return f; }

// sau if(wherex()==23)

Exemplul 8.5. Funcia calculeaz cel mai mare divizor comun a dou numere ntregi fr semn.
unsigned dc(unsigned a, unsigned b) { unsigned c, d=1; if (a==0||b==0) return a>b?a:b; else for(c=2;c<=(a<b?a:b);c++) if(a%c==0 && b%c==0) d=c; return d; }

Exemplul 8.6. Programul citete dou numere ntregi fr semn i calculeaz cel mai mic multiplu comun al lor. Este folosit funcia din exemplul precedent care a fost salvat n fiierul d:\bc\director\ex8_5.cpp
#include<stdio.h> #include<conio.h> #include d:\\bc\\director\\ex8_5.cpp void main() { unsigned a, b, c; clrscr();

53

puts(introdu doua numere fara semn:); scanf(%u%u,&a,&b); c=dc(a,b); printf(cmmmc(a,b)=%u,a*b/c); getch(); }

Exemplul 8.7. S se determine o rdcin a ecuaiei 6cos(x)+8sin(x)=0 pe segmentul [2,4] cu precizia eps=0.00017 prin metoda biseciei.
#include<stdio.h> #include<conio.h> #include<math.h> #define eps 0.0001 float f( float x) { return 6*cos(x)+8*sin(x);} void main() { clrscr(); float a=2.0, b=4.0; float ya,yc; double c; int n=0; lab1: c=(a+b)/2.0; ya=f(a); yc=f(c); n++; if ((c-a)<=eps){ printf("%7.4f-radacina aproximativa,n=%d",c,n); goto end; } if(n>=100) { printf ("convergenta slaba, n=%d",n); goto end; } if((ya*yc)<0){ b=c; goto lab1; } else { a=c; goto lab1; } end: getch(); }

Exemplul 8.8. Funcia schimb cu locurile simbolul cu cod maxim cu simbolul cu cod minim ntr-un ir de caractere
#include<stdio.h> #include<conio.h> void fct(char *s); void main() { int i; char *sir; puts(Input string:); gets(sir); fct(s); puts(s); } void fct(char *s) { int i = 0, max = *s, min = *s, pmin = 0, pmax = 0; char ch; for ( ; s[i]; i++) { if (s[i]>max) { max = s[i]; pmax = i; } if (s[i]<min) { min = s[i]; pmin = i; } } ch=*(s+pmax); *(s+pmax)=*(s+pmin); *(s+pmin)=ch; }

Exemplul 8.9. Programul prelucreaz un ir numeric. Se utilizeaz o funcie de citire a elementelor i o funcie ce returneaz numrul de elemente pare negative din ir.
#include<stdio.h> #include<conio.h> // prototipul functiei de citire a elementelor in masiv void citire(int s[], int n); // prototipul functiei de numarare a elementelor pare negative int numar(int s[], int n); void main() {

54

int i, m[10], dim; puts(dimensiunea sirului numeric:); scanf(%i,&dim); citire(m,dim); printf(sint %i numere pare negative, numar(m,dim)); } void citire(int s[], int n) { puts(Elementele masivului:); for(int i=0; i<n; i++) scanf(%i,&s[i]); } int numar(int s[], int n) { int i, c=0; for(i=0; i<n; i++) if(s[i]<0 && s[i]%2==0) c++; return c; }

Exemplul 8.10. Programul afieaz elementul maxim de pe liniile unei matrice. Se utilizeaz o funcie care primete drept argumeni un pointer la matrice i numrul liniei.
#include<stdio.h> #include<stdlib.h> int n, m; // variabile globale, acestea fiind dimensiunea matricei // prototipul functiei de determinare a elementului maxim pe linia k int max(int *p, int k); void main() { int *p, i, j, z; puts(dimensiunea matricei:); scanf(%i%i,&n, &m); //alocare dinamic de memorie pentru matrice p = (int*)malloc(n*m*sizeof(int)); for(i=0; i<n; i++) { for(j = 0; j < m; j++) { *(p+i*m+j)= random(11); // generare aleatoare a elementelor matricei printf( %i , *(p+i*m+j)); } printf(\n); } for( i = 0; i < n; i++) { // funcia primete ca argumeni pointerul la matrice i numrul liniei z = max(p,i); printf(Maximum pe linia %i - %i\n, i+1, z); } } int max(int *p, int k) { int M, x; M=*(p+k*m+0); for( x = 0; x < m; x++) if ( M < *(p+k*m+x) ) M = *(p+k*m+x); return M; }

Exemplul 8.11. Programul sumeaz componentele unui ir numeric. Se utilizeaz o funcie recursiv
#include<stdio.h> #include<conio.h> int suma(int v[], int n); // prototipul functiei recursive void main() { int i, a[10], dim; puts(dimensiunea sirului numeric:); scanf(%i,&dim); for(i = 0; i < dim; i++) scanf(%i,&a[i]); printf(suma elementelor - %i, suma(a,dim-1));

55

getch(); } int suma(int v[], int n) { if(n == 1) return 0; else return (v[n-1] + suma(v,n-1); }

Exemplul 8.12. Funcia cu numr variabil de parametri sumeaz numere ntregi.


#include<stdio.h> #include<conio.h> int suma(int m,...); // prototipul funciei cu numr variabil de parametri void main() { printf(suma elementelor - %i, suma(2,6,4)); printf(suma elementelor - %i, suma(6,1,2,3,4,5,6)); getch(); } int suma(int m,...) { int *p=&m, t=0; for(; m; m--) t += *(++p); return t; }

Probleme propuse spre rezolvare: 1. S se realizeze un program care conine o funcie ce citete elementele unui vector de dimensiunea n cu valori ntregi i o funcie ce returneaz cte elemente impare pozitive sunt. 2. S se realizeze un program care conine o funcie ce citete elementele unui vector de dimensiunea n cu valori ntregi i o funcie ce returneaz produsul elementelor pare pozitive. 3. S se realizeze un program care conine o funcie ce citete elementele unui vector de dimensiunea n cu valori reale i o funcie ce returneaz indicele celui mai mare element. 4. S se realizeze o funcie care primete un simbol ca parametru i returneaz numrul lui de ordine dac-i liter i -1 n caz contrar. (De ex.: i c i C sunt litere cu numrul de ordine 3). 5. S se realizeze o funcie care primete un ir de simboluri ca parametru i returneaz 1 dac irul e palindromic (se citete la fel din ambele direcii) i 0 n caz contrar. 6. S se realizeze un program care conine o funcie ce citete elementele unui vector de dimensiunea n cu valori ntregi i o funcie ce returneaz lungimea celui mai lung subir nedescresctor din acest tablou. 7. Programul calculeaz suma ptratelor numerelor din segmentul [m,n]. Se folosete o funcie recursiv pentru a calcula suma. 8. Programul determin cel mai mic numr dintr-un ir numeric. Se folosete o funcie recursiv. 9. Programul afieaz cuvintele cu lungimea mai mare dect 6 simboluri dintr-un ir de caractere, care este pasat unei funcii. 10. Date numerele reale s, t. De obinut y = f( t, -2s, 1.47 ) + f( 2.2, t, s-t ), unde 2a b sin c f (a, b, c) = 5+ | c | max(a, a + b) + max(a, b + c) 11. Date numerele reale a, b, c. De calculat y = . 1 + max(a + bc,1.15) ntrebri de control: 1. O funcie este total caracterizat de : ... 2. Dac funcia f are urmtorul prototip: tip f(lista parametrilor), atunci tip poate fi: i. vector ii. structur iii. ntreg, real sau caracter 56

iv. pointer spre un tip definit anterior v. tablou bidimensional 3. Cum se numesc parametrii folosii la definiia unui subprogram? 4. O funcie ntoarce obligatoriu o valoare? 5. O funcie trebuie s conin obligatoriu parametri? 6. Ce tipuri de subprograme cunoatei? 7. Ce trebuie s tim despre funcii? 8. Ce prezint antetul funciei? 9. Ce metode de transmitere a argumenilor n funcii cunoatei? 10. Ce este o funcie recursiv? 11. Funciile trebuie definite i descrise obligator n acelai fiier cu programul apelant? 12. Ce va tipri funcia?
int a=1; void f() { int b=1, c=1; printf(a=%i b=%i c=%i\n, a++, b++, c++); void main() { while(a<4) f(); } }

13. Ce va tipri funcia?


int fun(int n, int a, int b) { int z=1, i; for (i=1; i<n; i++) z=z+a*b; return z; void main() { int x=5, y=6, j=1; while (j<6) { printf(%i %i \n, j, fun(j,x,y)); j++; } } }

14. Ce se va afia n urma rulrii programului?:


f(int a, int &b, int c) { a=++b; c=a+=2; return a+b+c/3; } void main() { int a, b, c; a=b=c=1; printf(a=%i b=%i c=%i f=%i, a, b, c, f(a,b,c));

15. Ce valori va returna funcia f() apelat n programul principal?


int f(const char *s) { int n=0; for( ; *s++ != \0; n++ ); return n; } void main() { printf( %s, f(informatica);

57

Lucrare de laborator N9
Tema: Tipuri de date definite de utilizator, redenumirea tipurilor. Scopul lucrrii: Definirea i utilizarea unui tip nou de date: structuri, reuniuni, enumerri, cmpuri de bii; nsuirea modalitii de redenumire a tipurilor. Suport teoretic: Un mod de grupare al datelor este tabloul. Tabloul este un set ordonat de date de acelai tip. Un alt mod de grupare al datelor este structura. Structura reunete date de diferite tipuri, dar care se afl ntr-o legtur logic. Obiectele ce fac parte din structur se numesc cmpuri sau membrii structurii. La definirea i utilizarea structurilor e necesar a cunoate trei lucruri: 1) definirea structurii; 2) declararea variabilei, care corespunde acestui tip; 3) asigurarea accesului la componentele variabilei-structur. O declaraie de structur are forma:
struct nume { lista de declaraii } nume1, nume2,, numen;

Aici nume definete un tip nou de date, iar nume1, nume2,..., numen sunt structuri, adic variabile de tipul nume; lista de declaraii declar componentele structurii de tip nume. Exemplu de definire: struct { char title[20]; int year; float value; };. Structura dat are 3 cmpuri. In unul se pstreaz denumirea crii, n altul anul ediiei, n al treilea preul. Tipului structur i se poate asocia un nume generic, care poate fi indicat n forma: typedef struct { char title[20]; int year; float value; } book ;. Specificatorul typedef este executat de ctre compilator, nu de ctre preprocesor ca #define. n continuare numele generic book poate fi utilizat la definirea noilor structuri. Exist i alt modalitate de asociere a numelui generic tipului structura: struct book { char title[20]; int year; float value; };. Aceast modalitate este necesar la definirea structurilor recursive deoarece typedef nu este suficient: struct node{ int date; node* next; };. Structura S nu poate conine membri de tipul S, dar poate conine membri ce pointeaz ctre S. Observaie: cnd definii o structur, definii nu o variabil, ci un tip compus de variabile. Nu va exista nici o variabil pn nu vei declara una de acest tip. Declararea variabilelor de tip structur se poate face odat cu definirea ei: struct { char title[20]; int year; float value; } date1, mas[10];. n C++ dac a fost deja declarat o structur, putem declara variabile de acest tip folosind doar numele ei generic, fr a preceda cu cuvntul cheie struct. De exemplu avnd declararea struct book { char title[20]; int year; float value; }; putem declara book date2, date3[10]. Cnd este declarat o variabil de tip structur compilatorul de C/C++ aloc automat suficient memorie pentru toate elementele ei. Lungimea zonei de memorie rezervat pentru variabila de tip struct rezult din nsumarea lungimilor cmpurilor. Aceasta nu poate depi 65520 octei (ca orice variabil de tip structurat). Pentru o structur i dovedete utilitatea operatorul sizeof, care asigur determinarea lungimii zonei de memorie asociate unei variabile sau unui tip de date. Accesul la membrii stucturii se face n dou moduri: global sau pe componente. Referirea global este permis numai n operaia de atribuire, cu condiia ca ambele variabile (surs i destinaie) s aib acelai tip. Referirea pe componente (prin numele lor) este o reflectare a faptului c articolul este o structur cu acces direct. Referirea cmpurilor unei structuri se face prin calificare, folosind operatorul. (punct). De exemplu: dac declarm book libry, identificatorul libry.value indic la membrul value al structurii libry. Identificatorul libry.value 58

este variabil de tipul float i se utilizeaz asemntor variabilelor de acest tip, ca de exemplu: scanf( %f ,&libry.value). Dac sunt declarate dou variabile a i b de acelai tip structur putem efectua atribuirea a=b. Nu se admite atribuirea ntre variabile de tip structur care aparin abloanelor diferite, fie i foarte asemntoare. Se pot declara pointeri ctre structuri. Exist dou ntrebuinri ale pointerilor pentru structuri : generarea unei apelri de funcii prin referin i crearea listelor nlnuite. De exemplu : struct bal { float bilan; char nume[80]; } pers, *pstr;. Atunci pstr=&pers; plaseaz adresa structurii pers n pstr. Pentru a avea acces la membrii structurii folosind acest pstr se utilizeaz operatorul ->: pstr->bilan , pstr->nume[0]. Un alt mod de grupare a datelor este reuniunea. Diferena este doar aceea c se substituie cuvntul struct prin cuvntul union. Declararea tipului reuniune se realizeaz astfel: union nume_tip { tip_cimp1 cimp1; tip_cimp2 cimp2; ...; tip_cimpn cimpn;}; Spre deosebire de o structur lungimea zonei de memorie rezervate pentru o variabil de tip reuniune va fi egal cu maximul dintre lungimile cmpurilor componente. Gestiunea coninutului respectivei zone de memorie va trebui realizat de ctre programator. Referirea la elementele unei reuniuni se face ca i la structuri. Exemplu de declarare de reuniune: union a { int x; long y; double z; char z[5]; } p, r[6], *t; Aici s-au declarat reuniunea p de tipul a, tabloul de reuniuni r ce const din 6 elemente i fiecare element este o reuniune de tipul a, un pointer t ce pointeaz spre acelai tip a. Pentru fiecare reuniune declarat se vor aloca cte 8 octei, deoarece tipul double necesit 8 octei numrul maxim. Un alt tip definit de utilizator este tipul enumerare. Acest tip permite folosirea numelor sugestive pentru valori numerice. O declaraie de tip enumerare are forma: enum nume_generic { nume0, nume1, , numen} list_variabile; Aici nume_generic este numele tipului enumerare nou declarat, nume0, nume1,..., numen sunt numele sugestive care se vor folosi n continuare n locul valorilor numerice 0, 1, ..., n i anume: nume0 substituie valoarea 0, nume1 substituie valoarea 1, ..., numen substituie valoarea n. Iar list_variabile sunt declarate variabile de tipul nume_generic, adic variabile de acest tip enumerare. Aceste variabile sunt similare cu variabilele de tip int. De exemplu definim enum season { win,spr,sum,aut } s; Atunci printf(%d %d, spr,sum) va afia 1 2. La declaraia tipului enumerare se pot impune i alte valori pentru numele sugestive. De exemplu, dac vom folosi construcia numei=si n loc de numei n lista numelor sugestive, atunci aceasta va impune pentru numele sugestiv numei valoarea si. Respectiv numei+1 va avea valoarea si+1. Dac definim n felul urmtor enumerarea de mai sus enum seazon { win=1,spr,sum,aut } s; Atunci printf(%d %d, spr,sum) va afia 2 3. Limbajul de programare C permite accesul la unul sau mai muli bii din octet. Una din metodele de prelucrare pe bii este organizarea unui tip nou tipul cmpuri de bii. Acetia sunt

59

structuri speciale n care se definesc numrul de bii ocupai de fiecare element. O declaraie pentru un tip cmpuri de bii are forma:
struct nume { tip nume_cimp1 : lungime_cimp ; tip nume_cimp2 : lungime_cimp ; tip nume_cimpn : lungime_cimp ; } n1, n2,..., nm;

Aici tip poate fi unsigned, int, signed, char, unsigned char, iar lungime_cimp este lungimea cmpului n bii i nu poate depi doi octei. Numele cmpului poate lipsi, atunci el definete o zon de bii ne utilizat din octetul respectiv. Lungimea cmpului poate fi 0, atunci cmpul urmtor se aloc n octetul urmtor. Biii se aloc ncepnd de la biii de ordin inferior ai octetului spre cei de ordin superior. Dac un cmp nu ncape n octetul curent, el se aloc n octetul urmtor. Referirea la cmpurile de bii se face ca i n cazul structurilor obinuite. Exemplu de declarare a tipului cmpuri de bii:
struct BITFIELDS { unsigned a : 2; int b : 4; unsigned c : 1; unsigned : 3; int d : 2 ; } x;

Aici este declarat variabila x de tipul cmpuri de bii. Aceast declarare ne asigur urmtoarea amplasare: 15 14 13 12 ne utilizai 11 d 10 9 8 7 ne utilizai 6 c 5 4 b 3 2 1 a 0

Dac cmpul d ar fi avut lungimea mai mare dect 6 ar fi fost amplasat automat n urmtorul octet. Pentru a regla n mod forat acest lucru se folosete, dup cum s-a spus mai sus, lungimea 0 a unui cmp. n structuri pot fi utilizai n comun att componente obinuite ct i cmpuri de bii. De exemplu:
struct angajat { char nume[20]; float plata; unsigned active : 1; unsigned impozit : 3; // activ sau ntrerupt }

; definete o nregistrare despre salariat care folosete doar un octet pentru a pstra dou informaii: statutul angajatului i impozitul. Variabilele de tip cmpuri de bii au i restricii: 1) nu putem obine adresa unui cmp de bii; 2) nu pot fi introduse n tablouri. C admite o facilitate numit typedef pentru a crea nume pentru noi tipuri de date. O astfel de declaraie de tip are forma:
typedef nume_tip_vechi nume_tip_nou;

De exemplu declaraia: typedef int LENGTH; face numele LENGTH sinonim pentru "int". Tipul LENGTH poate fi utilizat n declaraii exact la fel ca int:
LENGTH len, maxlen; LENGTH *lengths[];

Similar, declararea: typedef char* STRING; face ca STRING sa fie sinonim cu char* sau pointerul unui caracter, care poate fi utilizat n declaraii ca: STRING p, lineptr[LINES] ; 60

Exemple de programe: Exemplul 9.1. Programul simplific o fracie raional. Simplificarea se face prin mprirea numrtorului i numitorului la cel mai mare divizor comun al lor.
#include<conio.h> #include<stdio.h> void main() {// cmpul n reprezint numrtorul, m - numitorul typedef struct { long unsigned n; long unsigned m; } Rational; Rational s; long unsigned k, cmmdc=1, h; clrscr(); puts(Introducei o fracie raional); scanf (%lu%lu,&s.n,&s.m) ; puts(Ai introdus fracia: ); printf(%lu/%lu\n,s.n,s.m); h=s.n < s.m ? s.n : s.m; // h este minimul dintre numrtor i numitor for(k=1;k<h/2;k++) if(s.m%k==0 && s.n%k==0) cmmdc=k; s.n=s.n/cmmdc; s.m=s.m/cmmdc; puts(Fracia simplificat este:); printf(%lu/%lu,s.n,s.m); getch(); }

Exemplul 9.2. Programul declar o structur carte care conine 3 elemente. Primul element conine numele autorului, al doilea denumirea crii, al treilea preul. Sunt prelucrate informaiile despre cteva cri.
#include<conio.h> #include<stdio.h> #define maxc 100 struct carte { char nume[20]; char titlu[40]; float pret; } void main() { carte bibl[maxc]; // tablou de cri int i, c=0; puts(Dati titlul crii. Pentru sfrit acionai [enter] la nceput de linie); while ( c<maxc && gets(bibl[c].titlu) !=NULL && bibl[c].titlu[0] != \0 ) { puts(Autor:); gets(bibl[c].nume); puts(Preul:); scanf(%f, &bibl[c++].pret); fflush(stdin); // golirea intrrii puts(Introducei titlul urmtoarei cri:); } puts(Iat lista crilor); for (i=0;i<c;i++) printf(%s, %s : $%.2f\n,bibl[i].titlu, bibl[i].nume, bibl[i].pret); }

Exemplul 9.3. Se d o list de persoane i punctajele obinute de acestea la un concurs. Programul ordoneaz descresctor persoanele n funcie de punctaj i afieaz lista ordonat.
#include<conio.h> #include<stdio.h> #define max 20 struct persoana { char nume[max]; int punctaj ; } ; int Citeste ( persoana p[]) { int i,n;

61

printf(Dai numrul de persoane: ); scanf(%d,&n); for (i=0; i<n; i++) {fflush ( stdin ); printf ( Dai numele persoanei nr. %d: , i+1); gets( p[i].nume ); p[i].nume[max]=\0 ; printf ( Dai punctajul lui %s: , p[i].nume ); scanf ( %d, &p[i].punctaj ) ; fflush ( stdin ) ; } return n; } void Schimba ( persoana *a, persoana *b) { persoana aux; aux=*a; *a=*b; *b=aux; } int Ordoneaza ( persoana p[], int n) { int i, j, ord=1 ; for ( i=0 ;i<n-1 ;i++) if ( p[i].punctaj<p[i+1].punctaj ) ord=0 ; if ( !ord ) { for ( i=0; i<n-1; i++ ) for ( j=i+1; j<n; j++) if ( p[i].punctaj<p[j].punctaj ) Schimba ( &p[i], &p[j] ); } return ( !ord ); } void Afiseaza ( persoana *x, int n ) { int i; for ( i=0; i<n; i++ ) printf ( %d. %20s -> %4d. \n , i+1, x[i].nume, x[i].punctaj ); } void main() { persoana x[max]; // irul persoanelor int n; clrscr(); puts ( Ordonare personae dupa punctaj ); if (( n = Citeste(x))==0 ) puts ( Nu exista persoane. ); else { if ( Ordoneaza (x,n) puts ( Am ordonat persoanele ); else printf ( Persoanele erau deja ordonate\n ); Afiseaza(x,n); } getch(); }

Exemplul 9.4. Programul exemplific folosirea reuniunilor pentru citirea i afiarea datelor despre mai multe persoane de ambele sexe.
#include<conio.h> #include<stdio.h> #include<stdlib.n> union partener { char sotie[20]; char sot[20]; } ; struct persoana { char nume[20]; char sex; int virsta; union partener p; } ; void Citeste ( int nr_p, persoana *x ) { int vs; char sx; printf ( Se citesc datele persoanei a %d-a:\n, nr_p ); fflush ( stdin ); puts ( Numele: ); gets ( x->nume );

62

puts ( Virsta: ); scanf ( %d, &vs ); x->virsta=vs; fflush ( stdin ); puts ( Sexul: ); scanf ( %c, &sx ); x->sex=sx; fflush ( stdin ); if ( x->sex==F || x->sex==f ) { puts ( Dati numele sotului: ); gets ( x->p.sot ); } else { puts ( Dati numele sotiei: ); gets ( x->p.sotie ); } } void Scrie ( int nr_p, persoana x ) { if ( wherey ()==20 ) { puts ( Apasati o tasta ); getch(); } printf ( Datele persoanei a %d-a:\n, nr_p ); printf ( Numele: %s Virsta: %d Sexul: %c , x.nume, x.virsta, x.sex ); if ( x.sex==F || x.sex==f ) printf ( Numele sotului: %s\n, x.p.sot ); else printf ( Numele sotiei: %s\n, x.p.sotie ); } void main() { clrscr(); persoana om[20]; int i,n; puts ( Dati numarul de personae: ); scanf ( %d, &n ); for ( i=0; i<n; i++) Citeste ( i+1, &om[i] ); for ( i=0; i<n; i++ ) Scrie ( i+1, om[i] ); getch(); }

Exemplul 9.5. Programul afieaz codul binar ASCII al simbolului introdus de la tastatur.
#include<stdio.h> #include<conio.h> struct byte { int b1:1; int b2:1; int b3:1; int b4:1; int b5:1; int b6:1; int b7:1; int b8:1; } ; union bits { char ch; byte bit;} b; void decode ( bits b ); void main() { do { b.ch=getche(); printf ( ":" ); decode ( b ); } while ( b.ch!='q' ); } void decode ( bits u ) { if ( u.bit.b8 ) printf ( "1" ); else printf ( "0" ); if (u.bit.b7 ) printf ( "1" ); else printf ( "0" ); if ( u.bit.b6 ) printf ( "1" ); else printf ( "0" ); if ( u.bit.b5 ) printf ( "1" ); else printf ( "0" ); if ( u.bit.b4 ) printf ( "1" ); else printf ( "0" ); if ( u.bit.b3 ) printf ( "1" ); else printf ( "0" ); if ( u.bit.b2 ) printf ( "1" ); else printf ( "0" ); if ( u.bit.b1 ) printf ( "1" ); else printf ( "0" ); printf ( "\n" ); }

63

Exemplul 9.6. Programul exemplific folosirea enumerrilor.


#include<stdio.h> #include<conio.h> enum spectrum { red, orange, yellow, green, blue, violet } ; void main() { enum spectrum color; puts ( Introduceti culoarea ( pentru ieire tastai q ) ); while ( ( scanf (%d, &color)) == 1 ) { switch ( color ) { case red : puts ( Trandafirii sunt rosii ); break; case orange : puts ( Macii sunt orange ); break; case yellow : puts ( Florile florii soarelui sunt galbene ); break; case green : puts ( Iarba este verde ); break; case blue : puts ( Clopoeii sunt albatri ); break; case violet : puts ( Toporasii sunt violeti ); break; default : printf ( Nu cunosc nimic de culoarea data.\n ); } puts ( Urmatoarea culoare ); } }

Exemplul 9.7. Programul declar un tablou de structuri student cu elementele: nume numele studentului, tabloul note[5] pentru a pstra notele, med pentru pstrarea notei medii. Se utilizeaz funciile de introducere a datelor despre fiecare student, de calculare a notei medii fiecrui student i atribuirii ei variabilei med, de afiare a listei studenilor. #include<stdio.h>
#include<conio.h> #include<stdlib.h> struct student { char nume[10]; int note[5]; float med; }; void initiere (student * s, int n); void calcul (student * s, int n); void afisare (student * s, int n); void main() { int n; clrscr(); student *m; puts (Dai numrul de studeni:); scanf (%d, &n); m=(student*)malloc(n*sizeof(student)); initiere (m,n); calcul (m,n); afisare (m,n); getch (); } void initiere (student * s, int n) { int i, j, q; for ( i=0; i<n; i++ ){ fflush ( stdin ); printf ( "nume %i: ", i+1 ); gets ((s+i)->nume); for ( j=0; j<5; j++ ) { printf ( "nota %i: ",j+1); scanf ( "%i",&q ); (s+i)->note[j]=q; } } } void calcul ( student* s, int n) { int i,j; float f; for (i=0; i<n; i++ ) { f=0.0;

64

for ( j=0; j<5; j++ ) (s+i)->med=f/5.0;

f+=(s+i)->note[j];

} } void afisare ( student *s, int n) { puts (" NUME | MEDIA "); for ( int i=0; i<n; i++ ) printf ( "%-10s|%7.1f\n",(s+i)->nume, (s+i)->med ); }

Probleme propuse spre rezolvare: 1. Programul realizeaz operaii cu fracii raionale ( introducere, extragere, atribuire, inversare, adunare, scdere, nmulire, mprire ). 2. Programul realizeaz admiterea la un liceu i permite: iniializarea vectorului de nregistrri de tip elev; adugarea unui elev n vector; nlocuirea unui elev cu alt elev; inserarea unui elev pe o anumit poziie n vector; eliminarea din vector a unui elev avnd un anumit nume; cutarea unui elev dup nume; calcularea mediilor; listarea alfabetic a elevilor; listarea elevilor n ordinea descresctoare a mediilor. 3. Programul administreaz un parc de automobile. Informaiile relative la un automobil sunt: numrul de locuri, marca, tipul de carburant, numrul de nmatriculare. Programul permite intrarea unei maini, ieirea unei maini, nlocuirea unei maini cu alta de acelai model (avnd alt numr de nmatriculare). 4. Programul invit utilizatorul s introduc ziua, luna (denumirea prescurtat), anul i afieaz numrul zilelor ce s-au scurs de la nceputul anului pn la ziua introdus. 5. Fiind date dou fracii p i q programul afieaz forma ireductibil a fraciilor p+q, p-q, p/q, p*q, punnd n eviden numrtorul i numitorul acestora. 6. Programul determin de cte ori o persoan nscut n anul A>1900, luna L, ziua z, avnd vrsta v i-a aniversat ziua de natere n aceeai zi a sptmnii cu cea n care s-a nscut. 7. Programul calculeaz valoarea unei expresii raionale. 8. Programul determin denumirea zilei dup o dat calendaristic presupus corect. Folosii tipul union. ntrebri de control: 1. Ce este un tip definit de utilizator ? Care sunt aceste tipuri i necesitatea lor ? 2. Ce este o structur ? Care este deosebirea dintre o structur i un tablou ? 3. Cum se declar o structur ? Cum se face referirea la componentele unei structuri ? 4. Cum se aloc memorie unei structuri ? 5. Definii o structur care s conin denumirea prescurtat a lunii pn la trei simboluri, numrul de zile a lunii i numrul de ordine al lunii. 6. Definii un tablou din 12 structuri ca n punctul 5 i efectuai iniializarea lui pentru un an bisect. 7. Condiia ca dou puncte distincte A i B ( de tip structur) s aparin aceleiai axe de coordonate este: a) A.x==0 && B.x==0 && A.y==0 && B.y==0 b) ( A.x==0 || B.x==0 ) && ( A.y==0 || B.y==0) 65

c) A.x==0 && B.x==0 || A.y==0 && B.y==0 d) A.x==0 || B.x==0 && A.y==0 || B.y==0 8. Este dat un fragment de program:
struct name { char first[20]; char last[20]; } ; struct bem { int limbs; name title; char type[30]; } ; bem *pb; bem deb = { 6, { Bernazel, Gwolkapwolk }, Arcturan };

A) Ce va afia: printf(%d\n, deb.limbs); printf(%s\n, pb->type); printf(%s\n, pb->type + 2) ? B) Cum poate fi accesat Gwolkapwolk ( n dou moduri ). 9. Ce este o reuniune ? Care este deosebirea dintre o structur i o reuniune ? 10. Cum se aloc memoria pentru o reuniune ? 11. Ce reprezint tipul cmpuri de bii ? 12. Cum se face referirea la cmpuri de bii ? 13. Ce tip poate avea un cmp de bii ? 14. Care este lungimea maxim a unui cmp de bii ? 15. Ce semnific lipsa numelui unui cmp de bii n declaraia tipului cmp de bii ? 16. Fie urmtoarea declarare :
struct cimp { unsigned a : 3; int b : 2; unsigned c : 4; unsigned d : 1; int e : 2 ;

} x;

Ce amplasare ne asigur aceast declarare ? 17. Ce reprezint tipul enumerare ? Cum se declar tipul enumerare ? 18. Cum se aloc memoria pentru datele de tip enumerare ? 19. Care valori implicite substituie numele sugestive din declaraia unui tip enumerare ? 20. Cum se pot impune alte valori dect cele implicite pentru numele sugestive din declaraia unui tip enumerare ? 21. Ce tip au valorile numelor sugestive din declaraia unui tip enumerare ? 22. Ce operaii pot fi efectuate cu datele de tip enumerare ? 23. Ce reprezint specificatorul typedef ? 24. Care-i deosebirea dintre typedef i #define ?

66

Lucrare de laborator N10


Tema: Prelucrarea fiierelor. Scopul lucrrii: Crearea, actualizarea, modificarea i utilizarea fiierelor n probleme de prelucrare a datelor. Suport teoretic: Un fiier este o colecie de date omogene, stocate pe un suport extern i identificat printrun nume. Datele fiierului se mai numesc elemente, componente, nregistrri, articole. Fiierele se pstreaz pe diferite dispozitive externe. Folosirea fiierelor permite pstrarea informaiei de orice natur pentru un timp ndelungat, transferarea datelor de pe un purttor informaional pe altul, citirea i afiarea datelor n caz de necesitate. n C, C++ tratarea fiierelor se face la dou nivele: 1. inferior: se realizeaz cu sprijinul direct al sistemului de operare, asemntor celui din UNIX, denumit i neformatat sau unbuffered; 2. superior: se realizeaz cu mijloacele sistemului de programare C, C++ cu utilizarea tipului structurat de date FILE denumit i sistem de fiiere de tip buffer sau formatat Vom deosebi un fiier de date de pe un dispozitiv extern i un fiier de date din program (din memoria operativ a calculatorului). Un fiier de date de pe un dispozitiv extern l vom numi fiier fizic, iar un fiier de date din program l vom numi flux (stream) de date sau fiier logic. Exist dou tipuri de fluxuri: text i binar. Un flux text este o succesiune de caractere i este format din linii. Fiecare linie se termin cu un caracter newline. La scrierea unui flux text pe un dispozitiv extern, n flux pot interveni unele schimbri impuse de dispozitivul concret. Deci, e posibil s nu existe o coresponden biunivoc ntre caracterele fluxului citit sau scris i caracterele fiierului respectiv de pe dispozitivul extern. Un flux binar este o secven de octei din memorie cu o coresponden biunivoc fa de octeii de pe dispozitivul extern respectiv. Aici la scriere i la citire nu intervin schimbri. Fiierele nu sunt toate la fel. De exemplu, dintr-un fiier putem extrage nregistrarea a cincea sau modifica nregistrarea a zecea. Acestea sunt fiiere cu acces direct (aleatoriu). Dar ntr-un fiier legat cu imprimanta sau alt port informaia poate fi transmis doar consecutiv n aceeai ordine ca n stream. Acestea sunt fiiere cu acces secvenial. Asta e deosebirea ntre stream i fiier: toate stream-urile sunt la fel, dar fiierele nu. n timpul intrrii datelor n program dintr-un fiier de pe disc, are loc copierea lor n memoria operativ a calculatorului, iar informaia din fiier ce se afl pe discul rigid rmne neschimbat pe parcursul executrii programului. La ieirea datelor din program pe disc, n fiier sunt nscrise datele ce se pstrau pn n acel moment n memoria operativ. nscrierea sau citirea informaiei din fiier este efectuat cu ajutorul indicatorului de poziie, care st pe nceputul fiierului la deschiderea acestuia. Pe msur ce fiecare caracter este citit sau scris n fiier indicatorul de poziie este incrementat, asigurnd parcurgerea fiierului. Cnd programul ncepe execuia, se deschid automat cinci stream-uri: stdin (standard input), stdout (standard output), stderr (standard error). n plus BC++ deschide stream-ul stdprn i stdaux, asociate printerului i portului consecutiv. Aceste stream-uri la fel se nchid automat. Prelucrarea fiierelor presupune un ir de operaii specifice: crearea, deschiderea, citirea, nchiderea, actualizarea, tergerea unui fiier, adugarea de noi nregistrri, poziionarea ntr-un fiier .a. Aceste operaii pot fi realizate prin funcii speciale de prelucrare a fiierelor. Aceste funcii au prototipul lor n fiierul <stdio.h> i numele unei astfel de funcii ncepe cu litera f. Fiierul antet <stdio.h> mai definete i urmtoarele tipuri: size_t, fpos_t i FILE. Tipul size_t ca i fpos_t este o varietate de ntreg fr semn. <stdio.h> definete mai multe funcii macro:NULL, EOF, FOPEN_MAX, SEEK_SET, SEEK_END, SEEK_CUR. Funcia macro NULL definete un pointer nul. EOF este definit drept -1 i este valoarea returnat cnd o funcie de intrare 67

ncearc s citeasc peste sfritul fiierului. FOPEN_MAX definete o valoare ntreag ce reprezint numrul maximal de fiiere ce pot fi deschise simultan. Celelalte sunt folosite cu funcia fseek(), care face accesul aleator dintr-un fiier. Pentru a citi sau scrie fiiere, e necesar a declara n program o variabil pointer de tip FILE. Sintaxa de declarare a unui indicator de fiier este urmtoarea: FILE *file_pointer; Pointerul este pentru fiier legtura cu fluxul de input/output. Un pointer pentru fiier este un pointer ctre informaiile care definesc diferite lucruri despre fiier, cum ar fi: numele, starea i poziia curent a fiierului. Deschiderea unui fiier se realizeaz cu ajutorul funciei fopen(), care are urmtoarea sintax: FILE *fopen(const char *calea, const char *mod); unde calea este un pointer spre un ir de caractere ce conine calea spre fiierul respectiv, iar mod este un pointer spre un ir de caractere ce indic modul de acces la fiier. Funcia returneaz un pointer spre tipul FILE sau pointerul nul n caz de eroare. Sunt posibile urmtoarele moduri de acces la un fiier: 1. r deschiderea unui fiier text pentru citire; 2. w - deschiderea unui fiier text pentru scriere; 3. a - deschiderea unui fiier text pentru a aduga nregistrri la sfritul fiierului; 4. r+ - deschiderea unui fiier text pentru citire i scriere; 5. w+ - crearea unui fiier text pentru citire i scriere; 6. a+ - deschiderea unui fiier text pentru adugarea nregistrrilor la sfritul fiierului sau crearea unui fiier text pentru citire i scriere; 7. rb - deschiderea unui fiier binar pentru citire; 8. wb - deschiderea unui fiier binar pentru scriere; 9. ab - deschiderea unui fiier binar pentru a aduga nregistrri la sfritul fiierului; 10. r+b - deschiderea unui fiier binar pentru citire i scriere; 11. w+b - crearea unui fiier binar pentru citire i scriere; 12. a+b - deschiderea unui fiier binar pentru adugarea nregistrrilor la sfritul fiierului sau crearea unui fiier binar pentru citire i scriere. Deschiderea cu modul w sau a a unui fiier inexistent duce la crearea lui. Deschiderea cu modul w a unui fiier existent duce la tergerea lui i crearea unui fiier nou. Deschiderea cu modul a a unui fiier existent permite adugarea nregistrrilor la sfritul fiierului. Deschiderea cu modul r a unui fiier inexistent duce la eroare. Deschiderea cu modul de citire i scriere a unui fiier inexistent duce la crearea lui. Deschiderea cu modul de citire i scriere a unui fiier existent nu terge fiierul. De exemplu, pentru a crea un fiier nou cu nume info.txt se va folosi sintaxa: FILE *fisier; fisier=fopen(info.txt,w). n unele cazuri apare situaia cnd sistemul operaional nu poate deschide fiierul indicat n funcia fopen(). Aceasta poate fi condiionat de lipsa spaiului pe discul rigid, sau de faptul c fiierul indicat pur i simplu nu exist. n cazul ncercrii folosirii fiierului ce nu poate fi deschis, programul va fi stopat n urma unei greeli de execuie. Pentru a evita stoparea avariat a programului poate fi controlat starea de deschidere a fiierului cu ajutorul instruciunii condiionate if, care va opri programul n caz de eec. Condiia pentru evitarea ieirii avariate din program are urmtoarea sintax: if ( fisier=fopen(info.txt,w))==NULL) { puts(fiierul nu poate fi deschis); 68

exit(1); } nchiderea unui fiier, care a fost deschis cu fopen(), se face cu funcia fclose() care are prototipul int fclose(FILE *fp ); aici fp este un pointer spre tipul FILE, returnat de funcia fopen(). Funcia returneaz 0, dac a reuit nchiderea fiierului, i -1, n caz de eroare. Funcia nscrie datele rmase n fluxul de date n fiier i apoi nchide fiierul, adic rupe legtura dintre fluxul de date i fiier. nchiderea corect a fiierului se va face: if ( fclose(fisier)!=0) puts(eroare la nchiderea fiierului); Mai mult ca att, nchiderea fiierului elibereaz indicatorul i dup aceasta el poate fi utilizat pentru accesul la alt fiier sau pentru ndeplinirea altor operaii cu fiierul. De menionat faptul, c dup nscrierea datelor, fiierul trebuie nchis i numai dup aceasta deschis pentru citire, astfel avnd acces respectiv la datele din fiier. Scrierea unui caracter ntr-un fiier se face cu funcia putc() (vezi i funcia fputc()), care are prototipul int putc(int ch, FILE *fp); aici fp este pointerul spre tipul FILE, returnat de funcia fopen() la deschiderea fiierului, iar ch este caracterul care se nscrie n fiier. Funcia returneaz codul caracterului scris n fiier sau EOF (adic -1) n caz de eroare. Citirea unui caracter dintr-un fiier se face cu funcia getc() (vezi i funcia fgetc()), care are prototipul int getc(FILE *fp); aici fp este pointerul spre tipul FILE, returnat de funcia fopen() la deschiderea fiierului. Funcia returneaz codul caracterului citit din fiier sau EOF, adic valoarea -1, dac s-a ajuns la sfritul fiierului. Funcia feof() determin momentul cnd a fost atins sfritul fiierului. Ea are prototipul int feof(FILE *fp); Funcia returneaz o valoare diferit de zero, dac a fost atins sfritul fiierului si 0 n caz contrar. Funcia fgets() cu prototipul char *fgets( char *s, int n, FILE *fp); citete un ir de caractere din fiierul specificat de pointerul fp, pn cnd se ajunge la un caracter newline sau au fost citite n-1 caractere; pointerul s indic spre zona de memorie unde se pstreaz irul de caractere citit din fiier; citirea din fiier se ntrerupe sau la citirea caracterului newline sau dup citirea a n-1 caractere. n zona indicat de s se scrie \n, dac el a fost citit din fiier, apoi se scrie caracterul NUL (\0). Funcia returneaz valoarea pointerului s sau pointerul NUL, n caz de EOF. Funcia fputs() cu prototipul int fputs (const char *s, FILE *fp); efectueaz nscrierea irului specificat de pointerul s n fiierul specificat de pointerul fp sau imprimarea lor pe hrtie fr nserarea caracterului sfrit de linie. Pentru ca fiecare ir nscris n aa mod n fiier s nceap din rnd nou, este necesar nserarea manual a simbolului sfrit de linie. Funcia returneaz codul ultimului caracter scris n fiier sau EOF, n caz de eroare. Funcia rewind() cu prototipul void rewind(FILE *fp); poziioneaz indicatorul de poziie al fiierului la nceputul fiierului. Funcia nu returneaz nici o valoare. Funcia ferror() cu prototipul int ferror(FILE *fp); determin dac o anumit operaie cu fiiere a generat o eroare. Funcia returneaz o valoare diferit de zero, dac a survenit vre-o eroare, i 0, dac n-a fost nici o eroare. Funciile pentru prelucrarea caracterelor i irurilor au destinaia de nscriere/citire din fiier numai a informaiei textuale. n caz, cnd e necesar de nscris n fiier date ce conin valori numerice este folosit funcia fprintf() cu urmtoarea sintax int fprintf (FILE *fp, const char *format, data); unde fp este indicatorul la fiierul n care se realizeaz nscrierea, format este irul de control al formatului datelor nscrise i data 69

este lista variabilelor sau valorilor ce trebuie nscrise n fiier. Ea se comport ca i funcia printf(), cu deosebirea c scrie datele n fiierul fp. Funcia returneaz numrul de caractere (octei) efectiv scrise n fiier. Dac survine o eroare pn la prima scriere, funcia returneaz o valoare negativ. Funcia fscanf() cu prototipul int fscanf (FILE *fp, const char *format, data); citete din fiierul indicat de pointerul *fp date sub controlul unor formate. Ea se comport ca i funcia scanf(), cu deosebirea c citete datele din fiierul fp. Funcia returneaz numrul de argumente crora li s-au atribuit efectiv valori. Dac a aprut o eroare pn la prima atribuire, atunci funcia returneaz EOF, adic valoarea -1. Funcia fflush() cu prototipul int fflush(FILE *fp); terge coninutul unui flux de ieire. Ea scrie datele din flux n fiier, apoi terge coninutul acestui flux. Dac fp este pointerul NUL, atunci se sterg toate fluxurile asociate cu fiierele deschise pentru scriere. Fucia returneaz valoarea zero n caz de succes, i -1, n caz de eroare. Funcia fwrite() cu prototipul unsigned fwrite (void *bufer, unsigned dim, unsigned n, FILE *fp); scrie n fiierul indicat de pointerul *fp n obiecte (blocuri) de dimensiunea dim octei fiecare. Datele se iau din zona de memorie indicat de pointerul bufer. Indicatorul de poziie al fiierului se mrete cu numrul de caractere (octei) scrise. Pentru determinarea mrimii dim se folosete funcia sizeof(dim). Dac vom deschide fiierul cu ajutorul unui redactor de texte obinuit vom observa n el un coninut neneles. n realitate informaia (sau mai bine zis nregistrrile) ce se afl n acest fiier este neleas de compilator i poate fi citit cu funcia fread(). Funcia returneaz numrul de obiecte (blocuri) efectiv scrise, care poate fi i mai mic dect numrul solicitat n. Funcia fread() cu prototipul unsigned fread (void *bufer, unsigned dim, unsigned n, FILE *fp); citete n obiecte (blocuri), fiecare avnd dim octei, din fiierul indicat de pointerul *fp. Datele se plaseaz n tabloul indicat de pointerul bufer. Indicatorul de poziie al fiierului se mrete cu numrul de octei citii. Funcia returneaz numrul de blocuri efectiv citite, care poate fi mai mic dect numrul solicitat n. Funcia fseek() cu prototipul int fseek(FILE *fp, long depl, int origine); deplaseaz indicatorul de poziie al fiierului. Funcia lucreaz la nivel de octei. Parametrul depl arat numrul de octei peste care se va deplasa indicatorul fiierului, iar parametrul origine arat de unde ncepe numrarea acestor octei. Parametrul origine poate avea una din urmtoarele valori: SEEK_SET, care are valoarea 0 i semnific numrarea de la nceputul fiierului; SEEK_CUR, care are valoarea 1 i semnific numrarea de la poziia curent nainte; SEEK_END, care are valoarea -1 i semnific numrarea de la sfritul fiierului napoi. Funcia returneaz valoarea 0, dac operaia de poziionare a reuit, i o valoare diferit de zero, n caz de eroare. Funcia ftell() cu prototipul long ftell(FILE *fp); returneaz poziia curent a indicatorului de fiier. Funcia determin poziia indicatorului de fiier i returneaz numrul de octei parcuri de la nceputul fiierului. Primul octet este sub numrul 0. Valoarea returnat reprezint octetul curent, nu nregistrarea curent i poate fi utilizat de funcia fseek(). Funcia returneaz valoarea indicatorului de poziie al fiierului, dac operaia de poziionare a reuit, i valoarea -1, n caz de eroare. Exemple de programe: 70

Exemplul 10.1. Programul copiaz intrarea standard la ieirea standard, adic citete cte un caracter din fiierul stdin i l scrie n fiierul stdout. Citirea se ntrerupe la ntlnirea caracterului EOF (adic la acionarea tastelor Ctrl + Z).
#include<conio.h> #include<stdio.h> void main() { char c; clrscr(); while ( ( c=getc(stdin))!=-1) putc(c, stdout); getch(); }

// EOF e definit n fiierul stdio.h ca -1

Exemplul 10.2. Programul citete caractere de la claviatur i le scrie n fiierul cu numele file01 pe disc pn la citiea caracterului EOF.
#include<conio.h> #include<stdio.h> void main() { FILE *fp; char c; clrscr(); fp = fopen(file01,w); while ( ( c=getc(stdin))!=EOF) putc(c, fp); fclose(fp); getch(); }

Exemplul 10.3. Programul demonstreaz utilizarea fluxului de citire/scriere pentru citirea din fiier i contorizarea simbolurilor citite.
#include<conio.h> #include<stdio.h> void main() { FILE *fp; char S[20]; long count=0; int ch; clrscr(); gets(S); // se ateapt introducerea numelui fiierului // deschiderea fiierului pentru citire i if ( ( fp = fopen(S, r) ) == NULL) { // verificarea execuiei deschiderii lui printf(Nu se deschide fiierul %s\n,S); exit(1); } // se citesc simboluri din fiier pn la EOF while ( ( c = getc(fp)) != EOF) { putc(ch,stdout); // sau putchar(ch); se tipresc la ecran simbolurile citite count++; } fclose(fp); printf(Fiierul %s conine %ld simboluri\n, S, count); getch(); }

Exemplul 10.4. Programul citete cte un caracter de la intrarea standard i l adaug la sfritul fiierului creat n exemplul 10.2.
#include<conio.h> #include<stdio.h> void main() { FILE *fp; char c; clrscr(); fp = fopen(file01,a); while ( ( c=getc(fp)) != -1) putc(c, fp); fclose(fp); getch(); }

71

Exemplul 10.5. Programul citete de la intrarea standard un ir de numere ntregi, scrie cu fprintf() numerele pare ntr-un fiier binar i numerele impare n alt fiier binar, apoi citete cu fscanf() fiierele i le afieaz la ecran.
#include<conio.h> #include<stdio.h> void main() { FILE *fp1, *fp2; int n; clrscr(); fp1 = fopen(fpar,wb); fp2 = fopen(fimpar,wb); while ( 1 ) // se introduc numere da la tastatur { if ( scanf( %d, &n )!=1) break; // pn se ntroduce un simbol (n%2==0) ? fprintf( fp1, %4d, n) : fpintf( fp2, %4d, n); } fclose( fp1 ); fclose( fp2 ); fp1 = fopen(fpar,rb); fp2 = fopen(fimpar,rb); puts(Fiierul cu numere pare:\n\n); while ( fscanf( fp1, %4d, &n)==1) printf( %d\t,n); puts(\nFiierul cu numere impare:\n\n); while ( fscanf( fp2, %4d, &n)==1) printf( %d\t,n); fclose(fp1); fclose(fp2); getch(); }

Exemplul 10.6. Programul citete de la intrarea standard un ir de numere ntregi, scrie cu fprintf() numerele pare ntr-un fiier text i numerele impare n alt fiier text, apoi citete cu fscanf() fiierele i le afieaz la ecran.
#include<conio.h> #include<stdio.h> void main() { FILE *fp1, *fp2; int n; clrscr(); fp1 = fopen(gpar,w+); fp2 = fopen(gimpar,w+); while ( 1 ) { if ( scanf( %d, &n )!=1) break; // citire de la tastatur (n%2==0) ? fprintf( fp1, %d, n) : fpintf( fp2, %d, n); } // scriere n fiiere fclose( fp1 ); fclose( fp2 ); // indicatorul de poziie al fiierelor este readus la nceputul lor rewind( fp1 ); rewind( fp2 ); puts(Fiierul cu numere pare:\n\n); while ( fscanf( fp1, %d, &n)==1) printf( %d\t,n); // citire din fiier i afiare la ecran puts(\nFiierul cu numere impare:\n\n); while ( fscanf( fp2, %d, &n)==1) printf( %d\t,n); // citire din fiier i afiare la ecran fclose(fp1); fclose(fp2); getch(); }

Exemplul 10.7. Programul citete cte un cuvnt de la intrarea standard i l adaug ntr-un fiier.
#include<conio.h> #include<stdio.h> #define max 40 void main() { FILE *fp; char words[max]; clrscr(); // deschiderea fiierului pentru adugare i if ( ( fp = fopen(wordy, a+) ) == NULL) { printf(Nu se deschide fiierul\n); exit(1); }

72

puts( Introdu cuvntul urmtor; acioneaz Enter la nceputul cuvntului pentru ntrerupere); // se citesc cuvinte de la tastatur while ( ( gets(words)) != NULL) && words[0] != \0) fprintf ( fp, %s, words ); // se nscriu cuvintele n fiier puts(Coninutul fiierului); rewind( fp ); while ( fscanf( fp, %s, words ) == 1 ) puts(words); if (fclose( fp ) != 0 ) fprintf( stderr, Eroare la nchiderea fiierului); }

Exemplul 10.8. Programul demonstreaz utilizarea funciilor de citire/scriere fgets() i fputs().


#include<conio.h> #include<stdio.h> #define max 20 void main() { char line[max]; clrscr(); while ( fgets(line, max, stdin) != NULL) && line[0] != \n) fputs ( line, stdout ); }

Funcia gets() citete irul pn la simbolul \n; Funcia fgets() citete irul inclusiv i simbolul \n; Funcia puts() adaug simbolul \n la ieire; Funcia fputs() nu adaug simbolul \n la ieire. n legtur cu aceasta fgets() se utilizeaz n pereche cu fputs(), dar nu cu puts(). n aa caz un simbol de linie nou s-ar preface la ieire n dou simboluri de linie nou. Exemplul 10.9. Programul creeaz fiierul binar Bursa i scrie n el articole ce conin: grupa, numele i prenumele studentului, nota medie obinut la sesiune i mrimea bursei. Datele se citesc de la intrarea standard. Dup introducerea ultimului articol se tasteaz EOF (<Ctrl+Z>).
#include<conio.h> #include<stdio.h> void main() { struct { char grupa[8], nume[15], pren[15]; float media; int bursa; } student; clrscr(); FILE *fp; float p; fp = fopen(Bursa, wb); while ( scanf(%s, student.grupa) != -1) { scanf(%s,student.nume); scanf(%s,student.pren); scanf(%f,&p); student.media=p; scanf(%i,&student.bursa); fprintf( fp, %-7s%-15s%-15s%.2f%4d\n,student.grupa, student.nume, student.pren, student.media, student.bursa); } fclose(fp); getch(); }

Exemplul 10.10. Programul caut n fiierul binar Bursa, creat n exemplul 10.9 studenii cu nota medie maxim i afieaz informaia despre aceti studeni la ecran.
#include<conio.h> #include<stdio.h> void main() {

73

struct { char grupa[8], nume[15], pren[15]; float media; int bursa; } student; clrscr(); FILE *fp; float nm=0; fp = fopen(Bursa, rb); while ( !feof(fp)) { fscanf( fp, %-7s%-15s%-15s%.2f%4d\n,student.grupa, student.nume, student.pren, student.media, student.bursa); if ( nm < student.media ) nm=student.media; } rewinf(fp); while ( !feof(fp)) { fscanf( fp, %-7s%-15s%-15s%.2f%4d\n,student.grupa, student.nume, student.pren, student.media, student.bursa); if ( nm == student.media ) { printf(%-7s,student.grupa); printf(%-15s,student.nume); printf(%-15s,student.pren); printf(%.2f, student.media); printf(%4i\n,student.bursa); } } fclose(fp); getch(); }

Exemplul 10.11. Programul creeaz fiierul binar Bursa i scrie n el articole ce conin: grupa, numele i prenumele studentului, nota medie obinut la sesiune i mrimea bursei. Datele se citesc de la intrarea standard. Se utilizeaz fwrite(). Pentru citirea din fiier se utilizeaz fread().
#include<conio.h> #include<stdio.h> void main() { struct { char grupa[8], nume[15], pren[15]; float media; int bursa; } student; clrscr(); FILE *fp; float p; fp = fopen(Bursa, w+b); // fiier deschis pentru scriere i citire while ( scanf(%s, student.grupa) != -1) { scanf(%s,student.nume); scanf(%s,student.pren); scanf(%f,&p); student.media=p; scanf(%i,&student.bursa); fwrite( &student, sizeof student, 1, fp ); } fclose(fp); rewinf(fp); while ( !feof(fp)) { fread( &student, sizeof student, 1, fp ); printf(%-7s,student.grupa); printf(%-15s,student.nume); printf(%-15s,student.pren); printf(%.2f, student.media); printf(%4i\n,student.bursa); } fclose(fp); getch(); }

74

Exemplul 10.12. Programul nscrie ntr-un fiier elementele unui tablou. Apoi demonstreaz accesul aleator la nregistrrile sale.
#include <stdio.h> #include <conio.h> #include<stdlib.h> #define ARSIZE 100 void main() { clrscr(); float numbers[ARSIZE], value; const char *file="numbers.dat"; int i; long pos; FILE *fp; // creaza tabloul de numere tip float for ( i=0; i < ARSIZE; i++) { numbers[i] = 100.0 * i + 1.0/( i + 1); printf("%f ",numbers[i]); } if ( ( fp = fopen( file, "wb")) == NULL ) { puts("Eroare la deschidere"); exit(1); } // inscrie in fisier tabloul de dimensiunea ARSIZE fwrite( numbers, sizeof( float ), ARSIZE, fp); fclose( fp); if ( ( fp = fopen(file, "rb"))==NULL) { puts("Eroare la deschidere"); exit(1); } // citeste din fisier inregistrarile selectate de utilizator printf( "\nintroduceti un numar din diapazonul 0 - %i.\n", ARSIZE - 1); scanf("%i", &i); while ( i >= 0 && i < ARSIZE) { pos = ( long ) i * sizeof( float ); //gaseste deplasamentul fseek( fp, pos, SEEK_SET ); // efectueaz deplasarea n cadrul fiierului // efectueaz citirea din fiier a unei nregistrri fread(&value, sizeof( float), 1, fp); printf("Valoarea = %f\n", value); printf("Urmatorul indice"); puts("pentru iesire indicati un indice ce nu apartine diapazonului"); scanf("%i",&i); } fclose( fp); getch(); }

Probleme propuse spre rezolvare: 1. Programul copie un fiier text iniial (numele cruia se citete de la tastatur) n altul final (numele cruia la fel se citete de la tastatur) doar cu majuscule. 2. Creai un program ce deschide dou fiiere, numele crora se introduc de la tastatur. Apoi afieaz o linie din primul fiier, o linie din al doilea fiier, o linie din primul fiier, o linie din al doilea fiier s.a.m.d. pn la ultima linie din fiierul cu cele mai multe linii. 3. Creai un fiier text i scriei n el numele, prenumele i numrul de telefon ale colegilor de grup. Apoi afiai pe monitor informaia nscris n fiier. 75

4. Creai un fiier text i scriei n el numele, prenumele, numrul de telefon i data naterii ale colegilor de grup. Folosii informaia din fiierul creat cu programul pentru sarcina 3. Apoi afiai pe monitor informaia nscris n fiier. 5. Programul citete de la intrarea standard un ir de numere ntregi, scrie numerele pare ntr-un fiier binar i numerele impare n alt fiier binar, apoi le afieaz la ecran. 6. Se consider fiierul text IN1.TXT i IN2.TXT. Fiecare din aceste fiiere conine cte un ir de numere reale, ordonate cresctor. Scriei un program care comaseaz aceste fiiere n fiierul OUT.TXT. Numerele vor fi scrise n fiier n ordine cresctoare. 7. Se consider fiierul IN.TXT care conine n numere separate prin spaiu ce reprezint elementele unui tablou. Scriei un program care calculeaz recursiv suma valorilor elementelor tabloului. 8. Se consider fiierul IN.TXT care conine pe fiecare linie cte o pereche de cuvinte, separate prin spaiu. Primul cuvnt din fiecare pereche este n limba englez, al doilea n limba romn. Scriei un program care aranjeaz aceste perechi n ordinea lexicografic a cuvintelor din limba englez. 9. Fiierul IN.TXT conine 3*n numere reale (n triplete). Scriei un program care modific fiierul astfel: fiecare al doilea element din triplete consecutive se nlocuiete cu media aritmetic a vecinilor si. 10. Fiierul text ELEVI.IN conine datele referitoare la examene a cel mult 200 concureni. Datele despre fiecare concurent snt numele, prenumele i media obinut la examene. Scriei un program care scrie n fiierul ELEVI.OUT lista elevilor admii ( care au media nu mai mic dect 5) ordonat descresctor dup medii. 11. Se numesc numere bine ordonate acele care au cifrele n ordine strict cresctoare sau strict descresctoare. Scriei un program care citete dintr-un fiier numere de 4 cifre i creaz alt fiier unde nscrie numerele bine ordonate. 12. Fiierul text BAC.TXT conine numele, prenumele, clasa i media obinut la bacalaureat ale fiecrui elev. Clasele sunt 12A, 12B, 12C. Scriei un program care afieaz media obinut pentru fiecare clas (se consider numai elevii care au media mai mare ca 5). ntrebri de control: 1. Ce este un fiier de date? 2. Ce este un flux de date? 3. Care este legtura dintre un fiier de date i un flux de date? 4. Ce este un flux text? 5. Ce este un flux binar? 6. Care este deosebirea dintre un flux text i un flux binar? 7. Cum se asociaz un flux de date la un fiier de date? 8. Ce este un fiier cu acces secvenial la date? 9. Ce este un fiier cu acces direct la date? 10. Care dintre urmtoarele afirmaii este adevrat? a. ntr-un fiier text se pot scrie numai litere, b.nu se poate terge o linie dintr-un fiier text, c. fiierele text permit numai acces secvenial, d.fiierele text nu pot fi modificate. 11. Ce se ntmpl la deschiderea cu modul w sau a a unui fiier inexistent? 12. Ce se ntmpl la deschiderea cu modul w a unui fiier existent? 13. Ce se ntmpl la deschiderea cu modul a a unui fiier existent? 14. Ce se ntmpl la deschiderea cu modul r a unui fiier inexistent? 15. Ce se ntmpl la deschiderea cu modul de citire i scriere a unui fiier inexistent? 16. Ce se ntmpl la deschiderea cu modul de citire i scriere a unui fiier existent? 17. Care moduri de deschidere a unui fiier duc la tergerea lui? 76

18. Funcia fseek(nume_p, nr, origine) a. precizeaz poziia indicatorului de fiier b.deplaseaz indicatorul de poziie cu nr octei fa de poziia curent c. deplaseaz indicatorul de poziie cu nr octei fa de nceputul de fiier d.deplaseaz indicatorul de poziie cu nr octei fa de origine. 19. Funcia void rewind(FILE *f); a. terge coninutul fiierului b.mut indicatorul de fiier la nceputul su c. recitete coninutul fiierului d.marcheaz sfritul de fiier. 20. Secvena:
FILE *f; f = fopen ( a.txt, r ); fseek ( f, 0L, SEEK_END ); long l = ftell ( f );

a) calculeaz n l lungimea fiierului b) calculeaz n l numrul de linii c) calculeaz n l numrul de caractere diferite de cele albe d) este eronat 21. Cnd se nchide un fiier? a. la apelul funciei close b.la apelul funciei freopen c. la terminarea blocului n care a fost declarat d.la apelul funciei fclose 22. Care sunt pointerii predefinii spre fiierele I/O standard? 23. Secvena
FILE *f = fopen ( a.txt, w); int n; scanf ( %i, &n); while ( n ) { if ( !feof ( f )) fprintf(f,%i,n ); scanf (%i,&n); } fclose ( f );

a. scrie un numr n fiier b.scrie n fiier numerele introduse pn la 0, c. afieaz numerele nenule din fiier, d.verific dac un numr se gsete n fiier.

77

Bibliografie
1. Herbert Shildt. C manual complet. Editura Teora, Bucure;ti, 1998 2. Liviu Negrescu. C i C++ pentru nceptori. Editura Microinformatica, Cluj-Napoca, 1995. 3. Vasile Petrovici, Florin Goicea. Programarea n limbajul C. Editura Tehnic. Bucureti, 1993. 4. Ana ntuneric, Cristina Sichim. Informatic. Editura Polirom, Bucureti, 2003. 5. Bogdan Ptru. Aplicaii n C i C++. Editura Teora, Bucureti, 1998. 6. . . DiaSoft, 2002. 7. . . , . . . . , 1999 8. . . , . . , . . , . . . . , , 1988.

78