75
Dragoş Burileanu Dragoş Burileanu Dragoş Burileanu Dragoş Burileanu Claudius Dan Claudius Dan Claudius Dan Claudius Dan Marius Pădure Marius Pădure Marius Pădure Marius Pădure

Indrumar Laborator Programarea calculatoarelor

Embed Size (px)

Citation preview

Page 1: Indrumar Laborator Programarea calculatoarelor

Dragoş BurileanuDragoş BurileanuDragoş BurileanuDragoş Burileanu Claudius DanClaudius DanClaudius DanClaudius Dan

Marius PădureMarius PădureMarius PădureMarius Pădure

Page 2: Indrumar Laborator Programarea calculatoarelor

1

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.

Page 3: Indrumar Laborator Programarea calculatoarelor

2

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.

Page 4: Indrumar Laborator Programarea calculatoarelor

3

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.

Page 5: Indrumar Laborator Programarea calculatoarelor

4

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

Page 6: Indrumar Laborator Programarea calculatoarelor

5

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

Page 7: Indrumar Laborator Programarea calculatoarelor

6

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

Page 8: Indrumar Laborator Programarea calculatoarelor

7

���� 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ă.

Page 9: Indrumar Laborator Programarea calculatoarelor

8

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.

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

Page 10: Indrumar Laborator Programarea calculatoarelor

9

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

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

Page 11: Indrumar Laborator Programarea calculatoarelor

10

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;

Page 12: Indrumar Laborator Programarea calculatoarelor

11

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

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

Page 13: Indrumar Laborator Programarea calculatoarelor

12

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.

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

Page 14: Indrumar Laborator Programarea calculatoarelor

13

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;

}

Page 15: Indrumar Laborator Programarea calculatoarelor

14

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

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

Page 16: Indrumar Laborator Programarea calculatoarelor

15

P4.4 ScrieŃi un program care calculează şi afişează rădăcinile ecuaŃiei de gradul doi cu coeficienŃi reali 2 0a x bx c+ + = (coeficienŃii fiind citiŃi de la tastatură); se va presupune, pentru simplificare, că 0a ≠ .

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

}

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

Page 17: Indrumar Laborator Programarea calculatoarelor

16

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

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

Page 18: Indrumar Laborator Programarea calculatoarelor

17

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

Page 19: Indrumar Laborator Programarea calculatoarelor

18

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 0ax b+ = (coeficienŃii fiind citiŃi de la tastatură); discuŃie.

IndicaŃie: ecuaŃia are soluŃie dacă 0a ≠ ; dacă 0a = : dacă 0b = ecuaŃia este nedeterminată, iar dacă 0b ≠ 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:

3 , pentru 0

3 , pentru x [0, 4]

3 9 , pentru 4

x x

y

x x

− + <

= ∈ − >

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.

Page 20: Indrumar Laborator Programarea calculatoarelor

19

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

Page 21: Indrumar Laborator Programarea calculatoarelor

20

���� 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 2n ≥

şi se afişează suma n+++ ...21 .

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

Page 22: Indrumar Laborator Programarea calculatoarelor

21

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

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

Page 23: Indrumar Laborator Programarea calculatoarelor

22

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

Page 24: Indrumar Laborator Programarea calculatoarelor

23

���� DiscuŃie:

– Programul foloseşte un ciclu cu contor pentru a căuta divizorii; se parcurge intervalul [2, / 2]n ,

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, / 2]i 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).

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

Page 25: Indrumar Laborator Programarea calculatoarelor

24

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

1 1 1 2 1s

n= + + +

+ + +K .

2. ScrieŃi un program care citeşte pe n natural şi afişează valoarea expresiei: 0! 1! 2! !s n= + + + +K

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

Page 26: Indrumar Laborator Programarea calculatoarelor

25

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

Page 27: Indrumar Laborator Programarea calculatoarelor

26

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

Page 28: Indrumar Laborator Programarea calculatoarelor

27

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

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

Page 29: Indrumar Laborator Programarea calculatoarelor

28

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

Page 30: Indrumar Laborator Programarea calculatoarelor

