Sunteți pe pagina 1din 75

Dragoş Burileanu Claudius Dan

Marius Pădure
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
către firma Bloodshed Software (Website: http://www.bloodshed.net). El foloseşte compilatorul GCC
(GNU C – Free Software Foundation) şi poate crea fişiere executabile Win32, fie în mod consolă, fie prin intermediul
unei interfeţe grafice (GUI), şi de asemenea biblioteci statice sau dinamice (DLL-uri).
Cerinţele de sistem recomandate de către autori sunt următoarele: sistem de operare MS-Windows 2000, XP; 32
MB memorie RAM; unitate centrală (compatibilă Intel) la 400 MHz; spaţiu pe disc disponibil 200 MB.
În afara distribuţiei sale gratuite, Dev-C++ are un număr de caracteristici care îl fac extrem de atractiv pentru
utilizare. Fără a intra în detalii, vom remarca în mod special faptul că interfaţa grafică este foarte flexibilă, dar şi
intuitivă şi uşor de folosit şi include toate facilităţile necesare unui mediu de programare evoluat (editare completă,
listare de funcţii, compilare şi rulare, depanare, creare de proiecte, adăugare de biblioteci etc.).
În această lucrare se utilizează mediul Dev-C++ pentru programarea în limbajul C, iar compilarea surselor va
avea ca rezultat obţinerea de fişiere executabile Win32.

1.1. Editarea unui program


Editarea (adică scrierea fişierului sursă al programului) se poate face în mediul Dev-C++ în două moduri. O
modalitate eficientă, recomandată în special atunci când avem mai multe fişiere sursă, este de a crea mai întâi un
Proiect (meniul File, opţiunile New şi apoi Project...); în acest mod se permite adăugarea sau eliminarea
imediată a unor fişiere şi editarea legăturilor după compilarea tuturor fişierelor sursă, ca şi un control al diferiţilor
parametri disponibili în mediul de programare. O a doua modalitate, mai simplă, este de a se crea direct un (singur)
fişier sursă; această metodă va fi descrisă succint şi ilustrată în cele ce urmează.
Presupunând ca suntem deja în interfaţa grafică, se selectează meniul File, iar din New se alege Source
File (sau se foloseşte combinaţia de taste CTRL+N), aşa cum este prezentat în Figura 1.1.
Se va deschide astfel o nouă fereastră (numita iniţial Untitled1) în care se va scrie efectiv programul sursă.
După încheierea editării, fişierul sursă trebuie salvat pe disc. Salvarea se face prin comanda Save As... (sau
Save) din meniul File, aşa cum este ilustrat în Figura 1.2; fişierele se vor salva ca fişiere C (C source), şi vor
avea pe disc extensia „.c”.

Figura 1.1. Deschiderea unui fişier sursă nou


1.2. Compilarea programului
Următoarea etapă ce trebuie parcursă este compilarea programului sursă rezultat după terminarea editării, adică
„traducerea” sa în limbajul calculatorului şi obţinerea unui program obiect, reprezentat în cod maşină sau într-un limbaj
apropiat de acesta. În cazul limbajului C, procesul de compilare şi editare de legături se împarte de fapt între mai multe
programe: preprocesorul, compilatorul propriu-zis, asamblorul şi editorul de legături, rezultând în final un fişier
executabil.

1
Figura 1.2. Salvarea fişierului editat

În mediul Dev-C++ etapele sugerate anterior (practic compilarea şi editarea legăturilor) sunt parcurse automat şi
transparent pentru utilizator prin apelarea opţiunii Compile din meniul Execute, sau folosind combinaţia de taste
Ctrl+F9 (Figura 1.3).

Figura 1.3. Opţiunea de compilare a fişierului sursă

În cazul în care nu există erori, este creat un fişier executabil (având extensia „.exe”) care poate fi rulat, partea
de jos a ferestrei interfeţei grafice arătând, de exemplu, ca în Figura 1.4.

În cazul în care se constată erori la compilare (tipic erori sintactice), lansarea în execuţie nu este posibilă, iar
erorile sunt semnalate în fereastra Compiler (aflată în colţul din stânga jos al interfeţei grafice). Figura 1.5 prezintă o
astfel de situaţie; este vorba de acelaşi exemplu (problema 2.2 din Capitolul 2), în care s-au omis intenţionat ghilimelele
ce încadrează specificatorul de format %d din linia 10.
După ce erorile au fost înlăturate este necesar să se facă o nouă compilare (de remarcat faptul că după fiecare
modificare adusă codului sursă, acesta trebuie recompilat). Când 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 execuţie programul, tipărind eventual mesaje şi rezultate pe ecranul calculatorului.

2
Figura 1.4. Compilarea cu succes a fişierului sursă

Figura 1.5. O situaţie ce conduce la erori de compilare a programului

În această etapă sunt puse în evidenţă erorile la execuţie, cum ar fi împărţirea cu zero, sau sunt puse în evidenţă
erorile de logică dacă rezultatele sunt eronate. Dacă se descoperă astfel de erori, programatorul trebuie să se reîntoarcă
la editarea programului sursă, să-l recompileze şi să-l ruleze din nou.

Pentru ca programul să fie lansat în execuţie automat după compilare se poate folosi comanda Compile &
Run (sau F9) din meniul Execute.

3
2. Programe simple; variabile şi constante,
operaţii de intrare/ieşire formatate
2.1. Probleme rezolvate
P2.1 Scrieţi un program care afişează pe ecran un text dat.

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

int main() {
printf("Acesta este un program C");
printf("\n");
printf("creat\n");
printf("de mine.");
printf("\n");
system("PAUSE");
return 0;
}

Programul va afişa pe ecran, după compilare şi execuţie:


Acesta este un program C
creat
de mine.

Discuţie:
– Comanda #include realizează includerea în fişierul sursă a unui alt fişier (situat într-un director cunoscut de
către compilator), în acest caz a unor fişiere speciale care descriu conţinutul unor biblioteci şi care poartă denumirea de
fişiere header, având extensia „.h”. În exemplul anterior, stdio.h este fişierul care defineşte funcţiile standard de
I/O din biblioteca C (printre acestea numărându-se şi funcţiile printf() şi scanf()), iar stdlib.h este un fişier
ce defineşte un număr de funcţii utilitare din biblioteca standard (cum este şi system()).
– Programul propriu-zis este descris de funcţia main(). Acoladele ‚{‘ şi ‚}’ din interiorul funcţiei marchează
practic începutul şi sfârşitul programului. Instrucţiunile se execută secvenţial; în cazul anterior, succesiunea operaţiilor
corespunde cu cea de scriere a comenzilor, deoarece nu se precizează explicit un salt la o altă instrucţiune.
– Funcţia printf() afişează şirul de caractere inclus între ghilimele. Secvenţa de caractere ‚\n’ determină
trecerea afişării la un rând nou („newline”). Există şi alte secvenţe de caractere care determină deplasarea poziţiei
următoare de afişare.
– Instrucţiunea system("PAUSE") are următorul efect: după afişarea rezultatelor, fereastra de rulare DOS
rămâne deschisă până când se introduce un caracter oarecare de la tastatură, permiţând astfel vizualizarea şi
interpretarea rezultatelor programului (în lipsa unei astfel de comenzi, fereastra se închide automat după rulare).
– Instrucţiunea return utilizată în main() determină întoarcerea unui cod de terminare către 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. Precizăm că toate programele din această lucrare întorc valori din
main(), deşi din punct de vedere tehnic acest lucru este opţional (strict formal, deoarece instrucţiunea return este
plasată pe ultima linie din main(), execuţia programului oricum se încheie).
=============================
P2.2 Scrieţi un program care citeşte 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;
}

4
Dacă se introduc de la tastatură, de exemplu, numerele –7 şi 7, programul va afişa pe ecran, după compilare
şi execuţie:
Introduceti primul numar, a: -7
Introduceti al doilea numar, b: 7
Suma celor doua numere este 0

Discuţie:
– Instrucţiunea 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.
– Funcţia scanf() citeşte 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 afişa pe ecran textul Suma
celor doua numere este urmat de valoarea calculată a lui s.
=============================
P2.3 Scrieţi un program care calculează diferenţa a două numere întregi introduse de la tastatură.

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

int main() {
int a, b;

printf("Introduceti doua numere intregi: ");


scanf("%d %d", &a, &b);
printf("%d - %d = %d", a, b, a - b);
printf("\n");
system("PAUSE");
return 0;
}

Dacă se introduc de la tastatură, de exemplu, numerele 7 şi 9, programul va afişa pe ecran, după compilare
şi execuţie:
Introduceti doua numere intregi: 7 9
7 - 9 = -2

Discuţie:
– Instrucţiunea 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ă spaţiul dintre cele
două grupe de caractere „%d” din "%d %d" spune funcţiei scanf() că cele două numere introduse de la
tastatură pot fi separate de spaţii.
– Este absolut corectă utilizarea unor expresii (cum este „a - b”) în lista de parametri a funcţiei
printf(); ele vor fi evaluate înainte de apelul funcţiei. Această variantă este chiar mai eficientă decât utilizarea unei
variabile suplimentare, sa spunem c, căreia să i se atribuie valoarea „a - b” (această metodă a fost folosită în
problema 2.2), deoarece reduce spaţiul de memorie necesar programului.
=============================
P2.4 Scrieţi un program care calculează aria unui cerc de rază dată; valoarea razei se va citi de la tastatură şi va fi
un număr î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;
}
5
Dacă se introduce de la tastatură, de exemplu, valoarea 3, programul va afişa:
Introduceti raza: 3
Aria cercului de raza 3 este 28.260000

Discuţie:
– Se declară variabila raza de tip întreg. Deoarece suprafaţa unui cerc nu este neapărat un număr întreg,
variabila aria în care este calculată va fi declarată de tip real (deci se va utiliza tipul float).
– Variabila reală pi se iniţializează cu valoarea 3.14. Deoarece această variabilă nu este de fapt asociată decât
valorii constante 3.14, acelaşi efect putea fi obţinut utilizând 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, instrucţiunea float aria, pi=3.14; din programul anterior se putea înlocui cu:
float aria;
const float pi = 3.14;

– Comentariile se pot introduce oriunde în program.


=============================
P2.5 Scrieţi un program care transformă temperatura exprimată în grade Fahrenheit în grade Celsius. Se va utiliza
formula: C = (F–32)*5/9 , unde C – grade Celsius (număr real), F – grade Fahrenheit (număr întreg).
#include <stdio.h>
#include <stdlib.h>
int main() {
int gradf;
float gradc;

printf("Introduceti temperatura in grade Fahrenheit: ");


scanf("%d", &gradf);
gradc = (gradf - 32) * 5.0 / 9.0;
printf("Temperatura in grade Celsius este %f", gradc);
printf("\n");
system("PAUSE");
return 0;
}

Dacă se introduce de la tastatură, de exemplu, valoarea 100, programul va afişa:


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

Discuţie:
– După cum s-a cerut în enunţul 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”; deşi asupra
acestui lucru vom reveni în capitolul următor, vom spune deocamdată doar faptul că rezultatul împărţirii 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 Scrieţi un program care transformă măsura unui unghi din grade (număr întreg) în radiani (număr real).
Se va utiliza relaţia 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;
}

6
Dacă se introduce de la tastatură, de exemplu, valoarea 360, programul va afişa:
Introduceti unghiul in grade: 360
Masura unghiului este de 6.28 radiani

Discuţie:
– După cum s-a arătat la partea teoretică, ca specificator de format pentru numere întregi zecimale poate fi
utilizat atât „%d” cât ş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 tipări valoarea. Astfel, în exemplul anterior, „%4.2f” utilizat la a
doua funcţie printf() are următoare semnificaţie: se va tipări un număr real în format zecimal utilizând în total 4
caractere (incluzând punctul zecimal), cu 2 cifre la partea fracţionară.
=============================

2.2. Probleme propuse


1. Scrieţi un program care să vă afişeze numele pe ecran, ca şi seria şi grupa, pe două rânduri succesive.

2. Se citeşte un întreg . Scrieţi un program care să afişeze: „Aţi introdus numărul ...”.

3. Scrieţi un program care citeşte doi întregi şi calculează produsul lor.

4. Scrieţi un program care calculează lungimea unui cerc de rază dată; valoarea razei se va citi de la tastatură şi va fi
un număr întreg.

5. Scrieţi un program care transformă temperatura exprimată în grade Celsius în grade Fahrenheit.

6. Scrieţi un program care transformă măsura unui unghi din radiani în grade.

7. Scrieţi programe care calculează arii pentru pătrat, dreptunghi, triunghi.

8. Scrieţi programe care calculează volume pentru cub, paralelipiped, piramidă.

7
3. Tipuri fundamentale de date, operatori şi expresii
3.1. Probleme rezolvate
P3.1 Următorul program ilustrează utilizarea tipurilor fundamentale de date în C.

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

int main() {
long int i = 66000;
unsigned short int u;
double x, y;
char b_mic, b_mare, ch;

u = 66000;
printf("%ld\t%hu\n\n", i, u);

x = 12.3468, y = 11.2e-2;
printf("x = %f sau %6.3f sau %e\n", x, x, x);
printf("y = %f sau %8.4f sau %E\n\n", y, y, y);

b_mic = 'b', b_mare = 'B', ch = 'm';


printf("Codurile ASCII pentru 'b' si 'B' sunt: %d, %d\n", b_mic, b_mare);
printf("Dupa '%c' urmeaza '%c'\n", b_mic, b_mic + 1);
printf("Majuscula corespunzatoare lui '%c' este '%c'", ch, ch - 'a' + 'A');
printf("\n");
system("PAUSE");
return 0;
}

