1 of 21

ADT - Abstract Data Type

3^ INFORMATICO - IIS PASCAL�DIPARTIMENTO INFORMATICA

2 of 21

ARGOMENTI

  • Concetto di Tipo di dato astratto
  • ADT in C++
  • Struct
  • Operazioni CRUD su struct
  • Array di structs
  • File CSV e Structs

2

3 of 21

CHE COS’È UN ADT ?

3

  • ADT è l’acronimo di Abstract Data Type ovvero “tipo di dato astratto

  • Definiamo Astratto un tipo di dato se NON è un tipo di dato predefinito dal linguaggio
  • Nel caso del C++ i tipi predefiniti sono �int, float, double, bool, string, char… (approfondisci)
  • E’ possibile definire nuovi tipi di dato assemblando variabili di tipi predefiniti e/o altri TDA creati in precedenza
  • Un TDA può avere caratteristiche (proprietà) e comportamenti (funzioni)

QUEST’ANNO CI LIMITIAMO A CREARE TDA CON DELLE CARATTERISTICHE

4 of 21

CHE COS’È UN ADT ?

4

Un TDA:

  • Incapsula i dati e le operazioni*.

  • Nasconde i dettagli di implementazione (principio dell'astrazione dei dati).

  • Garantisce un'interfaccia* chiara per l'uso del tipo di dato.

* per le operazioni e l’interfaccia si rimanda alle lezioni su OOP del quarto anno

5 of 21

Implementazione di un TDA in C++

5

In C++, i TDA sono solitamente implementati tramite classi* o struct, sfruttando i concetti di incapsulamento, astrazione e modularità.

Vantaggi dei TDA

  • Modularità: I TDA consentono di dividere il codice in moduli indipendenti, semplificando la manutenzione e la leggibilità.
  • Riutilizzabilità: Una volta implementato, un TDA può essere riutilizzato in più contesti senza modificarlo.
  • Flessibilità: Cambiare l'implementazione interna non influisce sull'interfaccia* del TDA, permettendo modifiche senza interrompere il codice esistente.

* per le operazioni e l’interfaccia si rimanda alle lezioni su OOP del quarto anno

6 of 21

Structs

6

La keyword struct del C++ permette di creare un TDA� che risponde alle seguenti esigenze:

  • raggruppare variabili anche di tipo diverso in �una sola struttura dati
  • superare il concetto di array paralleli

ESEMPIO:

Se dovessimo registrare i voti di 100 studenti memorizzando il loro nome, cognome, giorno della prova e valutazione, dovremmo utilizzare 4 array paralleli, ognuno del tipo corretto…

string nomi[100]; string cognomi[100]; string giorni[100]; float voti[100];

nome

Mario

Luca

Franca

Eva

Antonio

cognome

Bellini

Fontana

Rame

Righi

Marini

giorno

2024/01/15

2024/01/15

2024/02/08

2024/02/01

2024/03/21

voto

8

8

7

4.5

7

7 of 21

Structs - definizione

7

Possiamo in questo caso DEFINIRE UN TDA come segue:

struct valutazione {

string nome;

string cognome;

string giorno;

float voto;

};

e trattare quindi l’identificatore valutazione esattamente come fosse un tipo primitivo .

�Possiamo quindi definire una variabile di tipo valutazione

valutazione v;

o un array di oggetti di tipo valutazione

valutazione voti_studenti[100];

I tipi di dato assegnati ai diversi campi possono a loro volta essere TDA

8 of 21

Structs

8

Passiamo da questo a questo

nome

Mario

Luca

Franca

Eva

Antonio

cognome

Bellini

Fontana

Rame

Righi

Marini

giorno

2024/01/15

2024/01/15

2024/02/08

2024/02/01

2024/03/21

voto

8

8

7

4.5

7

Mario

Luca

Franca

Eva

Antonio

Bellini

Fontana

Rame

Righi

Marini

2024/01/15

2024/01/15

2024/02/08

2024/02/01

2024/03/21

8

8

7

4.5

7

voti_studenti

nome cognome giorno voto

9 of 21

Structs - accesso ai campi

9

Le singole variabili definite all’interno di una struct sono dette campi (fields).

L’accesso ai singoli campi di una struct è reso possibile dalla sintassi nota come dot notation e già vista per i metodi delle stringhe e di altre strutture

Se abbiamo ad esempio definito una variabile v di tipo valutazione

valutazione v;

possiamo accedere ai singoli campi (sia in lettura che in scrittura) con

v.nome = “Mario”;

v.cognome = “Bellini”;

…etc…

10 of 21

Structs - accesso ai campi

10

Potremo quindi scrivere:

cout << “Inserisci il nome dello studente “;� cin >> v.nome;

e

cout << “Lo studente “ << v.nome << “ “ << v.cognome ...

per variabili semplici e

cout << “Inserisci il nome dello studente “;� cin >> voti_studenti[i].nome;

per variabili di tipo array di struct come

valutazione voti_studenti[100];

copyright chatGPT

11 of 21

ESERCIZI PER IL LETTORE

11

  1. Definire il TDA rettangolo per realizzare un tipo di dato che modellizzi un rettangolo
  2. Definire il TDA automobile per realizzare un tipo di dato che permetta di registrare i dati relativi ad una automobile (targa, modello, marca, cilindrata, anno di immatricolazione)
  3. Definire il TDA calendar per realizzare un tipo di dato che che permetta di registrare una data (giorno, mese e anno)
  4. Definire il TDA studente per realizzare un tipo di dato che permetta di registrare i dati relativi ad uno studente (nome, cognome, data di nascita, classe, sezione, scuola di appartenenza)*
  5. Definire il TDA persona per realizzare un tipo di dato che permetta di registrare i dati relativi ad una persona generica (nome, cognome, data di nascita, codice fiscale, città di nascita, provincia di nascita)*
  6. Definire il TDA indirizzo per realizzare un tipo di dato che che permetta di registrare i dati relativi ad un indirizzo fisico (nome della via, cap, numero civico, città, etc)
  7. Utilizzando i tipi definiti nei punti precedenti, crea il TDA socio_aci per realizzare un tipo di dato che che permetta di registrare i dati relativi ad un socio ACI (dati della persona, dati dell’auto, dati della residenza, data di registrazione ACI)

* il campo “data di nascita” può essere tipizzato utilizzando il tipo dato “calendar” del punto 3

12 of 21

Structs - definizioni

12

Una variabile di un TDA può essere definita e inizializzata in vari modi:

Sia ad esempio il TDA persona

struct persona {

string nome;

string cognome;

int eta;

};

posso quindi definire

persona p;

e successivamente valorizzare i singoli campi

p.nome = “Luca”;

p.cognome = “Mariani”;

p.eta = 23;

13 of 21

Structs - definizioni

13

OPPURE:

posso definire e valorizzare direttamente in una sola istruzione con la sintassi

persona p {“Luca”, “Mariani”, 23};

posso anche valorizzare parte dei campi

persona p {“Luca”, “Mariani”};

in questo caso il campo “eta” rimarrà NON inizializzato

IN TUTTI I CASI I VALORI VANNO INSERITI NELL’ORDINE DELLA DEFINIZIONE DEL TDA

L’istruzione

persona p {23, “Luca”, “Mariani”};

genera un errore di type conversion a tempo di compilazione

14 of 21

Structs - assegnazione

14

Per due variabili dello stesso TDA è permessa di default l’operazione di assegnazione =

L’effetto è una assegnazione di valori campo a campo

posso quindi definire

persona p1 {"Lucia" , "Rossi", 21};

persona p2 = p1;

l’istruzione

cout << p2;

produce l’output

Lucia Rossi 21

Lucia

Rossi

21

p1

Lucia

Rossi

21

p2

15 of 21

Structs - assegnazione (2)

15

Siano ad esempio i due TDA rettangolo e rectangle di seguito: stessi campi, stessi tipi, stessa disposizione

struct rettangolo { struct rectangle {

float base; float base;

float altezza; float altezza;

}; };

le istruzioni

rettangolo r1 {10, 20};� rectangle r2;

r2 = r1;

produce il seguente errore:

error: no match for ‘operator=’ (operand types are ‘rectangle’ and ‘rettangolo’)

i due TDA vengono considerati 2 tipi diversi anche se hanno la stessa struttura!

16 of 21

Structs - confronto

16

Per due variabili dello stesso TDA NON è permessa di default l’operazione di confronto ==

L’ operazione

bool uguali = (p1 == p2);

produce il seguente errore:

error: no match for ‘operator==’ (operand types are ‘persona’ and ‘persona’)

17 of 21

Structs nidificate

17

Abbiamo detto che un TDA può essere utilizzato come un tipo qualsiasi.

Definiamo “nidificate” le struct che usano altri TDA come tipi dei campi�Ad esempio:� struct date {

int giorno, mese, anno;

};

struct persona {

string nome;

string cognome;

date data_di_nascita;

};�In questo caso le operazioni di lettura/scrittura utilizzeranno la dot notation più volte:

persona p;

p.nome = “Federico”;� p.cognome = “Fellini”;� p.data_di_nascita.giorno = 20;� p.data_di_nascita.mese = 1;� p.data_di_nascita.anno = 1920;�

18 of 21

Structs nidificate

18

o in alternativa:

persona p;

p.nome = “Federico”;� p.cognome = “Fellini”;� p.data_di_nascita = {20, 1, 1920}; // assegna tutti i valori in un colpo solo

19 of 21

Array di structs

19

Altro aspetto molto interessante dell’uso delle struct è di poter gestirli in maniera compatta�Gli array di structs permettono un uso più agile rispetto agli array paralleli.

DEFINIZIONE�Per definire un array di structs si usa la solita sintassi (a patto che il TDA utilizzato sia già definito)

L’istruzione

persona vett[10];

istanzia un array di 10 elementi di tipo persona

ACCESSO

L’accesso ad un elemento dell’array è possibile con offset+dot notation

Ad esempio:

vett[i].nome

per accedere al campo nome dell’i-esimo elemento di tipo persona dell’array

20 of 21

ESERCIZIO PER IL LETTORE

20

Definire un TDA partita per memorizzare i dati relativi ad una gara di basket.�E’ necessario memorizzare il nome della squadra di casa, della squadra ospite, la data della gara ed il risultato.

Crea successivamente un array per leggere da input i dati di 5 partite.

Stampa poi a video:

  • il numero V di vittorie della squadra di casa
  • il numero T di punti totali effettuati dalle squadre in trasferta
  • la media M dei punti di scarto delle gare registrate
  • i dati delle partite in cui la differenza D di punteggio è maggiore della media M dei punti di scarto

30 minuti (soluzione)

21 of 21

ESERCIZIO PER IL LETTORE

21

Definire un TDA libro per memorizzare i dati relativi ad una pubblicazione.�E’ necessario memorizzare il titolo del libro, i dati dell’autore e dell’editore, l’anno di pubblicazione, il numero di pagine e la tipologia del testo (romanzo, saggio, poesia, etc…)

Chiedere all’utente il numero di libri da inserire e successivamente creare un array per leggere da input i dati di alcuni libri.

Al termine dell’inserimento stampare a video:

  • il titolo di tutti i romanzi con anno di pubblicazione e numero di pagine
  • i dati delle pubblicazioni di un autore inserito da utente
  • i dati della pubblicazione più lunga

30 minuti