27
© Piero Demichelis Tipi strutturati • I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità. • Se il programma deve trattare collezioni di dati, anche se sono dello stesso tipo, a ognuno deve essere associato un identificatore. • Supponendo di dover gestire le paghe in una ditta di 3000 dipendenti sarebbe necessario definire 3000 variabili diverse, del tipo: operaio1, operaio2, ...., impiegato1, impiegato2, ....., ecc. 1

© Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

Embed Size (px)

Citation preview

Page 1: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis

Tipi strutturati

• I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità.

• Se il programma deve trattare collezioni di dati, anche se sono dello stesso tipo, a ognuno deve essere associato un identificatore.

• Supponendo di dover gestire le paghe in una ditta di 3000 dipendenti sarebbe necessario definire 3000 variabili diverse, del tipo: operaio1, operaio2, ...., impiegato1, impiegato2, ....., ecc.

1

Page 2: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 2

Tipi strutturati

• I linguaggi ad alto livello permettono di ovviare a questo inconveniente con i tipi strutturati, caratterizzati sia dal tipo dei loro componenti che dai legami strutturali tra i componenti stessi, cioè dal metodo di strutturazione.

• Il linguaggio C, anche in questo caso, si presenta ambivalente: permette di creare dati aggregati, senza peraltro che questi costituiscano dei tipi nell'accezione classica.

• Infatti l'organizzazione strutturale dei dati e le modalità di accesso ai singoli elementi che costituiscono la struttura non vengono nascoste all'utente, che invece può interagire con esse in piena libertà.

Page 3: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 3

Vettori

• Il vettore è una collezione di variabili tutte dello stesso tipo (detto appunto tipo base) di lunghezza prefissata.

• Questa collezione di variabili è individuata da un unico nome, il nome appunto del vettore.

• Ogni elemento del vettore è detto componente ed è individuato dal nome del vettore seguito da un indice posto tra parentesi quadre.

• L'indice può essere solo di tipo intero o enumerato e determina la posizione dell'elemento nel vettore.

Page 4: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 4

Vettori

• L'intervallo dei valori assunti dall'indice determina la dimensione del vettore, che deve essere limitata.

• Definizione generale di vettore:

tipo_componente nome_vettore [numero_componenti];

• tipo_componente può essere un qualunque tipo

semplice,

• nome_vettore è il nome da attribuire al vettore,

• numero_componenti, racchiuso tra parentesi quadre, è il numero di elementi che costituiscono il vettore e pertanto deve essere un intero o un'espressione costante di tipo intero.

Page 5: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 5

Vettori

• L'indice del vettore può assumere valori compresi tra 0 e numero_componenti – 1.

• L'indice corrisponde pertanto alla posizione nel vettore dell’elemento a cui è associato, rispetto al primo.

• Gli elementi del vettore sono memorizzati in celle di memoria contigue (successive)!

Vettore a (di 5 elementi): a[0] a[1] a[2] a[3] a[4]

Page 6: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 6

Vettori

• Esempi di definizioni di vettore:

#define NUM_MATERIE 20char s[8];double giornate[167];int voti_ottenuti[NUM_MATERIE];

• La variabile s è un vettore di 8 elementi: equivale alle 8 variabili di tipo char: s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7].

• La variabile giornate è un vettore di 167 elementi di tipo double il cui indice può variare tra 0 e 166.

• La variabile voti_ottenuti è un vettore di 20 elementi di tipo intero il cui indice può variare tra 0 e 19.

Page 7: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 7

Inizializzazione di un vettore

• E’ possibile assegnare un valore iniziale ad un vettore al momento della sua definizione.

• L’operazione consiste nell’indicare i valori degli elementi del vettore separati tra loro da virgola.

• Sintassi (per un vettore di N elementi):

= {<valore_0>, <valore_1>, ..., ,<valore_N-1>};

• Esempio:int lista[4] = { 2, 0, -1, 5 };

Page 8: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 8

Inizializzazione di un vettore

• NOTA: se vengono specificati meno di N elementi, l’inizializzazione comincia comunque a partire dal primo valore e lascia non assegnati i rimanenti.

• Esempi:

int s[4] = {2, 0, -1}; /* s[0]=2, s[1]=0, s[2]=-1, s[3]=? */

char p[5] = {‘a’, ‘b’, ‘c’}; /* p[0]=‘a’, p[1]=‘b’, p[2]=‘c’, p[3]=?, p[4]=?

*/double d[2] = {2.56}; /* d[0]=2.56, d[1]=? */

Page 9: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 9

Vettori e indici

• L’indice, che definisce la posizione di un elemento di un vettore, DEVE essere rigorosamente un intero!