Programul va afişa pe ecran, după compilare şi execuţie:


66000 464

x = 12.346800 sau 12.347 sau 1.234680e+001


y = 0.112000 sau 0.1120 sau 1.120000E-001

Codurile ASCII pentru 'b' si 'B' sunt: 98, 66


Dupa 'b' urmeaza 'c'
Majuscula corespunzatoate lui 'm' este 'M'

Discuţie:
– Programul are, aşa cum se observă, trei părţi complet distincte. În prima parte se dau două exemple de folosire
a numerelor întregi. Programul va afişa corect numărul 66000 declarat long int (de fapt, s-ar fi afişat corect şi
dacă ar fi fost declarat int, deoarece pe majoritatea calculatoarelor curente reprezentarea internă a lui int este pe
32 de biţi), însă nu afişează corect acelaşi număr declarat unsigned short int. Numerele de tipul unsigned
short int sunt întotdeauna reprezentate pe 16 biţi, gama lor fiind între 0 şi 216–1=65535; de altfel, compilatorul
semnalizează acest lucru printr-un mesaj de atenţionare (fereastra Compiler). Specificatorii de format „%ld” şi
„%hu” permit afişarea numerelor întregi zecimale de tipurile long int şi respectiv unsigned short int.
– Partea a doua ilustrează câteva modalităţi de afişare a numerelor reale. Variabilele x şi y se declară de
tipul double şi se iniţializează cu două valori concrete. În principiu, specificatorul de format „%f” poate fi folosit cu
oricare din tipurile float sau double şi afişarea se face uzual cu 6 cifre la partea fracţionară. Utilizarea
specificatorului „%e” sau „%E” conduce la afişarea numărului real în formatul ştiinţific; formatul „%6.3f” va duce la
afişarea lui x cu 6 caractere în total (5 cifre plus punctul zecimal) şi 3 cifre precizie pentru partea fracţionară (ca
atare, numărul 12.3468 se va rotunji la 12.347); în sfârşit, formatul „%8.4f” va duce la afişarea lui y sub
forma „ 0.1120” (deoarece lăţimea câmpului de afişare specificată prin format este 8, cu două unităţi mai mare
decât este necesar, afişarea se completează cu două spaţii libere la stânga numărului).
– În partea a treia a programului se exemplifică utilizarea şi afişarea 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 afişează ca
numere întregi dacă se foloseşte specificatorul de format ‚%d’, sau sunt reconvertite în caracterele corespunzătoare dacă
este folosit specificatorul ‚%c’. Această idee este reluată şi în problema următoare.
=============================

8
P3.2 Scrieţi un program care afişează codul ASCII al unui caracter citit de la tastatură.

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

int main() {
char ch;

printf ("Introduceti un caracter: ");


ch = getch();
printf("\nCaracterul %c are codul ASCII %3d", ch, ch);
printf("\n");
system("PAUSE");
return 0;
}

Dacă se introduce de la tastatură, de exemplu, caracterul ‚c’, programul va afişa:


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

Discuţie:
– Se declară variabila ch de tip caracter. Funcţia getch() citeşte un caracter de la tastatură, adică aşteaptă
până când este apăsată o tastă şi apoi întoarce codul său ASCII. Este o variantă a funcţiei de I/O getche(), dar spre
deosebire de aceasta din urmă, nu afişează automat pe ecran caracterul introdus de la tastatură (se mai spune că „nu are
ecou pe ecran”). Precizăm că funcţiile getch() şi getche() nu sunt funcţii ANSI. Bibliotecile standard ANSI
pun la dispoziţia utilizatorului doar funcţiile getc() şi getchar() care însă citesc primul caracter introdus şi
aşteaptă validarea scrierii de către utilizator prin tasta <Enter>. Caracterele necitite, inclusiv <Enter>, rămân în
buffer şi vor fi citite de următoarele apeluri la getc() sau getchar(). Recomandăm folosirea funcţiilor getch()
şi getche() care sunt mai flexibile.
– Specificatorul de format „%3d” defineşte dimensiunea minimă a câmpului în care se va afişa numărul întreg
(3 în cazul de faţă); deoarece codul ASCII al lui ‚c’ este 99 (pentru exemplul considerat anterior), deci necesită două
cifre, se va tipări un spaţiu suplimentar la stânga sa. De notat că dacă se indică o lăţime de câmp mai mică decât este
necesar, compilatorul va aloca totuşi lăţimea necesară (doar numărul de zecimale precizat prin format va fi respectat
întocmai).
=============================
P3.3 Scrieţi un program care adună şi înmulţeşte două numere complexe exprimate sub forma z1 = a + bi , z2 = c
+ d i (se citesc efectiv a, b, c, d – numere reale).
Indicaţie: (a + bi) + (c + d i) = (a + c) + (b + d)i
(a + bi)(c + d i) = (ac – bd) + (ad + bc)i
#include <stdio.h>
#include <stdlib.h>

int main() {
float a, b, c, d;

printf("Introduceti z1: ");


scanf("%f %f", &a, &b);
printf("Ati introdus z1 = %f + %fi", a, b);
printf("\nIntroduceti z2: ");
scanf("%f %f", &c, &d);
printf("Ati introdus z2 = %f + %fi", c, d);
printf("\nz1 + z2 = %f + %fi", a + c, b + d);
printf("\nz1 * z2 = %f + %fi ", a * c – b * d, a * d + b * c);
printf("\n");
system("PAUSE");
return 0;
}

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

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

9
P3.4 Următorul program ilustrează utilizarea operatorilor de împărţire (/) şi modulo (%).

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

int main() {
int i = 7, j = 4, k, l;
float f = 7.0, g = 4.0, h;

k = i / j;
h = i / j;
printf("7 / 4 = %d sau %f", k, h); /* rezultate incorecte */
h = f / g;
printf("\n7.0 / 4.0 = %f\n", h); /* rezultat corect */
l = i % j;
printf("Restul impartirii lui 7 la 4 este %d", l);
printf("\n");
system("PAUSE");
return 0;
}
Programul va afişa pe ecran, după compilare şi execuţie:
7 / 4 = 1 sau 1.000000
7.0 / 4.0 = 1.750000
Restul impartirii lui 7 la 4 este 3
=============================
P3.5 Următorul program ilustrează utilizarea operatorilor de incrementare şi decrementare.

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

int main() {
int x, y = 10, z;

x = ++y; /* secventa echivalenta cu: y++; x = y; */


printf("x = %d, y = %d\n", x, y);

y = 10;
z = --y + 5; /* secventa echivalenta cu: y--; z = y+5; */
printf("z = %d, y = %d\n", z, y);

y = 10;
x = y++; /* secventa echivalenta cu: x = y; y++; */
printf("x = %d, y = %d\n", x, y);

y = 10;
z = 3 * y--; /* secventa echivalenta cu: z = 3 * y; y--; */
printf("z = %d, y = %d", z, y);
printf("\n");
system("PAUSE");
return 0;
}

Programul va afişa pe ecran, după compilare şi execuţie:


x = 11, y = 11
z = 14, y = 9
x = 10, y = 11
z = 30, y = 9
=============================
P3.6 Următorul program ilustrează utilizarea operatorilor relaţionali ş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 afişa pe ecran, după compilare şi execuţie:
j = 1, k = 0
m = 1
n = 1

b = 7
b = 0, c = 8
b = 1
e = 0

Discuţie:
– Secţiunea 1: expresia i > 5 este evaluată „adevărat” (10 > 5), deci va primi valoarea ‚1’, apoi j = 1;
expresia i >= 50 este evaluată „fals”, deci va primi valoarea ‚0’, apoi k = 0.
– Secţiunea 2: se execută mai întâi parantezele; 0 && 1 = 0, apoi 0 || 1 = 1; în final m = 1.
– Secţiunea 3: ordinea de evaluare este următoarea:
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
– Secţiunea 4: operatorii ‚=’ şi „+=” au aceeaşi prioritate şi asociativitate de la dreapta spre stânga; prin
urmare, ordinea de evaluare este următoarea:
1. d += 2 ≡ d = d + 2 = 7
2. b = 7
– Secţiunea 5: ordinea de evaluare este următoarea:
1. c > 7 = 0
2. b = 0
3. c++ = 8
– Secţiunea 6: „==” are prioritate mai mare decât „&&”; ordinea de evaluare este următoarea:
1. a == 0 = 1
2. 1 && c = 1
3. b = 1
– Secţiunea 7: ordinea de evaluare este următoarea:
1. !a = 1
2. 1 > c = 0 , 0 >= 2 = 0
3. e = 0
=============================

11
P3.7 Următorul program ilustrează conversiile implicite de tip în expresii şi atribuiri, ca şi utilizarea operatorului
cast.

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

int main() {
/* Sectiunea 1 */
int a = 10, b = 3;
float c = 10.0, d;
int u, x, y;
unsigned char ch_1, ch_2;
double v;
int i, j;
float k, l, m, n, p;

d = c / (a / b);
printf("d = %f\n\n", d);

/* Sectiunea 2 */
u, x = 230, y = 260;
v = 10.333;
u = v;
ch_1 = x;
ch_2 = y;
printf("u = %d ch_1 = %d ch_2 = %d\n\n", u, ch_1, ch_2);

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

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

Programul va afişa pe ecran, după compilare şi execuţie:


d = 3.333333

u = 10 ch_1 = 230 ch_2 = 4

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

Discuţie:
– Secţiunea 1: se evaluează mai întâi paranteza; împărţirea 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 operaţie după
operaţie).
– Secţiunea 2: u primeşte valoarea întreagă a lui v; ch_1 este afişat corect, deoarece numărul întreg 230
intră în gama de reprezentare a tipului unsigned char, adică [0, 255], în schimb ch_2 nu este afişat corect,
producându-se o pierdere de informaţie (numai cei 8 biţi inferiori ai lui y sunt copiaţi în ch_2).
Observaţie: putem deduce simplu valoarea ce va fi afişată pe ecran în acest ultim caz; numărul întreg 260
exprimat în binar este 100000100, iar ultimii 8 biţi codifică practic numărul întreg 4 (numărul 4 reprezentat în binar este
100).
– Secţiunea 3: alături de lucrurile discutate deja până în acest moment, mai facem doar o precizare: teoretic, este
suficient sa forţăm tipul unuia dintre cei doi operanzi ce realizează o operaţie, deoarece cel de-al doilea operand va fi
adus automat la tipul celui dintâi.
=============================

12
3.2. Probleme propuse
1. Scrieţi un program care calculează şi afişează pe ecran media aritmetică a două numere întregi citite de la tastatură.
Propuneţi mai multe variante de a rezolva corect problema, ţinând cont de faptul că media trebuie să fie un număr
real.

2. Scrieţi un program care citeşte pe n întreg şi afişează valoarea expresiei n/(n+1) cu patru zecimale.

3. Deduceţi ce afişează următorul 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 următorul program?

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

int main() {
int x;

(float)x = 10.22;
printf("x = %f\n");
system("PAUSE");
return 0;
}

13
4. Instrucţiuni condiţionale
4.1. Probleme rezolvate
P4.1 Următorul program simplu determină dacă un număr î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 Următorul program simplu citeşte 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 Următorul program ilustrează valorile logice „adevărat” ş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 Scrieţi un program care calculează şi afişează rădăcinile ecuaţiei de gradul doi cu coeficienţi reali
a x 2 + bx + c = 0 (coeficienţii fiind citiţi 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 Următorul program simplu ilustrează funcţionarea instrucţiunilor 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 Scrieţi un program care să determine dacă trei numere întregi introduse de la tastatură pot constitui o dată
calendaristică (nu se iau în consideraţie anii bisecţi 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 Scrieţi un program care să calculeze şi să afişeze minimul dintre două numere reale citite de la tastatură, şi
respectiv maximul dintre valorile absolute a două numere întregi, folosind operatorul condiţional.

#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 Următorul program ilustrează funcţionarea structurii de selecţie. Se citesc două numere întregi a şi b şi o
operaţie între ele (+, –, *, sau /) şi se va afişa rezultatul operaţiei.
#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 Scrieţi un program care să calculeze şi să afişeze aria sau lungimea unui cerc de rază dată (număr întreg, citit
de la tastatură), în funcţie de opţiunea 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;
}

Discuţie:
– Secţiunile structurii de selecţie pot fi plasate în orice ordine; de exemplu, aşezarea lui default la
începutul structurii, ca în exemplul anterior, nu afectează în nici un fel funcţionarea programului.
– Aşa cum se cunoaşte, instrucţiunile asociate unui case pot lipsi complet; aceasta permite, de exemplu, ca
două sau mai multe case să execute aceleaşi instrucţiuni fără să fie nevoie de repetarea lor
– Secvenţa din program realizată cu switch se putea scrie şi folosind instrucţiuni 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. Probleme propuse


1. Ce este incorect la următorul program? Ce va afişa programul dacă după compilare şi execuţie se introduce de la
tastatură numărul –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. Scrieţi un program care calculează şi afişează rădăcina ecuaţiei de gradul întâi cu coeficienţi reali a x + b = 0
(coeficienţii fiind citiţi de la tastatură); discuţie.
Indicaţie: ecuaţia are soluţie dacă a ≠ 0 ; dacă a = 0 : dacă b = 0 ecuaţia este nedeterminată, iar dacă b ≠ 0
ecuaţia nu are soluţie.

3. Folosind instrucţiuni de decizie, scrieţi un program care citeşte de la tastatură un număr întreg x şi afişează o
valoare y calculată astfel:
 − x + 3 , pentru x < 0

y =  3 , pentru x ∈ [0, 4]
3x − 9 , pentru x > 4

