Sunteți pe pagina 1din 75

Drago Burileanu

Claudius Dan
Marius Pdure

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.

Programe simple; variabile i constante,


operaii de intrare/ieire formatate

2.1.

Probleme rezolvate

Scriei un program care afieaz pe ecran un text dat.

P2.1

#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.
=============================
Scriei un program care calculeaz diferena a dou numere ntregi introduse de la tastatur.

P2.3

#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.


=============================
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).

P2.5

#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.

Probleme propuse

1.

Scriei un program care s v afieze numele pe ecran, ca i seria i grupa, pe dou rnduri succesive.

2.

Se citete un ntreg . Scriei un program care s afieze: Ai introdus numrul ....

3.

Scriei un program care citete doi ntregi i calculeaz produsul lor.

4.

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.

5.

Scriei un program care transform temperatura exprimat n grade Celsius n grade Fahrenheit.

6.

Scriei un program care transform msura unui unghi din radiani n grade.

7.

Scriei programe care calculeaz arii pentru ptrat, dreptunghi, triunghi.

8.

Scriei programe care calculeaz volume pentru cub, paralelipiped, piramid.

3.

Tipuri fundamentale de date, operatori i expresii

3.1.

Probleme rezolvate

Urmtorul program ilustreaz utilizarea tipurilor fundamentale de date n C.

P3.1

#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;
}


66000

Programul va afia pe ecran, dup compilare i execuie:


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

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

P3.2

#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).
=============================
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

P3.3

#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

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

P3.4

#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

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

P3.5

#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;
}


x
z
x
z

=
=
=
=

11,
14,
10,
30,

Programul va afia pe ecran, dup compilare i execuie:


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

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

P3.7

#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

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

p = 1.250000

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.

Probleme propuse

1.

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.

2.

Scriei un program care citete pe n ntreg i afieaz valoarea expresiei n/(n+1) cu patru zecimale.

3.

Deducei ce afieaz urmtorul program:

#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

P4.1

4.

Instruciuni condiionale

4.1.

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.

3.

Folosind instruciuni de decizie, scriei un program care citete de la tastatur un numr ntreg x i afieaz o
valoare y calculat astfel:

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.

5.

Scriei un program care s calculeze i s afieze maximul i minimul dintre trei numere ntregi citite de la
tastatur, utiliznd operatorul condiional.

6.

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.

18

5.

Cicluri

5.1.

Probleme rezolvate

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

P5.1

#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);
}

=============================
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.

P5.2

#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);

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

P5.3

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;
}

20

scanf("%d", &i);

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

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


afieaz pe n!

P5.6

[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;
}

=============================
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.

P5.7

#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?
=============================
Scriei un program care citete de la tastatur dou numere naturale a i b ( a

P5.8

numerele prime din intervalul

< b ) i afieaz toate

[a, b] .

#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;
}

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

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.

P5.9

#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=

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

2.

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

3.

Scriei un program care afieaz numerele dintr-un interval

4.
5.
6.

Scriei un program care afieaz numerele prime mai mici dect un numr natural k citit.

7.

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

[a, b] ce se divid cu 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.

Tablouri i iruri de caractere

6.1.

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.

P6.1

#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.
=============================
Scriei un program care citete un vector de elemente ntregi, mpreun cu dimensiunea sa efectiv, i
determin maximul i minimul dintre elementele acestui vector.

P 6.3

#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.
=============================
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.

P6.4

#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

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.).

P6.5

#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

Matricea citita
1
2
6
7
11
12

este:
3
8
13

4
9
14

5
10
15

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[1][0]

A[1][1]

(6.a)

A[0][0]

A[0][1]

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.
=============================
Scriei un program care citete un ir de maximum 100 de caractere de la tastatur i afieaz acest ir n
ordine invers.

P6.9

#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.

Probleme propuse

1.

Scriei un program care citete de la tastatur un vector de maximum 50 de numere ntregi i determin numrul
elementelor impare ale vectorului.

2.

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).

3.

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.

4.

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.

5.

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.

6.

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.

7.

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.

8.

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.

9.

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.

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.

Alte tipuri de date:


structuri, uniuni, tipul enumerat

7.1.

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.

P7.1

#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 |.
=============================
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.

P7.2

#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);

reala a primului nr.: ");


imaginara a primului nr.: ");
reala celui de al doilea nr.: ");
imaginara celui de al ");

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;
}

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.
=============================
Scriei un program care determin spaiul de memorie ocupat de o structur.

P7.4

#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.
=============================
Reluai problema anterioar dar construii i o metod care v permite s aflai n orice moment tipul
informaiei stocate.

P7.7

#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.
=============================
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.

P7.8

#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.

Probleme propuse

1.

Scriei un program care citete de la tastatur un vector de elemente complexe, calculeaz i afieaz suma
complex a tuturor elementelor sale.

2.

Scriei un program care citete de la tastatur un vector de elemente complexe, calculeaz i afieaz produsul
complex al tuturor elementelor sale.

3.

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.

Modificai programul P7.8 astfel nct s memoreze numele materiilor i notele obinute n structuri.

6.

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;

8.

unsigned int numar;


unsigned int mobil;

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.

Funcii simple; recursivitate

8.1.

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.

P8.1

#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.
=============================
Scriei un program care citete un numr natural n i calculeaz i afieaz factorialul numrului n definit
astfel:

P8.3

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.
=============================
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:

P8.6

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.
=============================
Scriei un program care verific transferul unei structuri, ca parametru, ctre o funcie.

P8.8

#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

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

P8.9

#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.

Pointeri

9.1.

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.

P9.1

#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

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.

P9.3

#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

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

=
=
=
=
=
=
=

ptr
ptr
ptr
ptr
ptr
ptr

+
+
+
+
+
+

0
1
2
3
4
5

=
=
=
=
=
=

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

1
23
17
4
-5
100

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.
=============================
Scriei un program care ncarc valori ntr-o structur folosind un pointer ctre aceasta.

P9.7

#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 i, int j) {

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

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;
}

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.
=============================
Scriei un program care citete dimensiunea exact a unui vector de numere ntregi, construiete, citete i
afieaz acest vector.

P9.10

#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.
=============================
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.

P9.11

#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.

Probleme propuse

1.

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.

2.

Scriei un program care citete trei variabile a, b i c i apoi le rotete ntre ele astfel: a -> b,
c -> a.

3.

Scriei un program care citete i sorteaz n ordinea ascendent dat de cuvant_cheie un vector format din
nregistrri definite astfel:

b -> c i

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.

Scriei un program care citete un text, l desparte n cuvinte i afieaz cuvintele textului ordonate alfabetic.

7.

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,

"Ion",
"Vasile",
"Gheorghe",
"Maria"

};
struct lista *p_lista;

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.

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.

P10.1

#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

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:

P10.2

*
*

*
*

#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.

Probleme propuse Teme de cas

1.

Scriei un program care citete un numr ntreg reprezentat n baza 10 i l convertete i afieaz reprezentat n
baza 16.

2.

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.

3.

Scriei un program care citete perechi de numere reale care reprezint coordonatele carteziene ale unui poligon
convex i apoi calculeaz i afieaz aria poligonului.

4.

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).

5.

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.

6.

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.

7.

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.

8.

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.

9.

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.

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