Sunteți pe pagina 1din 75

Drago Burileanu Marius Pdure

Claudius Dan

1.

Descrierea mediului de lucru Dev-C++

Dev-C++ este un mediu integrat de dezvoltare pentru limbajul de programare C/C++ i este oferit gratuit de ctre firma Bloodshed Software (Website: http://www.bloodshed.net). El folosete compilatorul GCC (GNU C Free Software Foundation) i poate crea fiiere executabile Win32, fie n mod consol, fie prin intermediul unei interfee grafice (GUI), i de asemenea biblioteci statice sau dinamice (DLL-uri). Cerinele de sistem recomandate de ctre autori sunt urmtoarele: sistem de operare MS-Windows 2000, XP; 32 MB memorie RAM; unitate central (compatibil Intel) la 400 MHz; spaiu pe disc disponibil 200 MB. n afara distribuiei sale gratuite, Dev-C++ are un numr de caracteristici care l fac extrem de atractiv pentru utilizare. Fr a intra n detalii, vom remarca n mod special faptul c interfaa grafic este foarte flexibil, dar i intuitiv i uor de folosit i include toate facilitile necesare unui mediu de programare evoluat (editare complet, listare de funcii, compilare i rulare, depanare, creare de proiecte, adugare de biblioteci etc.). n aceast lucrare se utilizeaz mediul Dev-C++ pentru programarea n limbajul C, iar compilarea surselor va avea ca rezultat obinerea de fiiere executabile Win32. 1.1. Editarea unui program

Editarea (adic scrierea fiierului surs al programului) se poate face n mediul Dev-C++ n dou moduri. O modalitate eficient, recomandat n special atunci cnd avem mai multe fiiere surs, este de a crea mai nti un Proiect (meniul File, opiunile New i apoi Project...); n acest mod se permite adugarea sau eliminarea imediat a unor fiiere i editarea legturilor dup compilarea tuturor fiierelor surs, ca i un control al diferiilor parametri disponibili n mediul de programare. O a doua modalitate, mai simpl, este de a se crea direct un (singur) fiier surs; aceast metod va fi descris succint i ilustrat n cele ce urmeaz. Presupunnd ca suntem deja n interfaa grafic, se selecteaz meniul File, iar din New se alege Source File (sau se folosete combinaia de taste CTRL+N), aa cum este prezentat n Figura 1.1. Se va deschide astfel o nou fereastr (numita iniial Untitled1) n care se va scrie efectiv programul surs. Dup ncheierea editrii, fiierul surs trebuie salvat pe disc. Salvarea se face prin comanda Save As... (sau Save) din meniul File, aa cum este ilustrat n Figura 1.2; fiierele se vor salva ca fiiere C (C source), i vor avea pe disc extensia .c.

Figura 1.1. Deschiderea unui fiier surs nou

1.2.

Compilarea programului

Urmtoarea etap ce trebuie parcurs este compilarea programului surs rezultat dup terminarea editrii, adic traducerea sa n limbajul calculatorului i obinerea unui program obiect, reprezentat n cod main sau ntr-un limbaj apropiat de acesta. n cazul limbajului C, procesul de compilare i editare de legturi se mparte de fapt ntre mai multe programe: preprocesorul, compilatorul propriu-zis, asamblorul i editorul de legturi, rezultnd n final un fiier executabil. 1

Figura 1.2. Salvarea fiierului editat n mediul Dev-C++ etapele sugerate anterior (practic compilarea i editarea legturilor) sunt parcurse automat i transparent pentru utilizator prin apelarea opiunii Compile din meniul Execute, sau folosind combinaia de taste Ctrl+F9 (Figura 1.3).

Figura 1.3. Opiunea de compilare a fiierului surs n cazul n care nu exist erori, este creat un fiier executabil (avnd extensia .exe) care poate fi rulat, partea de jos a ferestrei interfeei grafice artnd, de exemplu, ca n Figura 1.4. n cazul n care se constat erori la compilare (tipic erori sintactice), lansarea n execuie nu este posibil, iar erorile sunt semnalate n fereastra Compiler (aflat n colul din stnga jos al interfeei grafice). Figura 1.5 prezint o astfel de situaie; este vorba de acelai exemplu (problema 2.2 din Capitolul 2), n care s-au omis intenionat ghilimelele ce ncadreaz specificatorul de format %d din linia 10. Dup ce erorile au fost nlturate este necesar s se fac o nou compilare (de remarcat faptul c dup fiecare modificare adus codului surs, acesta trebuie recompilat). Cnd compilarea a decurs bine, este permis rularea programului.

1.3.

Rularea programului

Rularea programului se face prin comanda Run (sau Ctrl+F10) din meniul Execute (a se vedea i Figura 1.4). Aceast comand lanseaz n execuie programul, tiprind eventual mesaje i rezultate pe ecranul calculatorului.

Figura 1.4. Compilarea cu succes a fiierului surs

Figura 1.5. O situaie ce conduce la erori de compilare a programului n aceast etap sunt puse n eviden erorile la execuie, cum ar fi mprirea cu zero, sau sunt puse n eviden erorile de logic dac rezultatele sunt eronate. Dac se descoper astfel de erori, programatorul trebuie s se rentoarc la editarea programului surs, s-l recompileze i s-l ruleze din nou. Pentru ca programul s fie lansat n execuie automat dup compilare se poate folosi comanda Compile &

Run (sau F9) din meniul Execute.

2.
2.1.
P2.1

Programe simple; variabile i constante, operaii de intrare/ieire formatate


Probleme rezolvate
Scriei un program care afieaz pe ecran un text dat.

#include <stdio.h> #include <stdlib.h> int main() { printf("Acesta este un program C"); printf("\n"); printf("creat\n"); printf("de mine."); printf("\n"); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


Acesta este un program C creat de mine.

Discuie:
Comanda #include realizeaz includerea n fiierul surs a unui alt fiier (situat ntr-un director cunoscut de ctre compilator), n acest caz a unor fiiere speciale care descriu coninutul unor biblioteci i care poart denumirea de fiiere header, avnd extensia .h. n exemplul anterior, stdio.h este fiierul care definete funciile standard de I/O din biblioteca C (printre acestea numrndu-se i funciile printf() i scanf()), iar stdlib.h este un fiier ce definete un numr de funcii utilitare din biblioteca standard (cum este i system()). Programul propriu-zis este descris de funcia main(). Acoladele { i } din interiorul funciei marcheaz practic nceputul i sfritul programului. Instruciunile se execut secvenial; n cazul anterior, succesiunea operaiilor corespunde cu cea de scriere a comenzilor, deoarece nu se precizeaz explicit un salt la o alt instruciune. Funcia printf() afieaz irul de caractere inclus ntre ghilimele. Secvena de caractere \n determin trecerea afirii la un rnd nou (newline). Exist i alte secvene de caractere care determin deplasarea poziiei urmtoare de afiare. Instruciunea system("PAUSE") are urmtorul efect: dup afiarea rezultatelor, fereastra de rulare DOS rmne deschis pn cnd se introduce un caracter oarecare de la tastatur, permind astfel vizualizarea i interpretarea rezultatelor programului (n lipsa unei astfel de comenzi, fereastra se nchide automat dup rulare). Instruciunea return utilizat n main() determin ntoarcerea unui cod de terminare ctre sistemul de operare (valoarea ntoars trebuie s fie un ntreg). Uzual, valoarea 0 indic faptul c programul s-a terminat normal; orice alt valoare indic faptul c exist o eroare. Precizm c toate programele din aceast lucrare ntorc valori din main(), dei din punct de vedere tehnic acest lucru este opional (strict formal, deoarece instruciunea return este plasat pe ultima linie din main(), execuia programului oricum se ncheie). ============================= P2.2 Scriei un program care citete dou numere ntregi a i b i calculeaz suma lor.

#include <stdio.h> #include <stdlib.h> int main() { int a, b, s; printf("Introduceti primul numar, a: "); scanf("%d", &a); printf("Introduceti al doilea numar, b: "); scanf("%d", &b); s = a + b; printf("Suma celor doua numere este %d", s); printf("\n"); system("PAUSE"); return 0; }

Dac se introduc de la tastatur, de exemplu, numerele 7 i 7, programul va afia pe ecran, dup compilare i execuie:
Introduceti primul numar, a: -7 Introduceti al doilea numar, b: 7 Suma celor doua numere este 0

Discuie:
Instruciunea int a, b, s; declar variabilele de tip ntreg a, b i s. Variabila s va fi folosit pentru a stoca valoarea sumei dintre a i b. Funcia scanf() citete un caracter introdus de la tastatur; conform specificatorului %d, valoarea citit va fi de tip ntreg i va fi stocat la adresa variabilei ce urmeaz simbolului &. Linia s = a + b; atribuie variabilei s valoarea a + b. Linia printf("Suma celor doua numere este %d", s); va afia pe ecran textul Suma celor doua numere este urmat de valoarea calculat a lui s. ============================= P2.3 Scriei un program care calculeaz diferena a dou numere ntregi introduse de la tastatur.

#include <stdio.h> #include <stdlib.h> int main() { int a, b; printf("Introduceti doua numere intregi: "); scanf("%d %d", &a, &b); printf("%d - %d = %d", a, b, a - b); printf("\n"); system("PAUSE"); return 0; }

Dac se introduc de la tastatur, de exemplu, numerele 7 i 9, programul va afia pe ecran, dup compilare i execuie:
Introduceti doua numere intregi: 7 9 7 - 9 = -2

Discuie:
Instruciunea scanf("%d %d", &a, &b); permite citirea de la tastatur a dou numere ntregi: prima valoare citit va fi stocat la adresa variabilei a, cea de a doua la adresa variabilei b. De notat c spaiul dintre cele dou grupe de caractere %d din "%d %d" spune funciei scanf() c cele dou numere introduse de la tastatur pot fi separate de spaii. Este absolut corect utilizarea unor expresii (cum este a - b) n lista de parametri a funciei printf(); ele vor fi evaluate nainte de apelul funciei. Aceast variant este chiar mai eficient dect utilizarea unei variabile suplimentare, sa spunem c, creia s i se atribuie valoarea a - b (aceast metod a fost folosit n problema 2.2), deoarece reduce spaiul de memorie necesar programului. ============================= P2.4 Scriei un program care calculeaz aria unui cerc de raz dat; valoarea razei se va citi de la tastatur i va fi un numr ntreg.

#include <stdio.h> #include <stdlib.h> int main() { /* Declaratii */ int raza; float aria, pi = 3.14; /* Comenzi */ printf("Introduceti raza: "); scanf("%d", &raza); aria = pi * raza * raza; /* calculul ariei */ printf("Aria cercului de raza %d este %f", raza, aria); printf("\n"); system("PAUSE"); return 0; }

Dac se introduce de la tastatur, de exemplu, valoarea 3, programul va afia:


Introduceti raza: 3 Aria cercului de raza 3 este 28.260000

Discuie:
Se declar variabila raza de tip ntreg. Deoarece suprafaa unui cerc nu este neaprat un numr ntreg, variabila aria n care este calculat va fi declarat de tip real (deci se va utiliza tipul float). Variabila real pi se iniializeaz cu valoarea 3.14. Deoarece aceast variabil nu este de fapt asociat dect valorii constante 3.14, acelai efect putea fi obinut utiliznd modificatorul const. Acesta poate fi folosit pentru a crea constante de un anumit tip; astfel, compilatorul va fi informat c variabila care urmeaz nu poate fi modificat de program. Prin urmare, instruciunea float aria, pi=3.14; din programul anterior se putea nlocui cu:
float aria; const float pi = 3.14;

Comentariile se pot introduce oriunde n program. ============================= P2.5 Scriei un program care transform temperatura exprimat n grade Fahrenheit n grade Celsius. Se va utiliza formula: C = (F32)*5/9 , unde C grade Celsius (numr real), F grade Fahrenheit (numr ntreg).

#include <stdio.h> #include <stdlib.h> int main() { int gradf; float gradc; printf("Introduceti temperatura in grade Fahrenheit: "); scanf("%d", &gradf); gradc = (gradf - 32) * 5.0 / 9.0; printf("Temperatura in grade Celsius este %f", gradc); printf("\n"); system("PAUSE"); return 0; }

Dac se introduce de la tastatur, de exemplu, valoarea 100, programul va afia:


Introduceti temperatura in grade Fahrenheit: 100 Temperatura in grade Celsius este 37.777779

Discuie:
Dup cum s-a cerut n enunul problemei, se declar variabilele gradf de tip ntreg i gradc de tip real. Cele dou constante utilizate (5 i 9) se vor introduce n program sub forma 5.0 i respectiv 9.0; dei asupra acestui lucru vom reveni n capitolul urmtor, vom spune deocamdat doar faptul c rezultatul mpririi a doi ntregi este un ntreg, deci evaluarea expresiei (gradf - 32)*5/9 ar fi dus la un rezultat incorect (chiar dac variabila gradc a fost declarat de tip float). ============================= P2.6 Scriei un program care transform msura unui unghi din grade (numr ntreg) n radiani (numr real). Se va utiliza relaia de transformare cunoscut: rad = grad * / 180.

#include <stdio.h> #include <stdlib.h> int main() { int grad; float rad; const float pi = 3.141593; printf("Introduceti unghiul in grade: "); scanf("%i", &grad); rad = grad * pi / 180; printf("Masura unghiului este de %4.2f radiani", rad); printf("\n"); system("PAUSE"); return 0; }

Dac se introduce de la tastatur, de exemplu, valoarea 360, programul va afia:


Introduceti unghiul in grade: 360 Masura unghiului este de 6.28 radiani

Discuie:
Dup cum s-a artat la partea teoretic, ca specificator de format pentru numere ntregi zecimale poate fi utilizat att %d ct i %i; s-a folosit aici a doua variant. Fiecare caracter ce indic formatul variabilei poate fi precedat n cadrul unui specificator de format de un modificator ce va determina felul n care se va tipri valoarea. Astfel, n exemplul anterior, %4.2f utilizat la a doua funcie printf() are urmtoare semnificaie: se va tipri un numr real n format zecimal utiliznd n total 4 caractere (incluznd punctul zecimal), cu 2 cifre la partea fracionar. =============================

2.2. 1. 2. 3. 4. 5. 6. 7. 8.

Probleme propuse

Scriei un program care s v afieze numele pe ecran, ca i seria i grupa, pe dou rnduri succesive. Se citete un ntreg . Scriei un program care s afieze: Ai introdus numrul .... Scriei un program care citete doi ntregi i calculeaz produsul lor. Scriei un program care calculeaz lungimea unui cerc de raz dat; valoarea razei se va citi de la tastatur i va fi un numr ntreg. Scriei un program care transform temperatura exprimat n grade Celsius n grade Fahrenheit. Scriei un program care transform msura unui unghi din radiani n grade. Scriei programe care calculeaz arii pentru ptrat, dreptunghi, triunghi. Scriei programe care calculeaz volume pentru cub, paralelipiped, piramid.

3.
3.1.
P3.1

Tipuri fundamentale de date, operatori i expresii


Probleme rezolvate
Urmtorul program ilustreaz utilizarea tipurilor fundamentale de date n C.

#include <stdio.h> #include <stdlib.h> int main() { long int i = 66000; unsigned short int u; double x, y; char b_mic, b_mare, ch; u = 66000; printf("%ld\t%hu\n\n", i, u); x = 12.3468, y = 11.2e-2; printf("x = %f sau %6.3f sau %e\n", x, x, x); printf("y = %f sau %8.4f sau %E\n\n", y, y, y); b_mic = 'b', b_mare = 'B', ch = 'm'; printf("Codurile ASCII pentru 'b' si 'B' sunt: %d, %d\n", b_mic, b_mare); printf("Dupa '%c' urmeaza '%c'\n", b_mic, b_mic + 1); printf("Majuscula corespunzatoare lui '%c' este '%c'", ch, ch - 'a' + 'A'); printf("\n"); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


66000 464

x = 12.346800 sau 12.347 sau 1.234680e+001 y = 0.112000 sau 0.1120 sau 1.120000E-001 Codurile ASCII pentru 'b' si 'B' sunt: 98, 66 Dupa 'b' urmeaza 'c' Majuscula corespunzatoate lui 'm' este 'M'

Discuie:
Programul are, aa cum se observ, trei pri complet distincte. n prima parte se dau dou exemple de folosire a numerelor ntregi. Programul va afia corect numrul 66000 declarat long int (de fapt, s-ar fi afiat corect i dac ar fi fost declarat int, deoarece pe majoritatea calculatoarelor curente reprezentarea intern a lui int este pe 32 de bii), ns nu afieaz corect acelai numr declarat unsigned short int. Numerele de tipul unsigned short int sunt ntotdeauna reprezentate pe 16 bii, gama lor fiind ntre 0 i 2161=65535; de altfel, compilatorul semnalizeaz acest lucru printr-un mesaj de atenionare (fereastra Compiler). Specificatorii de format %ld i %hu permit afiarea numerelor ntregi zecimale de tipurile long int i respectiv unsigned short int. Partea a doua ilustreaz cteva modaliti de afiare a numerelor reale. Variabilele x i y se declar de tipul double i se iniializeaz cu dou valori concrete. n principiu, specificatorul de format %f poate fi folosit cu oricare din tipurile float sau double i afiarea se face uzual cu 6 cifre la partea fracionar. Utilizarea specificatorului %e sau %E conduce la afiarea numrului real n formatul tiinific; formatul %6.3f va duce la afiarea lui x cu 6 caractere n total (5 cifre plus punctul zecimal) i 3 cifre precizie pentru partea fracionar (ca atare, numrul 12.3468 se va rotunji la 12.347); n sfrit, formatul %8.4f va duce la afiarea lui y sub forma 0.1120 (deoarece limea cmpului de afiare specificat prin format este 8, cu dou uniti mai mare dect este necesar, afiarea se completeaz cu dou spaii libere la stnga numrului). n partea a treia a programului se exemplific utilizarea i afiarea caracterelor. Cele trei variabile folosite sunt declarate de tipul char; constantele caracter se scriu ntre simbolurile apostrof. Compilatorul plaseaz, de exemplu, codul ASCII al lui b, 98, la adresa variabilei b_mic; similar pentru celelalte dou variabile. Aceste valori pot fi utilizate, de exemplu, pentru a face diferite calcule aritmetice (dup cum se arat i n program), i se afieaz ca numere ntregi dac se folosete specificatorul de format %d, sau sunt reconvertite n caracterele corespunztoare dac este folosit specificatorul %c. Aceast idee este reluat i n problema urmtoare. ============================= 8

P3.2

Scriei un program care afieaz codul ASCII al unui caracter citit de la tastatur.

#include <stdio.h> #include <stdlib.h> int main() { char ch; printf ("Introduceti un caracter: "); ch = getch(); printf("\nCaracterul %c are codul ASCII %3d", ch, ch); printf("\n"); system("PAUSE"); return 0; }

Dac se introduce de la tastatur, de exemplu, caracterul c, programul va afia:


Introduceti un caracter: (c) Caracterul c are codul ASCII 99

Discuie:
Se declar variabila ch de tip caracter. Funcia getch() citete un caracter de la tastatur, adic ateapt pn cnd este apsat o tast i apoi ntoarce codul su ASCII. Este o variant a funciei de I/O getche(), dar spre deosebire de aceasta din urm, nu afieaz automat pe ecran caracterul introdus de la tastatur (se mai spune c nu are ecou pe ecran). Precizm c funciile getch() i getche() nu sunt funcii ANSI. Bibliotecile standard ANSI pun la dispoziia utilizatorului doar funciile getc() i getchar() care ns citesc primul caracter introdus i ateapt validarea scrierii de ctre utilizator prin tasta <Enter>. Caracterele necitite, inclusiv <Enter>, rmn n buffer i vor fi citite de urmtoarele apeluri la getc() sau getchar(). Recomandm folosirea funciilor getch() i getche() care sunt mai flexibile. Specificatorul de format %3d definete dimensiunea minim a cmpului n care se va afia numrul ntreg (3 n cazul de fa); deoarece codul ASCII al lui c este 99 (pentru exemplul considerat anterior), deci necesit dou cifre, se va tipri un spaiu suplimentar la stnga sa. De notat c dac se indic o lime de cmp mai mic dect este necesar, compilatorul va aloca totui limea necesar (doar numrul de zecimale precizat prin format va fi respectat ntocmai). ============================= P3.3 Scriei un program care adun i nmulete dou numere complexe exprimate sub forma z1 = a + bi , z2 = c + d i (se citesc efectiv a, b, c, d numere reale). Indicaie: (a + bi) + (c + d i) = (a + c) + (b + d)i (a + bi)(c + d i) = (ac bd) + (ad + bc)i

#include <stdio.h> #include <stdlib.h> int main() { float a, b, c, d; printf("Introduceti z1: "); scanf("%f %f", &a, &b); printf("Ati introdus z1 = %f + %fi", a, printf("\nIntroduceti z2: "); scanf("%f %f", &c, &d); printf("Ati introdus z2 = %f + %fi", c, printf("\nz1 + z2 = %f + %fi", a + c, b printf("\nz1 * z2 = %f + %fi ", a * c printf("\n"); system("PAUSE"); return 0; }

b); d); + d); b * d, a * d + b * c);