4. Scrieţi un program care citeşte două numere întregi de la tastatură, împarte cele două numere şi afişează rezultatul.
Cum numitorul trebuie să fie diferit de zero, discutaţi această situaţie în două moduri: folosind o decizie if ...
else şi respectiv operatorul condiţional.

5. Scrieţi un program care să calculeze şi să afişeze maximul şi minimul dintre trei numere întregi citite de la
tastatură, utilizând operatorul condiţional.

6. Scrieţi un program care citeşte de la tastatură un număr întreg între 1 şi 7 şi afişează denumirea zilei din săptămână
corespunzătoare cifrei respective: 1 – luni, 2 – marţi etc. Programul va semnaliza printr-un mesaj de eroare dacă
numărul introdus nu a fost în intervalul solicitat.
Indicaţie: se va folosi o instrucţiune switch.

18
5. Cicluri
5.1. Probleme rezolvate
P5.1 Următorul program simplu ilustrează utilizarea ciclului cu test iniţial: se introduc continuu caractere de la
tastatură, până când este tastată litera ‚q’.
#include <stdio.h>
#include <stdlib.h>

int main() {
char ch;

printf("Introduceti un caracter ('q' pentru terminare): ");


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

printf("\n\nAti introdus q!");


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

Discuţie:
– Accentuăm faptul că în C, ciclurile acceptă pentru testarea condiţiei orice fel de expresii. Mai mult, se pot
realiza operaţii complexe în expresia ce semnifică testul de condiţie; astfel, partea de program următoare:
ch = getch();
while(ch != 'q') {
printf("\nAti introdus %c ", ch);
ch = getch();
}

se poate scrie mai simplu astfel:


while((ch = getch()) != 'q') {
printf("\nAti introdus %c ", ch);
}
=============================
P5.2 Următorul program simplu ilustrează utilizarea ciclului cu test final: se afişează pătratele numerelor întregi
cuprinse între a şi 2a, unde a este un întreg pozitiv care se citeşte de la tastatură.
#include <stdio.h>
#include <stdlib.h>

int main() {
int a, b;

printf("Introduceti un numar intreg pozitiv (<100): ");


scanf("%d", &a);
b = 2 * a;
printf("start\n");

do {
printf("%d * %d = %d\n", a, a, a * a);
a++;
} while(a <= b);

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

Dacă se introduce de la tastatură, de exemplu, numărul 4, programul va afişa:


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
Discuţie:
– Cu aceeaşi observaţie ca cea făcută 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 evaluării expresiei):

do {
printf("%d*%d = %d\n", a, a, a * a);
} while(++a <= b);
=============================
P5.3 Următorul program simplu ilustrează forma de bază a ciclului cu contor: se citeşte un număr natural n ≥ 2
şi se afişează suma 1 + 2 + ... + n .

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

Discuţie:
– O variantă a programului anterior, utilizând un ciclu cu test iniţial, este următoarea:
#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 afişează următorul program după compilare şi execuţie, ca şi particularităţile ciclului for
utilizat. Ce se întâmplă dacă se introduce de la tastatură un număr întreg negativ? Dar dacă se introduce un
număr natural impar?
#include <stdio.h>
#include <stdlib.h>

int main() {
int i, j;

printf("Introduceti un numar natural par: "); scanf("%d", &i);


for( ; i; i -= 2) {
j = i * i * i;
printf("%d %d\n", i, j);
}
system("PAUSE");
return 0;
}

20
Dacă se introduce de la tastatură, de exemplu, numărul 8, programul va afişa:
Introduceti un numar natural par: 8
8 512
6 216
4 64
2 8

Discuţie:
– Programul numără descrescător, din doi în doi, de la valoarea introdusă de utilizator şi până la 2, apoi afişează
aceste numere, împreună cu cuburile acestora, pe rânduri succesive.
– Sunt ilustrate o serie de variaţii în modul de utilizare ale ciclului cu contor în C:
• secţiunea iniţializare a ciclului lipseşte, deoarece contorul i este iniţializat practic de către utilizator în
afara ciclului (atenţie însă că semnul ‚;’ trebuie să fie prezent!);
• testul de condiţie are următoarea semnificaţie: ciclul se reia atât timp cât i este „adevărat”, 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, aşa cum s-a specificat şi la partea teoretică, deoarece valoarea contorului nu este modificată de operaţiile din
cadrul ciclului).
– Dacă numărul introdus de la tastatură este negativ, sau pozitiv impar, ciclul se repetă la infinit (justificaţi
această afirmaţie!).
=============================

P5.5 Scrieţi un program care citeşte de la tastatură două numere naturale a şi b, cu a < b , afişează numerele
naturale din intervalul [a, b] în ordine crescătoare şi apoi descrescătoare, şi de asemenea calculează şi
afişează media aritmetică a numerelor a şi b.
#include <stdio.h>
#include <stdlib.h>

int main() {
int a, b, i, s = 0;

printf("Introduceti a (natural): ");


scanf("%d", &a);
printf("Introduceti b (natural, b>a): ");
scanf("%d", &b);

printf("\nNumerele dintre a si b in ordine crescatoare:\n");


i = a;
while(i <= b) {
printf ("%d ", i);
i++;
}
printf("\n");

printf(
"Numerele dintre a si b in ordine descrescatoare:\n");
i--; /* dupa ultima iteratie a ciclului
anterior, i = b + 1! */
do {
printf("%d ", i);
i--;
} while (i >= a);

printf("\n");
printf("Media aritmetica a numerelor dintre a si b: ");
for (i = a; i <= b; i++) s = s + i;
printf("%.3f",(float)s / (b – a + 1));
printf("\n");
system("PAUSE");
return 0;
}

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

21
P5.6 Scrieţi un program care citeşte de la tastatură un număr întreg n din intervalul [0, 100] , calculează şi
afişează pe n!
#include <stdio.h>
#include <stdlib.h>

int main() {
int n, i;
double fact;
/* variabila fact = n! este declarata 'double' deoarece
poate avea valori care sa nu poata fi reprezentate nici
cu 4 octeti! */

printf("Introduceti un numar intreg intre 0 si 100: ");


scanf("%d", &n);
while(n < 0 || n > 100) {
printf("Numarul introdus nu apartine intervalului!");
printf("\nIntroduceti din nou numarul: ");
scanf("%d", &n);
}
if(n > 0) {
for(fact = 1.0, i = 2; i <= n; i++) {
fact = fact * i;
/* sectiunea initializare cuprinde doua expresii
separate de operatorul ','! */
}
}
else {
fact = 1;
/* pentru cazul n = 0 se foloseste definitia
standard 0! = 1 */
}
printf("Pentru n = %d, n! = %g\n", n, fact);
/* specificatorul de format '%g' asigura tiparirea in
formatul e sau f, care dintre ele este mai compact */
system("PAUSE");
return 0;
}
=============================
P5.7 Scrieţi un program care afişează toţi divizorii unui număr natural n citit de la tastatură; dacă numărul este
prim, se va afişa acest lucru printr-un mesaj.
#include <stdio.h>
#include <stdlib.h>

int main() {
int n, i, k;

printf("Introduceti un numar natural: ");


scanf("%d", &n);
k = 0;
for(i = 2; i <= n / 2; i++) {
if(n % i == 0) {
printf("%d ", i);
k = 1;
}
}
if(k == 1) printf("sunt divizorii lui %d", n);
else printf("Numarul %d este prim!", n);
printf("\n");
system("PAUSE");
return 0;
}

Dacă se introduce de la tastatură, de exemplu, numărul 36, programul va afişa:


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

