06 3 struct

19
Fondamenti di informatica Strutture dati composte: struct

description

 

Transcript of 06 3 struct

Page 1: 06 3 struct

Fondamenti di informatica

Strutture dati composte: struct

Page 2: 06 3 struct

Il sistema dei tipi del C++

• Uno degli obiettivi principali del C++ è permettere al programmatore di creare tipi personalizzati e usarli come se fossero offerti dal linguaggio

• Il sistema dei tipi del C++ comprende– Tipi predefiniti (predefined)– Tipi composti (composite) – Tipi definiti dall’utente (user defined)– Tipi classe (class types)

Page 3: 06 3 struct

I costruttori di tipi

• A partire dai tipi predefiniti si possono creare nuovi tipi, che aggiungono proprietà speciali ai tipi predefiniti– Const (visto)– Reference (visto) – Pointer (ancora da vedere)

• A questi si aggiungono costruttori di tipi definiti interamente dall'utente– struct (eredità del C, poco usato in C++)– Class

Page 4: 06 3 struct

4

• Variabili omogenee: sequenza finita / indefinita– ARRAY (sequenza predefinita), VECTOR (sequenza

indefinita)• Variabili disomogenee: tipi classe

– STRUCT (record)– CLASS (oggetti con dati e funzioni dichiarati e

definiti assieme)

Tipi composti aggregati

Page 5: 06 3 struct

Esigenza

• Nella progettazione dei dati, spesso capita di prevedere informazioni connesse in gruppi logici:– Parole in un testo e loro frequenza– Indirizzo, composto da via n. civico città– Dati dell'utente: username, password, email

• In questi casi, piuttosto che variabili separate, si usa un costruttore di tipo che definisce un gruppo logico di variabili correlate, detto "record" (ovvero: scheda, registrazione)

Page 6: 06 3 struct

Il costruttore di tipo record

• Record (o struct): memorizzano aggregazioni di dati di diversa natura

• Ciascun dato è chiamato “campo” o dato membro (member):struct {

string via; // 1o campo: stringaint numero; // 2o campo: interoint CAP; // 3o campo: interostring citta; // 4o campo: stringa

} indirizzo;

• indirizzo è un record formato da quattro campi di vario tipo

nome della variabile record

Page 7: 06 3 struct

Uso dei record

• Il record (o struct) è una sorta di “contenitore” di campi di tipo disomogeneo

• Il record raggruppa dati più semplici– Ne rende più ordinata la gestione, evitando confusioni

• I campi del record non sono accessibili individualmente– L'accesso avviene mediante il record a cui appartengono – Si utilizza l'operatore . come metodo di accesso ai campi

• indirizzo.citta

– Con gli iterator si usa l'operatore -> : iter->member– I nomi dei campi sono identificatori “locali” all’interno di una

variabile di tipo record, da usarsi come suffissi

Page 8: 06 3 struct

Operazioni su campi dei record

• Le operazioni che sono definite sono le stesse applicabili sui tipi dei campi

• Assegnamento ai campi del record:indirizzo.via = "Ponzio";indirizzo.numero 34;indirizzo.CAP 20133;indirizzo.citta = "Milano";

• Accesso (leggere, scrivere…):– cout << indirizzo.numero;– cin >> indirizzo.CAP;

Page 9: 06 3 struct

Assegnamento di record• Dati due record identici (cioè dichiarati insieme) è lecito assegnare

globalmente il primo al secondostruct … / campi / rec1, rec2;

• è lecito scrivere:rec2 rec1;

• tutti i campi di rec1 sono ordinatamente copiati nei campi corrispondenti di rec2.

• Se i due record sono diversi (anche solo per l’ordine dei campi) l’assegnamento è privo di senso !

• Memento: l’assegnamento “diretto” tra array è vietato– deve avvenire elemento per elemento

• Ma…. Diventa possibile tra membri array di una struct!

Page 10: 06 3 struct

Assegnamento di array nelle structint main() { struct { char via[20]; int numero; int CAP; string citta; } indirizzo1, indirizzo2; strcpy(indirizzo1.via, "Ponzio"); // non si può usare assegnamento indirizzo1.numero = 35; indirizzo1.CAP = 20133; indirizzo1.citta = "Milano";

cout << "RECORD 1: " << endl << indirizzo1.via << endl << indirizzo1.numero<< endl << indirizzo1.CAP << endl << indirizzo1.citta << endl;

indirizzo2 = indirizzo1; // copia anche l'array!!

cout << "RECORD 2: " << endl << indirizzo2.via << endl << indirizzo2.numero<< endl << indirizzo2.CAP << endl << indirizzo2.citta << endl;

return 0;}