Dac se introduc de la tastatur, de exemplu, numerele 1.2 i 2.1, respectiv 3.4 i 4.3, programul va afia:
Introduceti z1: 1.2 2.1 Ati introdus z1 = 1.200000 + 2.100000i Introduceti z2: 3.4 4.3 Ati introdus z2 = 3.400000 + 4.300000i z1 + z2 = 4.600000 + 6.400000i z1 * z2 = -4.950000 + 12.300000i

============================= 9

P3.4

Urmtorul program ilustreaz utilizarea operatorilor de mprire (/) i modulo (%).

#include <stdio.h> #include <stdlib.h> int main() { int i = 7, j = 4, k, l; float f = 7.0, g = 4.0, h; k = i / j; h = i / j; printf("7 / 4 = %d sau %f", k, h); /* rezultate incorecte */ h = f / g; printf("\n7.0 / 4.0 = %f\n", h); /* rezultat corect */ l = i % j; printf("Restul impartirii lui 7 la 4 este %d", l); printf("\n"); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


7 / 4 = 1 sau 1.000000 7.0 / 4.0 = 1.750000 Restul impartirii lui 7 la 4 este 3

============================= P3.5 Urmtorul program ilustreaz utilizarea operatorilor de incrementare i decrementare.

#include <stdio.h> #include <stdlib.h> int main() { int x, y = 10, z; x = ++y; /* secventa echivalenta cu: y++; x = y; */ printf("x = %d, y = %d\n", x, y); y = 10; z = --y + 5; /* secventa echivalenta cu: y--; z = y+5; */ printf("z = %d, y = %d\n", z, y); y = 10; x = y++; /* secventa echivalenta cu: x = y; y++; */ printf("x = %d, y = %d\n", x, y); y = 10; z = 3 * y--; /* secventa echivalenta cu: z = 3 * y; y--; */ printf("z = %d, y = %d", z, y); printf("\n"); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


x z x z = = = = 11, 14, 10, 30, y y y y = = = = 11 9 11 9

============================= P3.6 Urmtorul program ilustreaz utilizarea operatorilor relaionali i logici.


#include <stdio.h> #include <stdlib.h> int main() { int i = 10, j, k, l = 18, m, n; int a, b, c, d, e; /* Sectiunea 1 */ j = i > 5;

10

k = i >= 50; printf("j = %d, k = %d\n", j, k); /* Sectiunea 2 */ m = ((i > 11) && (l < 19)) || (l > 10); printf("m = %d\n", m); /* Sectiunea 3 */ n = 10 > 5 && !(10 < 9) || 3 >= 4; printf("n = %d\n\n", n); a = 0, b, c = 7, d = 5, e; /* Sectiunea 4 */ b = d += 2; printf("b = %d\n", b); /* Sectiunea 5 */ b = c++ > 7; printf("b = %d, c = %d\n", b, c); /* Sectiunea 6 */ b = a == 0 && c; printf("b = %d\n", b); /* Sectiunea 7 */ e = !a > c >= 2; printf("e = %d", e); printf("\n"); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


j = 1, k = 0 m = 1 n = 1 b b b e = = = = 7 0, c = 8 1 0

Discuie:
expresia Seciunea 1: expresia i > 5 este evaluat adevrat (10 > 5), deci va primi valoarea 1, apoi j = 1; i >= 50 este evaluat fals, deci va primi valoarea 0, apoi k = 0. Seciunea 2: se execut mai nti parantezele; 0 && 1 = 0, apoi 0 || 1 = 1; n final m = 1. Seciunea 3: ordinea de evaluare este urmtoarea: 1. (10 < 9) = 0 2. !(0) = 1 3. 10 > 5 = 1 , 3 >= 4 = 0 4. 1 && 1 || 0 (1 && 1) || 0 = 1 || 0 = 1 5. n = 1 Seciunea 4: operatorii = i += au aceeai prioritate i asociativitate de la dreapta spre stnga; prin urmare, ordinea de evaluare este urmtoarea: 1. d += 2 d = d + 2 = 7 2. b = 7 Seciunea 5: ordinea de evaluare este urmtoarea: 1. c > 7 = 0 2. b = 0 3. c++ = 8 Seciunea 6: == are prioritate mai mare dect &&; ordinea de evaluare este urmtoarea: 1. a == 0 = 1 2. 1 && c = 1 3. b = 1 Seciunea 7: ordinea de evaluare este urmtoarea: 1. !a = 1 2. 1 > c = 0 , 0 >= 2 = 0 3. e = 0 ============================= 11

P3.7

Urmtorul program ilustreaz conversiile implicite de tip n expresii i atribuiri, ca i utilizarea operatorului cast.

#include <stdio.h> #include <stdlib.h> int main() { /* Sectiunea 1 */ int a = 10, b = 3; float c = 10.0, d; int u, x, y; unsigned char ch_1, ch_2; double v; int i, j; float k, l, m, n, p; d = c / (a / b); printf("d = %f\n\n", d); /* Sectiunea 2 */ u, x = 230, y = 260; v = 10.333; u = v; ch_1 = x; ch_2 = y; printf("u = %d ch_1 = %d

ch_2 = %d\n\n", u, ch_1, ch_2);

/* Sectiunea 3 */ i = 5, j = 4; k = i / j; l = (float)(i / j); printf("k = %f\tl = %f\n", k, l); m = (float)i / j; n = i / (float)j; p = (float)i / (float)j; printf("m = %f\tn = %f\tp = %f\n", m, n, p); printf("(float)(4 * 6) / 5 = %f", (float)(4 * 6) / 5); printf("\n"); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


d = 3.333333 u = 10 ch_1 = 230 ch_2 = 4 p = 1.250000

k = 1.000000 l = 1.000000 m = 1.250000 n = 1.250000 (float)(4 * 6) / 5 = 4.800000

Discuie:
Seciunea 1: se evalueaz mai nti paranteza; mprirea lui a la b produce un rezultat ntreg (3), ambii operanzi fiind ntregi; aceast valoare este apoi convertit la o valoare real, deoarece tipul lui c este float (chiar dac rezultatul final al unei expresii va fi de tipul cel mai larg, regulile de conversie implicit sunt aplicate operaie dup operaie). Seciunea 2: u primete valoarea ntreag a lui v; ch_1 este afiat corect, deoarece numrul ntreg 230 intr n gama de reprezentare a tipului unsigned char, adic [0, 255], n schimb ch_2 nu este afiat corect, producndu-se o pierdere de informaie (numai cei 8 bii inferiori ai lui y sunt copiai n ch_2). Observaie: putem deduce simplu valoarea ce va fi afiat pe ecran n acest ultim caz; numrul ntreg 260 exprimat n binar este 100000100, iar ultimii 8 bii codific practic numrul ntreg 4 (numrul 4 reprezentat n binar este 100). Seciunea 3: alturi de lucrurile discutate deja pn n acest moment, mai facem doar o precizare: teoretic, este suficient sa form tipul unuia dintre cei doi operanzi ce realizeaz o operaie, deoarece cel de-al doilea operand va fi adus automat la tipul celui dinti. =============================

12

3.2. 1.

Probleme propuse

Scriei un program care calculeaz i afieaz pe ecran media aritmetic a dou numere ntregi citite de la tastatur. Propunei mai multe variante de a rezolva corect problema, innd cont de faptul c media trebuie s fie un numr real. Scriei un program care citete pe n ntreg i afieaz valoarea expresiei n/(n+1) cu patru zecimale. Deducei ce afieaz urmtorul program:

2. 3.

#include <stdio.h> #include <stdlib.h> int main() { int i=3, j=5, k=10, x, z, u; float y; x = i * k / j + k j + 3 * i; printf("x = %d\n", x); y = (2 * k) / (float)(i * j) + 7; printf("y = %f\n", y); i = 3, j = 5, k = 10; z = --i * j++; printf("z = %d\n", z); i = 3, j = 5, k = 10; u = i < j == j > k; printf("u = %d", u); printf("\n"); system("PAUSE"); return 0; }

4.

Ce este incorect la urmtorul program?

#include <stdio.h> #include <stdlib.h> int main() { int x; (float)x = 10.22; printf("x = %f\n"); system("PAUSE"); return 0; }

13

4.
4.1.
P4.1

Instruciuni condiionale
Probleme rezolvate
Urmtorul program simplu determin dac un numr ntreg introdus de la tastatur este pozitiv (strict pozitiv sau zero), sau strict negativ.

#include <stdio.h> #include <stdlib.h> int main() { int numar; printf("Introduceti un numar intreg: "); scanf("%d", &numar); if(numar < 0) printf("Ati introdus un numar negativ!"); else printf("Ati introdus un numar pozitiv!"); printf("\n"); system("PAUSE"); return 0; }

============================= P4.2 Urmtorul program simplu citete un caracter introdus de la tastatur i verific dac acesta a fost caracterul t.

#include <stdio.h> #include <stdlib.h> int main() { char ch; printf("Tastati un caracter: "); scanf("%c", &ch); if(ch == 't') printf("Ati tastat 't'!"); else printf("Ati tastat %c ...", ch); printf("\n"); system("PAUSE"); return 0; }

============================= P4.3 Urmtorul program ilustreaz valorile logice adevrat i fals n C, folosind dou decizii simple.

#include <stdio.h> #include <stdlib.h> int main() { if(32) printf("Acest text va fi intotdeauna afisat."); /* orice valoare diferit de 0 este considerat "adevarat"! */ if(0) printf("Acest text nu va fi afisat niciodata."); printf("\n"); system("PAUSE"); return 0; }

============================= 14

P4.4

Scriei un program care calculeaz i afieaz rdcinile ecuaiei de gradul doi cu coeficieni reali

a x 2 + bx + c = 0 (coeficienii fiind citii de la tastatur); se va presupune, pentru simplificare, c a 0 .


#include <stdio.h> #include <math.h> #include <stdlib.h> int main() { float a, b, c, delta, x1, x2; printf("Introduceti a (diferit de 0): "); scanf("%f", &a); printf("Introduceti b: "); scanf("%f", &b); printf("Introduceti c: "); scanf("%f", &c); delta = b * b 4 * a * c; if(delta >= 0) { x1 = (-b + sqrt(delta)) / (2 * a); /* functia sqrt() este definita in fisierul header 'math.h' */ x2 = (-b - sqrt(delta)) / (2 * a); printf("\nSe obtin radacini reale:\n"); printf("x1 = %1.3f\tx2 = %1.3f", x1, x2); } else { printf("\nSe obtin radacini complexe:\n"); printf("x1 = %1.3f + %1.3fi", -b / (2 * a), sqrt(-delta) / (2 * a)); printf("\nx2 = %1.3f - %1.3fi", -b / (2 * a), sqrt(-delta) / (2 * a)); } printf("\n"); system("PAUSE"); return 0; }

============================= P4.5 Urmtorul program simplu ilustreaz funcionarea instruciunilor if multiple.

#include <stdio.h> #include <stdlib.h> int main() { int i = 100, j = -20; if(i > 0) if(i > 1000) printf("i este foarte mare!"); else printf("i este mare"); /* se va afisa "i este mare"; else-ul este asociat celui mai apropiat if */ if(j > 0) { if(j > 1000) printf("\nj este foarte mare!"); } else printf("\nj este negativ"); /* se va afisa "j este negativ"; datorita folosirii acoladelor, else-ul este asociat primului if */ printf("\n"); system("PAUSE"); return 0; }

============================= 15

P4.6

Scriei un program care s determine dac trei numere ntregi introduse de la tastatur pot constitui o dat calendaristic (nu se iau n consideraie anii biseci sau dac luna are 30/31 zile).

#include <stdio.h> #include <stdlib.h> int main() { int zi, luna, an; printf("Introduceti ziua: "); scanf("%d", &zi); printf("Introduceti luna: "); scanf("%d", &luna); printf("Introduceti anul: "); scanf("%d", &an); if((zi > 0) && (zi <= 31)) if((luna > 0) && (luna <= 12)) if((an > 0) && (an < 10000)) printf ("Poate fi data calendaristica."); else printf("Nu poate fi data din cauza anului!"); else printf("Nu poate fi data din cauza lunii!"); else printf ("Nu poate fi data din cauza zilei!"); printf("\n"); system("PAUSE"); return 0; }

============================= P4.7 Scriei un program care s calculeze i s afieze minimul dintre dou numere reale citite de la tastatur, i respectiv maximul dintre valorile absolute a dou numere ntregi, folosind operatorul condiional.

#include <stdio.h> #include <stdlib.h> int main() { /* Sectiunea 1 */ float a, b, min; int c, d, e, f; printf("Introduceti a: "); scanf("%f", &a); printf("Introduceti b: "); scanf("%f", &b); min=(a < b) ? a : b; /* secventa echivalenta cu: if(a < b) min = a; else min = b; */ printf("Minimul dintre a si b este %f\n\n", min); /* Sectiunea 2 */ printf("Introduceti c: "); scanf("%d", &c); printf("Introduceti d: "); scanf("%d", &d); e = (c < 0) ? c : c; /* se calculeaza modulul lui c */ f = (d < 0) ? d : d; /* se calculeaza modulul lui d */ printf("Maximul dintre |c| si |d| este %d", (e > f) ? e : f); /* daca e>f se va afisa e, altfel se va afisa f */ printf("\n"); system("PAUSE"); return 0; }

============================= 16

P4.8

Urmtorul program ilustreaz funcionarea structurii de selecie. Se citesc dou numere ntregi a i b i o operaie ntre ele (+, , *, sau /) i se va afia rezultatul operaiei.

#include <stdio.h> #include <stdlib.h> int main() { int a, b; float rez; char op; printf("Introduceti a: "); scanf("%d", &a); printf("Introduceti b: "); scanf("%d", &b); printf("Introduceti operatia: "); op = getche(); switch(op) { case '+': printf("\nSuma este %d", a + b); break; case '-': printf("\nDiferenta este %d", a - b); break; case '*': printf("\nProdusul este %d", a * b); break; case '/': if(b == 0) printf ("\nImpartirea nu se poate efectua!"); else printf("\nCatul este %f", (float)a / (float)b); break; default: printf ("\nAti introdus un cod incorect!"); } printf("\n"); system("PAUSE"); return 0; }

============================= P4.9 Scriei un program care s calculeze i s afieze aria sau lungimea unui cerc de raz dat (numr ntreg, citit de la tastatur), n funcie de opiunea utilizatorului.

#include <stdio.h> #include <stdlib.h> int main() { int r; float pi = 3.14; char c; printf("Introduceti raza: "); scanf("%d", &r); printf("Introduceti optiunea, astfel:\n"); printf("pentru arie: A sau a \n"); printf("pentru lungime: L sau l \n"); printf("pentru iesire din program: Q sau q \n\n"); c=getch(); switch(c) { default: printf("Optiune necunoscuta!"); break; case 'q': case 'Q': printf("Iesire!"); break; case 'a': case 'A': printf("Aria este: %.2f", pi * r * r); break; case 'l': case 'L': printf("Lungimea este: %.2f", 2 * pi * r); break; }

17

printf("\n"); system("PAUSE"); return 0; }

Discuie:
Seciunile structurii de selecie pot fi plasate n orice ordine; de exemplu, aezarea lui default la nceputul structurii, ca n exemplul anterior, nu afecteaz n nici un fel funcionarea programului. Aa cum se cunoate, instruciunile asociate unui case pot lipsi complet; aceasta permite, de exemplu, ca dou sau mai multe case s execute aceleai instruciuni fr s fie nevoie de repetarea lor Secvena din program realizat cu switch se putea scrie i folosind instruciuni de decizie multiple de tipul if-else-if, dar era evident mai complicat:
if(c == 'a' || c == 'A') printf("Aria este: %.2f", pi * r * r); else if(c == 'l' || c == 'L') printf("Lungimea este: %.2f",2 * pi * r); else if(c == 'q' || c == 'Q') printf("Iesire!"); else printf("Optiune necunoscuta!");

=============================

4.2. 1.

Probleme propuse

Ce este incorect la urmtorul program? Ce va afia programul dac dup compilare i execuie se introduce de la tastatur numrul 10?

#include <stdio.h> #include <stdlib.h> int main() { int i; printf("Introduceti un numar intreg: "); scanf("%d", &i); if(i > 0); printf("Ati introdus un numar pozitiv!"); printf("\n"); system("PAUSE"); return 0; }

2.

Scriei un program care calculeaz i afieaz rdcina ecuaiei de gradul nti cu coeficieni reali a x + b = 0 (coeficienii fiind citii de la tastatur); discuie. Indicaie: ecuaia are soluie dac a 0 ; dac a = 0 : dac b = 0 ecuaia este nedeterminat, iar dac b 0 ecuaia nu are soluie. Folosind instruciuni de decizie, scriei un program care citete de la tastatur un numr ntreg x i afieaz o valoare y calculat astfel:

3.

x + 3 , pentru x < 0 y = 3 , pentru x [0, 4] 3x 9 , pentru x > 4


4.
Scriei un program care citete dou numere ntregi de la tastatur, mparte cele dou numere i afieaz rezultatul. Cum numitorul trebuie s fie diferit de zero, discutai aceast situaie n dou moduri: folosind o decizie if ... else i respectiv operatorul condiional. Scriei un program care s calculeze i s afieze maximul i minimul dintre trei numere ntregi citite de la tastatur, utiliznd operatorul condiional. Scriei un program care citete de la tastatur un numr ntreg ntre 1 i 7 i afieaz denumirea zilei din sptmn corespunztoare cifrei respective: 1 luni, 2 mari etc. Programul va semnaliza printr-un mesaj de eroare dac numrul introdus nu a fost n intervalul solicitat. Indicaie: se va folosi o instruciune switch.

5. 6.

18

5.
5.1.
P5.1

Cicluri
Probleme rezolvate
Urmtorul program simplu ilustreaz utilizarea ciclului cu test iniial: se introduc continuu caractere de la tastatur, pn cnd este tastat litera q.

#include <stdio.h> #include <stdlib.h> int main() { char ch; printf("Introduceti un caracter ('q' pentru terminare): "); ch = getch(); while(ch != 'q') { printf("\nAti introdus %c ", ch); ch = getch(); } printf("\n\nAti introdus q!"); printf("\n"); system("PAUSE"); return 0; }

Discuie:
Accentum faptul c n C, ciclurile accept pentru testarea condiiei orice fel de expresii. Mai mult, se pot realiza operaii complexe n expresia ce semnific testul de condiie; astfel, partea de program urmtoare:
ch = getch(); while(ch != 'q') { printf("\nAti introdus %c ", ch); ch = getch(); }

se poate scrie mai simplu astfel:


while((ch = getch()) != 'q') { printf("\nAti introdus %c ", ch); }

============================= P5.2 Urmtorul program simplu ilustreaz utilizarea ciclului cu test final: se afieaz ptratele numerelor ntregi cuprinse ntre a i 2a, unde a este un ntreg pozitiv care se citete de la tastatur.

