Sunteți pe pagina 1din 12

Universitatea Tehnică a Moldovei

FCIM
Departamentul Informatică și Ingineria Sistemelor

RAPORT
la lucrarea de laborator nr. 1,2

la Structuri de date și Algoritmi


Tema: Analiza eficienței prelucrării structurilor de date cu pointeri

A efectuat: Balaban Vladislav st. gr. TI-193

A verificat: Vitalii Mititelu

Chişinău – 2019
Sarcina şi obiectivele:
• De studiat şi însuşit materialul teoretic din lucrarea dată si prin lansarea exerciţiilor la execuţie pentru
analiza şi evidenţierea esenţialului prelucrării structurilor de date cu pointeri în elaborarea modelelor
soluţiei prin explicaţii, argumentări şi organigrame.
• In baza materialului teoretic la prima lucrare de laborator efectuati cate 2 exerciţii (unul de la inceput
si altul de la alt capat ) şi să se analizeze algoritmii şi si specificul organizarii programelor cu si fără
pointeri (declarări şi parcurgeri cu pointeri). Pentru aprofundarea înţelegerii implementarii pointeriilor in
lucrarea de laborator nr. 2 să se dezvolte algoritmii şi programele cu pointeri pentru condiţiile
problemelor din Anexa1a (Anexa2. De elaborat algoritmul și de scris programul cu pointeri si POINTERI
LA FUNCTII, propuse de profesor) şi să se elaboreze scenariile succinte de soluţionare prin pointeri cu
calculele de verificare şi explicaţii. Rularea programelor în limbajul C cu afişarea tuturor variabilor de
intrare, intermediare şi finale.
• În raport să fie expuse toate programele şi calculele efectuate. Să se analizeze tehnica programării
eficiente cu pointeri în baza exerciţiilor şi variantelor problemelor efectuate pentru diverse situaţii cu
argumentări.
Fiecare temă conţine cate două probleme care vor fi rezolvare cu mijloacele limbajului C (diferite
modele de date şi obiecte). Temele se iau în conformitate compartimentele propuse.
Lucrarea se consideră efecutată după ce studenţii demonstrează profesorului funcţionarea corectă a
programelor la calculator şi apoi prezintă darea de seamă cu analiza rezultatelor. Darea de seamă include:
foaia de titlu şi pentru fiecare lucrare să se descrie algoritmul de rezolvare a problemei, listingul
programului cu srinshot-urile, dotat cu comentariile de rigoare, Datele de intrare şi rezultatele să fie folosite
în simularea numerică şi să fie analizate în comparaţie cu rezultatele obţinute, concluzia şi bibliografia
studiată.
1. În raport să fie expuse toate programele şi calculele efectuate. Să se analizeze tehnica
programării eficiente cu pointeri în baza exerciţiilor şi variantelor problemelor efectuate pentru
diverse situaţii cu argumentări, elaborind algoritmii.

INTREBĂRI ŞI EXERCIŢII
Chestiuni teoretice in mod deosebit
1. În ce constă operaţia de incrementare a pointerilor?

Exemple de incrementare:
*p++ operatorul ++ incrementeaza pointerul
(*p)++ operatorul ++ incrementeaza continutul pointerului
*++p operatorul ++ incrementeaza pointerul
++(*p) operatorul ++ incrementeaza continutul pointerului.

2. Tablouri de pointeri.
Numele unui tablou x:
 este un pointer, deoarece are ca valoare adresa de memorie a primului sau element, adica
x=&x0
 este un pointer constant, lui nu i se poate atribui o alta valoare (adresa).
Daca p este un pointer spre tip si t este un tablou având elemente de tipul tip, atunci
 o atribuire de forma p=t este corecta, p va pointa spre primul element al tabloului
 o atribuire de forma t=p este incorecta, deoarece se încearca modificarea unui pointer
constant
În consecinta, urmatoarele declaratii sunt echivalente
char a10 si char *s;
int i10 si int *i;
double d1010 si double **d;

3. Ce sunt pointerii generici?

Tipul void * e folosit ca tip de adresă generică (nu indică nimic)


– poate fi atribuit în ambele sensuri la orice alt pointer, fără ( )
– nu poate fi dereferenţiat fără conversie (nu ştim ce indică)

Nu putem face dereference la void, sau sa il incrementam-eroare. Doar sa ne afiseze adresa.

