06 3 struct
-
Upload
piero-fraternali -
Category
Technology
-
view
218 -
download
2
description
Transcript of 06 3 struct
Fondamenti di informatica
Strutture dati composte: 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)
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
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
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)
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
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
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;
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!
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;}
Check this out
• http://stackoverflow.com/questions/8939090/why-array-assignment-operation-doesnt-exist-but-structure-assignment-does-in-c
12
Tipi definiti dall’utenteTipi di dato astratti (TDA)
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
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;
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
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
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 !
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
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}
}