#include <stdio.h> #include <stdlib.h> int main() { int a, b; printf("Introduceti un numar intreg pozitiv (<100): "); scanf("%d", &a); b = 2 * a; printf("start\n"); do { printf("%d * %d = %d\n", a, a, a * a); a++; } while(a <= b); printf("stop\n"); system("PAUSE"); return 0; }

Dac se introduce de la tastatur, de exemplu, numrul 4, programul va afia:


Introduceti un numar intreg pozitiv (<100): 4 start 4 * 4 = 16 5 * 5 = 25 6 * 6 = 36 7 * 7 = 49 8 * 8 = 64 stop

19

Discuie:
Cu aceeai observaie ca cea fcut la problema 5.1, ciclul cu test final din problem se mai poate scrie, de exemplu, astfel (reamintim c un operator de incrementare sau decrementare utilizat ca prefix determin ca valoarea nou s fie calculat naintea evalurii expresiei):
do { printf("%d*%d = %d\n", a, a, a * a); } while(++a <= b);

============================= P5.3 Urmtorul program simplu ilustreaz forma de baz a ciclului cu contor: se citete un numr natural i se afieaz suma 1 + 2 + ... + n .

n2

#include <stdio.h> #include <stdlib.h> int main() { int n, s, i; printf("Introduceti un numar natural (>=2): "); scanf("%d", &n); s = 0; for(i = 1; i <= n; i++) { s = s + i; } printf("Suma numerelor de la 1 la %d este %d", n, s); printf("\n"); system("PAUSE"); return 0; }

Discuie:
O variant a programului anterior, utiliznd un ciclu cu test iniial, este urmtoarea:
#include <stdio.h> #include <stdlib.h> int main() { int n, i = 0, s = 0; printf("Introduceti un numar natural (>=2): "); scanf("%d", &n); while(i < n) { i++; s += i; } printf("Suma numerelor de la 1 la %d este %d", n, s); printf("\n"); system("PAUSE"); return 0; }

============================= P5.4 S se explice ce afieaz urmtorul program dup compilare i execuie, ca i particularitile ciclului for utilizat. Ce se ntmpl dac se introduce de la tastatur un numr ntreg negativ? Dar dac se introduce un numr natural impar?

#include <stdio.h> #include <stdlib.h> int main() { int i, j; printf("Introduceti un numar natural par: "); for( ; i; i -= 2) { j = i * i * i; printf("%d %d\n", i, j); } system("PAUSE"); return 0; } scanf("%d", &i);

20

Dac se introduce de la tastatur, de exemplu, numrul 8, programul va afia:


Introduceti un numar natural par: 8 8 512 6 216 4 64 2 8

Discuie:
Programul numr descresctor, din doi n doi, de la valoarea introdus de utilizator i pn la 2, apoi afieaz aceste numere, mpreun cu cuburile acestora, pe rnduri succesive. Sunt ilustrate o serie de variaii n modul de utilizare ale ciclului cu contor n C: seciunea iniializare a ciclului lipsete, deoarece contorul i este iniializat practic de ctre utilizator n afara ciclului (atenie ns c semnul ; trebuie s fie prezent!); testul de condiie are urmtoarea semnificaie: ciclul se reia att timp ct i este adevrat, adic diferit de zero; de asemenea, se observ c modificarea contorului se poate face cu orice valoare, i nu numai cu 1 (ca n Pascal, de exemplu); contorul este utilizat i n corpul ciclului, n cazul problemei de fa pentru calculul lui j (acest lucru este posibil, aa cum s-a specificat i la partea teoretic, deoarece valoarea contorului nu este modificat de operaiile din cadrul ciclului). Dac numrul introdus de la tastatur este negativ, sau pozitiv impar, ciclul se repet la infinit (justificai aceast afirmaie!). ============================= P5.5 Scriei un program care citete de la tastatur dou numere naturale a i b, cu

a < b , afieaz numerele

naturale din intervalul [a, b] n ordine cresctoare i apoi descresctoare, i de asemenea calculeaz i afieaz media aritmetic a numerelor a i b.
#include <stdio.h> #include <stdlib.h> int main() { int a, b, i, s = 0; printf("Introduceti a (natural): "); scanf("%d", &a); printf("Introduceti b (natural, b>a): "); scanf("%d", &b); printf("\nNumerele dintre a si b in ordine crescatoare:\n"); i = a; while(i <= b) { printf ("%d ", i); i++; } printf("\n"); printf( "Numerele dintre a si b in ordine descrescatoare:\n"); i--; /* dupa ultima iteratie a ciclului anterior, i = b + 1! */ do { printf("%d ", i); i--; } while (i >= a); printf("\n"); printf("Media aritmetica a numerelor dintre a si b: "); for (i = a; i <= b; i++) s = s + i; printf("%.3f",(float)s / (b a + 1)); printf("\n"); system("PAUSE"); return 0; }

============================= 21

P5.6

Scriei un program care citete de la tastatur un numr ntreg n din intervalul afieaz pe n!

[0, 100] , calculeaz i

#include <stdio.h> #include <stdlib.h> int main() { int n, i; double fact; /* variabila fact = n! este declarata 'double' deoarece poate avea valori care sa nu poata fi reprezentate nici cu 4 octeti! */ printf("Introduceti un numar intreg intre 0 si 100: "); scanf("%d", &n); while(n < 0 || n > 100) { printf("Numarul introdus nu apartine intervalului!"); printf("\nIntroduceti din nou numarul: "); scanf("%d", &n); } if(n > 0) { for(fact = 1.0, i = 2; i <= n; i++) { fact = fact * i; /* sectiunea initializare cuprinde doua expresii separate de operatorul ','! */ } } else { fact = 1; /* pentru cazul n = 0 se foloseste definitia standard 0! = 1 */ } printf("Pentru n = %d, n! = %g\n", n, fact); /* specificatorul de format '%g' asigura tiparirea in formatul e sau f, care dintre ele este mai compact */ system("PAUSE"); return 0; }

============================= P5.7 Scriei un program care afieaz toi divizorii unui numr natural n citit de la tastatur; dac numrul este prim, se va afia acest lucru printr-un mesaj.

#include <stdio.h> #include <stdlib.h> int main() { int n, i, k; printf("Introduceti un numar natural: "); scanf("%d", &n); k = 0; for(i = 2; i <= n / 2; i++) { if(n % i == 0) { printf("%d ", i); k = 1; } } if(k == 1) printf("sunt divizorii lui %d", n); else printf("Numarul %d este prim!", n); printf("\n"); system("PAUSE"); return 0; }

Dac se introduce de la tastatur, de exemplu, numrul 36, programul va afia:


Introduceti un numar natural: 36 2 3 4 6 9 12 18 sunt divizorii lui 36

22

Discuie:
Programul folosete un ciclu cu contor pentru a cuta divizorii; se parcurge intervalul [2, n / 2] , incrementnd unitar contorul i i se caut numerele la care n se mparte exact (n%i==0). Variabila auxiliar k, iniializat cu 0, devine 1 dac s-a gsit cel puin un divizor. Justificai condiia de terminare a ciclului i<=n/2; este testul de condiie formulat corect indiferent dac n este par sau impar? ============================= P5.8 Scriei un program care citete de la tastatur dou numere naturale a i b ( a numerele prime din intervalul
#include <stdio.h> #include <stdlib.h> int main() { int a, b, i, j, k, m; printf("Introduceti a (natural): "); scanf("%d", &a); printf("Introduceti b (natural, b>a): "); scanf("%d", &b); m = 0; for(i = a; i <= b; i++) { k = 0; for(j = 2; j <= i / 2; j++) { if(i % j == 0) k=1; } if(k == 0) { printf("%d ", i); m = 1; } } if(m == 1) printf("sunt numerele prime dintre %d si %d", a, b); else printf("Intre %d si %d nu exista numere prime!", a, b); printf("\n"); system("PAUSE"); return 0; }

< b ) i afieaz toate

[a, b] .

Dac se introduc de la tastatur, de exemplu, perechile de numere 3, 18 i respectiv 24, 28, programul va afia n cele dou situaii:
Introduceti a (natural): 3 Introduceti b (natural, b>a): 18 3 5 7 11 13 17 sunt numerele prime dintre 3 si 18 Introduceti a (natural): 24 Introduceti b (natural, b>a): 28 Intre 24 si 28 nu exista numere prime!

Discuie:
Problema este ceva mai complicat dect cea anterioar, n special dac se dorete tratarea tuturor cazurilor posibile. Primul ciclu for folosete contorul i pentru a parcurge ntreg intervalul [a, b] ; se presupune mai nti c fiecare numr i din interval este prim i se iniializeaz cu 0 variabila k. Se parcurge apoi cu al doilea ciclu for (contor j) intervalul [2, i / 2] pentru a se cerceta dac fiecare i are sau nu divizori, similar algoritmului utilizat n problema 5.7; dac se gsete un divizor, k va lua valoarea 1. Dac dup parcurgerea ntregului ciclu interior k rmne 0, nseamn c i este prim, se afieaz, i ciclul exterior continu cu urmtoarea valoare a lui i. Variabila auxiliar m folosete n acest program pentru a se putea trata i cazul special n care n intervalul [a, b] nu exist numere prime; m se iniializeaz cu 0 nainte de primul ciclu, i devine 1 dac a fost gsit cel puin un numr prim (care s-a afiat). =============================

23

P5.9

Urmtorul program ilustreaz folosirea instruciunilor break i continue: se afieaz numerele impare dintre 1 i un numr natural ales de utilizator; trebuie s se permit reluarea exerciiului (fr ieirea din program), dac utilizatorul dorete acest lucru, iar dac valoarea introdus este 0 , programul va tipri un mesaj de eroare i va fi abandonat.

#include <stdio.h> #include <stdlib.h> int main() { int n, i, k; char ch; k = 1; do { printf("Introduceti un numar natural (>0): "); scanf("%d", &n); if(n <= 0) { printf("Valoare ilegala!\n"); break; /* se abandoneaza ciclul 'do...while' */ } for(i = 1; i <= n; i++) { if(i % 2 == 0) continue; /* se trece la inceputul ciclului 'for': se incrementeaza contorul, se reevalueaza conditia, apoi ciclul continua; programul nu va afisa numerele pare */ printf("%d ", i); } printf("sunt numerele impare intre 1 si %d", n); printf("\nDoriti sa reluati? (D/N): "); ch = getche(); if(ch == 'N') k=0; printf("\n\n"); } while(k); system("PAUSE"); return 0; }

=============================

5.2. 1.

Probleme propuse

Scriei un program care citete pe n natural i afieaz valoarea expresiei:

s=
2. 3. 4. 5. 6. 7.

1 1 1 + + K + . 1+1 1+ 2 1+ n

Scriei un program care citete pe n natural i afieaz valoarea expresiei:

s = 0! + 1! + 2! + K + n !

Scriei un program care afieaz numerele dintr-un interval

[a, b] ce se divid cu un numr natural k citit.

Scriei un program care afieaz numerele prime mai mici dect un numr natural k citit. Scriei un program care s descompun n factori primi un numr natural n citit. Reluai problema 5.9, cu urmtoarea modificare: se vor afia numerele divizibile cu 3 dintre 1 i un numr natural n citit. Este corect urmtorul fragment de program? Ce funcie realizeaz? Ce face, n principiu, ciclul cu contor scris sub forma for(;;)?
... for( ; ;) { ch = getche(); if(ch == 'A') } ...

break;

24

6.
6.1.
P6.1

Tablouri i iruri de caractere


Probleme rezolvate
Scriei un program care citete de la tastatur un vector de maxim 10 elemente ntregi mpreun cu dimensiunea sa efectiv i apoi afieaz elementele sale. Precizare: ntruct la rularea programului nu este cunoscut de la nceput numrul de elemente (el este mai mic dect 10) se va opta pentru citirea, la nceput, a numrului de elemente.

#include <stdio.h> #include <stdlib.h> int main() { int v[10], n, i; printf("Introduceti nr. de elemente: "); scanf("%d", &n); for(i = 0; i < n; i++) { printf("v[%d] = ", i); scanf("%d", &v[i]); } printf("Valorile citite sunt:\n"); for(i = 0; i < n; i++) printf("v[%d] = %d\n", i, v[i]); system("PAUSE"); return 0; }

Programul va afia pe ecran dup compilare i execuie:


Introduceti nr. de elemente: 3 v[0] = -1 v[1] = 0 v[2] = 1 Valorile citite sunt: v[0] = -1 v[1] = 0 v[2] = 1

Discuie:
Primul ciclu for citete elementele vectorului. Cel de al doilea ciclu for afieaz valorile citite i memorate. ============================= P6.2 Scriei un program citete un vector de elemente ntregi, mpreun cu dimensiunea sa efectiv, afieaz n ordine invers elementele vectorului i calculeaz media aritmetic a elementelor sale.

#include <stdio.h> #include <stdlib.h> int main() { int v[10], n, i, s; float m; printf("Introduceti n: "); scanf("%d", &n); for(i = 0; i < n; i++) { printf("v[%d] = ", i); scanf("%d", &v[i]); } for(i = n - 1; i >= 0; i--) printf("%d ", v[i]); s = 0; for(i = 0; i < n; i++) s += v[i];

25

m = (float)s / n; printf("\tma = %.2f\n", m); system("PAUSE"); return 0; }

Programul va afia pe ecran dup compilare i execuie:


Introduceti n: 4 v[0] = 1 v[1] = 2 v[2] = 3 v[3] = 4 4 3 2 1 ma = 2.50

Discuie:
Dup citire numrului de elemente, n, primul ciclu for citete elementele vectorului. Al doilea ciclu for parcurge vectorul de la ultimul (i ia valoarea n - 1) pn la primul su element (i >= 0) prin decrementarea (i--) contorului. Variabila s (ce va conine suma tuturor elementelor vectorului) se iniializeaz cu valoarea 0. Al treilea ciclu for parcurge vectorul i la fiecare pas al ciclului se adun la vechea valoare a variabilei s, valoarea lui v[i]. La final, media aritmetic, ma, este calculat i afiat. De remarcat conversia de tip (float)s / n. ============================= P 6.3 Scriei un program care citete un vector de elemente ntregi, mpreun cu dimensiunea sa efectiv, i determin maximul i minimul dintre elementele acestui vector.

#include <stdio.h> #include <stdlib.h> int main() { int v[20], n, i, max, min; printf("Introduceti numarul de elemente din vector: "); scanf("%d", &n); for(i = 0; i < n; i++) { printf("v[%d] = ", i); scanf("%d", &v[i]); } min = max = v[0]; for(i = 1; i < n; i++) { if(v[i] >= max) max = v[i]; if(v[i] <= min) min = v[i]; } printf("max = %d\tmin = %d\n", max, min); system("PAUSE"); return 0; }

Programul va afia pe ecran dup compilare i execuie:


Introduceti numarul de elemente din vector: 4 v[0] = -1 v[1] = 5 v[2] = -3 v[3] = 4 max = 5 min = -3

26

Discuie:
Dup citire numrului de elemente, n, primul ciclu for citete elementele vectorului. Variabilele min i max sunt iniializate cu valoarea primului element din vector, v[0]. Algoritmul parcurge vectorul i testeaz la fiecare pas al ciclului for pentru fiecare element v[i], relaia sa de inegalitate n raport cu min respectiv max. n primul caz, dac v[i] este mai mare dect max, atunci elementul v[i] reprezint un maxim local i deci valoarea lui v[i] i se atribuie variabilei max. n al doilea caz, dac v[i] este mai mic dect min atunci elementul v[i] reprezint un minim local i deci valoarea lui v[i] i se atribuie variabilei min. La sfritul ciclului for, variabilele min i max conin valorile minim respectiv maxim din vectorul v. ============================= P6.4 Scriei un program care citete un vector de elemente ntregi, mpreun cu dimensiunea sa efectiv, ordoneaz cresctor elementele vectorului i apoi afieaz vectorul ordonat. Se va utiliza metoda de ordonare (se utilizeaz i termenul sortare) denumit, n limba englez, bubble-sort.

#include <stdio.h> #include <stdlib.h> int main() { int v[20], n, i, ind, tmp; printf("Introduceti numarul de elemente din vector: "); scanf("%d", &n); for(i = 0; i < n; i++) { printf("v[%d] = ", i); scanf("%d", &v[i]); } do { ind = 0; for(i = 0; i < n - 1; i++) { if(v[i] > v[i+1]) { tmp = v[i]; v[i] = v[i+1]; v[i+1] = tmp; ind = 1; } } } while(ind); for(i = 0; i < n; i++) printf("v[%d] = %d\n", i, v[i]); system("PAUSE"); return 0; }

Programul va afia pe ecran dup compilare i execuie:


Introduceti numarul de elemente din vector: 4 v[0] = -1 v[1] = 4 v[2] = 2 v[3] = 0 v[0] = -1 v[1] = 0 v[2] = 2 v[3] = 4

Discuie:
Primul ciclu for citete elementele vectorului. Anterior acesteia a fost citit numrul de elemente ale vectorului, n. Programul utilizeaz o variabila ind, cu rol de indicator. Aceasta variabila se iniializeaz cu valoarea 0 naintea unui ciclu care compar perechile succesive de elemente ale vectorului, elementul curent i urmtorul. Pentru parcurgerea vectorului se folosete un ciclu for care evolueaz de la 0 pn la penultimul element (ultima comparaie se face ntre penultimul i ultimul element). Dac o pereche de elemente succesive este n ordinea dorit se trece la compararea urmtoarei perechi. Dac o pereche de elemente nu se afl n ordinea dorit se schimb ntre ele i variabilei ind i se atribuie valoarea 1. Parcurgerea ciclului se reia pn cnd toate elementele sunt n ordinea dorit, respectiv pn cnd ind i pstreaz valoarea 0 dup parcurgerea ntregului vector. Aceasta este metoda de ordonare / sortare bubble-sort. Pentru interschimbarea elementelor care nu se afl n ordinea dorit se utilizeaz variabila temporar tmp. ============================= 27

P6.5

Scriei un program care citete o matrice de maxim 10 10 elemente ntregi, mpreun cu dimensiunile sale efective (linii respectiv coloane) i afieaz att matricea iniial ct i matricea avnd coloanele pare interschimbate cu coloanele impare (interschimbarea afecteaz coloanele alturate, 0-1, 2-3 etc.).

#include <stdio.h> #include <stdlib.h> int main() { int A[10][10], m, n, i, j, tmp; printf("Introduceti nr. de linii: "); scanf("%d", &m); printf("Introduceti nr. de coloane: "); scanf("%d", &n); for(i = 0; i < m; i++) for(j = 0; j < n; j++) { printf("A[%d][%d] = ", i, j); scanf("%d", &A[i][j]); } printf("\nMatricea citita este:\n"); for(i = 0; i < m; i++) { for(j = 0; j < n; j++) printf("%d\t", A[i][j]); printf("\n"); } for(j = 0; j < (n / 2) * 2; j += 2) for(i = 0; i < m; i++) { tmp = A[i][j]; A[i][j] = A[i][j+1]; A[i][j+1] = tmp; } printf("\nMatricea avand coloanele interschimbate este:\n"); for(i = 0; i < m; i++) { for(j = 0; j < n; j++) printf("%d\t",A[i][j]); printf("\n"); } system("PAUSE"); return 0; }

Programul va afia pe ecran dup compilare i execuie:


Introduceti nr. de linii: 2 Introduceti nr. de coloane: 2 A[0][0] = 1 A[0][1] = 2 A[1][0] = 3 A[1][1] = 4 Matricea citita este: 1 2 3 4 Matricea avand coloanele interschimbate este: 2 1 4 3

Dac se introduce o alt matrice rezultatul va fi:


Introduceti nr. de linii: 3 Introduceti nr. de coloane: 5 A[0][0] = 1 A[0][1] = 2 A[0][2] = 3 A[0][3] = 4 A[0][4] = 5

28

A[1][0] A[1][1] A[1][2] A[1][3] A[1][4] A[2][0] A[2][1] A[2][2] A[2][3] A[2][4]

= = = = = = = = = =

6 7 8 9 10 11 12 13 14 15 este: 3 8 13 4 9 14 5 10 15

