Sunteți pe pagina 1din 22

Tipuri de date definite de

utilizator

1
Datele predefinite și tablourile(date structurate omogene) nu sunt
suficiente. În general, datele sunt organizate în ansambluri de date, de
diferite tipuri.
Pentru descrierea acestor ansambluri (structuri) de date, limbajele de
programare de nivel înalt permit programatorului să-și definească
propriile tipuri de date.
Limbajul C/C++ oferă posibilitatea de definire a unor noi tipuri de date
cu ajutorul:
- structurilor- care permit gruparea unor obiecte (date) de tipuri diferite,
referite printr-un nume comun;
- câmpurilor de biți – membri ai unei structuri pentru care se alocă un
grup de biți, în interiorul unui cuvânt de memorie;
- uniunilor – permit utilizarea în comun a unei zone de memorie de către
mai multe obiecte de diferite tipuri;
- declarațiilor typedef – care asociază nume tipurilor noi de date;
- enumerărilor - care sunt liste de identificatori cu valori constante,
întregi

2
Structuri

Structurile grupează date de tipuri diferite, constituind definiții ale unor


noi tipuri de date.

Componentele unei structuri se numesc membrii (câmpurile) structurii. La


declararea unei structuri se pot preciza tipurile, identificatorii elementelor
componente și numele structurii. Forma generală de declarare a unei
structuri este:

struct [<identificator_tip_structura>]
{ <lista_de declaratii-membri>;
} [<lista_identificatori_variabile>]; în care:
struct este un cuvânt cheie obligatoriu;
<identificator_tip_structura> reprezintă noului tip (opțional);
<lista_de declaratii-membri> este o listă în care apar tipurile și
identificatorii membrilor structurii;
<lista_identificatori_variabile> este o listă cu identificatorii variabilelor de
tipul declarat

3
O structură fără nume se numește structură anonimă, iar în acest caz, lista de
identificatori de variabile este OBLIGATORIE. (DE CE!!!)
Membrii unei structuri pot fi de orice tip, cu excepția tipului structură care se
declară. Se admit pointeri către tipul definit prin structură.

Exemple:
struct data {
int zi;
char luna[11];
int an;
} data_nasterii, data_angajarii;

Sau

struct data {
int zi;
char luna[11];
int an;
};
struct data data_nasterii, data_angajarii;

4
struct {
int zi;
char luna[11];
int an;
} data_nasterii, data_angajarii;

Structură anonimă, lipsește numele structurii, iar în acest caz obligatoriu pun lista de
variabile după definirea structurii.

Inițializarea variabilelor de tip nou, definit ca structură, se paote realiza prin enumerarea
valorilor membrilor (similar inițializării tablourilor!!!), în ordinea în care aceștia apar în
declarația structurii.

struct data {
int zi;
char luna[11];
int an;
};
struct data data_nasterii = {14, “martie”, 2017};
Sau
data_nasterii.zi = 13;
strcpy(data_nasterii.luna, “martie”);
data_nasterii.an = 2017;
5
Vezi struct1.cpp
Referirea unui membru al structurii se realizează cu ajutorul operatorului de selecție,
simbolizat de “.” Operatorul are prioritate maximă.
Operatorul are două componente:

x.y unde

x precizează numele variabilei de tipul introdus prin structură;


Y precizează numele membrului structurii.

Și pentru că lucrăm cu variabile, acestea pot apărea ca operanzi ai operatorului de


atribuire. În această situație atribuirile se fac membru cu membru.

Vezi același struct1.cpp

6
În programul prezentat s-a putut observa că în definirea structurii pot exista membri
de tip tablou(luna).

Limbajul permite definirea unei structuri ale căror membri sunt tot structuri.

Vezi programul struct2.cpp

Vezi programul 24feb_1_var.cpp


În acest program s-a utilizat operatorul de selecție indirectă(->)
S-a utilizat și o variabilă de tip pointer.

7
ÎNTREBARE

Se pot utiliza structuri și funcții? Cum se transmite o variabilă de tip structură struct
către o funcție?
RĂSPUNS: transmiterea ca parametri ai unor funcții a datelor de tip definit de
utilizator prin structuri se realizează NUMAI cu ajutorul pointerilor spre noul tip.