Page 12: 06 3 struct

12

Tipi definiti dall’utenteTipi di dato astratti (TDA)

Page 13: 06 3 struct

Tipi definiti dall'utente

• I record sono un caso esemplare in cui un tipo ha una struttura definita dal programmatore

• Tuttavia è un tipo "anonimo"• C e C++ forniscono un modo per dare un nome a un tipo • Esempio:

• typedef int intero;• intero numero;

• è equivalente a:• int numero;

• È la definizione di un sinonimo– Il nuovo tipo intero eredita le caratteristiche (valori e operazioni)

del tipo di partenza int

Page 14: 06 3 struct

Costruttore di record (struct)• Definizione di un tipo tipo data per le date:

typedef struct {int giorno;int mese;int anno;

} data;• Dichiarazione di variabili di tipo data:

data oggi, domani, dopodomani;• Altro esempio:

typedef struct {char nome[20];char cognome[20];data nato_il;char nato_a[15];char codice_fiscale[16];int stipendio;

} dipendente; dipendente piero;

Page 15: 06 3 struct

Esempi d'uso

• Si possono dichiarare le variabili: dipendente persona1, persona2;

• E modificare i dati membro:persona1.stipendio + (persona1.stipendio 10) 100; persona2.stipendio + (persona2.stipendio 10) 100;

• Anche innestati:persona2.nato_il.giorno = 15; // NB: accede a campo giorno del campo data di dipendente

Page 16: 06 3 struct

Progettazione dei dati

• Esempio vendite di libri– Si vuole costruire un programma che gestisca le vendite di libri

• Ogni libro è caratterizzato da un codice ISBN

– Il programma deve gestire per ogni libro il numero totale di copie vendute, il ricavo totale e medio

– L'utente inserisce sequenzialmente i dati di vendita per i diversi libri, il programma aggrega i dati per ciascun codice ISBN e stampa il dato aggregato

– Deve quindi essere possibile:• Inserire e stampare i dati di un libro• Sommare più dati di vendita relativi allo stesso libro • Stampare i dati di vendita aggregati relativi a un libro

Page 17: 06 3 struct

Suddivisione del programma

• Un file di libreria (Sales_item.h) conterrà la definizione del tipo che rappresenta il dato di vendita: Sales_item

• Definiamo ora Sales_item come struct, cioè un tipo definito dall'utente che comprende dati, ma non le operazioni relativi al dato di vendita– Campi: codice ISBN, copie vendute, ricavo

• Il programma principale importa e usa Sales_item come se fosse un tipo predefinito

– Sales_item item; // dichiara una var. di tipo Sales_item !

Page 18: 06 3 struct

Sales_item.h

#ifndef SALES_DATA_H#define SALES_DATA_H

#include <string>using namespace std;

struct Sales_data {string bookNo;unsigned units_sold = 0;double revenue = 0.0;

};#endif

Page 19: 06 3 struct

Programma principale#include <iostream>#include <string>#include "Sales_data.h"using namespace std;

int main(){ Sales_data data1, data2;

// code to read into data1 and data2double price = 0; // price per book, used to calculate total revenue// read the first transactions: ISBN, number of books sold, price per bookcin >> data1.bookNo >> data1.units_sold >> price;// calculate total revenue from price and units_solddata1.revenue = data1.units_sold * price;// read the second transactioncin >> data2.bookNo >> data2.units_sold >> price;data2.revenue = data2.units_sold * price;// check whether data1 and data2 have the same ISBN, if so print the sum of data1 and data2if (data1.bookNo == data2.bookNo) {

unsigned totalCnt = data1.units_sold + data2.units_sold;double totalRevenue = data1.revenue + data2.revenue;// print: ISBN, total sold, total revenue, average price per bookcout << data1.bookNo << " " << totalCnt << " " << totalRevenue << " ";if (totalCnt != 0)

cout << totalRevenue/totalCnt << endl;else

cout << "(no sales)" << endl;

return 0; // indicate success} else { cerr << "Data must refer to the same ISBN" << endl; // transactions not for same ISBN

return -1; // indicate failure}

}