• Può ovviamente anche essere un’espressione, più o meno complessa, purché con risultato intero.

• Esempio:

double x, a[30]; /* a vettore di double */int i, j, k;.............x = a[2*i+j-k]; /* espressione aritmetica per l’indice

*/

Page 10: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 10

Vettori e cicli

• I cicli sono particolarmente utili per “scandire” un vettore.

• Utilizzo tipico: applicazione iterativa di un’operazione sugli elementi di un vettore.

• Schema:

int data[10], ind; .............for (ind=0; ind<10; ind++) {

elaborazione dell’elemento data[ind] }

• Ad ogni ciclo è interessato l’elemento individuato dall’indice ind.

Page 11: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 11

Vettori

• Non ci sono operatori che agiscono sul vettore nel suo complesso: non è lecito pertanto l'assegnamento di un vettore ad un altro vettore!!!!!

• Se vett_x e vett_y sono vettori, l'istruzione:

vett_x = vett_y;

è errata anche se vett_x e vett_y sono dello stesso tipo.

 • Per trasferire un vettore in un altro occorre

copiare un elemento per volta. !!!!!

Page 12: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 12

Vettori

• Esempio: copia il vettore vett_iniz nel vettore vett_fin

#include <stdio.h>#define NUMDATI 5

int vett_iniz[NUMDATI] = {11, -2, -63, 4, 15};int vett_fin[NUMDATI], indice; main(){for (indice = 0; indice < NUMDATI; indice++) vett_fin[indice] = vett_iniz[indice];}

Page 13: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 13

Vettori

• Sugli elementi del vettore agiscono gli operatori previsti per il tipo_componente. Pertanto è lecito scrivere:

valor_fin = vett_x[m1] + vett_y[m2];

purché, naturalmente, valor_fin, il vettore vett_x e il vettore vett_y siano dello stesso tipo.

• Il tempo necessario per accedere a un elemento di un vettore è indipendente dal valore dell'indice: il vettore è pertanto una

struttura ad accesso casuale

Page 14: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 14

Esempio

• Leggere 10 valori da tastiera e memorizzarli in un vettore; quindi calcolarne il minimo ed il massimo.

• Pseudocodice:

Con un indice ind che varia tra 0 e 9:•legge un dato e lo salva in vettdati[ind];

Inizializzo la variabile massimo e la variabile minimo col primo elemento del vettore vettdati[0]; Con un indice ind che varia tra 1 e 9:

• se vettdati[ind] è più grande di massimo: massimo vettdati[ind]; altrimenti se vettdati[ind] è più piccolo di minimo:

minimo vettdati[ind]; Visualizza massimo e minimo

Page 15: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 15

Esempio

#include <stdio.h>#define NUMDATI 10 main(){int minimo, massimo, ind;int vettdati[NUMDATI];