22
Discuţie:
– Programul foloseşte un ciclu cu contor pentru a căuta divizorii; se parcurge intervalul [2, n / 2] ,
incrementând unitar contorul i şi se caută numerele la care n se împarte exact (n%i==0). Variabila auxiliară k,
iniţializată cu 0, devine 1 dacă s-a găsit cel puţin un divizor.
– Justificaţi condiţia de terminare a ciclului i<=n/2; este testul de condiţie formulat corect indiferent dacă n
este par sau impar?
=============================
P5.8 Scrieţi un program care citeşte de la tastatură două numere naturale a şi b ( a < b ) şi afişează toate
numerele prime din intervalul [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
afişa în cele două situaţii:
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!

Discuţie:
– Problema este ceva mai complicată decât cea anterioară, în special dacă se doreşte tratarea tuturor cazurilor
posibile. Primul ciclu for foloseşte contorul i pentru a parcurge întreg intervalul [a, b] ; se presupune mai întâi
că fiecare număr i din interval este prim şi se iniţializează 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 găseşte un divizor, k va lua valoarea 1. Dacă după parcurgerea întregului ciclu interior k
rămâne 0, înseamnă că i este prim, se afişează, şi ciclul exterior continuă cu următoarea valoare a lui i.
Variabila auxiliară m foloseşte în acest program pentru a se putea trata şi cazul special în care în intervalul
[a, b] nu există numere prime; m se iniţializează cu 0 înainte de primul ciclu, şi devine 1 dacă a fost găsit cel puţin
un număr prim (care s-a afişat).
=============================

23
P5.9 Următorul program ilustrează folosirea instrucţiunilor break şi continue: se afişează numerele
impare dintre 1 şi un număr natural ales de utilizator; trebuie să se permită reluarea exerciţiului (fără ieşirea
din program), dacă utilizatorul doreşte acest lucru, iar dacă valoarea introdusă este ≤ 0 , programul va tipări
un mesaj de eroare şi va fi abandonat.
#include <stdio.h>
#include <stdlib.h>

int main() {
int n, i, k;
char ch;

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

5.2. Probleme propuse


1. Scrieţi un program care citeşte pe n natural şi afişează valoarea expresiei:
1 1 1
s= + + … + .
1+1 1+ 2 1+ n
2. Scrieţi un program care citeşte pe n natural şi afişează valoarea expresiei:
s = 0! + 1! + 2! + … + n !
3. Scrieţi un program care afişează numerele dintr-un interval [a, b] ce se divid cu un număr natural k citit.
4. Scrieţi un program care afişează numerele prime mai mici decât un număr natural k citit.
5. Scrieţi un program care să descompună în factori primi un număr natural n citit.
6. Reluaţi problema 5.9, cu următoarea modificare: se vor afişa numerele divizibile cu 3 dintre 1 şi un număr natural
n citit.
7. Este corect următorul fragment de program? Ce funcţie 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
P6.1 Scrieţi un program care citeşte de la tastatură un vector de maxim 10 elemente întregi împreună cu
dimensiunea sa efectivă şi apoi afişează elementele sale.
Precizare: Întrucât la rularea programului nu este cunoscut de la început numărul de elemente (el este mai
mic decât 10) se va opta pentru citirea, la început, a numărului de elemente.

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

int main() {
int v[10], n, i;

printf("Introduceti nr. de elemente: ");


scanf("%d", &n);

for(i = 0; i < n; i++) {


printf("v[%d] = ", i);
scanf("%d", &v[i]);
}

printf("Valorile citite sunt:\n");


for(i = 0; i < n; i++)
printf("v[%d] = %d\n", i, v[i]);

system("PAUSE");
return 0;
}

Programul va afişa pe ecran după compilare şi execuţie:


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

Discuţie:
– Primul ciclu for citeşte elementele vectorului.
– Cel de al doilea ciclu for afişează valorile citite şi memorate.
=============================
P6.2 Scrieţi un program citeşte un vector de elemente întregi, împreună cu dimensiunea sa efectivă, afişează î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 afişa pe ecran după compilare şi execuţie:


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

Discuţie:
– După citire numărului de elemente, n, primul ciclu for citeşte elementele vectorului.
– Al doilea ciclu for parcurge vectorul de la ultimul (i ia valoarea n - 1) până la primul său element (i >= 0)
prin decrementarea (i--) contorului.
– Variabila s (ce va conţine suma tuturor elementelor vectorului) se iniţializează 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 afişată. De remarcat conversia de tip (float)s / n.
=============================

P 6.3 Scrieţi un program care citeşte un vector de elemente întregi, împreună cu dimensiunea sa efectivă, şi
determină maximul şi minimul dintre elementele acestui vector.

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

int main() {
int v[20], n, i, max, min;

printf("Introduceti numarul de elemente din vector: ");


scanf("%d", &n);

for(i = 0; i < n; i++) {


printf("v[%d] = ", i);
scanf("%d", &v[i]);
}

min = max = v[0];

for(i = 1; i < n; i++) {


if(v[i] >= max)
max = v[i];
if(v[i] <= min)
min = v[i];
}

printf("max = %d\tmin = %d\n", max, min);

system("PAUSE");
return 0;
}

Programul va afişa pe ecran după compilare şi execuţie:


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

26
Discuţie:
– După citire numărului de elemente, n, primul ciclu for citeşte elementele vectorului.
– Variabilele min şi max sunt iniţializate cu valoarea primului element din vector, v[0]. Algoritmul parcurge
vectorul şi testează la fiecare pas al ciclului for pentru fiecare element v[i], relaţia sa de inegalitate în raport cu
min respectiv max. În primul caz, dacă v[i] este mai mare decât 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 decât
min atunci elementul v[i] reprezintă un minim local şi deci valoarea lui v[i] i se atribuie variabilei min. La
sfârşitul ciclului for, variabilele min şi max conţin valorile minimă respectiv maximă din vectorul v.
=============================
P6.4 Scrieţi un program care citeşte un vector de elemente întregi, împreună cu dimensiunea sa efectivă,
ordonează crescător elementele vectorului şi apoi afişează vectorul ordonat. Se va utiliza metoda de ordonare
(se utilizează şi termenul sortare) denumită, în limba engleză, „bubble-sort”.

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

int main() {
int v[20], n, i, ind, tmp;

printf("Introduceti numarul de elemente din vector: ");


scanf("%d", &n);

for(i = 0; i < n; i++) {


printf("v[%d] = ", i);
scanf("%d", &v[i]);
}

do {
ind = 0;
for(i = 0; i < n - 1; i++) {
if(v[i] > v[i+1]) {
tmp = v[i];
v[i] = v[i+1];
v[i+1] = tmp;
ind = 1;
}
}
} while(ind);

for(i = 0; i < n; i++)


printf("v[%d] = %d\n", i, v[i]);
system("PAUSE");
return 0;
}

Programul va afişa pe ecran după compilare şi execuţie:


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

Discuţie:
– Primul ciclu for citeşte elementele vectorului. Anterior acesteia a fost citit numărul de elemente ale
vectorului, n.
– Programul utilizează o variabila ind, cu rol de indicator. Aceasta variabila se iniţializează cu valoarea 0
înaintea unui ciclu care compară perechile succesive de elemente ale vectorului, elementul curent şi următorul. Pentru
parcurgerea vectorului se foloseşte un ciclu for care evoluează de la 0 până la penultimul element (ultima comparaţie
se face între penultimul şi ultimul element). Dacă o pereche de elemente succesive este în ordinea dorită se trece la
compararea următoarei 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 până când toate elementele sunt în ordinea dorită,
respectiv până când ind îşi păstrează valoarea 0 după parcurgerea întregului vector. Aceasta este metoda de
ordonare / sortare „bubble-sort”.
– Pentru interschimbarea elementelor care nu se află în ordinea dorită se utilizează variabila temporară tmp.
=============================

27
P6.5 Scrieţi un program care citeşte o matrice de maxim 10 × 10 elemente întregi, împreună cu dimensiunile sale
efective (linii respectiv coloane) şi afişează atât matricea iniţială cât şi matricea având coloanele pare
interschimbate cu coloanele impare (interschimbarea afectează coloanele alăturate, 0-1, 2-3 etc.).

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

int main() {
int A[10][10], m, n, i, j, tmp;

printf("Introduceti nr. de linii: ");


scanf("%d", &m);
printf("Introduceti nr. de coloane: ");
scanf("%d", &n);

for(i = 0; i < m; i++)


for(j = 0; j < n; j++) {
printf("A[%d][%d] = ", i, j);
scanf("%d", &A[i][j]);
}

printf("\nMatricea citita este:\n");


for(i = 0; i < m; i++) {
for(j = 0; j < n; j++)
printf("%d\t", A[i][j]);
printf("\n");
}

for(j = 0; j < (n / 2) * 2; j += 2)
for(i = 0; i < m; i++) {
tmp = A[i][j];
A[i][j] = A[i][j+1];
A[i][j+1] = tmp;
}

printf("\nMatricea avand coloanele interschimbate este:\n");


for(i = 0; i < m; i++) {
for(j = 0; j < n; j++)
printf("%d\t",A[i][j]);
printf("\n");
}

system("PAUSE");
return 0;
}

Programul va afişa pe ecran după compilare şi execuţie:


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] = 6
A[1][1] = 7
A[1][2] = 8
A[1][3] = 9
A[1][4] = 10
A[2][0] = 11
A[2][1] = 12
A[2][2] = 13
A[2][3] = 14
A[2][4] = 15

Matricea citita este:


1 2 3 4 5
6 7 8 9 10
11 12 13 14 15

Matricea avand coloanele interschimbate este:


2 1 4 3 5
7 6 9 8 10
12 11 14 13 15

Discuţie:
– Atenţie: dacă textul problemei nu specifică în mod explicit că avem de a face cu o matrice pătrată, matricea
prelucrată poate avea numărul 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, utilizând şi parcurgerea pe coloane şi apoi pe linii ca în Figura 6.b.

A[0][0] A[0][1] A[0][0] A[0][1]

A[1][0] A[1][1] A[1][0] A[1][1]


(6.a) (6.b)

– Interschimbarea coloanelor pare cu cele impare se face utilizând a doua modalitate de parcurgere a matricei.
Cu excepţia cazului când n este impar, toate coloanele j se interschimbă cu coloanele j+1 utilizând o variabilă
temporară tmp pentru fiecare element A[i][j].
=============================
P6.6 Scrieţi un program care citeşte de la tastatură o matrice pătrată de dimensiune maximă 10 × 10 elemente
reale împreună cu dimensiunea sa efectivă şi determină şi afişează 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 afişa pe ecran, după compilare şi execuţie:


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

Matricea introdusa este:

1.000 2.000 3.000 4.000


5.000 6.000 7.000 8.000
9.000 10.000 11.000 12.000
13.000 14.000 15.000 16.000

Suma elementelor de pe diagonala principala este 34.000

Suma elementelor de pe diagonala secundara este 34.000

Discuţie:
– Mai întâi se citeşte dimensiunea efectivă a matricei şi apoi elementele sale. Programul nu verifică faptul că
dimensiunea nu depăşeşte dimensiunea maximă. Recomandăm ca citirea dimensiunii să se facă astfel:

do {
printf("Introduceti dimensiunea matricei patrate: ");
scanf("%d", &dim);
} while(dim < 1 || dim > 10);

– Apoi se afişează matricea citită pentru a verifica datele introduse.


– Se calculează şi se afişează suma elementelor de pe diagonala principală. Aceste elemente au acelaşi indice
pentru linii şi coloane.
– Se calculează şi se afişează suma elementelor de pe diagonala secundară. Aceste elemente au indicele coloanei
egal cu „dimensiunea – indicele rândului – 1”. În expresia anterioară trebuie să scădem 1 pentru că în C numărătoarea
începe de la 0!
=============================
P6.7 Scrieţi un program care citeşte două şiruri de maximum 100 de caractere de la tastatură, concatenează al
doilea şir de caractere la primul şi afişează 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

Discuţie:
– Cele două şiruri de caractere, s1 şi s2, sunt citite cu ajutorul funcţiei scanf().
– Primul ciclu while parcurge sir1 până la capăt prin detectarea condiţiei 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. Cât timp rezultatul atribuirii s1[i] = s2[j] nu
este NULL, adică sir2 nu s-a terminat, se incrementează i, apoi se incrementează j. Corpul instrucţiunii while
conţine o instrucţiune vidă întrucât atribuirile sunt realizate direct în condiţia instrucţiunii.
– La ieşirea din al doilea ciclu while, pentru a marca sfârşitul şirului concatenat, se atribuie s1[i] = NULL.
– Problema se poate rezolva şi apelând funcţia 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 Scrieţi un program care citeşte un şir de maximum 100 de caractere de la tastatură şi apoi citeşte încă un
caracter separat, care se va elimina din şirul de caractere dacă el există în şir. Programul va afişa 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

Discuţie:
– Ciclul for parcurge şirul de caractere, sir. Cât timp nu s-a atins sfârşitul şirului, adică sir[i] != NULL,
se testează dacă elementul curent este diferit de caracterul ce se doreşte eliminat, sir[i] != c, şi dacă da atunci
elementul curent din şir se păstrează pe poziţia curentă prin atribuirea sir[j++] = sir[i], echivalentă cu
secvenţa: sir[j] = sir[i]; j++; (j se incrementează pentru a pregăti următoarea iteraţie). Dacă elementul
curent este identic cu caracterul ce se doreşte eliminat, atunci atribuirea anterioară nu are loc, astfel că în următoarele
iteraţii, sir[j], care este următorul element din sir, va fi suprascris cu primul caracter diferit de c întâlnit în
sir.
– De remarcat atribuirea sir[j] = NULL care marchează sfârşitul de şir.
=============================

P6.9 Scrieţi un program care citeşte un şir de maximum 100 de caractere de la tastatură şi afişează acest şir în
ordine inversă.

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

int main() {
char sir[101];
int i = 0;

scanf("%s", sir);

while(sir[i] != NULL)
i++;

while(i >= 0) {
i--;
printf("%c", sir[i]);
}

system("PAUSE");
return 0;
}

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


abcd
dcba

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

32
6.2. Probleme propuse
1. Scrieţi un program care citeşte de la tastatură un vector de maximum 50 de numere întregi şi determină numărul
elementelor impare ale vectorului.

2. Scrieţi un program care citeşte de la tastatură doi vectori de maximum 100 de elemente întregi (numărul
elementelor poate fi diferit) apoi determină şi afişează intersecţia celor doi vectori (adică elementele comune celor
doi vectori).

3. Scrieţi un program care citeşte de la tastatură un vector de maximum 20 de elemente întregi şi interschimbă
elementele de pe poziţii pare cu cele de pe poziţiile impare.

4. Scrieţi un program care citeşte de la tastatură un vector de maximum 30 de elemente întregi şi sortează în ordine
crescătoare doar elementele de pe poziţiile impare.

5. Scrieţi un program care citeşte de la tastatură un vector de maximum 15 elemente întregi şi inserează un element
pe o poziţie k. Precizare: se vor citi de la tastatură vectorul împreună cu dimensiunea sa efectivă, elementul ce se
doreşte inserat precum şi poziţia unde se doreşte inserat elementul.

6. Scrieţi un program care citeşte de la tastatură o matrice pătrată de dimensiuni maxime 10 × 10 elemente reale,
afişează matricea transpusă şi apoi calculează suma elementelor matricei.

7. Scrieţi un program care citeşte de la tastatură o matrice de dimensiuni maxime 10 × 10 elemente întregi apoi
determină şi afişează elementele maxime de pe fiecare linie.

8. Scrieţi un program care citeşte de la tastatură o matrice pătrată de dimensiuni maxime 100 × 100 elemente reale
apoi calculează suma elementelor de sub şi de deasupra diagonalei principale.

9. Scrieţi un program care citeşte 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 înmulţi.

10. Scrieţi un program care citeşte de la tastatură două şiruri de caractere (de maximum 51 de caractere fiecare) şi
elimină toate caracterele conţinute în al doilea şir din primul şir.
Exemplu: sir1 = "abcdabcd", sir2 = "ad" şi trebuie să rezulte "bcbc".

11. Scrieţi un program care citeşte de la tastatură două şiruri de caractere (de maximum 11 caractere fiecare) şi
afişează pe ecran numărul de apariţii 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. Scrieţi un program care citeşte de la tastatură două şiruri de caractere (de maximum 41 de caractere fiecare) şi
determină de câte ori apare secvenţa de caractere din al doilea şir în primul.
Exemplu: sir1 = "abcdabcc", sir2 = "ab"
şi programul trebuie să afişeze "Sirul ab apare de 2 ori".

13. Scrieţi un program care citeşte 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ă afişeze "ABCDabc".

33
7. Alte tipuri de date:
structuri, uniuni, tipul enumerat
7.1. Probleme rezolvate
P7.1 Scrieţi un program care citeşte datele pentru un grup de cel mult 10 persoane şi afişează datele citite.
Precizări: Pentru fiecare persoana se vor memora numele, prenumele şi data naşterii. Datele fiecărei
persoane va fi memorat sub forma unei structuri. Data naşterii va fi tot o structură care va avea câmpurile zi,
lună şi an.

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

int main() {
struct data {
int zi;
char luna[12];
int an;
};

struct persoana {
char nume[20];
char prenume[20];
struct data datan;
};

struct persoana grup[10];


int i, n;

do {
printf("Introduceti numarul de persoane: ");
scanf("%d", &n);
} while ((n <= 0) || (n > 10));

for(i = 0; i < n; i++) {


do {
printf("Nume Prenume An Luna Zi\n");
scanf("%s\t%s\t%d\t%s\t%d",
&grup[i].nume, &grup[i].prenume,
&grup[i].datan.an, &grup[i].datan.luna,
&grup[i].datan.zi);
} while((grup[i].datan.an < 0) ||
((grup[i].datan.zi <= 0) &&
(grup[i].datan.zi >= 31)));
}

printf("Nume Prenume An Luna Zi\n");


for(i = 0; i < n; i++)
printf("|%s\t|%s\t|%d\t|%s\t|%d\t|\n",
grup[i].nume, grup[i].prenume, grup[i].datan.an,
grup[i].datan.luna, grup[i].datan.zi);

printf("\n");

system("PAUSE");
return 0;
}

Programul va afişa:
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
Discuţie:
– În programul anterior se definesc două structuri: data şi persoana. Structura persoana utilizează un
câmp datan care este de tipul struct data.
– Variabila grup este un tablou de 10 elemente de tipul persoana.
– Primul ciclu do – while citeşte numărul de persoane, n, care trebuie să fie un număr pozitiv şi mai mic
decât 10. Deci corpul ciclului va fi executat până când n va fi în intervalul [1, 10].
– Al doilea ciclu for citeşte element cu element persoanele din variabila grup. De notat că elementul
grup[i] are 3 câmpuri: primele două (nume, prenume) sunt de tipul şir de caractere în timp ce al treilea este de
tipul struct datan. Al treilea câmp are la rândul sau trei alte câmpuri: zi, luna şi an. Deci pentru accesarea
acestor subcâmpuri avem nevoie de operatorul ,,.” aplicat de două ori asupra unei variabile de tipul grup[i].
– Al treilea ciclu for afişează rezultatele citite de la tastatură ca un tabel sub forma:
| Nume | Prenume | An | Luna | Zi |.
=============================
P7.2 Scrieţi un program care citeşte două numere complexe de la tastatură, calculează şi afişează suma celor două
numere complexe.
Precizare: Un număr complex se va memora sub forma unei structuri cu câmpurile real şi imag.

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

int main(void) {
typedef struct {
float real;
float imag;
} complex;

complex a, b, sum;

printf("Introduceti partea reala a primului nr.: ");


scanf("%f", &a.real);
printf("Introduceti partea imaginara a primului nr.: ");
scanf("%f", &a.imag);
printf("Introduceti partea reala celui de al doilea nr.: ");
scanf("%f", &b.real);
printf("Introduceti partea imaginara celui de al ");
printf("doilea nr.: ");
scanf("%f", &b.imag);

sum.real = a.real + b.real;


sum.imag = a.imag + b.imag;

printf("Suma celor doua numere complexe este: ") ;


printf(" %.2f + (%.2f) * i\n", sum.real, sum.imag);

system("PAUSE");
return 0;
}

Programul va afişa:
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

Discuţie:
Declaraţia typedef introduce un tip utilizator cu numele complex. Structura are doua câmpuri: 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 utilizând
operatorul ,,.” pentru a selecta individual câmpurile real şi imag. De notat că atribuirea sum = a + b nu este
posibilă în C.
=============================
P7.3 Scrieţi un program care citeşte ş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 competiţie. Programul va afişa 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 afişa:
Introduceti start: 10:11:10
Introduceti stop: 10:12:11
timp: 61 s

Discuţie:
− 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. Relaţia de calcul are în vedere faptul că o oră are 3600 de secunde iar un minut are 60 de secunde. Diferenţa dintre
cele două variabile, stop_int - start_int, reprezintă echivalentul în secunde al timpului efectuat.
=============================
P7.4 Scrieţi un program care determină spaţiul de memorie ocupat de o structură.

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

struct exemplu {
int i;
int *p;
double d;
char str[80];
} s;

int main() {
printf("Structura exemplu are dimensiunea: %d octeti.", sizeof(struct exemplu));
printf("\n");

system("PAUSE");
return 0;
}

Programul va afişa:
Structura exemplu are dimensiunea: 96 octeti.
=============================
P7.5 Scrieţi un program care codează şi decodează un întreg folosind uniuni prin inversarea ordinii octeţilor care
compun numărul întreg. Pentru valorile variabilelor din program, se va afişa:
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 afişa pe ecran, după compilare şi execuţie:


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

Discuţie:
– Prin intermediul unei uniuni se pot accesa octeţii care compun un număr întreg.

P7.6 Scrieţi un program care memorează pe rând, în acelaşi spaţiu de memorie, un caracter, un număr întreg şi un
număr 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 afişa:
Un caracter: A
Codul ASCII: 65
Caracterul urmator: B
Un float: 65.14
Aria cercului de raza 2: 0.00

Discuţie:
– În cadrul programului se defineşte o variabilă u având tipul „union”. Variabila poate stoca la un moment
dat un caracter, un întreg sau un număr real.
– Primele două linii după declararea variabilei atribuie variabilei u, în câmpul c (adică u.c) valoarea 'A'.
Variabila este apoi tipărită cu ajutorul specificatorului de format %c pentru caractere.
– Următoarele trei linii ilustrează atribuirea valorii 65, de data aceasta, câmpului i. În acest punct al execuţiei
programului, valoarea câmpului c este distrusă. Tipărirea se va face utilizând specificatorul de format %d. A treia
linie ilustrează tipărirea caracterului asociat codului ASCII imediat următor. Întrucât codul ASCII are valoarea 65 (el
având asociat caracterul 'A'), programul va afişa caracterul 'B'.
– Următoarele 2 linii atribuie câmpului f o valoare egală cu vechea valoare a câmpului 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
operaţiilor se desfăşoară astfel încât se adună întâi 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 greşit. În primele două linii atribuirile u.f
= 3.14 (adică numărul PI) şi u.i = 2 (adică raza cercului) au ca efect modificarea valoarea lui PI astfel încât
rezultatul final este în mod greşit altul decât cel aşteptat. Întrucât o variabilă de tipul enumerat poate lua valori de mai
multe tipuri în timpul execuţiei programului, în lucrul cu uniuni trebuie avut grijă ca la orice moment de timp să fie ştiut
tipul datei ce se află stocat în variabila uniune.
=============================
P7.7 Reluaţi problema anterioară dar construiţi şi o metodă care vă permite să aflaţi în orice moment tipul
informaţiei stocate.
#include <stdio.h>
#include <stdlib.h>
int main() {
struct {
int tip;
union {
char c;
int i;
float f;
} u;
} z;
z.u.c = 'A';
z.tip = 0;
z.u.f = 3.1415;
z.tip = 2;
switch (z.tip) {
case 0: printf("Un caracter: %c\n", z.u.c);
break;
case 1: printf("Un intreg: %d\n", z.u.i);
break;
case 2: printf("Un float: %f\n", z.u.f);
break;
default: printf("Format necunoscut\n");
break;
}

system("PAUSE");
return 0;
}

Programul va afişa:
Un float: 3.141500

38
Discuţie:
– Acest program ilustrează utilizarea unei uniuni, u, în cadrul unei structuri, z. Structura are un câmp, tip, de
tipul întreg. Valorile pe care le ia câmpul tip (de exemplu: 0 pentru caractere, 1 pentru întregi şi 2 pentru real), pot fi
modificate la momentul atribuirii unui subcâmp al uniunii, u. Astfel, în orice moment de timp se cunoaşte tipul stocat
în câmpul u după valorile câmpului tip.
– Instrucţiunea switch decide, funcţie de valoarea din câmpul tip (0, 1, 2), cum trebuie afişată
variabila z.
=============================
P7.8 Scrieţi un program care calculează media notelor obţinute la probele de verificare (laborator, parţial şi
examen) ale unei materii (fizică, biologie şi chimie) utilizând tipul enumerat.

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

int main() {
typedef enum {laborator, partial, examen} didactic;
didactic activitate;

typedef enum {fizica, biologie, chimie} materii;


materii materie;

float nota, suma;

for(materie = fizica; materie <= chimie; materie++) {


suma = 0.0;
for(activitate = laborator; activitate <= examen;
activitate++) {
scanf("%f", &nota);
suma += nota;
}
printf("Media = %.2f\n", suma/3);
}

system("PAUSE");
return 0;
}

În urma introducerii notelor la laborator, parţial şi lucrarea finală, pentru fiecare din cele materii, programul
va afişa:
9
10
10
Media = 9.67
8
8
7.5
Media = 7.83

Discuţie:
– Programul anterior citeşte de la tastatură notele obţinute de un student la diferite materii, fiecare materie având
examinări, de exemplu, la laborator, pe parcursul semestrului, respectiv la examenul final. La finalul fiecărei materii,
programul afişează media la materia respectivă.
– Programul defineşte două enumerări, didactic şi materii, având ca membri tipul de examinare
(laborator, parţial 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 iniţializează cu valoarea 0 la începutul celui de al doilea ciclu
for. În interiorul acestuia se citeşte succesiv variabila nota, aceasta urmând să se adune la totalul din variabila
suma.
– La finalul ultimului ciclu for, se afişează valoarea mediei.
=============================

39
7.2. Probleme propuse
1. Scrieţi un program care citeşte de la tastatură un vector de elemente complexe, calculează şi afişează suma
complexă a tuturor elementelor sale.

2. Scrieţi un program care citeşte de la tastatură un vector de elemente complexe, calculează şi afişează produsul
complex al tuturor elementelor sale.

3. Să se modifice programul P7.3 astfel încât să nu mai afişeze numai numărul 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. Scrieţi un program care citeşte de la tastatură un vector de coordonate ale unei structuri împreună cu masele
plasate la coordonatele respective şi calculează centrul de greutate al structurii.
Precizări:
− 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 alcătuită din cel mult 100 de puncte.

5. Modificaţi programul P7.8 astfel încât să memoreze numele materiilor şi notele obţinute în structuri.
6. Scrieţi un program care memorează scorurile obţinute de cel mult 10 jucători împreună cu numele jucătorilor.
Informaţiile se vor memora într-o matrice constituită din structuri definite astfel:
typedef struct {
char nume[20];
int scor;
} jucator;

7. Scrieţi un program care implementează o agendă telefonică sub forma unei structuri cu următoarea definiţie:
typedef struct {
char nume[20];
char prenume[20];
char adresa[20];
unsigned int cod_postal; unsigned int numar;
unsigned int prefix; unsigned int mobil;
} intrare;

8. Scrieţi un program care scrie octeţii 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 puţin semnificativ.
Precizări:
− ordinea în memorie a octeţilor depinde de platforma de calcul: există calculatoare de tip „BIG_ENDIAN”, la
care primul octet din memorie este cel mai puţin semnificativ şi de tip „LITTLE_ENDIAN” la care primul octet
este cel mai semnificativ. Va trebui ca mai întâi să stabiliţi ce tip de calculator folosiţi şi apoi să parcurgeţi octeţii
în ordinea corespunzătoare;
− pentru a accesa octeţii care formează un număr de tip double utilizaţi uniunea:
typedef union {
char octet[8];
double numar;
} valoare;

40
8. Funcţii simple; recursivitate
8.1. Probleme rezolvate
P8.1 Scrieţi un program care calculează integrala unei funcţii oarecare, într-un interval [a, b] ale cărui limite se
vor citi de la tastatura. Utilizatorul va specifica şi numărul de subintervale de discretizare. Metoda de
integrare este metoda dreptunghiurilor.

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

float f(float x) {
return (x * x - x + 1);
}

int main() {
float a, b, intg, eps;
int n; /* numarul de subintervale */
int i;

printf("Introduceti limita de inceput a intervalului: ");


scanf("%f", &a);

printf("Introduceti limita de sfarsit a intervalului: ");


scanf("%f", &b);

printf("Introduceti numarul de subintervale ");


printf("de discretizare: ");
scanf("%d", &n);

eps = (b - a) / n; /* pasul integrarii */


intg = f(a) * eps; /* primul dreptunghi */
for(i = 1; i <= n; i++)
intg += f(a + i*eps) * eps;

printf("Valoarea integralei este %.3f\n", intg);

system("PAUSE");
return 0;
}

Programul va afişa pe ecran, după compilare şi execuţie:


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

Discuţie:
– Programul reprezintă implementarea directă a metodei dreptunghiurilor folosită la integrarea numerică a unei
funcţii pe un interval dat. Calculul valorii funcţiei într-un punct se face cu ajutorul funcţiei f();
=============================
P8.2 Scrieţi un program care afişează numerele pare dintr-un interval [a, b] cu ajutorul unei funcţii. 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 afişa pe ecran, după compilare şi execuţie:


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

Discuţie:
– Parcurgerea intervalului se face în programul principal. Pentru fiecare element din interval funcţia par()
verifică dacă acesta este par. Daca este par funcţia returnează 1, daca nu este par returnează 0.
=============================
P8.3 Scrieţi un program care citeşte un număr natural n şi calculează şi afişează factorialul numărului n definit
astfel:

1, pentru n = 1
n! = 
n ⋅ (n − 1)! , pentru n > 1
Calculul factorialului se va realiza cu ajutorul unei funcţii 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 afişa pe ecran, după compilare şi execuţie:


Introduceti n: 12
12! = 479001600

Discuţie:
– Programul verifică valoarea introdusă deoarece o valoare eronată poate conduce la executarea la nesfârşit a
funcţiei factorial(). Funcţia factorial() se auto-apelează până când se ajunge la factorial de 1.
=============================
P8.4 Scrieţi un program care citeşte două numere naturale a şi b şi calculează şi afişează 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
a dacă a = b

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

Discuţie:
– Se remarcă faptul că funcţia cmmdc() implementează exact definiţia matematică formulată în enunţ.
Programul principal nu face decât să citească cele două numere, să apeleze funcţia cmmdc() şi să afişeze rezultatul.
=============================
P8.5 Scrieţi un program care citeşte un număr şi stabileşte şi afişează dacă numărul este prim sau nu. Se va scrie
şi utiliza o funcţie care verifică dacă un număr 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 afişa pe ecran, după compilare şi execuţie:
Introduceti un numar natural: 397
Este prim

Discuţie:
– Pentru a verifica dacă un număr, n, este prim se parcurge intervalul (1, n) şi pentru fiecare număr din interval
se verifică dacă acesta este divizor al lui n. Atunci când am găsit un divizor înseamnă că numărul nu este prim şi ieşim
din ciclul while (i devine n + 1). Funcţia divizibil verifică dacă contorul i care parcurge intervalul divide pe n.
Daca îl divide returnează 0 iar dacă nu îl divide returnează 1.
=============================
P8.6 Scrieţi un program care citeşte două numere naturale n şi p şi calculează cu ajutorul unei funcţii recursive
valoarea expresiei np. Valoarea expresie va fi afişată. Funcţia np se va defini astfel:

n dacă p = 1
np =  p −1
n ⋅ n dacă p > 1
#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 afişa pe ecran, după compilare şi execuţie:


Introduceti 2 numere naturale: 2 16
65536

Discuţie:
– Funcţia putere implementează direct definiţia 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 Scrieţi un program care calculează media aritmetică a elementelor unui vector cu ajutorul unei funcţii.

#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 afişa pe ecran, după compilare şi execuţie:


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

Discuţie:
– La parcurgerea vectorului, funcţiei medie() i se transmit poziţia curentă (i), suma elementelor anterioare
(s), elementul curent (v[i]) şi lungimea vectorului (n). Funcţia medie() însumează elementele vectorului
(s = s + z) până în momentul în care a însumat şi ultimul element. Atunci va împarţi această sumă la numărul de
elemente.
=============================
P8.8 Scrieţi un program care verifică transferul unei structuri, ca parametru, către o funcţie.

#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 afişa pe ecran, după compilare şi execuţie:


Diferenta dintre cele 2 elemente ale structurii este: -0.400000

Discuţie:
– Pentru a face verificarea cerută s-a definit o structură cu marca strp2 care are două câmpuri: i de tip
întreg şi d de tip fracţionar cu precizie dublă. În programul principal se atribuie valori celor două câmpuri ale structurii
şi apoi se apelează funcţia f. Această funcţie calculează şi afişează diferenţa dintre cele două câmpuri.
=============================

45
P8.9 Scrieţi un program care determină şi afişează lungimea unui şir de maxim 200 de caractere cu ajutorul unei
funcţii.
#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 afişa pe ecran, după compilare şi execuţie:


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

Discuţie:
– Citirea şirului de caractere se realizează apelând funcţia gets(). Aşa cum am mai precizat în Capitolul 6,
folosirea acestei funcţii este nerecomandabilă. Pentru citirea şirului de caractere recomandăm utilizarea instrucţiunilor:
fgets(sir, 201, stdin);
if(sir[strlen(sir)-1] == '\n') sir[strlen(sir)-1] = '\0';
Cea de a doua instrucţiune elimină caracterul „newline” din şirul citit.
– Funcţia lungime() primeşte ca parametru un vector de caractere. Lungimea şirului de caractere este
determinat prin oprirea ciclului for la întâlnirea caracterului '\0'. Se remarcă utilizarea instrucţiunii vide pentru
ciclul for. Funcţia lungime() funcţionează similar cu funcţia standard strlen().
=============================
P8.10 Scrieţi un program care citeşte de la tastatură o matrice pătrată de dimensiune maximă 10 × 10 elemente
reale împreună cu dimensiunea sa efectivă şi determină şi afişează suma elementelor de pe diagonala
principală şi de pe diagonala secundară. Se vor scrie şi utiliza funcţii 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 funcţii.
#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 afişa pe ecran, după compilare şi execuţie:


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

Matricea introdusa este:

1.000 2.000 3.000 4.000


5.000 6.000 7.000 8.000
9.000 10.000 11.000 12.000
13.000 14.000 15.000 16.000

Suma elementelor de pe diagonala principala este 34.000

Suma elementelor de pe diagonala secundara este 34.000

Discuţie:
– Funcţia citeste() realizează citirea efectivă a elementele matricei folosind proprietatea particulară a
tablourilor de a putea fi modificate într-o funcţie astfel încât modificările să fie permanente. Funcţia tip_mat()
afişează matricea citită. Funcţiile suma1() şi suma2() calculează suma elementelor de pe diagonala principală şi,
respectiv, de pe diagonala secundară. Programul principal citeşte dimensiunea efectivă a matricei şi apelează funcţiile
definite anterior.
=============================

47
8.2. Probleme propuse
1. Scrieţi un program C care citeşte 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 iniţial iar cel de al doilea va fi format din numerele impare din vectorul iniţial. Citirea vectorului se va
face cu ajutorul unei funcţii cu prototipul:
void cit_vect(int v[10], int dim);

2. Reluaţi programul anterior, dar pentru formarea vectorilor scrieţi şi utilizaţi două funcţii având prototipurile:
int pare(int v[10], int par_v[10]);
int impare(int v[10], int impar_v[10]);
Funcţiile vor returna numărul valorilor pare şi respectiv, numărul valorilor impare.

3. Scrieţi un program C care calculează suma complexă a elementelor dintr-un tablou unidimensional de numere
complexe.
Precizări:
a. Tabloul de numere complexe va fi declarat utilizând următoarele definiţii:
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. Scrieţi câte o funcţie care calculează partea reală şi, respectiv, partea imaginară a sumei a două numere
complexe. Prototipurile acestor funcţii sunt:
float suma_re(complex a, complex b);
float suma_im(complex a, complex b);
Suma globală cerută se va calcula folosind funcţiile definite anterior.

4. Reluaţi programul anterior dar pentru calculul sumei a două numere complexe scrieţi şi utilizaţi o funcţie având
prototipul:
complex suma(complex a, complex b);

5. Scrieţi un program C care citeşte de la tastatură o matrice de numere reale de dimensiuni maxime 100 × 100
împreună cu dimensiunile sale efective şi afişează elementele maxime de pe fiecare linie şi apoi de pe fiecare
coloană.
Precizări:
a. Pentru determinarea maximului de pe linii / coloane se va scrie şi utiliza o funcţie cu prototipul:
float max_vec(int dim, float vec[100]);
b. Se vor forma, pe rând, vectori din fiecare linie şi apoi din fiecare coloană.

6. Scrieţi un program care citeşte un număr natural şi calculează şi afişează secvenţa Halberstam a acestui număr.
Precizări:
a. Secvenţa Halberstam a unui număr se calculează astfel: dacă numărul este par el se împarte la 2; dacă numărul
este impar se adună 3 şi se adună 1; se reiau operaţiile până când valoarea ajunge egală cu 1.
b. Calculul numărului următor al secvenţei Halberstam se va face cu ajutorul unei funcţii.

7. Scrieţi o funcţie care afişează o întrebare şi citeşte răspunsul utilizatorului care poate fi doar ‚d’, pentru „da”, sau
‚n’, pentru „nu”; citirea se repetă până când răspunsul este ‚d’ sau ‚n’. Scrieţi apoi un program care verifică
funcţionarea corectă a funcţiei.
Precizare: Prototipul funcţiei este:
int ok(char s[]);

8. Scrieţi o funcţie care calculează suma de plată pentru o activitate primind numărul de ore lucrate şi salariul orar.
Dacă numărul de ore lucrate este mai mic decât sau egal cu 40 se plăteşte salariul orar. Pentru orele cuprinse între
40 şi 60 salariul orar creşte cu 50 %. Pentru orele care depăşesc 60 se plăteşte dublu. Scrieţi şi programul principal
care verifică funcţionarea funcţiei.

48
9. Scrieţi o funcţie care caută toate spaţiile dintr-un şir de caractere şi le înlocuieşte cu semnul ‚-’ returnând numărul
de spaţii înlocuit. Prototipul funcţiei este:
int inlocuieste(char sir[]);
Scrieţi şi programul principal care verifică funcţionarea funcţiei.

10. Scrieţi o funcţie care determină şi returnează momentul sosirii primului tren într-o staţie de cale ferată. Funcţia
primeşte ca argumente momentul plecării din staţie şi o structură care conţine orele de plecare şi de sosire.
Precizări:
a. Structura pentru memorarea programului de circulaţie 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 circulaţie între două staţii este alcătuit dintr-un tablou format din structuri de tip
Program_tren.

c. Funcţia va căuta primul tren care pleacă după ora indicată şi va afişa orele de plecare şi sosire.

Scrieţi şi programul principal care verifică funcţionarea funcţiei.

11. Scrieţi o funcţie care afişează şirul de caractere primit ca parametru şi apoi îl subliniază scriind numărul
corespunzător de caractere ‚_’ pe rândul următor. Pentru determinarea lungimii şirului de caractere se va folosi
funcţia standard strlen(), „string length”, care are următorul prototip:
int strlen(char s[]);
Scrieţi şi programul principal care verifică funcţionarea funcţiei.

49
9. Pointeri
9.1. Probleme rezolvate
P9.1 Scrieţi un program care determină suma elementelor de pe diagonala unei matrice pătrate de dimensiune
maximă 10 × 10 formată din numere reale. Pentru citirea matricei se va scrie şi utiliza o funcţie care citeşte
matricea împreună cu dimensiunile sale efective.

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

#define DIMMAX 10

void citmat(float mat[][DIMMAX], int *dim);

int main(void) {
int dimef, i;
float mat[DIMMAX][DIMMAX], sumdiag;

citmat(mat, &dimef);
sumdiag = 0.0;
for(i = 0; i < dimef; i++)
sumdiag += mat[i][i];
printf("Suma elementelor de pe diagonala este: %f\n",
sumdiag);
system("PAUSE");
return 0;
}

void citmat(float mat[][DIMMAX], int *dim) {


int i, j;
do {
printf("Introduceti dimensiunea efectiva (<=10): ");
scanf("%i", dim);
} while (*dim > 10 || *dim < 0);

for(i = 0; i < *dim; i++)


for(j = 0; j < *dim; j++) {
printf("mat[%d][%d] = ", i, j);
scanf("%f", &mat[i][j]);
}
}

Programul va afişa pe ecran, după compilare şi execuţie:


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

Discuţie:
– Acest program pune în evidenţă utilizarea pointerilor la transferul unei valori dintr-o funcţie. Al doilea
parametru al funcţiei citmat() este un pointer prin intermediul căruia se transferă dimensiunea efectivă a metricei.
=============================
P9.2 Scrieţi un program care determină suma elementelor de pe diagonala unei matrice pătrate formată din
numere reale. Pentru citirea matricei se va scrie şi utiliza o funcţie care citeşte matricea împreună cu
dimensiunile sale efective. Precizare: deşi problema pare identică cu problema 9.1 nu este aşa; de această
dată programul trebuie să poată prelucra matrice oricât 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 afişa pe ecran, după compilare şi execuţie:


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!

Discuţie:
– 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 funcţia citmat() se alocă mai
întâi un vector de pointeri care reprezintă matricea propriu-zisă şi apoi se alocă câte un pointer către fiecare rând din
matrice. Se observă că procedând astfel elementele matricei se pot adresa exact ca atunci când matricea a fost alocată
static.
=============================

51
P9.3 Scrieţi un program care afişează pe ecran conţinutul şi adresele a două variabile de tip întreg, apoi atribuie
adresa uneia dintre ele unui pointer şi reia afişarea utilizând pointerul.

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

int main() {
int j, k;
/* declarare variabila de tip pointer */
int *ptr;
j = 1;
k = 2;

/* ptr contine adresa la care este stocata variabila k */


ptr = &k;

printf("\nj are valoarea %d si este stocat la adresa %p ", j, &j);


printf("\nk are valoarea %d si este stocat la adresa %p", k, &k);
printf("\nptr are valoarea %p si este stocat la adresa %p”, ptr, &ptr);
printf("\nValoarea int catre care arata pointerul este: %d", *ptr);
printf("\n");
system("PAUSE");
return 0;
}

Programul va afişa pe ecran, după compilare şi execuţie:


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

Discuţie:
– 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 instrucţiunea:
ptr = &k;

afişarea va arăta 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

– Precizăm că adresele afişate pot diferi de cele de mai sus în funcţie de spaţiul de memorie alocat programului
de către sistemul de operare precum şi faptul că în varianta eronată este posibil ca programul să nu funcţioneze de loc.
=============================
P9.4 Scrieţi un program care construieşte un vector şi îl afişează atât în mod obişnuit, cât şi utilizând pointeri.
Programul va afişa apoi adresele elementelor din vector şi valorile lor. Se va încerca şi depăşirea
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");

/* Afişare 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 afişa pe ecran, după compilare şi execuţie:


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

adresa pentru tablou[0]: 2293576


adresa pentru tablou[1]: 2293580
adresa pentru tablou[2]: 2293584
adresa pentru tablou[3]: 2293588
adresa pentru tablou[4]: 2293592
adresa pentru tablou[5]: 2293596

ptr + 0 = 1
ptr + 1 = 23
ptr + 2 = 17
ptr + 3 = 4
ptr + 4 = -5
ptr + 5 = 100
ptr + 6 = 2293664

Discuţie:
– Prima instrucţiune atribuie pointerului ptr adresa primului element din vectorul tablou. Aşa cum se arată
şi în comentariu, această instrucţiune se poate scrie şi:

ptr = tablou;

Observaţie: Precizăm că un tablou nu este un vector. Din acest motiv atribuirea:


tablou = ptr;

nu este corectă.
– Primul ciclu for afişează valorile memorate în vector utilizând atât direct vectorul cât şi pointerul.
– Cel de al doilea ciclu afişează adresele de memorie la care sunt stocate elementele vectorului. Se observă că
elementele vectorului sunt memorate în locaţii succesive de memorie.
– În cel de al treilea ciclu se repetă afişarea, dar se depăşeşte dimensiunea vectorului. Aşa cum se observă din
rezultatul rulării programului, limbajul C nu verifică depăşirea dimensiunii vectorului. În acest mod programul rulează
mult mai repede dar programatorul trebuie să fie foarte atent pentru a nu comite astfel de greşeli.
=============================
P9.5 Scrieţi 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 înlocuieşte cu secvenţa
"CCC". În final, se va alipi şi porţiunea rămasă din strA la stringul final. Prima concatenare se va realiza
cu ajutorul pointerilor. Pentru copierile şi concatenările ulterioare se vor utiliza funcţiile 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 afişa pe ecran, după compilare şi execuţie:


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
Discuţie:
– Modul în care se realizează concatenarea este similar codului din funcţia standard strcat(). Această
secţiune 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 întâi acesta este localizat. Apoi se salvează restul şirului de caractere
care urmează după acesta şi se compune noul şir de caractere prin două operaţii succesive de concatenare.
=============================
P9.6 Scrieţi un program care, prin două funcţii distincte, verifică egalitatea alfabetică sau numerică a
argumentelor, folosind pointeri. Afişarea se va face utilizând funcţia 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 afişa pe ecran, după compilare şi execuţie:
Introduceti primul argument:
str1
Introduceti al doilea argument:
str2
Argumente de tip caracter

Verificarea egalitatii: Argumentele nu sunt egale

Discuţie:
– Pentru verificarea tipului de valori citite se foloseşte funcţia standard isalpha() care returnează
„adevărat” 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 funcţiei verifica() este un pointer către o funcţie. Funcţia verifica()
apelează funcţia de verificare a egalităţii prin intermediul pointerului la funcţie.
=============================
P9.7 Scrieţi un program care încarcă valori într-o structură folosind un pointer către aceasta.

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

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

system("PAUSE");
return 0;
}

Programul va afişa pe ecran, după compilare şi execuţie:


10 10 tablou unidimensional de caractere

Discuţie:
– Programul pune în evidenţă utilizarea operatorului ->.
=============================
P9.8 Scrieţi 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 funcţii diferite pentru citirea unei matrice, afişarea 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 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;
}
}

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 afişa pe ecran, după compilare şi execuţie:
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

Discuţie:
– Schimbarea între ele a liniilor matricei se face utilizând două funcţii diferite. Funcţia schimba1() pune în
evidenţă faptul că în limbajul C o matrice bidimensională este o matrice unidimensională formată din matrice
unidimensionale. Funcţia schimba2() utilizează pointerii pentru accesul la valorile din matrice.
=============================
P9.9 Scrieţi un program care caută un subşir într-un şir de caractere. Programul va afişa poziţia subşirului în şir
sau un mesaj de eroare dacă subşirul nu a fost găsit.
#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 afişa pe ecran, după compilare şi execuţie:
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'

Discuţie:
– Se remarcă modul în care se face căutarea cu ajutorul a două cicluri cu contor. Ciclul cu contor exterior
avansează poziţia de căutare în şirul în care se caută. Cel de al doilea ciclu realizează căutarea propriu-zisă. Mai întâi, la
iniţializarea ciclului, se aduc cei doi pointeri, la începutul celor două şiruri de caractere. Căutarea continuă cât timp mai
există caractere în cele două şiruri şi caracterele din cele două şiruri sunt identice. Dacă la ieşirea din ciclul intern s-au
epuizat caracterele din şirul căutat înseamnă că şirul a fost găsit. Poziţia se determină prin diferenţa dintre pointerul care
indică începutul şirului în care se caută şi pointerul care indică începutul subşirului găsit.
=============================
P9.10 Scrieţi un program care citeşte dimensiunea exactă a unui vector de numere întregi, construieşte, citeşte şi
afişează acest vector.
#include <stdio.h>
#include <stdlib.h>

int main(void) {
int dim, i;
int *vector;

do {
printf("Introduceti dimensiunea vectorului: ");
scanf("%d", &dim);
} while(dim <= 0);

if(!(vector = (int *)malloc(dim * sizeof(int)))) {


printf("Dimensiunea %d este prea mare!\n", dim);
printf("Vectorul nu are loc in memorie!\n");
system("PAUSE");
return 1;
}

printf("Citire\n");
for(i = 0; i < dim; i++) {
printf("vector[%d] = ", i);
scanf("%d", vector + i);
}

printf("Scriere\n");
for(i = 0; i < dim; i++)
printf("vector[%d] = %d\n", i, *(vector + i));

free(vector);

system("PAUSE");
return 0;
}

Programul va afişa pe ecran, după compilare şi execuţie:


Introduceti dimensiunea vectorului: 3
Citire
vector[0] = 1
vector[1] = 2
vector[2] = 3
Scriere
vector[0] = 1
vector[1] = 2
vector[2] = 3
59
sau
Introduceti dimensiunea vectorului: 1567311664
Dimensiunea 1567311664 este prea mare!
Vectorul nu are loc in memorie!

Discuţie:
– Programul alocă spaţiul de memorie necesar stocării vectorului. Se verifică faptul că spaţiul de memorie a
putut fi alocat. Dacă alocarea eşuează, execuţia programului se întrerupe. După citire şi scriere spaţiul de memorie
alocat este eliberat.
=============================
P9.11 Scrieţi un program care citeşte, sortează şi afişează un vector de şiruri de caractere implementând o
procedură de tip bubble-sort şi comparând pointerii alăturaţi.

#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 afişa pe ecran, după compilare şi execuţie:


Sirurile nesortate sunt:
Gabi
Bebe
Alina
Claudia
Catalin
Andrei
Ana

Sirurile sortate sunt:


Alina
Ana
Andrei
Bebe
Catalin
Claudia
Gabi

60
Discuţie:
– Prin utilizarea pointerilor către şirurile de caractere sunt modificate adresele către care indică pointerii şi nu
sunt mutate şirurile de caractere propriu-zise. Efectul rămâne cel dorit, dar este obţinut cu un efort de calcul mult mai
mic.
=============================

9.2. Probleme propuse


1. Scrieţi un program care determină de câte ori un subşir de caractere se regăseşte într-un alt şir de caractere.
Indicaţie: se va generaliza soluţia de la problema 9.9.

2. Scrieţi un program care citeşte trei variabile a, b şi c şi apoi le roteşte între ele astfel: a -> b, b -> c şi
c -> a.

3. Scrieţi un program care citeşte şi sortează în ordinea ascendentă dată de cuvant_cheie un vector format din
înregistrări definite astfel:
typedef struct {
char cuvant_cheie[10];
int alte_date;
} Inregistrare;

Pentru ordonare / sortare se va utiliza funcţia qsort() disponibilă în bibliotecile standard C şi declarată în
stdlib.h.
Indicaţie: funcţia 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ă numărul de elemente din vector;
- size este dimensiunea în octeţi a unui element din vector şi
- compar este un pointer către o funcţie definită de utilizator care realizează comparaţia între două
elemente ale vectorului, elem1 şi elem2, returnând o valoare întreagă mai mică decât, egală cu, sau mai
mare decât zero după cum elem1 este mai mic, egal cu, sau mai mare decât elem2.

4. O metodă de sortare presupune adăugarea valorilor dintr-un vector una câte una într-un vector nou. Prima valoare
este adăugată la începutul vectorului. Valorile următoare sunt adăugate în poziţia corespunzătoare ordinii sale prin
deplasarea datelor adăugate deja pentru a face loc valorii care se adaugă. Această metodă poartă numele de
„sortare prin inserare” („insertion sort”). Scrieţi o funcţie denumită insort() care realizează astfel sortarea şi
se comportă în acelaşi mod precum funcţia qsort() descrisă în problema anterioară. Funcţia 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 funcţiei qsort() realizând 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 funcţia
compar().
Scrieţi şi programul principal care testează funcţia.

5. Scrieţi o funcţie care primeşte ca argument un şir de caractere şi returnează un pointer către primul caracter care nu
este spaţiu din acest şir de caractere.
Precizări:
a. Se vor considera spaţii caracterele ' ' („space”) şi '\t' („tab”).
b. Prototipul funcţiei este:
char *primul_caracter(char *sir);
c. Scrieţi şi programul principal care testează funcţia.

6. Scrieţi un program care citeşte un text, îl desparte în cuvinte şi afişează cuvintele textului ordonate alfabetic.

7. Scrieţi un program care citeşte un text şi afişează doar ultimele 5 linii ale textului.

61
8. Scrieţi un program care parcurge lista definită mai jos cu ajutorul pointerului p_lista şi afişează numărul şi
numele.
define MAX 4

struct lista {
int numar;
char nume[10];
} data[MAX] = {
1, "Ion",
2, "Vasile",
3, "Gheorghe",
4, "Maria"
};

struct lista *p_lista;

9. Scrieţi un program care citeşte o expresie matematică simplă formată din doi operanzi numerici şi un operator (+,
-, *, /) şi determină şi afişează valoarea expresiei. Un exemplu de rulare a programului va arăta astfel:
Introduceti expresia:
1.25 * 4
= 5

10. Scrieţi un program care citeşte de la tastatură o matrice de numere reale de dimensiuni maxime 10 x 10, împreună
cu dimensiunile sale efective şi determină câtul împărţirii modulului sumei numerelor negative din matrice la
suma numerelor pozitive din matrice. Programul va semnala cazul special al împărţirii prin zero. Pentru calculul
sumelor se va folosi o funcţie cu următorul prototip:
void suma(float A[][10], int n, int m, float *pos, float *neg);

unde:
A[][10] este matricea de lucru;
n, m sunt dimensiunile efective ale matricei;
pos suma numerelor pozitive;
neg suma numerelor negative.

11. Reluaţi problema anterioară şi scrieţi un program care citeşte de la tastatură o matrice de numere reale de orice
dimensiuni, împreună cu dimensiunile sale efective şi determină câtul împărţirii modulului sumei numerelor
negative din matrice la suma numerelor pozitive din matrice. Programul va semnala cazul special al împărţirii prin
zero. Pentru calculul sumelor se va folosi o funcţie cu următorul prototip:
void suma(float **A, int n, int m, float *pos, float *neg);

unde:
A este matricea de lucru;
n, m sunt dimensiunile efective ale matricei;
pos suma numerelor pozitive;
neg suma numerelor negative.

12. Scrieţi un program care citeşte de la tastatură o matrice de numere reale de dimensiuni maxime 10 x 10, împreună
cu dimensiunile sale efective şi determină câtul împărţirii modulului produsului elementelor de pe diagonala
principală a matricei la produsul elementelor de pe diagonala secundară a matricei. Programul va semnala cazul
special al împărţirii prin zero. Pentru calculul sumelor se va folosi o funcţie cu următorul prototip:
void prod_diag(float A[][10], int n, float *dprin, float *dsec);
unde:
A[][10] este matricea de lucru;
n este dimensiunea efectivă a matricei;
dprin produsul elementelor de pe diagonala principală;
dsec produsul elementelor de pe diagonala secundară.

13. Scrieţi o funcţie care primeşte ca parametru un număr întreg şi returnează un pointer către numele lunii
calendaristice corespunzătoare. Dacă numărul nu reprezintă o lună, este mai mic decât 1 sau mai mare decât 12,
funcţia va returna un pointer către şirul de caractere „nici o luna”.
Precizări:
a. Denumirile lunilor vor fi memorate într-o variabilă locală statică a funcţiei definită astfel:
static char *luna[] = {
"nici o luna",
"ianuarie",

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

b. Prototipul funcţiei este:


char *denumire_luna(int numar);

Scrieţi şi programul principal care verifică funcţionarea funcţiei.

14. Folosind funcţia din exerciţiul anterior scrieţi o altă funcţie care primind un şir de caractere de forma
"zzllaaaa" returnează data scrisă sub forma "zi luna an". De exemplu: funcţia primeşte "15042004"
şi returnează "15 aprilie 2004". Funcţia va verifica şi corectitudinea datei rejectând date cum ar fi
"2902001" (anul 2001 nu a fost bisect) sau "31042005" (aprilie nu are 31 de zile). Scrieţi şi programul
principal care verifică funcţionarea funcţiei.

15. Scrieţi o funcţie care citeşte cel mult n numere reale de tip float şi le plasează în memorie începând de la
adresa indicată de pfloat. Funcţia va returna numărul valorilor citite. Prototipul funcţiei este:
int citeste_n_nr(int n, float *pfloat);
Scrieţi şi programul principal care verifică funcţionarea funcţiei.

63
10. Probleme recapitulative
10.1. Probleme rezolvate
P10.1 Scrieţi un program care să calculeze şi să afişeze, în funcţie de opţiunea utilizatorului, următoarele mărimi
pentru un cilindru cu raza bazei şi înălţimea date (numere reale): aria bazei, circumferinţa cercului de bază
şi volumul cilindrului; programul va fi reluat până când utilizatorul doreşte terminarea sa şi se va cere
repetarea opţiunii, dacă aceasta nu s-a făcut corect.
#include <stdio.h>
#include <stdlib.h>

#define PI 3.14159265358979323846

int main() {
float raza, inaltimea;
char ch;
double raspuns;
int semnal=1;

while(semnal) {
printf("Alegeti una din optiunile:\n");
printf(
"Aria (A), Circumferinta (C), Volumul (V), Iesire (Q): ");
ch = getche();
printf("\n");
ch = toupper(ch);
if(ch == 'A' || ch == 'C' || ch == 'V')
do {
printf("Introduceti raza: ");
} while(scanf("%f", &raza) != 1);
if(ch == 'V')
do {
printf("Introduceti inaltimea: ");
} while(scanf("%f", &inaltimea) != 1);
switch(ch) {
case 'A':
raspuns = PI * raza * raza;
printf("Aria bazei este: %g\n\n", raspuns);
break;
case 'C':
raspuns = 2 * PI * raza;
printf(
"Circumferinta bazei este: %g\n\n", raspuns);
break;
case 'V':
raspuns = PI * raza * raza * inaltimea;
printf(
"Volumul cilindrului este: %g\n\n", raspuns);
break;
case 'Q':
semnal=0;
break;
default:
printf(
"Optiunea necunoscuta '%c' este ignorata!\n\n", ch);
break;
}
}

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

Programul va afişa pe ecran, după compilare şi execuţie:


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

Alegeti una din optiunile:


Aria (A), Circumferinta (C), Volumul (V), Iesire (Q): q
=============================

64
P10.2 Scrieţi un program care să deseneze pe ecran un ‚X’ cu dimensiunea specificată de utilizator (număr natural
≤ 20, înălţimea egală cu lăţimea), folosind simbolul ‚ * ’.
De exemplu, dacă se introduce numărul 5, desenul va trebui să arate astfel:

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

int main() {
int d; /* dimensiunea */
int r; /* numarul liniei */
int c; /* numarul coloanei */
printf("Introduceti dimensiunea: ");
scanf("%d", &d);

/* pentru "diagonala principala", '*' va apare cand r = c; pentru "diagonala


secundara", '*' va apare cand c=d–r+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 afişa pe ecran, după compilare şi execuţie:


Introduceti dimensiunea: 8
Desenul cerut arata astfel:

* *
* *
* *
**
**
* *
* *
* *
=============================
P10.3 Programul următor citeşte 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 afişa pe ecran, după compilare şi execuţie:


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 următor citeşte de la tastatură o matrice de maximum 10 × 10 numere întregi şi sortează
crescător liniile matricei. Precizare: prin convenţie, o linie este mai mare decât alta dacă primul element de
pe o linie este mai mare decât primul element de pe a doua. Dacă primele elemente sunt egale regula se
aplică pentru următoarele 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 afişa pe ecran, după compilare şi execuţie:


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 următor citeşte de la tastatură o matrice de maximum 10 × 10 numere întregi apoi elimină o linie
a matricei. Precizare: indexul liniei ce se doreşte 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 afişa pe ecran, după compilare şi execuţie:


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 următor citeşte de la tastatură o matrice de dimensiuni n × m de numere întregi (maximum
10 × 10) şi înlocuieşte coloana k cu un vector de n elemente ce se va citi tot de la tastatură.
Precizare: poziţia 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 afişa pe ecran, după compilare şi execuţie:


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 următor afişează graficul unei funcţii (de exemplu sin(x) pe o perioadă) în format ASCII.
Programul scalează funcţia în intervalul ce se doreşte afişat şi tipăreşte un singur caracter '*' pe poziţia
corespunzătoare valorii funcţiei. 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 afişa pe ecran, după compilare şi execuţie:


*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
=============================
P10.8 Scrieţi un program care să implementeze un calculator de buzunar foarte simplu (doar cele 4 operaţii
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 afişa pe ecran, după compilare şi execuţie:


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. Scrieţi un program care citeşte un număr întreg reprezentat în baza 10 şi îl converteşte şi afişează reprezentat în
baza 16.

2. Scrieţi un program care citeşte de la tastatură un număr natural n cu cel mult 9 cifre şi determină numărul natural
k < n care are numărul maxim de divizori primi.

3. Scrieţi un program care citeşte perechi de numere reale care reprezintă coordonatele carteziene ale unui poligon
convex şi apoi calculează şi afişează aria poligonului.

4. Scrieţi un program care citeşte un număr întreg pozitiv n < 50 000 reprezentând numărul de zile care au trecut de
la 1 ianuarie 1900 şi determină şi afişează data calendaristică corespunzătoare. Se vor lua în consideraţie şi anii
bisecţi (1900 a fost an bisect iar 2000 nu a fost an bisect).

5. Scrieţi un program care citeşte din fişierul „nr.in” un număr natural cu minim 2 cifre şi maxim 5000 de cifre
zecimale şi apoi calculează şi scrie în fişierul „nr.out” pătratul acestui număr.

6. Scrieţi un program care determină câte perechi de numere naturale care nu depăşesc un număr dat, n, au cel mai
mic divizor comun un alt număr dat, d. Programul va afişa perechile de numere obţinute.

7. Scrieţi un program care determină toate numerele naturale i < n care au proprietatea că sunt egale cu suma
factorialelor cifrelor care le conţin.
Exemplu: 145 = 1! + 4! + 5!
Numărul n va fi citit de la tastatură.

8. Scrieţi un program care determină care este numărul natural maxim care se poate construi din cifrele distincte ale
unui număr natural în baza 10 cu maxim 80 de cifre care se citeşte de la tastatură.

9. Scrieţi un program care citeşte un număr natural n cu maxim 50 de cifre zecimale şi determină şi afişează secvenţa
maximă de cifre consecutive care se repetă de cel puţin 2 ori în scrierea numărului n.

10. Scrieţi un program care citeşte ecuaţiile a n drepte din plan şi determină şi afişează dreptele care aparţin aceleiaşi
clase de paralelism. Ecuaţia unei drepte este dată de formula: a ⋅ x + b ⋅ y + c = 0; două drepte aparţin aceleaşi
clase de paralelism dacă au aceeaşi pantă.

11. Scrieţi un program care citeşte într-un şir de caractere care reprezintă o expresie care conţine mai multe numere
complexe şi operaţii între acestea apoi calculează şi afişează rezultatul expresiei.
Precizări:
71
Operaţii: + , - , * , ^
Exemplu: (2 + 3 * i) ^ 3 + (7 + 9 * i) * (10 – 4 * i)

12. Scrieţi un program care citeşte coordonatele a trei figuri geometrice formate doar din linii drepte şi determină şi
afişează doar segmentele care se înscriu în suprafaţa unui dreptunghi ale cărui coordonate vor fi şi ele citite de la
tastatură. Precizare: această operaţie, denumită în limba engleză „clipping”, este foarte importantă în afişarea
grafică a informaţiei.

13. Scrieţi un program care citeşte coordonatele unui graf orientat şi îi ordonează vârfurile astfel încât toate arcele să
aibă aceeaşi 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ă aceeaşi orientare.

14. Scrieţi un program care citeşte un fişier reprezentând un program C şi scrie la ieşire acelaşi program în care
acoladele corespunzătoare - ‚{‘ respectiv ‚}’ - au fost aşezate 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 aceeaşi coordonată cu cele
două acolade corespunzătoare.

15. Scrieţi un program care citeşte un arbore n-ar (n este un număr natural) şi îi scrie reprezentarea fiu – frate.
Precizare: în reprezentarea fiu - frate un arbore n-ar este reprezentat ca un arbore binar astfel încât pentru un vârf x
legătura stânga reprezintă primul fiu iar legătura dreapta reprezintă fratele.

16. Scrieţi un program care citeşte un număr natural n (cu maxim 10 cifre) şi determină toate numerele ce pot fi
obţinute mutând pe rând prima cifră a numărului n şi a celor obţinute pe parcurs pe ultima poziţie.
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. Scrieţi un subprogram care să calculeze valoarea 2 la puterea 3000. Transformaţi apoi subprogramul pentru
calculul oricărei puteri adică: n la puterea m (n < 10, m < 3001, m > 0, n şi m întregi).

18. Scrieţi un program care citeşte polinoame rare şi le memorează sub forma unei liste simplu înlănţuite, unde pentru
fiecare monom, se memorează gradul şi coeficientul. Scrieţi o funcţie pentru suma a două polinoame rare,
specificate ca parametru.

19. Scrieţi un program care citeşte 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 conţine în interior toate cele n puncte
date, precum şi raza cercului. Precizări: datele vor fi citite din fişierul text „PUNCTE.TXT” , ce are pe prima linie
valoarea lui n, iar pe următoarele n linii coordonatele carteziene ale punctelor, câte două pe linie (x respectiv y),
valori reale.

20. Scrieţi un program care citeşte fişierul text „TEST.IN” care conţine un text scris pe mai multe linii şi afişează
toate caracterele folosite, codul ASCII corespunzător precum şi frecvenţa lor de apariţie.

21. Scrieţi un program care estimează cu 6 zecimale numărul π (3.1415926535...) în modul următor:
a) Se vor genera perechi de numere pseudo-aleatoare de tipul (x, y) cu 0 < x, y < 1;
b) Se vor număra câte 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 × <numărul_de_puncte_din_interiorul_sfertului_de_cerc> / <numărul_total_de_puncte>.

22. Scrieţi un program care să citească elementele a două matrice, fiecare dintr-un fişier, să calculeze matricea produs
şi să o tipărească într-un al treilea fişier. Matricele vor fi structurate în fişiere pe linii şi coloane. Se va afişa un
mesaj de eroare dacă înmulţirea matricelor nu este posibilă.

23. Scrieţi un program care citeşte elementele unei matrice pătrate, dintr-un fişier ASCII, calculează matricea
transpusă şi o tipăreşte într-un alt fişier.
Precizări: Matricea va fi structurată în primul fişier pe linii şi coloane astfel:
1.0 -1.33 3.44
-3.14 5.67 0
0 4.67 10.01

72
24. Scrieţi un program care citeşte din fişierul „INPUT.TXT” două propoziţii scrise fiecare pe câte o linie.
Propoziţiile conţin cuvinte formate din literele alfabetului englez. Orice alt caracter este considerat separator.
Programul:
− va afişa numărul de cuvinte din fiecare propoziţie;
− va verifica dacă ultimul cuvânt din prima propoziţie este o anagramă (are aceleaşi litere) a ultimului cuvânt din
cealaltă propoziţie. Pentru verificarea cuvintelor scrieţi şi folosiţi o funcţie recursivă.
Precizări:
Rezultatele se vor scrie în fişierul „OUTPUT.TXT” astfel:
− pe primele două linii programul va scrie numărul de cuvinte din fiecare propoziţie;
− pe ultima linie va scrie mesajul „DA” sau „NU” pentru cazurile în care ultimele cuvinte sunt sau nu anagrame.

25. Scrieţi un program care citeşte fişierul „AMENZI.TXT” care conţine evidenţa amenzilor de circulaţie pe o
perioadă dată. Fiecărui conducător auto i se alocă 4 linii: prima linie va conţine numele, cea de a doua numărul de
înmatriculare al maşinii, ce de a treia suma de bani corespunzătoare amenzii şi cea de a patra dacă amenda a fost
sau nu plătită (0 – neplătită, 1 - plătită). Programul va citi mai întâi numărul de înregistrări, n. Apoi programul:
− va afişa suma de bani rezultată din amenzi, precum şi numele şoferilor şi numărul maşinii care a plătit amenzile
cele mai mari;
− numele şoferilor care nu au plătit amenda/amenzile ordonate alfabetic;
− procentul de amenzi neîncasate.

26. Scrieţi un program care citeşte lista abonaţilor telefonici dintr-un oraş dintr-un fişier care conţine numărul de
telefon şi numele abonatului pe câte o linie. Programul va crea o listă de premiere care să cuprindă abonaţii al
căror numere de telefon cuprind doar cifre pare iar prima şi ultima cifră sunt proporţionale.

27. Scrieţi un program care citeşte două fişiere ASCII structurate astfel:
a. primul fişier va conţine, structurat pe linii, numele şi prenumele candidaţilor la un concurs de admitere, separate
prin unul sau mai multe spaţii, în formatul <nume> <prenume>;
b. al doilea fişier va conţine, structurat pe linii, media la examenul de admitere.
Programul va asocia numele şi prenumele persoanei de la linia i din primul fişier cu nota de la linia i din al doilea
fişier. Programul va concatena cele trei câmpuri (numele, prenumele şi nota), le va sorta în ordinea crescătoare a
mediei şi va scrie rezultatul într-un al treilea fişier ASCII.
Exemple de fişiere:
fişier1.txt
CONSTANTIN Ioana
POPESCU George
VASILESCU Costin
fişier2.txt
8.66
9.52
7.89
fişier3.txt
POPESCU George 9.52
CONSTANTIN Ioana 8.66
VASILESCU Costin 7.89

28. Scrieţi un program care citeşte două fişiere ASCII structurate astfel:
a. primul fişier va conţine, structurat pe linii, numele şi prenumele angajaţilor unei firme, separate prin unul sau
mai multe spaţii, în formatul <nume> <prenume>;
b. al doilea fişier va conţine, structurat pe linii, data naşterii, în formatul <zi> <luna> <an>.
Programul va asocia numele şi prenumele persoanei de la linia i din primul fişier cu data naşterii de la aceeaşi linie
din al doilea fişier. Programul va concatena cele cinci câmpuri (numele, prenumele, zi, luna, an), le va sorta în
ordinea descrescătoare a vârstei şi va scrie rezultatul într-un al treilea fişier ASCII.
Exemplu:
fişier1.txt
CONSTANTIN Ioana
POPESCU George
VASILESCU Costin
fişier2.txt
8 Ianuarie 1978
27 August 1980
16 Octombrie 1978
fişier3.txt
CONSTANTIN Ioana 8 Ianuarie 1978
VASILESCU Costin 16 Octombrie 1978
POPESCU George 27 August 1980

73
29. Scrieţi un program care să recunoască într-un fişier sursă C directiva de preprocesare „#define” şi care să
genereze un alt fişier preprocesat.
Exemplu:
fişier1.c
#include <stdio.h>
#include <stdlib.h>
#define PI 3.1415
int main() {
printf("pi = %f", PI);
return 0;
}
fişier2.c
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("pi = %f", 3.1415);
return 0;
}

30. Scrieţi un program care citeşte fişierul „TEXT.TXT” care conţine un text ce se încheie cu o linie goală. Să se
afişeze toate cuvintele textului în ordine alfabetică.
Precizări:
− lungimea unui cuvânt este de maxim 25 caractere;
− numărul de cuvinte din text este cel mult 100;
− cuvintele sunt despărţite printr-un spaţiu;
− se va folosi sortarea prin inserţie.
Rescrieţi programul pentru a putea prelucra un text oricât de mare şi în care cuvintele sunt despărţite prin orice tip
de spaţiu sau semn de punctuaţie.

31. Scrieţi un program care construiască un fişier cu înregistrări de tip bibliotecă cu următoarele câmpuri:
Numele autorului
Titlul cărţii
Editura
Anul apariţiei
Lista cuvintelor cheie

Programul va permite următoarele operaţii:


a. introducerea unei înregistrări noi în bibliotecă;
b. ştergerea unei înregistrări din bibliotecă;
c. extragerea într-un fişier nou a înregistrărilor în funcţie de valoarea unui anumit câmp:
Numele autorului
Titlul cărţii
Editura
Anul apariţiei
Existenţa unui anumit cuvânt în lista cuvintelor cheie
d. sortarea fişierului în ordinea crescătoare a numelor autorilor (ordine lexicografică), iar pentru acelaşi autor,
înregistrările se ordonează în funcţie de anul apariţiei;
e. interclasarea a două fişiere ordonate conform punctului anterior. Numele fişierelor se citesc de la tastatură.
Programul va construi un fişier ordonat care conţine reuniunea celor două fişiere iniţiale şi va elimina duplicatele
din fişier.

32. Scrieţi un program care citeşte fişierul text „INTRARE.IN” care conţine 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ă.
Rescrieţi programul extinzându-l pentru a putea împărţirea textul în k coloane.

74

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