Structuri de date
CLASA TIMP]
1.OBIECTIVUL PROBLEMEI
Proiectul urmareste implementarea unei clase numita Timp, care sa fie folosita pentru: gestionarea principalelor operatii si functii cu date de tipul timp (hh:mm:ss), aflarea timpului local, aflarea timpului din principalele orase ale lumii precum si a decalajului orar dintre doua orase sau zone.
2. NECES 323d32d ITATEA SI MIJLOACELE DE REALIZARE
Programul, in esenta, este foarte user-friendly, permitand utilizatorilor alegerea uneia sau mai multor operatii cu date de tipul timp, afisand in acelasi timp mesaje corespunzatoare fiecarei optiuni. Ca si structura, programul surprinde mare parte din paleta operatiilor posibile la nivelul acestui tip de date oferind o baza solida in realizarea unor aplicatii mult mai complexe. De asemenea poate fi inclus intr-un fisier de tip header si utilizat ulterior in alte programe care foloseste date de tipul timp.
3. STRUCTURA PROGRAMULUI
In principiu, proiectul implementeaza o structura de baza 'timp' (campurile: int ora, int minut, int secunda) care 'imprumuta' comportamentul unei clase din programarea orientata obiect, in sensul definirii unor metode si apelarii lor pornind de la un articol al structurii respective, prin calificare. Prin urmare, am declarat ca si campuri in structura diferiti pointeri la functii care primesc apoi adresa principalelor functii cu date de tipul timp, definite in afara structurii.
Aditional am implementat si o structura clasica ('fusOrar'), utilizata in popularea unui vector care retine principalele diferente de fus orar. Ulterior acest vector este transmis ca parametru in functiile care calculeaza timpul in diferite orase ale lumii precum si decalajul orar dintre doua orase sau zone.
In main am creat un meniu care vine in intampinarea optiunilor utilizatorilor, implementand doar acele functii care sunt apelate in mod explicit de catre acestia.
4. STRUCTURILE DE DATE UTILIZATE INTERN
Pentru implementarea programului am utilizat urmatoarele structuri de date: doua structuri de tip articol (una numita “timp” care este structura de baza si una numita “fusOrar” utilizata pentru retinerea diferentelor de fus orar in principalele orase ale lumii), un vector alocat dinamic (care incarca practic diferentele de fus orar) si un fisier.
a)ARTICOLUL
Articolele sunt structuri de date neomogene si continue. Ele au un numar fix de elemente numite campuri, iar accesul la acestea se face direct. Utilitatea articolelor apare in manipularea datelor complexe (care presupun stocarea unui numar de caracteristici pentru fiecare entitate) si in crearea structurilor de date evoluate.
Articolul poate fi reprezentat sub forma de arbore, ale carui noduri sunt asociate componentelor structurii. Componentele de pe ultimul nivel sunt scalare si se numesc date elementare sau campuri. Datele de pe celelalte niveluri, denumite date de grup, se constituie prin agregarea datelor de pe nivelurile inferioare. Data de grup de cel mai inalt nivel (radacina arborelui) corespunde articolului in ansamblu. Conceptual, datele de grup de pe diverse niveluri au aceleasi proprietati ca si articolul, ceea ce permite ca aceasta structura sa fie construita recursiv, prin descompunerea in structuri cu aceleasi proprietati.
Declararea impreuna a tipului articol si a variabilelor de acest tip se realizeaza conform sintaxei:
struct tip_articol var1,var2,…,varn;
unde tip_articol este identificatorul asociat tipului articol, iar var1, var2,…, varn
sunt identificatorii asociati variabilelor de tipul articol declarat. O variabila de tip articol poate fi declarata si ulterior definirii tipului:
struct tip_articol var1;
Variabilele de tip articol se reprezinta intern ca succesiuni de campuri elementare, cu reprezentarea interna si lungimea fizica specifice tipurilor lor. Lungimea zonei de memorie rezervata pentru variabila de tip articol rezulta din insumarea lungimilor campurilor. Aceasta nu poate depasi 65520 octeti (ca orice variabila de tip structurat). Pentru structura unui articol isi dovedeste utilitatea operatorul sizeof, care asigura determinarea lungimii zonei de memorie asociate unei variabile sau unui tip de date.
Din punct de vedere fizic, identificatorii campurilor din descrierea articolului reprezinta deplasari fata de inceputul acestuia. Adresa fizica a unui camp rezulta din insumarea adresei articolului cu deplasarea sa. Structura arborescenta a articolelor poate fi exprimata sugestiv si prin machete, care evidentiaza componentele, natura, lungimea declarata si lungimea fizica ale acestora.
Datele de tip articol pot fi referite in doua moduri: global sau pe componente. Referirea globala este permisa numai in operatia de atribuire, cu conditia ca ambele variabile (sursa si destinatie) sa fie articole de acelasi tip. Referirea pe componente (prin numele lor) este o reflectare a faptului ca articolul este o structura cu acces direct. Referirea unor componente de tip articol din structura altui articol este posibila numai in operatia de atribuire, in conditiile precizate anterior la referirea globala. Referire campurilor unei structuri se face prin calificare, folosind operatorul. (punct). In referirea prin calificare, asigurarea identificarii unice a campurilor se realizeaza prin asocierea numelui acestora cu numele articolului carele contine. Constructia ramane la aceasta forma in cazul in care structura are numai doua niveluri: articolul si campurile elementare ale acestuia.
In articolele cu structura recursiva se realizeaza calificarea progresiva cu articolele de pe nivelurile superioare, primul calificator fiind numele articolului radacina. In lantul de calificari, numele articolului radacina este nume de variabila, celelalte fiind nume de campuri ale articolului. Daca anumite componente sunt structuri de date de alte tipuri (de exemplu masive sau siruri de caractere), in referirea elementelor lor se aplica, pe langa calificare, regulile specifice acestor structuri.
In ceea ce priveste articolul “fusOrar”, acesta are drept campuri numele
orasului si decalajul orar, fiind utilizat la declararea elementelor
vectorului (struct fusOrar **fo). Fiecare
(*fo)[*n].dec=d;
(*fo)[*n].nume=(char *) malloc ((strlen(buf)+1)*sizeof(char));
strcpy((*fo)[*n].nume,buf);
Articolul “timp” are drept campuri ora, numarul de minute si de secunde precum si o serie de pointeri la functii utilizati in apelarea functiilor specifice datelor de tipul “hh:mm:ss”. Operatiile elementare aplicate asupra acestui articol sunt:
a) atribuirea la nivel global folosind operatorul = :
x.pf4=modifCeasMinPlus;
y=x.pf4(min,x);
Copierea structurilor se face bit cu bit. In cazul in care structura contine pointeri, zonele de memorie referite trebuie copiate manual de catre programator. Singura exceptie o constituie masivele, care sunt copiate automat de compilator.
b) transmiterea ca argument in functie si returnarea ca rezultat:
struct timp modifCeasMinus(struct timp t,struct timp p)
Structurile de date, spre deosebire de masive, sunt transmise prin valoare. In cazul in care structura contine un masiv, acesta va fi copiat in intregime la momentul apelului.
b)VECTORUL (alocat dinamic)
Masivele sunt structuri de date omogene cu un numar finit si cunoscut de elemente, ce ocupa un spatiu contiguu de memorie, fiind caracterizate de urmatoarele elemente:
• numele
• tipul de data asociat
• numarul de dimensiuni
• numarul de elemente pentru fiecare dimensiune
Vectorii sunt masive unidimensionale care se declara folosind sintaxa (pentru masivele alocate static):
tip nume[n
unde:
• tip – tipul de data folosit; poate fi unul din tipurile de baza (int, float, char, …) sau un tip definit de utilizator (articole, obiecte)
• nume – numele prin care va fi referit vectorul
• n – numarul de elemente ale vectorului
Memorarea vectorilor se face intr-un spatiu continuu de memorie. Numele vectorului este de fapt un pointer catre adresa primului element. Dimensiunea totala a vectorului este calculata ca produs intre numarul de elemente si dimensiunea unui element. Accesul la elementele vectorului se face direct; compilatorul calculand adresa elementului pe baza indexului si a dimensiunii unui element. Numerotarea elementelor se face incepand cu zero. Pentru un vector v cu n elemente referirea elementelor se face folosind v[0], v[1], v[2], …, v[n-1].
Vectorii pot fi trimisi ca parametri in functii direct prin nume urmat de paranteze drepte. Toate modificarile efectuate de catre functie asupra valorilor stocate in vector vor fi vizibile si in apelator. Acest lucru este posibil datorita faptului ca prin nume se transfera de fapt adresa primului element din vector.
Prin urmare, pentru a memora un vector in heap este necesar sa se declare un pointer catre acel tip de data, apoi sa se rezerve memoria necesara.
(*fo)=(struct fusOrar*) malloc (dim*sizeof(struct fusOrar));
Pentru realizarea functiilor de afisare a ceasului intr-un oras dat si a decalajului dintre doua zone a fost necesara crearea unui vector care sa retina pentru fiecare oras decalajul orar. Vectorul a fost creat intr-o procedura (void incarcareVectorDecalaje(struct fusOrar **fo,int *n)) si transmis apoi ca parametru in functiile amintite mai sus (struct timp afisTimpOras (struct timp t,char*oras,struct fusOrar*fo,int n,int *ok); int afisDecalajOrase (char*o1,char*o2,struct fusOrar*fo,int n,int *ok1,int*ok2)
c)FISIERUL
Fisierul reprezinta termenul generic care desemneaza structurile de date externe. El este o multime (colectie) de date omogene din punct de vedere al semnificatiei si al cerintelor de prelucrare. In purtatorul extern, fisierul are, pe langa partea de date, si alte informatii de identificare (etichete).
Privit din punctul de vedere al prelucrarii, un fisier este o colectie ordonata de date, numite articole. Articolul este constituit dintr-o multime ordonata de valori ale unor caracteristici ce apartin, uzual, unei singure entitati (obiect, fenomen, proces etc.) din domeniul de activitate abordat.
Componentele articolului destinate diverselor caracteristici sunt denumite campuri de date. Depinzand de natura, ordinul de marime si forma de reprezentare externa a valorilor asociate, fiecare camp de date are o lungime, exprimata uzual in octeti. Lungimea unui articol este data de suma lungimilor campurilor care il compun. Dupa cum toate articolele dintr-un fisier au sau nu aceeasi lungime, se face distinctie intre fisierele cu articole de lungime fixa sau variabila. Modul de implementare fizica a celor doua tipuri de fisiere difera de la un sistem la altul si chiar de la un limbaj la altul.
Pe purtatorul fizic extern, partea de date a fisierului se prezinta ca o succesiune de octeti cu un continut binar fara semnificatie informationala. In momentul prelucrarii, prin descrieri si operatii adecvate, din succesiunea memorata extern se „decupeaza' entitati (articole, blocuri, linii sau campuri) cu structuri corespunzatoare prelucrarii. Tipul entitatii care se „decupeaza' depinde de tipul fisierului.
Principiile si regulile dupa care se memoreaza articolele unui fisier pe purtatorul extern, cu asigurarea protectiei si regasirii acestora, constituie metoda de organizare. In evolutia organizarii datelor externe s-au cristalizat mai multe metode, dintre care, cele mai uzuale sunt secventiala, relativa si indexata. Principala diferentiere intre metodele de organizare o reprezinta tipurile de acces admise.
Tipul de acces reprezinta modalitatea de regasire (localizare) a articolelor din fisier. Notiunea de acces trebuie aplicata atat pentru operatia de scriere, cit si pentru cea de citire a datelor.
Pozitia din/in care se face citirea/scrierea in cadrul fisierului este indicata de un pointer. Accesul la datele inregistrate pe un purtator tehnic poate fi secvential sau direct, in functie de modul in care se stabileste pointerul.
Din punct de vedere al reprezentarii datelor in suportul extern, se disting fisiere text, in care toate datele sunt sub forma ASCII (un caracter/octet) si fisiere binare, in care toate datele sunt memorate in forma identica cu cea din memoria principala (MP).
Strans legat de lucrul cu cele doua tipuri de fisiere este modul in care se face transferul datelor intre memoria principala si suportul extern: transfer posibil cu conversie (in cazul fisierelor text) si transfer fara conversie (in cazul fisierelor binare). Indiferent de natura fisierului, operatiile necesare pentru prelucrare sunt:
• descrierea fisierului (crearea tabelei care memoreaza caracteristicile fisierului)
• asignarea fisierului intern (numele logic) la unul extern (fizic);
• deschiderea fisierului;
• operatii de acces la date („articole”);
• inchiderea fisierului.
In implementarea programului pentru stocarea informatiilor privind decalajele orare specifice fiecarui oras s-a utilizat un fisier text “decalaje.txt” .Acest este deschis in vederea citirii articol cu articol si incarcarii informatiilor respective intr-un vector pentru folosirea lor ulterioara.
f=fopen('decalaje.txt','r+'); deschiderea fisierului
fscanf(f,'%s %d',&buf,&d); - citirea din fisier articol cu articol
fclose(f); - inchiderea fisierului
Totodata a fost folosita si structura implicita 'tm' din 'time.h' care retine de fapt data calendaristica si ceasul, continand noua componente de tipul int : int tm_sec; int tm_min; int tm_hour;int tm_mday; int tm_mon; int tm_year; int tm_wday;
int tm_yday; int tm_isdst
5.DESCRIEREA IMPLEMENTARII OPERATIILOR DE BAZA
In realizarea proiectului operatiile de baza au fost implementate utilizand urmatoarele proceduri
void incarcareVectorDecalaje(struct fusOrar **fo,int *n) - procedura de populare a unui vector cu articole de tip fusOrar, fiecare element retinand numele orasului si decalajul. Citirea se face din fisierul 'decalaje.txt , element cu element, facandu-se totusi in prealabil o parcurgere pentru identificarea numarului de articole utilizat in alocarea vectorlui.
2-struct timp incOraTas (int o,int m,int s) - functie care permite retinerea orei locale (ora,numarul de minute si numarul de secunde fiind primite ca parametri) intr-o variabila de tipul timp cu validarea in prealabil a datelor primite (0<=ora<24 ; 0<=minut<60 ; 0<=secunda<60). Functia returneaza aceasta variabila care apoi va fi incarcata in main in variabila supusa diverselor operatii dorite de utilizator.
3-struct timp incOraSistem() - aceasta functie permite retinerea orei locale de la sistem.Pentru implementarea acesteia am utlizat structura tm si functiile time si localtime din libraria 'time.h', retinand intr-un pointer outputul functiei localtime. Ulterior s-a facut atribuirea orei,numarului de minute si secunde conform calificarilor specifice structurii tm.
4-void afisare1(struct timp t) - aceasta procedura permite afisarea timpului in format 'hh:mm:ss'
5-void afisare2 (struct timp t) - aceasta procedura permite afisarea timpului in format 'hh/mm/ss'
6-struct timp modifCeasMinPlus(int m,struct timp t) - aceasta functie primeste ca parametrii numarul de minute cu care utlizatorul doreste sa modifice ora locala in sens incremental si o variabila de tipul timp pe care o returneaza. Transmiterea acesteia s-a realizat prin valoare pentru a nu modifica valoarea initiala a variabilei,outputul functiei fiind retinut si afisat intr-o alta variabila in main.
7-struct timp modifCeasMinMinus(int m,struct timp t- aceasta functie primeste ca parametrii numarul de minute cu care utlizatorul doreste sa modifice ora locala in sens decremental si o variabila de tipul timp pe care o returneaza. Transmiterea acesteia s-a realizat prin valoare pentru a nu modifica valoarea initiala a variabilei,outputul functiei fiind retinut si afisat intr-o alta variabila in main.
-struct timp modifCeasPlus(struct timp t,struct timp p) - aceasta functie primeste ca prametrii variabila initiala (transmitere prin valoare) asupra carei se vor opera modificarile si un interval de tipul 'hh:mm:ss'.Functia returneaza noua ora locala incrementata cu intervalul primit ca parametru, noua ora fiind retinuta intr-o alta variabila
si afisata in main.
9-struct timp modifCeasMinus(struct timp t,struct timp p) aceasta functie primeste ca prametrii variabila initiala (transmitere prin valoare) asupra carei se vor opera modificarile si un interval de tipul 'hh:mm:ss'.Functia returneaza noua ora locala decrementata cu intervalul primit ca parametru, noua ora fiind retinuta intr-o alta variabila si afisata in main.
10-struct timp afisTimpOras (struct timp t,char*oras,struct fusOrar*fo,int n,int *ok) - aceasta functie permite afisarea orei locale transmisa ca parametru intr-un oras dat, tinand cont de diferenta de fus orar corespunzatoare. Prin urmare, functia primeste ca parametru si vectorul decalajelor orare, dimensiunea lui precum si o variabila pointer ok care ia valoarea '1' daca orasul se afla in baza de date si '0' in caz contrar.
11-int afisDecalajOrase (char*o1,char*o2,struct fusOrar*fo,int n,int *ok1,int*ok2) - aceasta functie returneaza decalajul orar dintre doua orase date de utlizator. Functia primeste ca parametrii cele doua orase, vectorul decalajelor si dimensiunea lui precum si doua variabile pointer ok1 si ok2 care primesc valoarea '1' daca orasele exista si '0'
in caz contrar.
12-int minuteIntervalOrar (struct timp *t,struct timp *p) - functia returneaza diferenta de minute dintre doua intervale orare primite ca parametri.Pentru usurarea implementarii se retine in doua variabile numarul de secunde si apoi se calculeaza diferenta, care ulterior se transforma in numar de minute.
6.CONCLUZII
Programul incearca prin structurile utilizate sa se apropie cat mai mult de programarea orientata obiect, atribuind elementelor un comportament. Astfel in structura de baza au fost definiti ca si campuri pointeri la functii care au fost incarcati ulterior cu adresa functiilor elementare corespunzatoare datelor de tipul timp (hh:mm:ss). Acesta ar fi unul dintre principalele avantaje ale implementarii programului, pe langa existenta unui grad ridicat de interactivitate.
La nivelul structurilor utilizate se pot identifica o serie de avantaje si dezavantaje, care se anuleaza totusi la nivel global. Astfel in ceea ce priveste vectorul, se remarca urmatoarele aspecte pozitive: acces direct si facil la date, utilizarea eficienta a memoriei (se aloca spatiu atat cat are nevoie aplicatia), aplicabilitate la nivelul unor cantitati variabile de date. Ca si dezavantaj se remarca manipularea destul de greoaie a variabilelor de tip pointer, mai ales din perspectiva programatorului.
Articolul ca si structura de baza a programului, prezinta ca avantaje principale posibilitatea atribuirii unor comportamente variabilelor precum si existenta unui anumit grad de libertate al programatorului in a-si defini propria structura de date, capabila sa stocheze informatiile dorite. Totodata folosirea articolului este strans legata de utilizarea fisierelor permitand retinerea unei cantitati suficiente si diverse de date.
Dezavantajele utilizarii acestui tip de data survin in momentul copierii articolelor care se face bit cu bit. Astfel in cazul in care structura contine pointeri, zonele referite trebuie copiate manual de catre programator. De asemenea pot aparea diverse inconveniente la calificarea campurilor din cadrul structurilor recursive, mai ales din perspectiva programatorului.
BIBLIOGRAFIE
[SMEU01] |
Ion SMEUREANU, Marian DARDALA - Programarea in limbajul C/C++, Editura Cison, 2001. |
[GHIL03] |
Bogdan GHILIC-MICU, Ion Gh.ROSCA, Marian STOICA, Lucia Catalina COCIANU - Algoritmi in programare, Editura ASE, 2003 |
www.bibliotecadigitala.ase.ro/biblioteca/carte2.asp?id=496&idb=11. |
ANEXE
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <time.h>
struct fusOrar;
struct timp;
struct timp incOraTas (int o,int m,int s)
t.ora=o;
while ((m<0) ||(m>50))
t.minut=m;
while ((s<0) ||(s>50))
t.secunda=s;
return t;
struct timp incOraSistem()
void afisare1(struct timp t)
void afisare2 (struct timp t)
struct timp modifCeasMinPlus(int m,struct timp t)
if ((t.minut+m)>=60)
else
t.minut=t.minut+m;
t.ora=t.ora+h;
if (t.ora>=24) t.ora=t.ora-24*(t.ora/24);
return t;
struct timp modifCeasMinMinus(int m,struct timp t)
if ((t.minut-m)<0)
else
t.minut=t.minut-m;
t.ora=t.ora-h;
if (t.ora<0)
return t;
}
struct timp modifCeasPlus(struct timp t,struct timp p)
t.minut=t.minut+p.minut;
if (t.minut>=60)
t.ora=t.ora+p.ora;
if (t.ora>=24) t.ora=t.ora-24*(t.ora/24);
return t;
struct timp modifCeasMinus(struct timp t,struct timp p)
t.minut=t.minut-p.minut;
if (t.minut<0)
t.ora=t.ora-p.ora;
if (t.ora<0)
return t;
void incarcareVectorDecalaje(struct fusOrar **fo,int *n)
//printf ('n %dn',dim);
fseek (f,0,SEEK_SET);
(*fo)=(struct fusOrar*) malloc (dim*sizeof(struct fusOrar));
*n=0;
while (!feof(f))
fclose(f);
struct timp afisTimpOras (struct timp t,char*oras,struct fusOrar*fo,int n,int *ok)
}
return t;
int afisDecalajOrase (char*o1,char*o2,struct fusOrar*fo,int n,int *ok1,int*ok2)
if (strcmp(o2,fo[i].nume)==0)
}
if ((*ok1==0) || (*ok2==0))
return 100 ;
else
int minuteIntervalOrar (struct timp *t,struct timp *p)
void main()
while((opt!=1) && (opt!=2));
if (opt==1)while ((m<0) || (m>59));
//dowhile ((s<0) || (s>59));
x.pf1=incOraTas;
x=x.pf1(o,m,s);
}
else
printf ('n');
printf ('Dati formatul in care doriti sa afisati ora locala :n 1-hh:mm:ss n 2-hh/mm/ss n 0-nu doresc afisarea ceasului n');
dowhile((opt1!=1) && (opt1!=2)&& (opt1!=0));
if (opt1==1)
else
if (opt1==2)
printf ('n');
incarcareVectorDecalaje(&fus,&nr);
printf ('Principalele operatii cu date de tipul timp:n 1-afisare ceas cu un numar dat de minute inainte/inapoi n 2-afisare ceas cu un numar dat de ore:minute:secunde inainte/inapoi n 3-afisarea orei locale intr-un oras dat n 4-afisarea decalajului intre 2 orase date n 5-afisarea nuamrului de minute intre 2 intervale n 0-iesire n');
k=1;
while (k)
while((opt1!=1) && (opt1!=0)&& (opt1!=2)&& (opt1!=3)&& (opt1!=4)&& (opt1!=5));
if (opt1==1)
printf ('n');
if (opt1==2)while ((m<0) || (m>59));
dowhile ((s<0) || (s>59));
y.ora=o;
y.minut=m;
y.secunda=s;
//y.pf1=incOraTas;
//y=y.pf1(o,m,s);
//y.pf3=afisare1;
//y.pf3(y);
printf ('n afisare incrementala:');
x.pf5=modifCeasPlus;
z=x.pf5(x,y);
z.pf3=afisare1;
z.pf3(z);
printf ('n afisare decrementala:');
x.pf5=modifCeasMinus;
v=x.pf5(x,y);
v.pf3=afisare1;
v.pf3(v);
}
//printf ('n');
if (opt1==3)
else
printf ('Orasul % s nu exista in baza de date!!',oras);
}
//printf ('n');
if (opt1==4)
else
printf ('Decalajul orar dintre %s si % s este de %d ore',or1,or2,x.pf7(or1,or2,fus,nr,&ok1,&ok2));
}
//printf ('n');
if (opt1==5)
//printf ('n');
if (opt1==0)
}
//printf ('%d',nr);
//printf (' %s %d',fus[103].nume,fus[103].dec)
//printf ('n');
//x.pf3(x);
|