Vezi programul struct3.cpp

Utilizare structuri

Structurile sunt utilizate în mid frecvent la definirea unor tipuri de date recursive( În
implementarea listelor înlănțuite, arborilor, etc).

Definiție: un tip de date este direct recursiv dacă are cel puțin un membru care este
de tip pointer spre el însuși.
Exemplu:
struct nod{
char nume[100];
int an;
struct nod *urmator; //pointerul catre urmatorul element al listei
};
Liste (simplu) înlănțuite, liste dublu înlănțuite, arbori, etc. (Vezi tipuri de date)
8
CÂMPURI DE BIȚI

Trebuie să utilizăm uneori date care pot avea doar 2 valori(0 și 1), cum ar fi datele
pentru controlul unor dispozitive periferice, sau datele de valori mici. Declarând
aceste date de tip int sau short int în memorie se rezervă 32, respectiv 16 biți, prea
mulți!!!

Definiție: un șir de biți adiacenți(unul după altul) formează un câmp de biți.

Câmpurile de biți se pot declara ca membri ai unei structuri, astfel:


struct <identificator_tip_struct> {
tip_elem_1 identificator_elem_1:<lungime1>;
tip_elem_2 identificator_elem_2:<lungime2>;

tip_elem_n identificator_elem_n:<lungimen>;
} lista_identif_var_struct;

Unde lungime1, lungime2, … reprezintă lungimea fiecărui câmp de biți, rezervat


penru memorarea membrilor. Câmpurile se alocă de la biții de ordin inferior au
unui cuvânt (2 octeți), către cei de ordin superior.

9
Exemplu:
struct {
int a:2;
unsigned int b:1;
int c:3;
} x, y;

Câmpurile se referă ca orice membru al unei structuri, prin nume calificate:

x.a=-1; x.b = 0; x.c = 4;

Restricții:
1. Tipul membrilor poate fi int sau unsigned int.
2. Lungimea este o constantă întreagă din intervalul [0, 1].
3. Un câmp de biți nu paote fi opeandul unui operator de refențiere.
4. Nu se pot organiza tablouri de câmpuri de biți

10
DECLARAȚII DE TIP

Permit atribuirea unui nume pentru un tip (predefinit sau utilizator) de date.

typedef <tip> <nume_tip>;

nume_tip poate fi folosit la declararea datelor în mod similar cuvintelor cheie


pentru tipurile predefinite.

Exemple:
1. typedef int INTREG;
INTREG x, y;
intreg z = 4;

2. typedef struct{
double parte_reala;
double parte_imaginara;
} COMPLEX;
COMPLEX x, y;

11
UNIUNI

Aceeași zonă de memorie paote fi utilizată pentru păstrarea unor obiecte(date) de


diferite tipuri, prin declararea uniunilor: Uniunile sunt similare cu structurile, singura
diferență constând în modul de memorare.

Declararea uniunilor:
union [<identificator_tip_uniune>] {
<lista_de_declaratii_membri>;
} [<lista_identificatori_variabile>];

REGULĂ: spațiul de memorie alocat corespunde tipului membrului de dimensiune


maximă.

Vezi uniuni1.cpp

12
ENUMERĂRI

Tipul enumerare asociază fiecărui identificator o constantă întreagă. Mod de declarare:


enum [<identificator_tip_enumerare>]{
<identificator_element1> [=<constanta1>], …
} [<lista_identif_variabile>];

Din declarație pot lipsi fie identificator_tip_enumerare, fie lista_identif_variabile.


Pentru fiecare element al enumerării, constanta poate fi asociată explicit, sau în mod
implicit. În mod implicit nu se specifică nici o constantă, iar valoarea implicită este 0
pentru primul element, iar restul elementelor, valoarea precedentă incrementată cu 1.
Enumerările se folosesc în situațiile în care variabilele pot avea un număr mic de valori
întregi, asociind un nume sugestiv penrtu fieare valoare.

Eexemplu:
enum boolean {FALSE, TRUE};
Nefiind precizate valorile acestea se asociază în mod implicit: 0 pentru primul
identificator, FALSE, apoi prin incrementarea cu 1 rezultă a doua valoare 1 pentru TRUE.