29

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.

– 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"); }

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

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

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

A[1][0] A[1][1] (6.a) (6.b)

Page 31: Indrumar Laborator Programarea calculatoarelor

30

/* 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;

Page 32: Indrumar Laborator Programarea calculatoarelor

31

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

Page 33: Indrumar Laborator Programarea calculatoarelor

32

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

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

Page 34: Indrumar Laborator Programarea calculatoarelor

33

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

Page 35: Indrumar Laborator Programarea calculatoarelor

34

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 |

Page 36: Indrumar Laborator Programarea calculatoarelor

35

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

Page 37: Indrumar Laborator Programarea calculatoarelor

36

#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

Page 38: Indrumar Laborator Programarea calculatoarelor

37

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

Page 39: Indrumar Laborator Programarea calculatoarelor

38

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

Page 40: Indrumar Laborator Programarea calculatoarelor

39

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

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

Page 41: Indrumar Laborator Programarea calculatoarelor

40

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;

Page 42: Indrumar Laborator Programarea calculatoarelor

41

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

Page 43: Indrumar Laborator Programarea calculatoarelor

42

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:

( )

>−⋅

==

1pentru,!1

1pentru,1!

nnn

nn

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:

Page 44: Indrumar Laborator Programarea calculatoarelor

43

<−

>−

=

=

abbba

ababa

baa

ba

dacă),(c.m.m.d.c.

dacă),(c.m.m.d.c.

dacă

),(c.m.m.d.c.

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

Page 45: Indrumar Laborator Programarea calculatoarelor

44

���� 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:

>⋅

== − 1dacă

1dacă1 pnn

pnn

p

p

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

Page 46: Indrumar Laborator Programarea calculatoarelor

45

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.

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

Page 47: Indrumar Laborator Programarea calculatoarelor

46

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

Page 48: Indrumar Laborator Programarea calculatoarelor

47

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.

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

Page 49: Indrumar Laborator Programarea calculatoarelor

48

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.

Page 50: Indrumar Laborator Programarea calculatoarelor

49

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.

Page 51: Indrumar Laborator Programarea calculatoarelor

50

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;

Page 52: Indrumar Laborator Programarea calculatoarelor

51

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.

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

Page 53: Indrumar Laborator Programarea calculatoarelor

52

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

Page 54: Indrumar Laborator Programarea calculatoarelor

53

/* 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>

Page 55: Indrumar Laborator Programarea calculatoarelor

54

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'

Page 56: Indrumar Laborator Programarea calculatoarelor

55

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

Page 57: Indrumar Laborator Programarea calculatoarelor

56

���� 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]);

}

}

}

Page 58: Indrumar Laborator Programarea calculatoarelor

57

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

Page 59: Indrumar Laborator Programarea calculatoarelor

58

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

Page 60: Indrumar Laborator Programarea calculatoarelor

59

���� 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

Page 61: Indrumar Laborator Programarea calculatoarelor

60

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

Page 62: Indrumar Laborator Programarea calculatoarelor

61

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

Page 63: Indrumar Laborator Programarea calculatoarelor

62

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",

Page 64: Indrumar Laborator Programarea calculatoarelor

63

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

Page 65: Indrumar Laborator Programarea calculatoarelor

64

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

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

Page 66: Indrumar Laborator Programarea calculatoarelor

65

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++) {

Page 67: Indrumar Laborator Programarea calculatoarelor

66

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++) {

Page 68: Indrumar Laborator Programarea calculatoarelor

67

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++) {

Page 69: Indrumar Laborator Programarea calculatoarelor

68

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

Page 70: Indrumar Laborator Programarea calculatoarelor

69

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

Page 71: Indrumar Laborator Programarea calculatoarelor

70

/* 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;

Page 72: Indrumar Laborator Programarea calculatoarelor

71

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.

Page 73: Indrumar Laborator Programarea calculatoarelor

72

Precizări: 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

Page 74: Indrumar Laborator Programarea calculatoarelor

73

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

Page 75: Indrumar Laborator Programarea calculatoarelor

74

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.