Matricea citita 1 2 6 7 11 12

Matricea avand coloanele interschimbate este: 2 1 4 3 5 7 6 9 8 10 12 11 14 13 15

Discuie:
Atenie: dac textul problemei nu specific n mod explicit c avem de a face cu o matrice ptrat, matricea prelucrat poate avea numrul de linii diferit de cel de coloane! Citirea elementelor matricei A se face cu ajutorul a dou cicluri for imbricate: prima din ele, care utilizeaz contorul i, parcurge liniile matricei; a doua, ce utilizeaz contorul j, parcurge coloanele matricei A. Reprezentarea sugestiva a parcurgerii matricei n acest caz este prezentat n Figura 6.a. Parcurgerea unei matrice se poate face, n general, utiliznd i parcurgerea pe coloane i apoi pe linii ca n Figura 6.b.

A[0][0]

A[0][1]

A[0][0]

A[0][1]

A[1][0]

A[1][1]

(6.a)

A[1][0]

A[1][1]

(6.b)

Interschimbarea coloanelor pare cu cele impare se face utiliznd a doua modalitate de parcurgere a matricei. Cu excepia cazului cnd n este impar, toate coloanele j se interschimb cu coloanele j+1 utiliznd o variabil temporar tmp pentru fiecare element A[i][j]. ============================= P6.6 Scriei un program care citete de la tastatur o matrice ptrat de dimensiune maxim 10 10 elemente reale mpreun cu dimensiunea sa efectiv i determin i afieaz suma elementelor de pe diagonala principal i de pe diagonala secundar.

#include <stdio.h> #include <stdlib.h> int main() { float mat[10][10]; int dim, i ,j; float sum1 = 0.0, sum2 = 0.0; printf("Introduceti dimensiunea matricei patrate: "); scanf("%d", &dim); /* Citirea matricei */ for(i = 0; i < dim; i++) for(j = 0; j < dim; j++) { printf("Introduceti mat[%d][%d]: ", i, j); scanf("%f", &mat[i][j]); } /* Afisarea matricei citite */ printf("\nMatricea introdusa este:\n\n"); for(i = 0; i < dim; i++) { for(j = 0; j < dim; j++) { printf("%1.3f\t",mat[i][j]); } printf("\n"); }

29

/* Suma elementelor de pe diagonala principala */ for(i = 0; i < dim; i++) sum1 += mat[i][i]; printf("\nSuma elementelor de pe diagonala principala"); printf(" este %1.3f\n", sum1); /* Suma elementelor de pe diagonala secundara */ for(i = 0; i < dim; i++) sum2 += mat[i][dim-i-1]; printf("\nSuma elementelor de pe diagonala secundara"); printf(" este %1.3f\n", sum2); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti dimensiunea matricei patrate: 4 mat[0][0]: 1 mat[0][1]: 2 mat[0][2]: 3 mat[0][3]: 4 mat[1][0]: 5 mat[1][1]: 6 mat[1][2]: 7 mat[1][3]: 8 mat[2][0]: 9 mat[2][1]: 10 mat[2][2]: 11 mat[2][3]: 12 mat[3][0]: 13 mat[3][1]: 14 mat[3][2]: 15 mat[3][3]: 16

Matricea introdusa este: 1.000 5.000 9.000 13.000 2.000 6.000 10.000 14.000 3.000 7.000 11.000 15.000 4.000 8.000 12.000 16.000

Suma elementelor de pe diagonala principala este 34.000 Suma elementelor de pe diagonala secundara este 34.000

Discuie:
Mai nti se citete dimensiunea efectiv a matricei i apoi elementele sale. Programul nu verific faptul c dimensiunea nu depete dimensiunea maxim. Recomandm ca citirea dimensiunii s se fac astfel:
do { printf("Introduceti dimensiunea matricei patrate: "); scanf("%d", &dim); } while(dim < 1 || dim > 10);

Apoi se afieaz matricea citit pentru a verifica datele introduse. Se calculeaz i se afieaz suma elementelor de pe diagonala principal. Aceste elemente au acelai indice pentru linii i coloane. Se calculeaz i se afieaz suma elementelor de pe diagonala secundar. Aceste elemente au indicele coloanei egal cu dimensiunea indicele rndului 1. n expresia anterioar trebuie s scdem 1 pentru c n C numrtoarea ncepe de la 0! P6.7 ============================= Scriei un program care citete dou iruri de maximum 100 de caractere de la tastatur, concateneaz al doilea ir de caractere la primul i afieaz rezultatul.

#include <stdio.h> #include <stdlib.h> int main() { char s1[201], s2[101]; int i, j;

30

i = j = 0; printf("Introduceti sirul 1: "); scanf("%s", s1); printf("Introduceti sirul 2: "); scanf("%s", s2); while(s1[i] != NULL) i++; /* atribuie de la capatul sirului 1 caracterele din s2 cat timp mai sunt caractere in s2 */ while(s2[j] != NULL) { s1[i] = s2[j]; i++; j++; } s1[i] = NULL; printf("%s\n", s1); system("PAUSE"); return 0; }

Dac se introduc de la tastatur irurile "aaa" respectiv "bbb" programul va rula astfel:
Introduceti sirul 1: aaa Introduceti sirul 2: bbb aaabbb

Discuie:
Cele dou iruri de caractere, s1 i s2, sunt citite cu ajutorul funciei scanf(). Primul ciclu while parcurge sir1 pn la capt prin detectarea condiiei s1[i] == NULL. Din acel moment caracterele din al doilea ir se adaug n continuare n primul ir cu al doilea ciclu while. Al doilea ciclu while se putea scrie condensat astfel: while((s1[i++] = s2[j++]) != NULL); Se remarc utilizarea operatorului de post-incrementare. Ct timp rezultatul atribuirii s1[i] = s2[j] nu este NULL, adic sir2 nu s-a terminat, se incrementeaz i, apoi se incrementeaz j. Corpul instruciunii while conine o instruciune vid ntruct atribuirile sunt realizate direct n condiia instruciunii. La ieirea din al doilea ciclu while, pentru a marca sfritul irului concatenat, se atribuie s1[i] = NULL. Problema se poate rezolva i apelnd funcia standard strcat() astfel:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char s1[201], s2[101]; printf("Introduceti sirul 1: "); scanf("%s", s1); printf("Introduceti sirul 2: "); scanf("%s", s2); strcat(s1, s2); printf("%s\n", s1); system("PAUSE"); return 0; }

============================= P6.8 Scriei un program care citete un ir de maximum 100 de caractere de la tastatur i apoi citete nc un caracter separat, care se va elimina din irul de caractere dac el exist n ir. Programul va afia rezultatul.

#include <stdio.h> #include <stdlib.h> int main() { char sir[101], c; int i, j; printf("Introduceti sirul de caractere\n"); printf("apoi caracterul ce se doreste eliminat ");

31

printf("separat prin spatiu\n"); scanf("%s %c", sir, &c); for(i = j = 0; sir[i] != NULL; i++) if(sir[i] != c) sir[j++] = sir[i]; sir[j] = NULL; printf("%s\n", sir); system("PAUSE"); return 0; }

Dac se introduc de la tastatur irul "orar" respectiv caracterul 'o', programul va rula astfel:
Introduceti sirul de caractere apoi caracterul ce se doreste eliminat separat prin spatiu orar o rar

Discuie:
Ciclul for parcurge irul de caractere, sir. Ct timp nu s-a atins sfritul irului, adic sir[i] != NULL, se testeaz dac elementul curent este diferit de caracterul ce se dorete eliminat, sir[i] != c, i dac da atunci elementul curent din ir se pstreaz pe poziia curent prin atribuirea sir[j++] = sir[i], echivalent cu secvena: sir[j] = sir[i]; j++; (j se incrementeaz pentru a pregti urmtoarea iteraie). Dac elementul curent este identic cu caracterul ce se dorete eliminat, atunci atribuirea anterioar nu are loc, astfel c n urmtoarele iteraii, sir[j], care este urmtorul element din sir, va fi suprascris cu primul caracter diferit de c ntlnit n sir. De remarcat atribuirea sir[j] = NULL care marcheaz sfritul de ir. ============================= P6.9 Scriei un program care citete un ir de maximum 100 de caractere de la tastatur i afieaz acest ir n ordine invers.

#include <stdio.h> #include <stdlib.h> int main() { char sir[101]; int i = 0; scanf("%s", sir); while(sir[i] != NULL) i++; while(i >= 0) { i--; printf("%c", sir[i]); } system("PAUSE"); return 0; }

Dac de la tastatur se introduce irul "abcd", programul va rula astfel:


abcd dcba

=============================

32

6.2. 1. 2.

Probleme propuse

Scriei un program care citete de la tastatur un vector de maximum 50 de numere ntregi i determin numrul elementelor impare ale vectorului. Scriei un program care citete de la tastatur doi vectori de maximum 100 de elemente ntregi (numrul elementelor poate fi diferit) apoi determin i afieaz intersecia celor doi vectori (adic elementele comune celor doi vectori). Scriei un program care citete de la tastatur un vector de maximum 20 de elemente ntregi i interschimb elementele de pe poziii pare cu cele de pe poziiile impare. Scriei un program care citete de la tastatur un vector de maximum 30 de elemente ntregi i sorteaz n ordine cresctoare doar elementele de pe poziiile impare. Scriei un program care citete de la tastatur un vector de maximum 15 elemente ntregi i insereaz un element pe o poziie k. Precizare: se vor citi de la tastatur vectorul mpreun cu dimensiunea sa efectiv, elementul ce se dorete inserat precum i poziia unde se dorete inserat elementul. Scriei un program care citete de la tastatur o matrice ptrat de dimensiuni maxime 10 10 elemente reale, afieaz matricea transpus i apoi calculeaz suma elementelor matricei. Scriei un program care citete de la tastatur o matrice de dimensiuni maxime 10 10 elemente ntregi apoi determin i afieaz elementele maxime de pe fiecare linie. Scriei un program care citete de la tastatur o matrice ptrat de dimensiuni maxime 100 100 elemente reale apoi calculeaz suma elementelor de sub i de deasupra diagonalei principale. Scriei un program care citete de la tastatur dou matrice A i B (de dimensiuni maxime 10 10 elemente reale) apoi calculeaz produsul lor. Precizare: programul va semnala cazul n care cele doua matrice nu se pot nmuli.

3. 4. 5.

6. 7. 8. 9.

10. Scriei un program care citete de la tastatur dou iruri de caractere (de maximum 51 de caractere fiecare) i
elimin toate caracterele coninute n al doilea ir din primul ir. Exemplu: sir1 = "abcdabcd", sir2 = "ad" i trebuie s rezulte "bcbc".

11. Scriei un program care citete de la tastatur dou iruri de caractere (de maximum 11 caractere fiecare) i
afieaz pe ecran numrul de apariii ale caracterelor din primul ir n cel de al doilea ir. Exemplu: sir1 = "abc", sir2 = "aacde" i trebuie s rezulte "a = 2, b = 0, c = 1"

12. Scriei un program care citete de la tastatur dou iruri de caractere (de maximum 41 de caractere fiecare) i
determin de cte ori apare secvena de caractere din al doilea ir n primul. Exemplu: sir1 = "abcdabcc", sir2 = "ab" i programul trebuie s afieze "Sirul ab apare de 2 ori".

13. Scriei un program care citete de la tastatur dou iruri de caractere (de maximum 31 de caractere fiecare) i
transform caracterele majuscule n minuscule i caracterele minuscule n majuscule. Exemplu: sir = "abcdABC" i programul trebuie s afieze "ABCDabc".

33

7.
7.1.
P7.1

Alte tipuri de date: structuri, uniuni, tipul enumerat


Probleme rezolvate
Scriei un program care citete datele pentru un grup de cel mult 10 persoane i afieaz datele citite. Precizri: Pentru fiecare persoana se vor memora numele, prenumele i data naterii. Datele fiecrei persoane va fi memorat sub forma unei structuri. Data naterii va fi tot o structur care va avea cmpurile zi, lun i an.

#include <stdio.h> #include <stdlib.h> int main() { struct data { int zi; char luna[12]; int an; }; struct persoana { char nume[20]; char prenume[20]; struct data datan; }; struct persoana grup[10]; int i, n; do { printf("Introduceti numarul de persoane: "); scanf("%d", &n); } while ((n <= 0) || (n > 10)); for(i = 0; i < n; i++) { do { printf("Nume Prenume An Luna Zi\n"); scanf("%s\t%s\t%d\t%s\t%d", &grup[i].nume, &grup[i].prenume, &grup[i].datan.an, &grup[i].datan.luna, &grup[i].datan.zi); } while((grup[i].datan.an < 0) || ((grup[i].datan.zi <= 0) && (grup[i].datan.zi >= 31))); } printf("Nume Prenume An Luna Zi\n"); for(i = 0; i < n; i++) printf("|%s\t|%s\t|%d\t|%s\t|%d\t|\n", grup[i].nume, grup[i].prenume, grup[i].datan.an, grup[i].datan.luna, grup[i].datan.zi); printf("\n"); system("PAUSE"); return 0; }

Programul va afia:
Introduceti numarul de persoane: 2 Nume Prenume An Luna Zi POPA Marius 1980 Mai 22 Nume Prenume An Luna Zi DUTA Ioana 1981 Iunie 2 Nume Prenume An Luna Zi |POPA |Marius |1980 |Mai |22 |DUTA |Ioana |1981 |Iunie |2

| |

34

Discuie:
n programul anterior se definesc dou structuri: data i persoana. Structura persoana utilizeaz un cmp datan care este de tipul struct data. Variabila grup este un tablou de 10 elemente de tipul persoana. Primul ciclu do while citete numrul de persoane, n, care trebuie s fie un numr pozitiv i mai mic dect 10. Deci corpul ciclului va fi executat pn cnd n va fi n intervalul [1, 10]. Al doilea ciclu for citete element cu element persoanele din variabila grup. De notat c elementul grup[i] are 3 cmpuri: primele dou (nume, prenume) sunt de tipul ir de caractere n timp ce al treilea este de tipul struct datan. Al treilea cmp are la rndul sau trei alte cmpuri: zi, luna i an. Deci pentru accesarea acestor subcmpuri avem nevoie de operatorul ,,. aplicat de dou ori asupra unei variabile de tipul grup[i]. Al treilea ciclu for afieaz rezultatele citite de la tastatur ca un tabel sub forma: | Nume | Prenume | An | Luna | Zi |. ============================= P7.2 Scriei un program care citete dou numere complexe de la tastatur, calculeaz i afieaz suma celor dou numere complexe. Precizare: Un numr complex se va memora sub forma unei structuri cu cmpurile real i imag.

#include <stdio.h> #include <stdlib.h> int main(void) { typedef struct { float real; float imag; } complex; complex a, b, sum; printf("Introduceti partea scanf("%f", &a.real); printf("Introduceti partea scanf("%f", &a.imag); printf("Introduceti partea scanf("%f", &b.real); printf("Introduceti partea printf("doilea nr.: "); scanf("%f", &b.imag); sum.real = a.real + b.real; sum.imag = a.imag + b.imag; printf("Suma celor doua numere complexe este: ") ; printf(" %.2f + (%.2f) * i\n", sum.real, sum.imag); system("PAUSE"); return 0; } reala a primului nr.: "); imaginara a primului nr.: "); reala celui de al doilea nr.: "); imaginara celui de al ");

Programul va afia:
Introduceti partea reala a primului nr.: 1.2 Introduceti partea imaginara a primului nr.: 1.0 Introduceti partea reala a celui de al doilea nr.: -0.2 Introduceti partea imaginara a celui de al doilea nr.: 0 Suma celor doua numere complexe este: 1.00 + (1.00) * i

Discuie:
Declaraia typedef introduce un tip utilizator cu numele complex. Structura are doua cmpuri: real i imag de tipul float. a, b i sum sunt cele trei variabile utilizate n cadrul programului. a i b se citesc de la tastatur iar rezultatul sumei complexe se atribuie variabilei sum. Aceast atribuire se poate face numai utiliznd operatorul ,,. pentru a selecta individual cmpurile real i imag. De notat c atribuirea sum = a + b nu este posibil n C. ============================= P7.3 Scriei un program care citete i stocheaz dou momente succesive de timp, ce reprezint, de exemplu, momentul la care a plecat un atlet i respectiv a sosit un atlet ntr-o competiie. Programul va afia timpul scurs ntre cele dou momente. 35

#include <stdio.h> #include <stdlib.h> int main() { struct timp { int ora; /* ora */ int min; /* minutul */ int sec; /* secunda */ }; struct timp start, stop; int start_int, stop_int; printf("Introduceti start: "); scanf("%d:%d:%d", &start.ora, &start.min, &start.sec); printf("Introduceti stop: "); scanf("%d:%d:%d", &stop.ora, &stop.min, &stop.sec); start_int = start.ora * 3600 + start.min * 60 + start.sec; stop_int = stop.ora * 3600 + stop.min * 60 + stop.sec; printf("timp: %d s\n", stop_int - start_int); system("PAUSE"); return 0; }

Programul va afia:
Introduceti start: 10:11:10 Introduceti stop: 10:12:11 timp: 61 s

Discuie:
start i stop reprezint dou variabile care stocheaz ora, minutul i secunda n care a plecat respectiv a terminat proba atletul. start_int i stop_int reprezint echivalentul n secunde al celor dou momente de timp. Relaia de calcul are n vedere faptul c o or are 3600 de secunde iar un minut are 60 de secunde. Diferena dintre cele dou variabile, stop_int - start_int, reprezint echivalentul n secunde al timpului efectuat. ============================= P7.4 Scriei un program care determin spaiul de memorie ocupat de o structur.

#include <stdio.h> #include <stdlib.h> struct exemplu { int i; int *p; double d; char str[80]; } s; int main() { printf("Structura exemplu are dimensiunea: %d octeti.", sizeof(struct exemplu)); printf("\n"); system("PAUSE"); return 0; }

Programul va afia:
Structura exemplu are dimensiunea: 96 octeti.

============================= P7.5 Scriei un program care codeaz i decodeaz un ntreg folosind uniuni prin inversarea ordinii octeilor care compun numrul ntreg. Pentru valorile variabilelor din program, se va afia:
10 codat este: 167772160 167772160 decodat este: 10

36

#include <stdio.h> #include <stdlib.h> int encode(int i); int main() { int i; int in; union coddecod { int num; char c[4]; } crypt; unsigned char ch; printf("Intoduceti un numar intreg: "); scanf("%d", &in); /* codarea intregului */ crypt.num = in; ch = crypt.c[0]; crypt.c[0] = crypt.c[3]; crypt.c[3] = ch; ch = crypt.c[1]; crypt.c[1] = crypt.c[2]; crypt.c[2] = ch; i = crypt.num; printf("%d codat este: %d\n", in, i); /* decodarea intregului */ crypt.num = i; ch = crypt.c[0]; crypt.c[0] = crypt.c[3]; crypt.c[3] = ch; ch = crypt.c[1]; crypt.c[1] = crypt.c[2]; crypt.c[2] = ch; in = crypt.num; printf("%d decodat este: %d", i, in); printf("\n"); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


Intoduceti un numar intreg: 10 10 codat este: 167772160 167772160 decodat este: 10

Discuie:
Prin intermediul unei uniuni se pot accesa octeii care compun un numr ntreg. P7.6 Scriei un program care memoreaz pe rnd, n acelai spaiu de memorie, un caracter, un numr ntreg i un numr real.

#include <stdio.h> #include <stdlib.h> int main() { union { char c; int i; float f; } u; u.c = 'A'; printf("Un caracter: %c\n", u.c); u.i = 65; printf("Codul ASCII: %d\n", u.i);

37

printf("Caracterul urmator: %c\n", u.c + 1); u.f = u.i + 0.14; printf("Un float: %.2f\n", u.f); u.f = 3.14; u.i = 2; printf("Aria cercului de raza %d: %.2f\n", u.i, u.f * u.i * u.i); system("PAUSE"); return 0; }