13
typedef enum temperatura { mica =-10, medie= 15, mare=80};

Exemple la ora de laborator!!!

14
FIȘIERE

Noțiunea de fișier(file) desemnează o colecție de date memorată pe un suport


permanent, percepută ca un ansamblu, căreia i se asociază un nume, în vederea
regăsirii ulterioare.
Caracteristicile unui fișier:
-Identificatorul de fișier, format din 4 componente:
[suport][cale]nume[.extensie]
-Atributele care determină operațiile ce pot fi efectuate asupra fișierului:
R – Read-only doar în citire
A – archive
H – hidden – nu se permite nici măcar vizualizarea
S – system - fișierele sistem asupra cărora numai sistemul de operare
poate realiza operații.

În limbajul C, operațiile cu fișiere se realizează cu funcții din biblioteca standard


(stdio.h)

15
Intrarile si iesirile în limbajul C++ sunt implementate cu ajutorul fluxurilor
(stream).

Fluxurile sunt obiecte care transporta si formateaza siruri de bytes. Fluxurile pot
fi unidirectionale (de intrare sau de iesire) sau bidirectionale (permit si intrari si
iesiri).

Clasele care reprezinta fluxuri asociate fisierelor sunt definite în biblioteca


fstream;
aceste clase sunt:
• ifstream: flux unidirectional care permite citirea de date dintr-un fisier
• ofstream: flux unidirectional care permite scrierea de date dintr-un fisier
• fstream: flux bidirectional care permite citiri si scrieri în/din fisier

16
Operatii de baza

Deschiderea fișierelor

Deschiderea fisierelor se poate face în doua moduri: prin constructor sau prin
apelarea functiei membru open. Ambele variante primesc ca parametri numele
fisierului si optiunile de deschidere:

Varianta folosind constructorul:

fstream fisier("nume_fisier", [optiuni]);

Varianta folosind functia open:

fstream fisier;
fisier.open("nume_fisier", [optiuni]);

Partea cu optiunile poate lipsi. Pentru clasele istream si ostream, operatiunea de


deschidere se efectueaza similar. Optiunile la deschiderea fisierelor se dau prin
intermediul urmatoarelor constante:

17
Optiunile se pot combina folosind operatorul „|”.În cazul în care optiunile lipsesc,
valorile implicite sunt:

18
Exemple de utilizare:

// creaza obiectul fisier pentru citire/scriere


// si deschide fisierul "test.txt" folosind
// constructorul si optiunile implicite
fstream fisier("test.txt");

// deschide fisierul pentru citire in mod binar


ifstream fcitire;
fcitire.open("date.dat", ios::in | ios::binary);

// deschide fisierul "studenti.txt" in mod text pentru


// scriere la sfarsitul fisierului
ofstream fscriere("studenti.txt", ios::out | ios::app);

Verificarea faptului ca un fisier este deschis se poate face folosind functia membru
is_open().

19
Închiderea fișierelor
Fisierele deschise folosind clasele din fstream sunt închise automat de catre
destructorul clasei. Închiderea fisierului se poate face explicit prin apelul functiei
membru close; dupa apelul functiei, obiectul poate fi refolosit pentru a accesa alt
obiect. Exemplu:

void main()
{
// deschidem fisierul binar "studenti.dat"
fstream fisier("studenti.dat", ios::in | ios::binary);

// operatii ...

// inchidem fisierul
fisier.close();

// deschidem fisierul "lista.txt"


fisier.open("lista.txt", ios::out);

// operatii ...
} // fisierul "lista.txt" este inchis automat la
// distrugerea obiectului "fisier“
20
Detectarea erorilor
Detectarea erorilor aparute se poate face prin intermediul unor functii membre ale
claselor:

În cazul în care se doreste stergerea indicatorilor de eroare se poate folosi functia


Clear.

21
Exemplu de utilizare:

// deschidere fisier
fstream fisier("studenti.dat", ios::in | ios::binary);

// verificare
if (!fisier)
{
cerr << "Eroare la deschiderea fisierului!" << endl;
return;
}

Vezi fisier.cpp

22