4. Ce operaţii se pot realiza asupra variabilelor pointer?


Operatiile care se pot realiza cu pointeri sunt:
* comparatia
*0 adunarea unui pointer cu un intreg
*1 scaderea unui intreg dintr-un pointer
5. De ce numele unui pointer este rvalue? Poate aparea in dreapta unei atribuiri.
6. Ce fel de variabile pot constitui operandul operatorului de deferenţiere? Variabilele dinamice
7. Operatorul de referenţiere: & (preia adresa variabilei)
8. Unui pointer generic i se poate atribui valoarea unui pointer cu tip? Da.
Exercitiul1: Analizati efectele utilizarii pointerilor la inversarea ordinii de apariţie a elementelor unui şir .

Programul dat:
#include<stdio.h>

void main(void)

{ int sir[]={1,2,3,4,5,6,7,8,9}, aux;

int *p_init,*p_fin;

for(p_init=sir,p_fin=sir+sizeof(sir)/sizeof(sir[0])-1;

p_init<p_fin; p_init++,p_fin--){ aux=*p_init; *p_init=*p_fin; *p_fin=aux; }

for(p_init=sir; p_fin=sir+sizeof(sir)/sizeof(sir[0]); p_init++)

printf("\n %d",*p_init);

}
Programul modificat:
1. #include<stdio.h>
2. void main(void)
3. { int sir[]={1,2,3,4,5,6,7,8,9}, aux;
4. int *p_init,*p_fin;
5. for(
6. p_init=sir ,p_fin=sir+sizeof(sir)/sizeof(sir[0])-1;
7. p_init<p_fin;
8. p_init++,p_fin--
9. )
10. {
11. aux=*p_init;
12. *p_init=*p_fin;
13. *p_fin=aux;
14. }
15. for(p_init = sir; p_init<sir+sizeof(sir)/sizeof(sir[0]);p_init++)
16. printf("\n %d",*p_init);
17. }

Explicație :
Programul inițial avea doar o singură erroare, el nu afișa cum trebuie elementele, condiția din
ciclul for nu era logică, eu am corectat- o, în linia (15) am pus p_init< , și acum pointerul prelua
adresa primului element al tabloului, și in fiecare iterație prelua adresa următoare al elementului,
atâta timp cât p_init este mai mic decât adresa ultimului element.
În liniile 11 – 13 avea loc așa numita sortare ,,bubble – sort,, dar cu pointeri.
Exercitiul .30: Da-ţi la execuţie pentru a înţelege principiile principale. Analizaţi definiţiile funcţiilor, modul de
organizare a apelurilor şi obţinere a rezultatelor prin antetul funcţiilor. Face-ţi îmbunătăţiri şi rulaţi din nou. Comparaţi.

Programul modificat:

#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <stdbool.h>

void SimetricPare(char*);
void SimetricImpare(char*);
void Transpune(char*);
char* Trim(char*);
void EnterProp(char*);
void SimetricImpare(char*);
void Calculate(char*);
int countPare = -1, countImpare = 50, probels = 0, len;
char *cMaiLung, *cMaiScurt, *cuvintele[10];
bool bPar = false, bImpar = false, entered = false;