Programul va afia:
Un caracter: A Codul ASCII: 65 Caracterul urmator: B Un float: 65.14 Aria cercului de raza 2: 0.00

Discuie:
n cadrul programului se definete o variabil u avnd tipul union. Variabila poate stoca la un moment dat un caracter, un ntreg sau un numr real. Primele dou linii dup declararea variabilei atribuie variabilei u, n cmpul c (adic u.c) valoarea 'A'. Variabila este apoi tiprit cu ajutorul specificatorului de format %c pentru caractere. Urmtoarele trei linii ilustreaz atribuirea valorii 65, de data aceasta, cmpului i. n acest punct al execuiei programului, valoarea cmpului c este distrus. Tiprirea se va face utiliznd specificatorul de format %d. A treia linie ilustreaz tiprirea caracterului asociat codului ASCII imediat urmtor. ntruct codul ASCII are valoarea 65 (el avnd asociat caracterul 'A'), programul va afia caracterul 'B'. Urmtoarele 2 linii atribuie cmpului f o valoare egal cu vechea valoare a cmpului i (adic 65) la care se adun 0.14. De remarcat faptul c vechea valoare, 65, se pierde numai dup ce a avut loc atribuirea, adic ordinea operaiilor se desfoar astfel nct se adun nti 65 cu 0.14 i apoi se atribuie lui u.f valoarea 65.14. n acest moment, u.i i pierde valoarea 65. Ultimele trei linii ilustreaz calculul ariei unui cerc ntr-un mod greit. n primele dou linii atribuirile u.f = 3.14 (adic numrul PI) i u.i = 2 (adic raza cercului) au ca efect modificarea valoarea lui PI astfel nct rezultatul final este n mod greit altul dect cel ateptat. ntruct o variabil de tipul enumerat poate lua valori de mai multe tipuri n timpul execuiei programului, n lucrul cu uniuni trebuie avut grij ca la orice moment de timp s fie tiut tipul datei ce se afl stocat n variabila uniune. ============================= P7.7 Reluai problema anterioar dar construii i o metod care v permite s aflai n orice moment tipul informaiei stocate.

#include <stdio.h> #include <stdlib.h> int main() { struct { int tip; union { char c; int i; float f; } u; } z; z.u.c = 'A'; z.tip = 0; z.u.f = 3.1415; z.tip = 2; switch (z.tip) { case 0: printf("Un caracter: %c\n", z.u.c); break; case 1: printf("Un intreg: %d\n", z.u.i); break; case 2: printf("Un float: %f\n", z.u.f); break; default: printf("Format necunoscut\n"); break; } system("PAUSE"); return 0; }

Programul va afia:
Un float: 3.141500

38

Discuie:
Acest program ilustreaz utilizarea unei uniuni, u, n cadrul unei structuri, z. Structura are un cmp, tip, de tipul ntreg. Valorile pe care le ia cmpul tip (de exemplu: 0 pentru caractere, 1 pentru ntregi i 2 pentru real), pot fi modificate la momentul atribuirii unui subcmp al uniunii, u. Astfel, n orice moment de timp se cunoate tipul stocat n cmpul u dup valorile cmpului tip. Instruciunea switch decide, funcie de valoarea din cmpul tip (0, 1, 2), cum trebuie afiat variabila z. ============================= P7.8 Scriei un program care calculeaz media notelor obinute la probele de verificare (laborator, parial i examen) ale unei materii (fizic, biologie i chimie) utiliznd tipul enumerat.

#include <stdio.h> #include <stdlib.h>

int main() { typedef enum {laborator, partial, examen} didactic; didactic activitate; typedef enum {fizica, biologie, chimie} materii; materii materie; float nota, suma; for(materie = fizica; materie <= chimie; materie++) { suma = 0.0; for(activitate = laborator; activitate <= examen; activitate++) { scanf("%f", &nota); suma += nota; } printf("Media = %.2f\n", suma/3); } system("PAUSE"); return 0; }

n urma introducerii notelor la laborator, parial i lucrarea final, pentru fiecare din cele materii, programul va afia:
9 10 10 Media = 9.67 8 8 7.5 Media = 7.83

Discuie:
Programul anterior citete de la tastatur notele obinute de un student la diferite materii, fiecare materie avnd examinri, de exemplu, la laborator, pe parcursul semestrului, respectiv la examenul final. La finalul fiecrei materii, programul afieaz media la materia respectiv. Programul definete dou enumerri, didactic i materii, avnd ca membri tipul de examinare (laborator, parial sau examen) respectiv numele materiilor la care s-a efectuat examinarea (fizica, biologie, chimie). Variabilele activitate i materie sunt de tipul didactic respectiv materii. Variabilele nota i suma sunt de tipul float. Cu ajutorul a dou cicluri for se parcurg toate materiile posibile, respectiv toate probele. Variabila suma se iniializeaz cu valoarea 0 la nceputul celui de al doilea ciclu for. n interiorul acestuia se citete succesiv variabila nota, aceasta urmnd s se adune la totalul din variabila suma. La finalul ultimului ciclu for, se afieaz valoarea mediei. ============================= 39

7.2. 1. 2.
3.

Probleme propuse

Scriei un program care citete de la tastatur un vector de elemente complexe, calculeaz i afieaz suma complex a tuturor elementelor sale. Scriei un program care citete de la tastatur un vector de elemente complexe, calculeaz i afieaz produsul complex al tuturor elementelor sale. S se modifice programul P7.3 astfel nct s nu mai afieze numai numrul total de secunde, ci i timpul efectuat sub forma: ore : minute : secunde. Exemplu: 3700 secunde reprezint 1 ora, 1 minut i 40 de secunde adic 1:1:40.

4.

Scriei un program care citete de la tastatur un vector de coordonate ale unei structuri mpreun cu masele plasate la coordonatele respective i calculeaz centrul de greutate al structurii. Precizri: fiecare coordonat mpreun cu masa asociat se va memora ntr-o structur definit astfel:
typedef struct { float x, y, masa; } punct;

punctele se vor memora ntr-o matrice definit astfel:


punct mase[MAX];

structura va putea fi alctuit din cel mult 100 de puncte. 5. 6. Modificai programul P7.8 astfel nct s memoreze numele materiilor i notele obinute n structuri. Scriei un program care memoreaz scorurile obinute de cel mult 10 juctori mpreun cu numele juctorilor. Informaiile se vor memora ntr-o matrice constituit din structuri definite astfel:
typedef struct { char nume[20]; int scor; } jucator;

7.

Scriei un program care implementeaz o agend telefonic sub forma unei structuri cu urmtoarea definiie:
typedef struct { char nume[20]; char prenume[20]; char adresa[20]; unsigned int cod_postal; unsigned int prefix; } intrare;

unsigned int numar; unsigned int mobil;

8.

Scriei un program care scrie octeii care formeaz o valoare de tip double sub form zecimal n ordinea octet7, octet6, octet5, octet4, octet3, octet2, octet1, i octet0, unde octet7 este octetul cel mai semnificativ iar octet0 este octetul cel mai puin semnificativ. Precizri: ordinea n memorie a octeilor depinde de platforma de calcul: exist calculatoare de tip BIG_ENDIAN, la care primul octet din memorie este cel mai puin semnificativ i de tip LITTLE_ENDIAN la care primul octet este cel mai semnificativ. Va trebui ca mai nti s stabilii ce tip de calculator folosii i apoi s parcurgei octeii n ordinea corespunztoare; pentru a accesa octeii care formeaz un numr de tip double utilizai uniunea:
typedef union { char octet[8]; double numar; } valoare;

40

8.
8.1.
P8.1

Funcii simple; recursivitate


Probleme rezolvate
Scriei un program care calculeaz integrala unei funcii oarecare, ntr-un interval [a, b] ale crui limite se vor citi de la tastatura. Utilizatorul va specifica i numrul de subintervale de discretizare. Metoda de integrare este metoda dreptunghiurilor.

#include <stdio.h> #include <stdlib.h> float f(float x) { return (x * x - x + 1); } int main() { float a, b, intg, eps; int n; /* numarul de subintervale */ int i; printf("Introduceti limita de inceput a intervalului: "); scanf("%f", &a); printf("Introduceti limita de sfarsit a intervalului: "); scanf("%f", &b); printf("Introduceti numarul de subintervale "); printf("de discretizare: "); scanf("%d", &n); eps = (b - a) / n; intg = f(a) * eps; for(i = 1; i <= n; intg += f(a + /* pasul integrarii */ /* primul dreptunghi */ i++) i*eps) * eps;

printf("Valoarea integralei este %.3f\n", intg); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


Introduceti limita de inceput a intervalului: 0 Introduceti limita de sfarsit a intervalului: 2 Introduceti numarul de subintervale de discretizare: 1000 Valoarea integralei este 2.671

Discuie:
Programul reprezint implementarea direct a metodei dreptunghiurilor folosit la integrarea numeric a unei funcii pe un interval dat. Calculul valorii funciei ntr-un punct se face cu ajutorul funciei f(); ============================= P8.2 Scriei un program care afieaz numerele pare dintr-un interval [a, b] cu ajutorul unei funcii. Limitele intervalului vor fi specificate de utilizator.

#include <stdio.h> #include <stdlib.h> int par(int k) { if(k % 2 == 0) return 1; else return 0; } int main() { int a, b, i; printf("a = "); scanf("%d", &a); printf("b = "); scanf("%d", &b);

41

for(i = a; i <= b; i++) if(par(i) == 1) printf("%d ",i); printf("\n"); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


a = 1 b = 20 2 4 6 8 10 12 14 16 18 20

Discuie:
Parcurgerea intervalului se face n programul principal. Pentru fiecare element din interval funcia par() verific dac acesta este par. Daca este par funcia returneaz 1, daca nu este par returneaz 0. ============================= P8.3 Scriei un program care citete un numr natural n i calculeaz i afieaz factorialul numrului n definit astfel:

pentru n = 1 1, n! = n (n 1)! , pentru n > 1


Calculul factorialului se va realiza cu ajutorul unei funcii recursive.
#include <stdio.h> #include <stdlib.h> int factorial(int n) { if(n == 1) return 1; else return (n * factorial(n - 1)); } int main() { int i, j, k, n; do { printf("Introduceti n: "); scanf("%d", &n); } while(n < 1); k = factorial(n); printf("%d! = %d\n", n, k); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


Introduceti n: 12 12! = 479001600

Discuie:
Programul verific valoarea introdus deoarece o valoare eronat poate conduce la executarea la nesfrit a funciei factorial(). Funcia factorial() se auto-apeleaz pn cnd se ajunge la factorial de 1. ============================= P8.4 Scriei un program care citete dou numere naturale a i b i calculeaz i afieaz cel mai mare divizor comun, c.m.m.d.c., al celor dou numere. Cel mai mare divizor comun se va calcula recursiv astfel:

42

dac a = b a c.m.m.d.c.(a , b) = c.m.m.d.c.( a, b a ) dac b > a c.m.m.d.c.( a b, b) dac b < a


#include <stdio.h> #include <stdlib.h> int cmmdc(int a, int b) { if(a == b) return a; if(a > b) a = cmmdc(a - b, b); if(a < b) a = cmmdc(a, b - a); return a; } int main() { int i, j, k, a, b; scanf("%d", &a); scanf("%d", &b); k = cmmdc(a, b); printf("%d", k); printf("\n"); system("PAUSE"); return 0; }

Discuie:
Se remarc faptul c funcia cmmdc() implementeaz exact definiia matematic formulat n enun. Programul principal nu face dect s citeasc cele dou numere, s apeleze funcia cmmdc() i s afieze rezultatul. ============================= P8.5 Scriei un program care citete un numr i stabilete i afieaz dac numrul este prim sau nu. Se va scrie i utiliza o funcie care verific dac un numr este prim.

#include <stdio.h> #include <stdlib.h> int divizibil(int n , int i) { if(n % i == 0) return 0; else return 1; } int main() { int n, i; printf("Introduceti un numar natural: "); scanf("%d", &n); i = 2; while(i < n) { if(divizibil(n, i) == 1) i++; else { i = n+1; printf("Nu este prim\n");} } if(i == n) printf("Este prim\n"); system("PAUSE"); return 0; }

43

Programul va afia pe ecran, dup compilare i execuie:


Introduceti un numar natural: 397 Este prim

Discuie:
Pentru a verifica dac un numr, n, este prim se parcurge intervalul (1, n) i pentru fiecare numr din interval se verific dac acesta este divizor al lui n. Atunci cnd am gsit un divizor nseamn c numrul nu este prim i ieim din ciclul while (i devine n + 1). Funcia divizibil verific dac contorul i care parcurge intervalul divide pe n. Daca l divide returneaz 0 iar dac nu l divide returneaz 1. ============================= P8.6 Scriei un program care citete dou numere naturale n i p i calculeaz cu ajutorul unei funcii recursive valoarea expresiei np. Valoarea expresie va fi afiat. Funcia np se va defini astfel:

dac p = 1 n np = p 1 dac p > 1 n n


#include <stdio.h> #include <stdlib.h> int putere(int n, int p) { if(p == 1) return n; else { n = n * putere(n, p - 1); return n; } } int main() { int i, j, k, n, p; printf("Introduceti 2 numere naturale: "); scanf("%d", &n); scanf("%d", &p); k = putere(n, p); printf("%d\n", k); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


Introduceti 2 numere naturale: 2 16 65536

Discuie:
Funcia putere implementeaz direct definiia propus. Ea se poate scrie mai compact astfel:
int putere(int n, int p) { if(p != 1) n = n * putere(n, p - 1); return n; }

============================= P8.7 Scriei un program care calculeaz media aritmetic a elementelor unui vector cu ajutorul unei funcii.

#include <stdio.h> #include <stdlib.h> float medie(int x, float s , int z, int n) { s = s + z; if(x == n) s = s / n; return s; }

44