/* lettura dei dati */for (ind = 0; ind < NUMDATI; ind++) { printf (“\nIntroduci vettdati[%d]: ", ind); scanf ("%d", &vettdati[ind]); }

Page 16: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 16

Esempio

/* cerca il massimo e il minimo */

massimo = vettdati[0]; minimo = vettdati[0];for (ind = 1; ind < NUMDATI; ind++) { if (vettdati[ind] > massimo) massimo = vettdati[ind]; else { if (vettdati[ind] < minimo) minimo = vettdati[ind]; } }printf (“\nIl massimo è %d e il minimo è %d\n ", massimo,

minimo);}

Page 17: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 17

Esempio

• Scrivere un programma che legga un numero decimale positivo minore di 1024 e lo converta nella corrispondente codifica binaria.

• Analisi

Per convertire in binario puro un numero decimale occorre eseguire una sequenza di divisioni per 2 prendendo i resti (0 oppure 1): occorre dunque un vettore per memorizzare questi resti.

Poiché i numeri devono essere compresi tra 0 e 1023 sono sufficienti 10 bit: il nostro vettore sarà pertanto lungo 10 elementi e in ogni elemento memorizzeremo una cifra.

Page 18: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 18

Esempio

Analisi (continua):

I resti ottenuti dalle divisioni per 2 vanno però letti al contrario, conviene pertanto riempire il vettore a partire dall’ultimo elemento.

Per eseguire le divisioni per due è intuitivo che conviene servirsi di un ciclo il quale, ad ogni iterazione, calcola un nuovo bit (resto della divisione per 2).

for o while? È pressochè indifferente usare un ciclo for o un ciclo while: occorre però che le inizializzazioni delle variabili siano adattate al ciclo prescelto.

Se usiamo il for avremo come “dato-guida” del ciclo l’indice del vettore;

Se usiamo il while il “dato-guida” sarà il resto delle divisioni per 2.

Page 19: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 19

Esempio (con while)

#include <stdio.h>

main(){ int ind, numero, num;

int binario[10];

 /* inizializza il vettore risultato con tutti zeri */

for (ind = 0; ind < 10; binario[ind++]=0); /* equivale a : for (ind=0; ind<10; ind++) binario[ind] = 0; */ printf (“\nIntroduci un numero intero positivo minore di 1024: ");

scanf ("%d", &numero);

Page 20: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 20

Esempio (con while) if ((numero >= 0) && (numero < 1024)) {

num = numero; /* num è il “dato-guida” del ciclo */ ind = 9; while (num != 0) /* finché num è diverso da 0! */ {

binario[ind] = num % 2; /* calcola un nuovo bit */ num /= 2; /* aggiorna num per il prossimo ciclo */ ind--; /* aggiorna l’indice del vettore */

} printf ("\nConversione del numero %d: ", numero); for (ind=0; ind<10; ind++) /* Visualizza il vettore: */ printf ("%1d",binario[ind]); /* un bit per volta */ } else printf (“\nNumero non lecito!”);}

Page 21: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 21

Esempio (con for)

#include <stdio.h>

main(){ int ind, numero, num; int binario[10];

/* non è necessario inizializzare il vettore in quanto il ciclo for deve */

/* scrivere comunque tutti gli elementi del vettore */

printf (“\nIntroduci un numero intero positivo minore di 1024: ");

scanf ("%d", &numero);

Page 22: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 22

Esempio (con for)

if ((numero >= 0) && (numero < 1024)) { num = numero; for (ind = 9; ind >= 0; ind--) /* con un indice che va da 9 a 0 */ {

binario[ind] = num % 2; /* calcola un nuovo bit */ num /= 2; /* aggiorna num per il prossimo ciclo */

} printf ("\nConversione del numero %d: ", numero); for (ind = 0; ind < 10; ind++) /* Visualizza il vettore: */ printf ("%1d",binario[ind]); /* un bit per volta! */ } else printf (“\nNumero non lecito!”);}

Page 23: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 23

Vettori

• Quando si definisce un vettore il compilatore riserva un’area di memoria sufficiente per contenerlo e associa l'indirizzo iniziale di quell'area al nome simbolico (identificatore) da noi scelto per il vettore.

 • Pertanto il nome vett_dati non è una vera e propria

variabile, ma piuttosto un puntatore : in pratica vett_dati è l'indirizzo di memoria del primo elemento del vettore cioè l'indirizzo di vett_dati[0].

 • Ecco perché è errata l'istruzione:

voti_ottenuti = voti_semestre;

Page 24: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 24

Vettori multidimensionali

• Il concetto di vettore come collezione di elementi consecutivi, può essere esteso immaginando che gli elementi siano a loro volta dei vettori: si ottiene così un vettore multidimensionale o matrice.

• La definizione di matrice ricalca pienamente quella del vettore:

tipo_comp nome [dim1] [dim2].........; • tipo_comp può essere un qualunque tipo semplice,

• dim1, dim2, ecc.; racchiusi tra parentesi quadre, definiscono il numero di elementi di ogni dimensione.

Page 25: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 25

Vettori multidimensionali

a[0][0] a[1][0] a[2][0] a[3][0] a[4][0]

a[0][1] a[1][1] a[2][1] a[3][1] a[4][1]

a[0][2] a[1][2] a[2][2] a[3][2] a[4][2]

a

int a[3][5];

a[0]

a[1]

a[2]

Esempio:

matrice bidimensionale di numeri interi formata da tre righe e 5 colonne:

Page 26: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 26

Vettori multidimensionali

• Accesso ad un elemento:

<nome vettore> [<posizione1>] [<posizione2>].............

• Per esempio matrix [10][20][15]

individua l'elemento di coordinate rispettivamente 10, 20 e 15 nella matrice a 3 dimensioni matrix.

• Inizializzazione di un vettore multidimensionale: deve essere effettuata per righe!

int vett[3][2] = { {8,1}, /* vett[0] */ {1,9}, /* vett[1] */

{0,3} /* vett[2] */

};

Page 27: © Piero Demichelis Tipi strutturati I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità

© Piero Demichelis 27

Vettori multidimensionali e cicli

• Per un vettore a più dimensioni, la scansione va applicata a tutte le dimensioni: in questo caso si devono in genere utilizzare “cicli annidati ”.

• Esempio: elaborazione degli elementi di un vettore bidimensionale.

int vett [3][5];…for (i = 0; i < 3; i++) { /* per ogni riga

*/ for (j = 0; j < 5; j++) { /* per ogni colonna

*/ ... elaborazione su vett[i][j] }}