int main(void)
{
char cPropozitia[125];
int i=0, j, mi;
printf("Menu:\n----------\n");
printf("1. Introducerea propozitiei\n");
printf("2. Calcule\n");
printf("3. Simetric lung pe poz.pare\n");
printf("4. Simetric scurt pe poz.impare\n");
printf("5. Transpusa\n");
printf("6. Iesire\n");
printf("\n-=Alegeti un punct al meniului=-:\n");
mi = getch();
while(mi!=(int)'6')
{ switch(mi)
{
case (int)'1': EnterProp(cPropozitia); break;
case (int)'2': if(!entered){printf("Introd. propozitia!"); break;}Calculate(cPropozitia);
break;
case (int)'3': if(!entered){printf("Introd. propozitia!");
break;}if(bPar)printf("\nSimetric Lung de pe pare: %s\n", cMaiLung);else printf("\n\nSimetric Lung pe pare
nu a fost gasit\n"); break;
case (int)'4': if(!entered){printf("Introd. propozitia!");
break;}if(bImpar)printf("\nSimetric Scurt de pe impare: %s\n", cMaiScurt);else printf("\n\nSimetric Scurt pe
impare nu a fost gasit\n"); break;
case (int)'5':
{ if(!entered){printf("Introd. propozitia!"); break;}
for(i=0; i<probels+1; i+=2)
{ Transpune(cuvintele[i]); }
if(!bPar || !bImpar)
{
puts("Propozitia transpusa: ");
for(int i=0; i<len; i++) printf("%c", cPropozitia[i]);
}
else printf("Cuvinte transpuse nu sunt\n");
}
break;
default: printf("Comanda necunoscuta\n"); break;
}
mi = getch();
}
return 0;
}

void EnterProp(char* c)
{ printf("Introduceti propozitia: ");
gets(c);
c = Trim(c);
entered = true;
return;
}

void Calculate(char* c)
{ int i, j;
len = strlen(c);
for(i=0; i<strlen(c); i++)
if(c[i]==' ')probels++;
/* SPLIT */
cuvintele[0] = strtok(c, " ");
for(i=0; i<probels; i++)
cuvintele[i+1] = strtok(NULL, " ");
/* *** */
for(i=0, j=1; i<probels+1; i+=2, j+=2) //j-pare, i-impare
{
SimetricImpare(cuvintele[i]);
if(j<probels+1)SimetricPare(cuvintele[j]);
}
printf("\nCalcule si operatii cu propozitia au fost efectuate\n");
return;
}

void SimetricPare(char* c)
{ int j=strlen(c)-1, i;
for(i=0; i<strlen(c)/2; i++, j--)
if(c[i]!=c[j])return;
bPar = true;
if(countPare<(int)strlen(c))
{ cMaiLung = c;
countPare = strlen(c);
}
return;
}

void SimetricImpare(char* c)
{ int j=strlen(c)-1, i;
for(i=0; i<strlen(c)/2; i++, j--)
if(c[i]!=c[j])return;
bImpar = true;
if(countImpare>(int)strlen(c))
{
cMaiScurt = c;
countImpare = strlen(c);
}
return;
}
void Transpune(char* cuvintul)
{ int i, j=strlen(cuvintul)-1;
char c;
for(i=0; i<strlen(cuvintul)/2; i++, j--)
{
c = cuvintul[i];
cuvintul[i] = cuvintul[j];
cuvintul[j] = c;
}
return;
}
char* Trim(char* c)
{ int index, i, j;
char* str2trim;
str2trim = c;
index = strlen(str2trim);
for(i=0, j=0; i<strlen(str2trim); i++)
{
if(str2trim[i]==' ' && str2trim[i+1]==' '){ index--; continue; }
str2trim[j] = str2trim[i];
j++;
}
str2trim[index] = '\0';
printf("%s",str2trim);
return str2trim;
}

Analiza-
*cMaiLung – In caz ca s-a gasit cuvint palindrom pe pozitie para , pointerul *cMaiLung va
lua din tabloul de pointeri cuvintele[10] cuvintul palindrome.

*cMaiScurt – Asimilar(invers) pointerului *cMaiLung ;

char* Trim(char*) – Functie care returneaza un pointer si primeste ca argument un pointer

Sarcini laborator 2
1. Scrieţi un program cu pointeri care generează o mie de seturi de cinci numere aleatoare cuprinse între
1 şi 40, în final afişând frecvenţa cu care a fost generat fiecare număr.

#include <stdio.h>
#include <stdlib.h>
void main()
{
int i,c,s=0;
int *p_a;
p_a = (int*) calloc(41,sizeof(int)); // alocam memorie, si o umplem cu 0
for(i=0;i<5000;i++)
{
if(i%5==0) printf("\n");
c=rand()%40+1;
printf("%3.d ",c);
p_a[c]++;
}
for(i=1;i<=40;i++){
printf("\nnumarul %d s-a intilnit de %d ori",i,p_a[i]);s+=p_a[i];}
free(p_a);
printf("\n\ns=%d",s);
}
Analiză: Inițial am alocat memorie pentru tabelul. Am alocat 41 de locuri dar nu 40 deoarece
programa lucreaza dupa principiul: cand se intilneste elementul X, elementul cu indicele X al
tabloului primeste +1, deci pointerul dat avea nevoie de 41 de locuri, caci 0 tot intra in ele, desi nu il
foloseam in program.
La fel pentru a controla corectitudinea programului am introdus variabila s, care reprezinta suma
numarului de intilniri a tuturor numerelor [1 – 40], si asa cum s –a cerut o mie de seturi a cate 5
numere, am primit s = 5000
83. (a)Functie care schimba intre ele doua linii i si j dintr-o matrice patratica.
(b)Program care foloseste functia pentru a aduce pe diagonal principala numai elemente nenule (daca este
posibil). Se va afisa matricea obtinuta prin schimbari de linii.

(a)
#include <stdio.h>
#include <stdlib.h>
void afisare(int **pt,int n);
void citire(int **pt,int n);
void schimb(int **pt,int z, int x,int n);
void main() {
//creare pointer la functie
void(*fooint)(int **pt,int n);
int **t = NULL;
int i,j,n;
printf("Introdu dimensiunile matricii:\n");
scanf("%d",&n);
// alocam memorie pentru matrice
t = (int**) calloc(n,sizeof(int*));
for (int i = 0; i < n; i++)
{
t[i] = (int*) calloc(n,sizeof(int));
}
// fooint pointer la fun. citire
fooint = citire;
fooint(&*t, n);

printf("Introdu numarul randurilor care doriti sa le schimbati cu locul:");


printf("\ni="); scanf("%d",&i);
printf("\nj="); scanf("%d",&j);

schimb(&*t,i-1,j-1,n);

// fooint pointer la fun. afisare


fooint = afisare;
fooint(&*t, n);
// golirea memoriei
for (i = 0; i < n; i++) {
free(t[i]);
}
free(t);
}
void citire(int **pt,int n){
printf("Introduceti elementele matricii:\n\n");
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
scanf("%d",&pt[i][j]);
}
void afisare(int **pt,int n){
printf("\n");
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
printf("%d ",pt[i][j]);
printf("\n");
}
}
void schimb(int **pt,int z, int x,int n){
int m2[n];
for(int i=0;i<n;i++)
{
m2[i] = pt[z][i];
pt[z][i] = pt[x][i];
}
for(int i=0;i<n;i++)
pt[x][i] = m2[i];
}

(b)

#include <stdio.h>
#include <stdlib.h>
void afisare(int **pt,int n);
void citire(int **pt,int n);
void inloc(int **pt,int i,int n);
void main() {
//creare pointer la functie
void(*fooint)(int **pt,int n);
int **t = NULL;
int i,j,n;
printf("Introdu dimensiunile matricii:\n");
scanf("%d",&n);
// alocam memorie pentru matrice
t = (int**) calloc(n,sizeof(int*));
for (int i = 0; i < n; i++)
{
t[i] = (int*) calloc(n,sizeof(int));
}
// fooint pointer la fun. citire
fooint = citire;
fooint(&*t, n);
for(i = 0;i < n; i++)
if (t[i][i] == 0)
{
inloc(&*t,i,n);
}
// fooint pointer la fun. afisare
fooint = afisare;
fooint(&*t, n);
// golirea memoriei
for (i = 0; i < n; i++) {
free(t[i]);
}
free(t);
}
void citire(int **pt,int n){
printf("Introduceti elementele matricii:\n\n");
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
scanf("%d",&pt[i][j]);
}
void afisare(int **pt,int n){
printf("\nMatricea modificata:\n\n");
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
printf("%d ",pt[i][j]);
printf("\n");
}
}
void inloc(int **pt,int i,int n)
{
for(int j = 0;j < n; j++)
if (pt[i][j]!=0){
pt[i][i] = pt[i][j];
pt[i][j] = 0;
break;
}
}
Analiza: Pointerii ne –au dat noi posibilitati in programare de a modifica matrici, si nu doar una,
cu ajutorul pointerilor, in programul dat am folosit pointeri la functia de citire si de afisare.
In program am alocat memorie pentr n*n elemente de tip int (cu ajutorul calloc –ului) si massivul
cu marimea n*n are toate elementele egale cu 0.

Concluzie: In lucrarea data de laborator am exersat lucrul cu pointerii, am utilizat functia random.
Am folosit pointeri la functie, desi se putea si fara ei, dar asa cere conditia, si in unele cazuri ele
sunt foarte comode. In decursul acestei lucrari de laborator am invatat cum mai eficient sa folosesc
pointerii

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