int main() { int i, n, v[10]; float s, k; printf("n = "); scanf("%d", &n); for(i = 1; i <= n; i++) { printf("v[%d] = ", i); scanf("%d", &v[i]); } s = 0; for(i = 1; i <= n; i++) { k = medie(i, s, v[i], n); s = k; } printf("Media este %f\n", s); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


n = 4 v[1] = 1 v[2] = 2 v[3] = 3 v[4] = 4 Media este 2.500000

Discuie:
La parcurgerea vectorului, funciei medie() i se transmit poziia curent (i), suma elementelor anterioare (s), elementul curent (v[i]) i lungimea vectorului (n). Funcia medie() nsumeaz elementele vectorului (s = s + z) pn n momentul n care a nsumat i ultimul element. Atunci va mpari aceast sum la numrul de elemente. ============================= P8.8 Scriei un program care verific transferul unei structuri, ca parametru, ctre o funcie.

#include <stdio.h> #include <stdlib.h> struct strp2 { int i; double d; } var1; void f(struct strp2 temp); int main() { var1.i = 99; var1.d = 98.6; f(var1); system("PAUSE"); return 0; } void f(struct strp2 temp) { printf("Diferenta dintre cele 2 elemente "); printf("ale structurii este: %lf\n", temp.d - temp.i); }

Programul va afia pe ecran, dup compilare i execuie:


Diferenta dintre cele 2 elemente ale structurii este: -0.400000

Discuie:
Pentru a face verificarea cerut s-a definit o structur cu marca strp2 care are dou cmpuri: i de tip ntreg i d de tip fracionar cu precizie dubl. n programul principal se atribuie valori celor dou cmpuri ale structurii i apoi se apeleaz funcia f. Aceast funcie calculeaz i afieaz diferena dintre cele dou cmpuri. ============================= 45

P8.9

Scriei un program care determin i afieaz lungimea unui ir de maxim 200 de caractere cu ajutorul unei funcii.

#include <stdio.h> #include <stdlib.h> int lungime(char sir[]) { int i; for(i = 0; sir[i] != '\0'; i++); return i; } int main() { char sir[201]; printf("Introduceti sirul dorit:\n"); gets(sir); printf("Lungimea sirului este de %d caractere\n", lungime(sir)); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


Introduceti sirul dorit: Acesta este sirul a carui lungime o dorim. Lungimea sirului este de 42 caractere

Discuie:
Citirea irului de caractere se realizeaz apelnd funcia gets(). Aa cum am mai precizat n Capitolul 6, folosirea acestei funcii este nerecomandabil. Pentru citirea irului de caractere recomandm utilizarea instruciunilor:
fgets(sir, 201, stdin); if(sir[strlen(sir)-1] == '\n') sir[strlen(sir)-1] = '\0';

Cea de a doua instruciune elimin caracterul newline din irul citit. Funcia lungime() primete ca parametru un vector de caractere. Lungimea irului de caractere este determinat prin oprirea ciclului for la ntlnirea caracterului '\0'. Se remarc utilizarea instruciunii vide pentru ciclul for. Funcia lungime() funcioneaz similar cu funcia standard strlen(). ============================= P8.10 Scriei un program care citete de la tastatur o matrice ptrat de dimensiune maxim 10 10 elemente reale mpreun cu dimensiunea sa efectiv i determin i afieaz suma elementelor de pe diagonala principal i de pe diagonala secundar. Se vor scrie i utiliza funcii separate pentru: citirea matricei, scrierea matricei, calculul sumei de pe diagonala principal i calculul sumei de pe diagonala secundar. Precizare: este vorba de reluarea problemei P6.6 dar cu utilizarea unor funcii.

#include <stdio.h> #include <stdlib.h> void citeste(float mat[][10], int dim) { int i, j; for(i = 0; i < dim; i++) for(j = 0; j < dim; j++) { printf("Introduceti mat[%d][%d]: ", i, j); scanf("%f", &mat[i][j]); } } float suma1(float mat[][10], int dim) { int i, j; float sum = 0; for(i = 0; i < dim; i++) sum += mat[i][i]; return sum; } float suma2(float mat[][10], int dim) { int i, j; float sum = 0; for(i = 0; i < dim; i++) sum += mat[i][dim-i-1]; return sum; }

46

void tip_mat(float mat[][10], int dim) { int i, j; printf("\nMatricea introdusa este:\n\n"); for(i = 0; i < dim; i++) { for(j = 0; j < dim; j++) { printf("%1.3f\t",mat[i][j]); } printf("\n"); } } int main() { float matrice[10][10]; int dim; do { printf("Introduceti dimensiunea matricei patrate: "); scanf("%d", &dim); } while(dim < 1 || dim > 10); citeste(matrice, dim); print(matrice, dim); printf("\nSuma elementelor de pe diagonala principala"); printf(" este %1.3f\n", suma1(matrice, dim)); printf("\nSuma elementelor de pe diagonala secundara"); printf(" este %1.3f\n", suma2(matrice, dim)); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti Introduceti dimensiunea matricei patrate: 4 mat[0][0]: 1 mat[0][1]: 2 mat[0][2]: 3 mat[0][3]: 4 mat[1][0]: 5 mat[1][1]: 6 mat[1][2]: 7 mat[1][3]: 8 mat[2][0]: 9 mat[2][1]: 10 mat[2][2]: 11 mat[2][3]: 12 mat[3][0]: 13 mat[3][1]: 14 mat[3][2]: 15 mat[3][3]: 16

Matricea introdusa este: 1.000 5.000 9.000 13.000 2.000 6.000 10.000 14.000 3.000 7.000 11.000 15.000 4.000 8.000 12.000 16.000

Suma elementelor de pe diagonala principala este 34.000 Suma elementelor de pe diagonala secundara este 34.000

Discuie:
Funcia citeste() realizeaz citirea efectiv a elementele matricei folosind proprietatea particular a tablourilor de a putea fi modificate ntr-o funcie astfel nct modificrile s fie permanente. Funcia tip_mat() afieaz matricea citit. Funciile suma1() i suma2() calculeaz suma elementelor de pe diagonala principal i, respectiv, de pe diagonala secundar. Programul principal citete dimensiunea efectiv a matricei i apeleaz funciile definite anterior. ============================= 47

8.2. 1.

Probleme propuse

Scriei un program C care citete de la tastatur un vector de maximum 10 numere ntregi mpreun cu dimensiunea sa efectiv i separ acest vector n doi vectori: primul vector va fi format din numerele pare din vectorul iniial iar cel de al doilea va fi format din numerele impare din vectorul iniial. Citirea vectorului se va face cu ajutorul unei funcii cu prototipul:
void cit_vect(int v[10], int dim);

2.

Reluai programul anterior, dar pentru formarea vectorilor scriei i utilizai dou funcii avnd prototipurile:
int pare(int v[10], int par_v[10]); int impare(int v[10], int impar_v[10]);

Funciile vor returna numrul valorilor pare i respectiv, numrul valorilor impare. 3. Scriei un program C care calculeaz suma complex a elementelor dintr-un tablou unidimensional de numere complexe. Precizri: a. Tabloul de numere complexe va fi declarat utiliznd urmtoarele definiii:
typedef struct { float re; float im; } complex; complex vector[10];

b. Elementele tabloului se citesc de la tastatur, element cu element, iar pentru fiecare element, partea real i partea imaginar. c. Scriei cte o funcie care calculeaz partea real i, respectiv, partea imaginar a sumei a dou numere complexe. Prototipurile acestor funcii sunt:
float suma_re(complex a, complex b); float suma_im(complex a, complex b);

Suma global cerut se va calcula folosind funciile definite anterior. 4. Reluai programul anterior dar pentru calculul sumei a dou numere complexe scriei i utilizai o funcie avnd prototipul:
complex suma(complex a, complex b);

5.

Scriei un program C care citete de la tastatur o matrice de numere reale de dimensiuni maxime 100 100 mpreun cu dimensiunile sale efective i afieaz elementele maxime de pe fiecare linie i apoi de pe fiecare coloan. Precizri: a. Pentru determinarea maximului de pe linii / coloane se va scrie i utiliza o funcie cu prototipul:
float max_vec(int dim, float vec[100]);

b. Se vor forma, pe rnd, vectori din fiecare linie i apoi din fiecare coloan. 6. Scriei un program care citete un numr natural i calculeaz i afieaz secvena Halberstam a acestui numr. Precizri: a. Secvena Halberstam a unui numr se calculeaz astfel: dac numrul este par el se mparte la 2; dac numrul este impar se adun 3 i se adun 1; se reiau operaiile pn cnd valoarea ajunge egal cu 1. b. Calculul numrului urmtor al secvenei Halberstam se va face cu ajutorul unei funcii. 7. Scriei o funcie care afieaz o ntrebare i citete rspunsul utilizatorului care poate fi doar d, pentru da, sau n, pentru nu; citirea se repet pn cnd rspunsul este d sau n. Scriei apoi un program care verific funcionarea corect a funciei. Precizare: Prototipul funciei este:
int ok(char s[]);

8.

Scriei o funcie care calculeaz suma de plat pentru o activitate primind numrul de ore lucrate i salariul orar. Dac numrul de ore lucrate este mai mic dect sau egal cu 40 se pltete salariul orar. Pentru orele cuprinse ntre 40 i 60 salariul orar crete cu 50 %. Pentru orele care depesc 60 se pltete dublu. Scriei i programul principal care verific funcionarea funciei. 48

9.

Scriei o funcie care caut toate spaiile dintr-un ir de caractere i le nlocuiete cu semnul - returnnd numrul de spaii nlocuit. Prototipul funciei este:
int inlocuieste(char sir[]);

Scriei i programul principal care verific funcionarea funciei. 10. Scriei o funcie care determin i returneaz momentul sosirii primului tren ntr-o staie de cale ferat. Funcia primete ca argumente momentul plecrii din staie i o structur care conine orele de plecare i de sosire. Precizri: a. Structura pentru memorarea programului de circulaie a unui tren va fi definit astfel:
typedef struct moment { int ora; int minut; } Moment; typedef struct program { Moment plecare; Moment sosire; } Program_tren;

b. Programul de circulaie ntre dou staii este alctuit dintr-un tablou format din structuri de tip Program_tren. c. Funcia va cuta primul tren care pleac dup ora indicat i va afia orele de plecare i sosire. Scriei i programul principal care verific funcionarea funciei. 11. Scriei o funcie care afieaz irul de caractere primit ca parametru i apoi l subliniaz scriind numrul corespunztor de caractere _ pe rndul urmtor. Pentru determinarea lungimii irului de caractere se va folosi funcia standard strlen(), string length, care are urmtorul prototip:
int strlen(char s[]);

Scriei i programul principal care verific funcionarea funciei.

49

9.
9.1.
P9.1

Pointeri
Probleme rezolvate
Scriei un program care determin suma elementelor de pe diagonala unei matrice ptrate de dimensiune maxim 10 10 format din numere reale. Pentru citirea matricei se va scrie i utiliza o funcie care citete matricea mpreun cu dimensiunile sale efective.

#include <stdio.h> #include <stdlib.h> #define DIMMAX 10 void citmat(float mat[][DIMMAX], int *dim); int main(void) { int dimef, i; float mat[DIMMAX][DIMMAX], sumdiag; citmat(mat, &dimef); sumdiag = 0.0; for(i = 0; i < dimef; i++) sumdiag += mat[i][i]; printf("Suma elementelor de pe diagonala este: %f\n", sumdiag); system("PAUSE"); return 0; } void citmat(float mat[][DIMMAX], int *dim) { int i, j; do { printf("Introduceti dimensiunea efectiva (<=10): "); scanf("%i", dim); } while (*dim > 10 || *dim < 0); for(i = 0; i < *dim; i++) for(j = 0; j < *dim; j++) { printf("mat[%d][%d] = ", i, j); scanf("%f", &mat[i][j]); } }

Programul va afia pe ecran, dup compilare i execuie:


Introduceti dimensiunea efectiva (<=10) :20 Introduceti dimensiunea efectiva (<=10) :2 mat[0][0] = 1 mat[0][1] = 2 mat[1][0] = 3 mat[1][1] = 4 Suma elementelor de pe diagonala este: 5.000000

Discuie:
Acest program pune n eviden utilizarea pointerilor la transferul unei valori dintr-o funcie. Al doilea parametru al funciei citmat() este un pointer prin intermediul cruia se transfer dimensiunea efectiv a metricei. ============================= P9.2 Scriei un program care determin suma elementelor de pe diagonala unei matrice ptrate format din numere reale. Pentru citirea matricei se va scrie i utiliza o funcie care citete matricea mpreun cu dimensiunile sale efective. Precizare: dei problema pare identic cu problema 9.1 nu este aa; de aceast dat programul trebuie s poat prelucra matrice orict de mari.

#include <stdio.h> #include <stdlib.h> float **citmat(int *dim); int main(void) { int dimef, i; float **mat, sumdiag;

50

if(!(mat = citmat(&dimef))) { printf("Matricea nu se poate citi!\n"); system("PAUSE"); return 1; } sumdiag = 0.0; for(i = 0; i < dimef; i++) sumdiag += mat[i][i]; printf("Suma elementelor de pe diagonala este: %f\n", sumdiag); system("PAUSE"); return 0; } float **citmat(int *dim) { int i, j; float **mat; printf("Introduceti dimensiunea efectiva: "); scanf("%i", dim); /* Se aloca memorie pentru tabloul de pointeri care constituie matricea */ if(!(mat = (float **)malloc(*dim * sizeof(float *)))) { printf("Matricea este prea mare!\n"); return NULL; } /* Se aloca memorie pentru fiecare linie a matricei */ for(i = 0; i < *dim; i++) if(!(mat[i] = (float *)malloc(*dim * sizeof(float)))) { printf("Matricea este prea mare!\n"); return NULL; } /* Se citesc elementele matricei */ for(i = 0; i < *dim; i++) for(j = 0; j < *dim; j++) { printf("mat[%d][%d] = ", i, j); scanf("%f", &mat[i][j]); } return mat; }

Programul va afia pe ecran, dup compilare i execuie:


Introduceti dimensiunea efectiva: 2 mat[0][0] = 1 mat[0][1] = 2 mat[1][0] = 3 mat[1][1] = 4 Suma elementelor de pe diagonala este: 5.000000

sau
Introduceti dimensiunea efectiva: 123456 Matricea este prea mare! Matricea nu se poate citi!

Discuie:
Acest program pune n eviden utilizarea pointerilor pentru alocarea dinamic a unei matrice. Se observ c matricea este declarat ca fiind de tip loat ** adic de tip pointer la pointer. n funcia citmat() se aloc mai nti un vector de pointeri care reprezint matricea propriu-zis i apoi se aloc cte un pointer ctre fiecare rnd din matrice. Se observ c procednd astfel elementele matricei se pot adresa exact ca atunci cnd matricea a fost alocat static. ============================= 51

P9.3

Scriei un program care afieaz pe ecran coninutul i adresele a dou variabile de tip ntreg, apoi atribuie adresa uneia dintre ele unui pointer i reia afiarea utiliznd pointerul.

#include <stdio.h> #include <stdlib.h> int main() { int j, k; /* declarare variabila de tip pointer */ int *ptr; j = 1; k = 2; /* ptr contine adresa la care este stocata variabila k */ ptr = &k; printf("\nj are valoarea %d si este stocat la adresa %p ", j, &j); printf("\nk are valoarea %d si este stocat la adresa %p", k, &k); printf("\nptr are valoarea %p si este stocat la adresa %p, ptr, &ptr); printf("\nValoarea int catre care arata pointerul este: %d", *ptr); printf("\n"); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


j are valoarea 1 si este stocat la adresa 0022FF6C k are valoarea 2 si este stocat la adresa 0022FF68 ptr are valoarea 0022FF68 si este stocat la adresa 0022FF64 Valoarea int catre care arata pointerul este: 2

Discuie:
Programul pune n eviden modul de utilizare a pointerilor. Se observ faptul c nainte de a fi utilizat, pointerului trebuie s i se atribuie o adres valid. Dac se omite instruciunea:
ptr = &k;

afiarea va arta astfel:


j are valoarea 1 si este stocat la adresa 0022FF6C k are valoarea 2 si este stocat la adresa 0022FF68 ptr are valoarea 004010C0 si este stocat la adresa 0022FF64 Valoarea int catre care arata pointerul este: 807409035

Precizm c adresele afiate pot diferi de cele de mai sus n funcie de spaiul de memorie alocat programului de ctre sistemul de operare precum i faptul c n varianta eronat este posibil ca programul s nu funcioneze de loc. ============================= P9.4 Scriei un program care construiete un vector i l afieaz att n mod obinuit, ct i utiliznd pointeri. Programul va afia apoi adresele elementelor din vector i valorile lor. Se va ncerca i depirea dimensiunilor tabloului.

#include <stdio.h> #include <stdlib.h> int main() { int tablou[] = {1, 23, 17, 4, -5, 100}; int *ptr; int i; ptr = &tablou[0]; /* sau ptr = tablou; */ printf("\n"); /* Afisarea vectorului */ for(i = 0; i < 6; i++) { printf("tablou[%d] = %d", i, tablou[i]); printf("\tptr + %d = %d\n", i, *(ptr+i)); } printf("\n");

52

/* Afisarea adreselor la care sunt stocate elementele vectorului */ for(i = 0; i < 6; i++) printf("adresa pentru tablou[%d]: %d\n", i, ptr+i); printf("\n"); /* Afiare cu depasirea spatiului vectorului */ for(i = 0; i <= 6; i++) { printf("ptr + %d = %d\n", i, *(ptr++)); } printf("\n"); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


tablou[0] tablou[1] tablou[2] tablou[3] tablou[4] tablou[5] adresa adresa adresa adresa adresa adresa ptr ptr ptr ptr ptr ptr ptr + + + + + + + = = = = = = 1 23 17 4 -5 100 ptr ptr ptr ptr ptr ptr + + + + + + 0 1 2 3 4 5 = = = = = = 1 23 17 4 -5 100

pentru pentru pentru pentru pentru pentru 0 1 2 3 4 5 6 = = = = = = =

tablou[0]: tablou[1]: tablou[2]: tablou[3]: tablou[4]: tablou[5]:

2293576 2293580 2293584 2293588 2293592 2293596

1 23 17 4 -5 100 2293664

Discuie:
Prima instruciune atribuie pointerului ptr adresa primului element din vectorul tablou. Aa cum se arat i n comentariu, aceast instruciune se poate scrie i:
ptr = tablou;

Observaie: Precizm c un tablou nu este un vector. Din acest motiv atribuirea:


tablou = ptr;

nu este corect. Primul ciclu for afieaz valorile memorate n vector utiliznd att direct vectorul ct i pointerul. Cel de al doilea ciclu afieaz adresele de memorie la care sunt stocate elementele vectorului. Se observ c elementele vectorului sunt memorate n locaii succesive de memorie. n cel de al treilea ciclu se repet afiarea, dar se depete dimensiunea vectorului. Aa cum se observ din rezultatul rulrii programului, limbajul C nu verific depirea dimensiunii vectorului. n acest mod programul ruleaz mult mai repede dar programatorul trebuie s fie foarte atent pentru a nu comite astfel de greeli. ============================= P9.5 Scriei un program care concateneaz dou iruri de caractere (stringuri) strA i strB, rezultatul fiind depozitat n stringul strA. Programul caut apoi prima liter 'c' din strA i o nlocuiete cu secvena "CCC". n final, se va alipi i poriunea rmas din strA la stringul final. Prima concatenare se va realiza cu ajutorul pointerilor. Pentru copierile i concatenrile ulterioare se vor utiliza funciile standard strcpy() i strcat().

#include <stdio.h> #include <stdlib.h> #include <string.h>

53

int main() { char strA[80] = "Sir de caractere demonstrativ"; char strB[80] = "SIR2"; char strC[80] = "CCC"; char aux[80]; /* Declara pointeri catre tipul caracter */ char *pA, *pB, *paux; int i; /* Afiseaza stringul strA */ printf("strA = '%s'\n", strA); /* Pointerul pA va contine adresa stringului strA */ pA = strA; printf("Adresa stringului strA: %p\n", &pA); /* Pointerul pB va contine adresa stringului strB */ pB = strB; printf("strB = '%s'\n", pB); /* Avanseza pana la sfarsitul lui strB */ while(*pB != '\0') *pB++; /* Concateneaza strB cu strA */ while (*pA != '\0') *pB++ = *pA++; /* Adauga caracterul NULL care marcheza sfarsitul stringului */ pB = '\0'; /* Afiseaza rezultatul concatenarii */ printf("Concatenare stringuri: '%s'\n\n", strB); /* Inlocuire 'c' cu 'CCC' */ printf("Inlocuire 'c' cu 'CCC'\n"); printf("======================\n"); /* pB arata din nou catre inceputul stringului strB */ pB = strB; /* Cauta primul caracter 'c' */ while((*pB != '\0') && (*pB != 'c')) pB++; /* Copiaza caracterele de dupa litera 'c' intr-un string auxiliar. Mai intai verifica faptul ca s-a gasit litera 'c' */ if(*pB == 'c') { pB++; /* Avanseaza la caracterul de dupa 'c' */ paux = aux; (void)strcpy(paux, pB); pB--; /* Aduce inapoi la adresa lui 'c' */ } /* Copiaza strC in locul unde era litera 'c' */ (void)strcpy(pB, strC); printf("Noul strB: '%s'\n", strB); /* Adauga sirul de caractere salvat */ (void)strcat(pB, paux); printf("String final: '%s'\n", strB); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


strA = 'Sir de caractere demonstrativ' Adresa stringului strA: 0022FE24 strB = 'SIR2' Concatenare stringuri: 'SIR2Sir de caractere demonstrativ' Inlocuire 'c' cu 'CCC' ====================== Noul strB: 'SIR2Sir de CCC' String final: 'SIR2Sir de CCCaractere demonstrativ'

54

Discuie:
Modul n care se realizeaz concatenarea este similar codului din funcia standard strcat(). Aceast seciune se poate rescrie ntr-un mod mai compact astfel:
/* Avanseza pana la sfarsitul lui strB */ while(*pB++ != '\0'); /* Aduce inapoi la caracterul NULL */ pB--; /* Copiaza strA in strB inclusiv caracterul NULL */ while((*pB++ = *pA++) != '\0');

Pentru nlocuirea caracterului 'c' mai nti acesta este localizat. Apoi se salveaz restul irului de caractere care urmeaz dup acesta i se compune noul ir de caractere prin dou operaii succesive de concatenare. ============================= P9.6 Scriei un program care, prin dou funcii distincte, verific egalitatea alfabetic sau numeric a argumentelor, folosind pointeri. Afiarea se va face utiliznd funcia standard puts() i citirea se va face cu fgets().

#include <stdio.h> #include <stdlib.h> #include <string.h> void verifica(char *a, char *b, int (*cmp)(const char *, const char *)); int comparanum(const char *a, const char *b); int main() { char s1[80], s2[80]; puts("Introduceti primul argument:"); fgets(s1, 80, stdin); if(s1[strlen(s1)-1] == '\n') s1[strlen(s1)-1] = '\0'; puts("Introduceti al doilea argument:"); fgets(s2, 80, stdin); if(s2[strlen(s2)-1] == '\n') s2[strlen(s2)-1] = '\0'; /* Parametrii functiei apelate sunt 2 pointeri de tip caracter */ if(isalpha(*s1)) { puts("Argumente de tip caracter\n"); /* Utilizeaza functia standard strcmp */ verifica(s1, s2, strcmp); } else { puts("Argumente de tip numeric\n"); /* Utilizeaza functia comparanum */ verifica(s1, s2, comparanum); } puts("\n"); system("PAUSE"); return 0; } void verifica(char *a, char *b, int (*cmp)(const char *, const char *)) { /* Utilizeaza printf pentru a lasa cursorul pe aceeasi linie */ printf("Verificarea egalitatii: "); /* (*cmp)(a,b)apeleaza functia de comparare a carei adresa se afla in cmp cu argumentele a si b */ if(!(*cmp)(a,b)) puts("Argumentele sunt egale"); else puts("Argumentele nu sunt egale"); } int comparanum(const char *a, const char *b) { /* atoi(x) converteste stringul catre care arata pointerul x intr-un numar intreg (atoi = ASCII to int) */ if(atoi(a) == atoi(b)) return 0; else return 1; }

55

Programul va afia pe ecran, dup compilare i execuie:


Introduceti primul argument: str1 Introduceti al doilea argument: str2 Argumente de tip caracter Verificarea egalitatii: Argumentele nu sunt egale

Discuie:
Pentru verificarea tipului de valori citite se folosete funcia standard isalpha() care returneaz adevrat dac irul de caractere este de tip alfanumeric (cuprinde i litere) sau fals dac este format doar din cifre. Cel de al treilea argument al funciei verifica() este un pointer ctre o funcie. Funcia verifica() apeleaz funcia de verificare a egalitii prin intermediul pointerului la funcie. ============================= P9.7 Scriei un program care ncarc valori ntr-o structur folosind un pointer ctre aceasta.

#include <stdio.h> #include <stdlib.h> #include <string.h> struct strpoint { int i; char str[80]; } s, *p; /* s este variabila de tip structura si p un pointer catre o astfel de structura */ int main() { p = &s; /* pointerul arata catre adresa de inceput a structurii */ s.i = 10; /* incarcare obisnuita */ p->i = 10; /* incarcare folosind pointerul */ strcpy(p->str, "tablou unidimensional de caractere"); printf("%d %d %s", s.i, p->i, p->str); printf("\n"); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


10 10 tablou unidimensional de caractere

Discuie:
Programul pune n eviden utilizarea operatorului ->. ============================= P9.8 Scriei un program care schimb ntre ele dou linii ale unei matrice de dimensiuni 3 3 elemente reale i apoi le schimb la loc. Se vor defini i utiliza funcii diferite pentru citirea unei matrice, afiarea unei matrice precum i pentru schimbarea ntre ele a liniilor.

#include <stdio.h> #include <stdlib.h> void citeste(float mat[][3]) { int i, j; for(i = 0; i < 3; i++) { for(j = 0; j < 3; j++) { printf("Introduceti elem. mat[%d][%d]: ", i, j); scanf("%f", &mat[i][j]); } } }

56

void afiseaza(float mat[][3]) { int i, j; for(i = 0; i < 3; i++) { for( j = 0; j < 3; j++) { printf("%f\t", mat[i][j]); } printf("\n"); } } void schimba1(float mat[][3], int i, int j) { int k; float temp; for(k = 0; k < 3; k++) { temp = *(mat[i] + k); *(mat[i] + k) = *(mat[j] + k); *(mat[j] + k) = temp; } } void schimba2(float mat[][3], int k; float temp; for(k = 0; k < 3; k++) { temp = *(*(mat + i) *(*(mat + i) + k) = *(*(mat + j) + k) = } } int main(void) { int i, j; float m[3][3]; citeste(m); printf("***********************************************\n"); printf("Inainte de inversarea liniilor\n"); afiseaza(m); printf("***********************************************\n"); printf("Introduceti indicele primei linii (<3): "); scanf("%d", &i); while(i < 0 || i >= 3) { printf("Date incorecte\n"); printf("Introduceti indicele primei linii (<3): "); scanf("%d", &i); } printf("Introduceti indicele celei de a doua linii (<3): "); scanf("%d", &j); while(j < 0 || j >= 3) { printf("Date incorecte\n"); printf( "Introduceti indicele celei de a doua linii (<3): "); scanf("%d", &j); } printf("***********************************************\n"); printf("Liniile inversate\n"); schimba1(m, i, j); afiseaza(m); printf("***********************************************\n"); printf("Liniile inversate din nou\n"); schimba2(m, i, j); afiseaza(m); system("PAUSE"); return 0; } int i, int j) {

+ k); *(*(mat + j) + k); temp;

57

Programul va afia pe ecran, dup compilare i execuie:


Introduceti elem. mat[0][0]: 1 Introduceti elem. mat[0][1]: 2 Introduceti elem. mat[0][2]: 3 Introduceti elem. mat[1][0]: 4 Introduceti elem. mat[1][1]: 5 Introduceti elem. mat[1][2]: 6 Introduceti elem. mat[2][0]: 7 Introduceti elem. mat[2][1]: 8 Introduceti elem. mat[2][2]: 9 *********************************************** Inainte de inversarea liniilor 1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000 8.000000 9.000000 *********************************************** Introduceti indicele primei linii (<3): 0 Introduceti indicele celei de a doua linii (<3): 1 *********************************************** Liniile inversate 4.000000 5.000000 6.000000 1.000000 2.000000 3.000000 7.000000 8.000000 9.000000 *********************************************** Liniile inversate din nou 1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000 8.000000 9.000000

Discuie:
Schimbarea ntre ele a liniilor matricei se face utiliznd dou funcii diferite. Funcia schimba1() pune n eviden faptul c n limbajul C o matrice bidimensional este o matrice unidimensional format din matrice unidimensionale. Funcia schimba2() utilizeaz pointerii pentru accesul la valorile din matrice. ============================= P9.9 Scriei un program care caut un subir ntr-un ir de caractere. Programul va afia poziia subirului n ir sau un mesaj de eroare dac subirul nu a fost gsit.

#include <stdio.h> #include <stdlib.h> int cauta(char *sir1, char *sir2) { char *p, *q, *temp; for(p = sir1; *p != '\0'; p++) { for(q = sir2, temp = p; *q != '\0' && *temp != '\0' && *temp == *q; q++, temp++); if(*q == '\0') return p - sir1; } return -1; } int main(void) { char sir1[200], sir2[200]; int poz; printf("Introduceti primul sir\n"); fgets(sir1, 200, stdin); if(sir1[strlen(sir1)-1] == '\n') sir1[strlen(sir1)-1] = '\0'; printf("Introduceti sirul al doilea\n"); fgets(sir2, 200, stdin); if(sir2[strlen(sir2)-1] == '\n') sir2[strlen(sir2)-1] = '\0'; poz = cauta(sir1, sir2); if(poz != -1) printf("Sirul '%s' se gaseste in '%s' la pozitia %d\n", sir2, sir1, poz); else printf("Sirul '%s' nu se gaseste in '%s'\n", sir2, sir1); system("PAUSE"); return 0; }

58

Programul va afia pe ecran, dup compilare i execuie:


Introduceti primul sir Unu doi trei Introduceti sirul al doilea doi Sirul 'doi' se gaseste in 'Unu doi trei' la pozitia 4

sau
Introduceti primul sir Unu doi trei Introduceti sirul al doilea patru Sirul 'patru' nu se gaseste in 'Unu doi trei'

Discuie:
Se remarc modul n care se face cutarea cu ajutorul a dou cicluri cu contor. Ciclul cu contor exterior avanseaz poziia de cutare n irul n care se caut. Cel de al doilea ciclu realizeaz cutarea propriu-zis. Mai nti, la iniializarea ciclului, se aduc cei doi pointeri, la nceputul celor dou iruri de caractere. Cutarea continu ct timp mai exist caractere n cele dou iruri i caracterele din cele dou iruri sunt identice. Dac la ieirea din ciclul intern s-au epuizat caracterele din irul cutat nseamn c irul a fost gsit. Poziia se determin prin diferena dintre pointerul care indic nceputul irului n care se caut i pointerul care indic nceputul subirului gsit. ============================= P9.10 Scriei un program care citete dimensiunea exact a unui vector de numere ntregi, construiete, citete i afieaz acest vector.

#include <stdio.h> #include <stdlib.h> int main(void) { int dim, i; int *vector; do { printf("Introduceti dimensiunea vectorului: "); scanf("%d", &dim); } while(dim <= 0); if(!(vector = (int *)malloc(dim * sizeof(int)))) { printf("Dimensiunea %d este prea mare!\n", dim); printf("Vectorul nu are loc in memorie!\n"); system("PAUSE"); return 1; } printf("Citire\n"); for(i = 0; i < dim; i++) { printf("vector[%d] = ", i); scanf("%d", vector + i); } printf("Scriere\n"); for(i = 0; i < dim; i++) printf("vector[%d] = %d\n", i, *(vector + i)); free(vector); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


Introduceti Citire vector[0] = vector[1] = vector[2] = Scriere vector[0] = vector[1] = vector[2] = dimensiunea vectorului: 3 1 2 3 1 2 3

59

sau
Introduceti dimensiunea vectorului: 1567311664 Dimensiunea 1567311664 este prea mare! Vectorul nu are loc in memorie!

Discuie:
Programul aloc spaiul de memorie necesar stocrii vectorului. Se verific faptul c spaiul de memorie a putut fi alocat. Dac alocarea eueaz, execuia programului se ntrerupe. Dup citire i scriere spaiul de memorie alocat este eliberat. ============================= P9.11 Scriei un program care citete, sorteaz i afieaz un vector de iruri de caractere implementnd o procedur de tip bubble-sort i comparnd pointerii alturai.

#include <stdio.h> #include <stdlib.h> void sort(char *p[], int nr) { char *temp; int i, j, k; for(k = 0; k < nr - 1; k++) { for(i = 0; i < nr - 1; i++) { j = i + 1; if(strcmp(p[i], p[j]) > 0) { temp = p[i]; p[i] = p[j]; p[j] = temp; } } } } int main() { char *p[] = {"Gabi", "Bebe", "Alina", "Claudia", "Catalin", "Andrei"}; int j; printf("Sirurile nesortate sunt:\n"); for(j = 0; j < 6; j++) printf("%s\n", p[j]); sort(p, 6); printf("\nSirurile sortate sunt:\n"); for(j = 0; j < 6; j++) printf("%s\n", p[j]); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


Sirurile nesortate sunt: Gabi Bebe Alina Claudia Catalin Andrei Ana Sirurile sortate sunt: Alina Ana Andrei Bebe Catalin Claudia Gabi

60

Discuie:
Prin utilizarea pointerilor ctre irurile de caractere sunt modificate adresele ctre care indic pointerii i nu sunt mutate irurile de caractere propriu-zise. Efectul rmne cel dorit, dar este obinut cu un efort de calcul mult mai mic. =============================

9.2. 1. 2. 3.

Probleme propuse

Scriei un program care determin de cte ori un subir de caractere se regsete ntr-un alt ir de caractere. Indicaie: se va generaliza soluia de la problema 9.9. Scriei un program care citete trei variabile a, b i c i apoi le rotete ntre ele astfel: a -> b, c -> a. b -> c i

Scriei un program care citete i sorteaz n ordinea ascendent dat de cuvant_cheie un vector format din nregistrri definite astfel:
typedef struct { char cuvant_cheie[10]; int alte_date; } Inregistrare;

Pentru ordonare / sortare se va utiliza funcia qsort() disponibil n bibliotecile standard C i declarat n stdlib.h. Indicaie: funcia qsort() este declarat astfel:
void qsort(void *base, int nmemb, int size,

int(*compar)(const void *elem1, const void *elem2)); unde: base este adresa de nceput a vectorului; nmemb reprezint numrul de elemente din vector; size este dimensiunea n octei a unui element din vector i compar este un pointer ctre o funcie definit de utilizator care realizeaz comparaia ntre dou elemente ale vectorului, elem1 i elem2, returnnd o valoare ntreag mai mic dect, egal cu, sau mai mare dect zero dup cum elem1 este mai mic, egal cu, sau mai mare dect elem2. 4. O metod de sortare presupune adugarea valorilor dintr-un vector una cte una ntr-un vector nou. Prima valoare este adugat la nceputul vectorului. Valorile urmtoare sunt adugate n poziia corespunztoare ordinii sale prin deplasarea datelor adugate deja pentru a face loc valorii care se adaug. Aceast metod poart numele de sortare prin inserare (insertion sort). Scriei o funcie denumit insort() care realizeaz astfel sortarea i se comport n acelai mod precum funcia qsort() descris n problema anterioar. Funcia insort() va avea prototipul:
void insort(void *base, int nmemb, int size, int(*compar)(const void *elem1, const void *elem2));

Prototipul este similar cu al funciei qsort() realiznd sortarea unui vector cu adresa de nceput indicat de base, format din nmemb elemente de tip arbitrar i de dimensiune size i care sunt comparate de funcia compar(). Scriei i programul principal care testeaz funcia.

5.

Scriei o funcie care primete ca argument un ir de caractere i returneaz un pointer ctre primul caracter care nu este spaiu din acest ir de caractere. Precizri: a. Se vor considera spaii caracterele ' ' (space) i '\t' (tab). b. Prototipul funciei este:
char *primul_caracter(char *sir);

c.

Scriei i programul principal care testeaz funcia.

6.
7.

Scriei un program care citete un text, l desparte n cuvinte i afieaz cuvintele textului ordonate alfabetic. Scriei un program care citete un text i afieaz doar ultimele 5 linii ale textului.

61

8.

Scriei un program care parcurge lista definit mai jos cu ajutorul pointerului p_lista i afieaz numrul i numele.
define MAX 4 struct lista { int numar; char nume[10]; } data[MAX] = { 1, 2, 3, 4, }; struct lista *p_lista; "Ion", "Vasile", "Gheorghe", "Maria"

9.

Scriei un program care citete o expresie matematic simpl format din doi operanzi numerici i un operator (+, -, *, /) i determin i afieaz valoarea expresiei. Un exemplu de rulare a programului va arta astfel:
Introduceti expresia: 1.25 * 4 = 5

10. Scriei un program care citete de la tastatur o matrice de numere reale de dimensiuni maxime 10 x 10, mpreun cu dimensiunile sale efective i determin ctul mpririi modulului sumei numerelor negative din matrice la suma numerelor pozitive din matrice. Programul va semnala cazul special al mpririi prin zero. Pentru calculul sumelor se va folosi o funcie cu urmtorul prototip:
void suma(float A[][10], int n, int m, float *pos, float *neg);

unde: A[][10] n, m pos neg

este matricea de lucru; sunt dimensiunile efective ale matricei; suma numerelor pozitive; suma numerelor negative.

11. Reluai problema anterioar i scriei un program care citete de la tastatur o matrice de numere reale de orice dimensiuni, mpreun cu dimensiunile sale efective i determin ctul mpririi modulului sumei numerelor negative din matrice la suma numerelor pozitive din matrice. Programul va semnala cazul special al mpririi prin zero. Pentru calculul sumelor se va folosi o funcie cu urmtorul prototip:
void suma(float **A, int n, int m, float *pos, float *neg);

unde: A n, m pos neg

este matricea de lucru; sunt dimensiunile efective ale matricei; suma numerelor pozitive; suma numerelor negative.

12. Scriei un program care citete de la tastatur o matrice de numere reale de dimensiuni maxime 10 x 10, mpreun cu dimensiunile sale efective i determin ctul mpririi modulului produsului elementelor de pe diagonala principal a matricei la produsul elementelor de pe diagonala secundar a matricei. Programul va semnala cazul special al mpririi prin zero. Pentru calculul sumelor se va folosi o funcie cu urmtorul prototip:
void prod_diag(float A[][10], int n, float *dprin, float *dsec);

unde: A[][10] n dprin dsec

este matricea de lucru; este dimensiunea efectiv a matricei; produsul elementelor de pe diagonala principal; produsul elementelor de pe diagonala secundar.

13. Scriei o funcie care primete ca parametru un numr ntreg i returneaz un pointer ctre numele lunii calendaristice corespunztoare. Dac numrul nu reprezint o lun, este mai mic dect 1 sau mai mare dect 12, funcia va returna un pointer ctre irul de caractere nici o luna. Precizri: a. Denumirile lunilor vor fi memorate ntr-o variabil local static a funciei definit astfel:
static char *luna[] = { "nici o luna", "ianuarie",

62

"februarie", "martie", "aprilie", "mai", "iunie", "iulie", "august", "septembrie", "octombrie", "noiembrie", "decembrie" };

b. Prototipul funciei este:


char *denumire_luna(int numar);

Scriei i programul principal care verific funcionarea funciei. 14. Folosind funcia din exerciiul anterior scriei o alt funcie care primind un ir de caractere de forma "zzllaaaa" returneaz data scris sub forma "zi luna an". De exemplu: funcia primete "15042004" i returneaz "15 aprilie 2004". Funcia va verifica i corectitudinea datei rejectnd date cum ar fi "2902001" (anul 2001 nu a fost bisect) sau "31042005" (aprilie nu are 31 de zile). Scriei i programul principal care verific funcionarea funciei. 15. Scriei o funcie care citete cel mult n numere reale de tip float i le plaseaz n memorie ncepnd de la adresa indicat de pfloat. Funcia va returna numrul valorilor citite. Prototipul funciei este:
int citeste_n_nr(int n, float *pfloat);

Scriei i programul principal care verific funcionarea funciei.

63

10. Probleme recapitulative


10.1.
P10.1

Probleme rezolvate

Scriei un program care s calculeze i s afieze, n funcie de opiunea utilizatorului, urmtoarele mrimi pentru un cilindru cu raza bazei i nlimea date (numere reale): aria bazei, circumferina cercului de baz i volumul cilindrului; programul va fi reluat pn cnd utilizatorul dorete terminarea sa i se va cere repetarea opiunii, dac aceasta nu s-a fcut corect.

#include <stdio.h> #include <stdlib.h> #define PI 3.14159265358979323846 int main() { float raza, inaltimea; char ch; double raspuns; int semnal=1; while(semnal) { printf("Alegeti una din optiunile:\n"); printf( "Aria (A), Circumferinta (C), Volumul (V), Iesire (Q): "); ch = getche(); printf("\n"); ch = toupper(ch); if(ch == 'A' || ch == 'C' || ch == 'V') do { printf("Introduceti raza: "); } while(scanf("%f", &raza) != 1); if(ch == 'V') do { printf("Introduceti inaltimea: "); } while(scanf("%f", &inaltimea) != 1); switch(ch) { case 'A': raspuns = PI * raza * raza; printf("Aria bazei este: %g\n\n", raspuns); break; case 'C': raspuns = 2 * PI * raza; printf( "Circumferinta bazei este: %g\n\n", raspuns); break; case 'V': raspuns = PI * raza * raza * inaltimea; printf( "Volumul cilindrului este: %g\n\n", raspuns); break; case 'Q': semnal=0; break; default: printf( "Optiunea necunoscuta '%c' este ignorata!\n\n", ch); break; } } printf("\n"); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


Alegeti una din optiunile: Aria (A), Circumferinta (C), Volumul (V), Iesire (Q): v Introduceti raza: 10 Introduceti inaltimea: 1 Volumul cilindrului este: 314.159 Alegeti una din optiunile: Aria (A), Circumferinta (C), Volumul (V), Iesire (Q): q

============================= 64

P10.2

Scriei un program care s deseneze pe ecran un X cu dimensiunea specificat de utilizator (numr natural 20, nlimea egal cu limea), folosind simbolul * . De exemplu, dac se introduce numrul 5, desenul va trebui s arate astfel:

* * * * *
#include <stdio.h> #include <stdlib.h>

* * * *

int main() { int d; /* dimensiunea */ int r; /* numarul liniei */ int c; /* numarul coloanei */ printf("Introduceti dimensiunea: "); scanf("%d", &d); /* pentru "diagonala principala", '*' va apare cand r = c; pentru "diagonala secundara", '*' va apare cand c=dr+1 */ printf("Desenul cerut arata astfel:\n\n"); for(r = 1; r <= d; r++) { for(c = 1; c <= d; c++) { if(r == c || c == d r + 1) printf("*"); else printf(" "); } printf("\n"); } printf("\n"); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


Introduceti dimensiunea: 8 Desenul cerut arata astfel: * * * * *

* ** ** * * * * * *

============================= P10.3 Programul urmtor citete de la tastatur o matrice de maxim 10 10 numere ntregi apoi determin elementele minime pe linii i maxime pe coloane.

#include <stdio.h> #include <stdlib.h> int main() { int A[10][10], n, m, i, j, min, max; printf("Introduceti nr. de linii: "); scanf("%d", &n); printf("Introduceti nr. de coloane: "); scanf("%d", &m); for(i = 0; i < n; i++) for(j = 0; j < m; j++) { printf("A[%d][%d] = ", i, j); scanf("%d", &A[i][j]); } printf("Elementele minime pe linii: \n"); for(i = 0; i < n; i++) { min = A[i][0]; for(j = 0; j < m; j++) {

65

if (A[i][j] < min) min = A[i][j]; } printf("Linia %d are minimul: %d\n", i, min); } printf("Elementele maxime pe coloane: \n"); for(j = 0; j < m; j++) { max = A[0][j]; for(i = 0; i < n; i++) { if (A[i][j] > max) max = A[i][j]; } printf("Coloana %d are maximul: %d\n", j, max); } system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


Introduceti nr. de linii: 3 Introduceti nr. de coloane: 3 A[0][0] = 1 A[0][1] = 2 A[0][2] = 3 A[1][0] = 4 A[1][1] = 5 A[1][2] = 6 A[2][0] = 7 A[2][1] = 8 A[2][2] = 9 Elementele minime pe linii: Linia 0 are minimul: 1 Linia 1 are minimul: 4 Linia 2 are minimul: 7 Elementele maxime pe coloane: Coloana 0 are maximul: 7 Coloana 1 are maximul: 8 Coloana 2 are maximul: 9

============================= P10.4 Programul urmtor citete de la tastatur o matrice de maximum 10 10 numere ntregi i sorteaz cresctor liniile matricei. Precizare: prin convenie, o linie este mai mare dect alta dac primul element de pe o linie este mai mare dect primul element de pe a doua. Dac primele elemente sunt egale regula se aplic pentru urmtoarele perechi de elemente de pe liniile respective.

#include <stdio.h> #include <stdlib.h> /* functie care interschimba linia l1 cu l2 in matricea A */ void int_linii(int A[][10], int n, int m, int l1, int l2) { int j, tmp; for(j = 0; j < m; j++) { tmp = A[l1][j]; A[l1][j] = A[l2][j]; A[l2][j] = tmp; } } int main() { int A[10][10], n, m, i, j, ind; printf("Introduceti nr. de linii: "); scanf("%d", &n); printf("Introduceti nr. de coloane: "); scanf("%d", &m); /* citirea matricii */ for(i = 0; i < n; i++) for(j = 0; j < m; j++) {

66

printf("A[%d][%d] = ", i, j); scanf("%d", &A[i][j]); } ind = 1; /* setare indicator */ while(ind) { ind = 0; /* parcurgere matrice pe linii */ for(i = 0; i < n; i++) for(j = 0; j < m; j++) if(A[i][j] <= A[i+1][j]) /* s-a gasit un element mai mic pe linia urmatoare deci parcurgerea liniei i se incheie */ break; else { /* se interschimba linia curenta cu urmatoarea */ int_linii(A, n, m, i, i+1); ind = 1; /* setam indicatorul */ break; /* terminam parcurgerea liniei i */ } } /* afisare matrice */ for(i = 0; i < n; i++) for(j = 0; j < m; j++) printf("A[%d][%d] = %d\n", i, j, A[i][j]); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


Introduceti nr. de linii: 3 Introduceti nr. de coloane: 3 A[0][0] = 9 A[0][1] = 8 A[0][2] = 7 A[1][0] = 6 A[1][1] = 5 A[1][2] = 4 A[2][0] = 3 A[2][1] = 2 A[2][2] = 1 A[0][0] = 3 A[0][1] = 2 A[0][2] = 1 A[1][0] = 6 A[1][1] = 5 A[1][2] = 4 A[2][0] = 9 A[2][1] = 8 A[2][2] = 7

============================= P10.5 Programul urmtor citete de la tastatur o matrice de maximum 10 10 numere ntregi apoi elimin o linie a matricei. Precizare: indexul liniei ce se dorete eliminat va fi citit tot de la tastatur.

#include <stdio.h> #include <stdlib.h> int main() { int A[10][10], n, m, i, j, ie; printf("Introduceti nr. de linii: "); scanf("%d", &n); printf("Introduceti nr. de coloane: "); scanf("%d", &m); /* citirea matricii */ for(i = 0; i < n; i++) for(j = 0; j < m; j++) {

67

printf("A[%d][%d] = ", i, j); scanf("%d", &A[i][j]); } /* citirea corecta a indicelui ie al liniei ce se doreste eliminata */ while(1) { printf( "Introduceti indicele liniei ce se doreste eliminata: "); scanf("%d", &ie); if ((ie >= 0) && (ie <= n)) break; else printf("Indice incorect\n"); } /* cu i de la ie la n se aduc liniile i+1 pe liniile i */ for(i = ie; i < n; i++) for(j = 0; j < m; j++) A[i][j] = A[i+1][j]; /* decrementam numarul total de linii */ n--; /* afisam matricea */ for(i = 0; i < n; i++) for(j = 0; j < m; j++) printf("A[%d][%d] = %d\n", i, j, A[i][j]); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


Introduceti nr. de linii: 3 Introduceti nr. de coloane: 3 A[0][0] = 1 A[0][1] = 2 A[0][2] = 3 A[1][0] = 4 A[1][1] = 5 A[1][2] = 6 A[2][0] = 7 A[2][1] = 8 A[2][2] = 9 Introduceti indicele liniei ce se doreste eliminata: 1 A[0][0] = 1 A[0][1] = 2 A[0][2] = 3 A[1][0] = 7 A[1][1] = 8 A[1][2] = 9

============================= P10.6 Programul urmtor citete de la tastatur o matrice de dimensiuni n m de numere ntregi (maximum 10 10) i nlocuiete coloana k cu un vector de n elemente ce se va citi tot de la tastatur. Precizare: poziia coloanei, k, se va citi tot de la tastatur.

#include <stdio.h> #include <stdlib.h> int main() { int A[10][10], n, m, k, i, j, v[10]; printf("Introduceti nr. de linii: "); scanf("%d", &n); printf("Introduceti nr. de coloane: "); scanf("%d", &m); for(i = 0; i < n; i++) for(j = 0; j < m; j++) { printf("A[%d][%d] = ", i, j); scanf("%d", &A[i][j]); }

68

while(1) { printf("Introduceti indicele coloanei ce se "); printf("doreste inlocuita: "); scanf("%d", &k); if ((k >= 0) && (k <= m)) break; else printf("Indice incorect\n"); } /* citim in vectorul v noua coloana a matricii A */ printf("Acum introduceti noile elemente ale coloanei:\n"); for(i = 0; i < n; i++) { printf("A[%d][%d] = ", i, k); scanf("%d", &v[i]); } /* parcurgem coloana k si inlocuim elementele sale */ for(i = 0; i < n; i++) A[i][k] = v[i]; /* tiparim noua matrice */ printf("Noua matrice are elementele:\n"); for(i = 0; i < n; i++) for(j = 0; j < m; j++) printf("A[%d][%d] = %d\n", i, j, A[i][j]); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


Introduceti nr. de linii: 3 Introduceti nr. de coloane: 3 A[0][0] = 1 A[0][1] = 2 A[0][2] = 3 A[1][0] = 4 A[1][1] = 5 A[1][2] = 6 A[2][0] = 7 A[2][1] = 8 A[2][2] = 9 Introduceti indicele coloanei ce se doreste inlocuita: 1 Acum introduceti noile elemente ale coloanei: A[0][1] = 1 A[1][1] = 2 A[2][1] = 3 Noua matrice are elementele: A[0][0] = 1 A[0][1] = 1 A[0][2] = 3 A[1][0] = 4 A[1][1] = 2 A[1][2] = 6 A[2][0] = 7 A[2][1] = 3 A[2][2] = 9

============================= P10.7 Programul urmtor afieaz graficul unei funcii (de exemplu sin(x) pe o perioad) n format ASCII. Programul scaleaz funcia n intervalul ce se dorete afiat i tiprete un singur caracter '*' pe poziia corespunztoare valorii funciei. Terminalul alfanumeric se va considera de 80 coloane i 25 linii.

#include <stdio.h> #include <stdlib.h> #include <math.h> #define NC 40 /* numarul de coloane */ #define NL 25 /* numarul de linii */ main() { float v[NL-1], x, M, m, q; int i, j; for(i = 0; i < NL - 1; i++) { x = (float)(i-12); /* functia ce se afiseaza */ v[i] = sin(2 * 3.1415926535 * x / NL); }

69

/* Se gasesc maximumul, M, si minimul, m, functiei */ M = m = v[0]; for(i = 0; i < NL - 1; i++) if(v[i] > M) M = v[i]; for(i = 0; i < NL - 1; i++) if(v[i]<m) m=v[i]; /* gaseste pasul minim */ q = (NC - 1) / (M - m); /* parcurge terminalul alfanumeric linie cu linie */ for(i = 0; i < NL - 1; i++) for(j = 0; j < NC; j++) { if(j == ceil((v[i] - m) * q)) { printf("*\n"); /* tipareste '*' si trece pe linia urmatoare */ break; /* iese de ciclul for ce parcurge liniile daca s-a tiparit **/ } else printf(" "); /* tipareste spatiu */ } system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie: * * * * * * * * * * * * * * * * * * * * * * * * ============================= P10.8 Scriei un program care s implementeze un calculator de buzunar foarte simplu (doar cele 4 operaii elementare).

#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { float nr1, nr2, rez; char op; printf("Introduceti expresia (nr op nr, op = +-x/)\n"); scanf("%f %c %f", &nr1, &op, &nr2); switch(op) { case '+': rez = nr1 + nr2; break; case '-': rez = nr1 - nr2;

70

break; case 'x': rez = nr1 * nr2; break; case '/': if(nr2 == 0) { printf("Impartire la 0!\n"); system("PAUSE"); exit(4); } else rez = nr1 / nr2; break; default: printf("Eroare: operator necunoscut\n"); system("PAUSE"); exit(5); } printf("%g %c %g = %g\n", nr1, op, nr2, rez); system("PAUSE"); return 0; }

Programul va afia pe ecran, dup compilare i execuie:


Introduceti expresia (nr op nr, op = +-x/) 25.75 x 3.14 25.75 x 3.14 = 80.855

=============================

10.2.
1. 2. 3. 4.

Probleme propuse Teme de cas

Scriei un program care citete un numr ntreg reprezentat n baza 10 i l convertete i afieaz reprezentat n baza 16. Scriei un program care citete de la tastatur un numr natural n cu cel mult 9 cifre i determin numrul natural k < n care are numrul maxim de divizori primi. Scriei un program care citete perechi de numere reale care reprezint coordonatele carteziene ale unui poligon convex i apoi calculeaz i afieaz aria poligonului. Scriei un program care citete un numr ntreg pozitiv n < 50 000 reprezentnd numrul de zile care au trecut de la 1 ianuarie 1900 i determin i afieaz data calendaristic corespunztoare. Se vor lua n consideraie i anii biseci (1900 a fost an bisect iar 2000 nu a fost an bisect). Scriei un program care citete din fiierul nr.in un numr natural cu minim 2 cifre i maxim 5000 de cifre zecimale i apoi calculeaz i scrie n fiierul nr.out ptratul acestui numr. Scriei un program care determin cte perechi de numere naturale care nu depesc un numr dat, n, au cel mai mic divizor comun un alt numr dat, d. Programul va afia perechile de numere obinute. Scriei un program care determin toate numerele naturale i < n care au proprietatea c sunt egale cu suma factorialelor cifrelor care le conin. Exemplu: 145 = 1! + 4! + 5! Numrul n va fi citit de la tastatur. Scriei un program care determin care este numrul natural maxim care se poate construi din cifrele distincte ale unui numr natural n baza 10 cu maxim 80 de cifre care se citete de la tastatur. Scriei un program care citete un numr natural n cu maxim 50 de cifre zecimale i determin i afieaz secvena maxim de cifre consecutive care se repet de cel puin 2 ori n scrierea numrului n.

5.

6. 7.

8. 9.

10. Scriei un program care citete ecuaiile a n drepte din plan i determin i afieaz dreptele care aparin aceleiai clase de paralelism. Ecuaia unei drepte este dat de formula: a x + b y + c = 0; dou drepte aparin aceleai clase de paralelism dac au aceeai pant. 11. Scriei un program care citete ntr-un ir de caractere care reprezint o expresie care conine mai multe numere complexe i operaii ntre acestea apoi calculeaz i afieaz rezultatul expresiei. 71

Precizri: Operaii: + , - , * , ^ Exemplu: (2 + 3 * i) ^ 3 + (7 + 9 * i) * (10 4 * i) 12. Scriei un program care citete coordonatele a trei figuri geometrice formate doar din linii drepte i determin i afieaz doar segmentele care se nscriu n suprafaa unui dreptunghi ale crui coordonate vor fi i ele citite de la tastatur. Precizare: aceast operaie, denumit n limba englez clipping, este foarte important n afiarea grafic a informaiei. 13. Scriei un program care citete coordonatele unui graf orientat i i ordoneaz vrfurile astfel nct toate arcele s aib aceeai orientare. Programul va semnala dac acest lucru nu este posibil. Exemplu: Dac avem (1, 2) (2, 3) (3, 1) nu este posibil ca toate arcele s aib aceeai orientare. 14. Scriei un program care citete un fiier reprezentnd un program C i scrie la ieire acelai program n care acoladele corespunztoare - { respectiv } - au fost aezate una sub alta. n cazul mai multor acolade imbricate, cele din interior se vor deplasa fa de cele din exterior. Restul textului se va alinia pe aceeai coordonat cu cele dou acolade corespunztoare. 15. Scriei un program care citete un arbore n-ar (n este un numr natural) i i scrie reprezentarea fiu frate. Precizare: n reprezentarea fiu - frate un arbore n-ar este reprezentat ca un arbore binar astfel nct pentru un vrf x legtura stnga reprezint primul fiu iar legtura dreapta reprezint fratele. 16. Scriei un program care citete un numr natural n (cu maxim 10 cifre) i determin toate numerele ce pot fi obinute mutnd pe rnd prima cifr a numrului n i a celor obinute pe parcurs pe ultima poziie. Exemplu: 4273 2734 7342 3427 Problema va fi rezolvat n trei moduri: folosind unul sau mai multe tablouri cu elemente de tip numeric; folosind tipul ir de caractere; folosind metode aritmetice. 17. Scriei un subprogram care s calculeze valoarea 2 la puterea 3000. Transformai apoi subprogramul pentru calculul oricrei puteri adic: n la puterea m (n < 10, m < 3001, m > 0, n i m ntregi). 18. Scriei un program care citete polinoame rare i le memoreaz sub forma unei liste simplu nlnuite, unde pentru fiecare monom, se memoreaz gradul i coeficientul. Scriei o funcie pentru suma a dou polinoame rare, specificate ca parametru. 19. Scriei un program care citete n puncte din plan (n 100) date prin coordonatele lor carteziene i determin n care dintre aceste puncte putem alege centrul cercului de raz minim ce conine n interior toate cele n puncte date, precum i raza cercului. Precizri: datele vor fi citite din fiierul text PUNCTE.TXT , ce are pe prima linie valoarea lui n, iar pe urmtoarele n linii coordonatele carteziene ale punctelor, cte dou pe linie (x respectiv y), valori reale. 20. Scriei un program care citete fiierul text TEST.IN care conine un text scris pe mai multe linii i afieaz toate caracterele folosite, codul ASCII corespunztor precum i frecvena lor de apariie. 21. Scriei un program care estimeaz cu 6 zecimale numrul (3.1415926535...) n modul urmtor: a) Se vor genera perechi de numere pseudo-aleatoare de tipul (x, y) cu 0 < x, y < 1; b) Se vor numra cte perechi de astfel de numere pseudo-aleatoare cad n interiorul sfertului de cerc situat n cadranul 1 al planul (x, y); c) se va evalua pi ca 4 <numrul_de_puncte_din_interiorul_sfertului_de_cerc> / <numrul_total_de_puncte>. 22. Scriei un program care s citeasc elementele a dou matrice, fiecare dintr-un fiier, s calculeze matricea produs i s o tipreasc ntr-un al treilea fiier. Matricele vor fi structurate n fiiere pe linii i coloane. Se va afia un mesaj de eroare dac nmulirea matricelor nu este posibil. 23. Scriei un program care citete elementele unei matrice ptrate, dintr-un fiier ASCII, calculeaz matricea transpus i o tiprete ntr-un alt fiier. Precizri: Matricea va fi structurat n primul fiier pe linii i coloane astfel:
1.0 -3.14 0 -1.33 5.67 4.67 3.44 0 10.01

72

24. Scriei un program care citete din fiierul INPUT.TXT dou propoziii scrise fiecare pe cte o linie. Propoziiile conin cuvinte formate din literele alfabetului englez. Orice alt caracter este considerat separator. Programul: va afia numrul de cuvinte din fiecare propoziie; va verifica dac ultimul cuvnt din prima propoziie este o anagram (are aceleai litere) a ultimului cuvnt din cealalt propoziie. Pentru verificarea cuvintelor scriei i folosii o funcie recursiv. Precizri: Rezultatele se vor scrie n fiierul OUTPUT.TXT astfel: pe primele dou linii programul va scrie numrul de cuvinte din fiecare propoziie; pe ultima linie va scrie mesajul DA sau NU pentru cazurile n care ultimele cuvinte sunt sau nu anagrame. 25. Scriei un program care citete fiierul AMENZI.TXT care conine evidena amenzilor de circulaie pe o perioad dat. Fiecrui conductor auto i se aloc 4 linii: prima linie va conine numele, cea de a doua numrul de nmatriculare al mainii, ce de a treia suma de bani corespunztoare amenzii i cea de a patra dac amenda a fost sau nu pltit (0 nepltit, 1 - pltit). Programul va citi mai nti numrul de nregistrri, n. Apoi programul: va afia suma de bani rezultat din amenzi, precum i numele oferilor i numrul mainii care a pltit amenzile cele mai mari; numele oferilor care nu au pltit amenda/amenzile ordonate alfabetic; procentul de amenzi nencasate. 26. Scriei un program care citete lista abonailor telefonici dintr-un ora dintr-un fiier care conine numrul de telefon i numele abonatului pe cte o linie. Programul va crea o list de premiere care s cuprind abonaii al cror numere de telefon cuprind doar cifre pare iar prima i ultima cifr sunt proporionale. 27. Scriei un program care citete dou fiiere ASCII structurate astfel: a. primul fiier va conine, structurat pe linii, numele i prenumele candidailor la un concurs de admitere, separate prin unul sau mai multe spaii, n formatul <nume> <prenume>; b. al doilea fiier va conine, structurat pe linii, media la examenul de admitere. Programul va asocia numele i prenumele persoanei de la linia i din primul fiier cu nota de la linia i din al doilea fiier. Programul va concatena cele trei cmpuri (numele, prenumele i nota), le va sorta n ordinea cresctoare a mediei i va scrie rezultatul ntr-un al treilea fiier ASCII. Exemple de fiiere:
fiier1.txt CONSTANTIN Ioana POPESCU George VASILESCU Costin fiier2.txt 8.66 9.52 7.89 fiier3.txt POPESCU George CONSTANTIN Ioana VASILESCU Costin

9.52 8.66 7.89

28. Scriei un program care citete dou fiiere ASCII structurate astfel: a. primul fiier va conine, structurat pe linii, numele i prenumele angajailor unei firme, separate prin unul sau mai multe spaii, n formatul <nume> <prenume>; b. al doilea fiier va conine, structurat pe linii, data naterii, n formatul <zi> <luna> <an>. Programul va asocia numele i prenumele persoanei de la linia i din primul fiier cu data naterii de la aceeai linie din al doilea fiier. Programul va concatena cele cinci cmpuri (numele, prenumele, zi, luna, an), le va sorta n ordinea descresctoare a vrstei i va scrie rezultatul ntr-un al treilea fiier ASCII. Exemplu:
fiier1.txt CONSTANTIN Ioana POPESCU George VASILESCU Costin fiier2.txt 8 Ianuarie 1978 27 August 1980 16 Octombrie 1978 fiier3.txt CONSTANTIN Ioana VASILESCU Costin POPESCU George

8 Ianuarie 1978 16 Octombrie 1978 27 August 1980

73

29. Scriei un program care s recunoasc ntr-un fiier surs C directiva de preprocesare #define i care s genereze un alt fiier preprocesat. Exemplu:
fiier1.c #include <stdio.h> #include <stdlib.h> #define PI 3.1415 int main() { printf("pi = %f", PI); return 0; } fiier2.c #include <stdio.h> #include <stdlib.h> int main() { printf("pi = %f", 3.1415); return 0; }

30. Scriei un program care citete fiierul TEXT.TXT care conine un text ce se ncheie cu o linie goal. S se afieze toate cuvintele textului n ordine alfabetic. Precizri: lungimea unui cuvnt este de maxim 25 caractere; numrul de cuvinte din text este cel mult 100; cuvintele sunt desprite printr-un spaiu; se va folosi sortarea prin inserie. Rescriei programul pentru a putea prelucra un text orict de mare i n care cuvintele sunt desprite prin orice tip de spaiu sau semn de punctuaie. 31. Scriei un program care construiasc un fiier cu nregistrri de tip bibliotec cu urmtoarele cmpuri: Numele autorului Titlul crii Editura Anul apariiei Lista cuvintelor cheie Programul va permite urmtoarele operaii: a. introducerea unei nregistrri noi n bibliotec; b. tergerea unei nregistrri din bibliotec; c. extragerea ntr-un fiier nou a nregistrrilor n funcie de valoarea unui anumit cmp: Numele autorului Titlul crii Editura Anul apariiei Existena unui anumit cuvnt n lista cuvintelor cheie d. sortarea fiierului n ordinea cresctoare a numelor autorilor (ordine lexicografic), iar pentru acelai autor, nregistrrile se ordoneaz n funcie de anul apariiei; e. interclasarea a dou fiiere ordonate conform punctului anterior. Numele fiierelor se citesc de la tastatur. Programul va construi un fiier ordonat care conine reuniunea celor dou fiiere iniiale i va elimina duplicatele din fiier. 32. Scriei un program care citete fiierul text INTRARE.IN care conine un text scris pe mai multe linii i rescrie textul pe pagini formate din dou coloane cu linii de lungime egal. Lungimea unei linii ln i dimensiunea unei pagini lp se citesc de la tastatur. Rescriei programul extinzndu-l pentru a putea mprirea textul n k coloane.

74

S-ar putea să vă placă și