Linguaggio C Aggregati di dati Limiti delle variabili semplici Come elaborare e salvare grandi quantità di dati? Ad esempio, un sensore invia un dato ogni intervallo di tempo, la sequenza va poi conservata per un certo tempo per essere elaborata Occorre definire tante variabili diverse ad esempio numerate? Come descrivere dati strutturati anagrafici? Ad esempio dati anagrafici di un comune molte variabili scollegate, nome, cognome, data nascita, residenza, etc? Ripetute per ogni cittadino? Strutture La struttura è una collezione di variabili (di solito non dello stesso tipo) raggruppate sotto lo stesso nome. struct tempo {! int ore;! int minuti;! int secondi;! } orologio1, orologio2;! struct tempo {! int ore;! int minuti;! int secondi;! };! struct tempo orologio1, orologio2;! Nuovi tipi di dati: typedef L'istruzione typedef definisce un sinonimo per un tipo. typedef int intero; intero x = 3;! Con le strutture, typedef serve a definire un sinonimo per strutture complesse typedef struct tempo{...} orologio;! orologio swatch, sector;! typedef è un sinonimo per la dichiarazione di istanze di strutture /*dichiarazione con typedef*/! typedef struct {int x; int y;} coord;! /*istanza*/! coord punto1, punto2;! /*dichiarazione senza typedef*/! struct coord {int x; int y;};! /*istanza*/! struct coord punto1, punto2;! Operatori per strutture l'operatore punto (".") è lo strumento per accedere ai singoli campi delle variabili struct orologio1.ore = 18;! orologio1.minuti = 21;! orologio1.secondi = 22;! Le strutture si possono nidificare (cioè si può inserire una struttura dentro un'altra struttura) struct nascita {! struct tempo ora;! struct data data;! };! Esempio concorso # include <stdio.h> /* definizione di tipo globale*/! struct concorso {! int serie;! char organizzatore;! int partecipanti;! };! main()! {! struct concorso c0, c1;! c0.serie = 2; c0.organizzatore = 'F';! c0.partecipanti = 482;! c1.serie = 0; c1.organizzatore = 'G';! c1.partecipanti = 33;! printf("Serie della concorso 0: %d\n", c0.serie);! printf("Organizzatore della concorso 1: %c\n",! c1.organizzatore);! }! /*Programma distanza con variabili singole*/! ….! double lato1, lato2, distanza, x1=1, y1=5, x2=4,! y2=7;! lato1= x2-x1; lato2= y2-y1;! distanza=sqrt(lato1*lato1 + lato2*lato2);! /* visualizzazione */! printf (“la distanza fra i due punti è”! “%5.2lf\n”, distanza);! }! •un punto nel piano cartesiano può essere visto come struct o come array /* Programma distanza con struct per punto*/! ….! double lato1, lato2, distanza;! struct punto {! double x;! double y;! } p1, p2;! p1.x = 1; p1.y = 5;! p2.x = 4; p2.y = 7;! lato1= p2.x - p1.x; lato2= p2.y - p1.y;! distanza=sqrt(lato1*lato1 + lato2*lato2);! /* visualizzazione! */! printf (“la distanza fra i due punti = %5.2lf\n”,! distanza);! }! Molti dati dello stesso tipo Occorre un costruttore che permette di usare lo stesso nome per tante variabili dello stesso tipo Nella notazione matematica (serie, etc) si usano i pedici In C si usano indici Questi dati saranno memorizzati in memoria di lavoro in posizioni contigue L’area per memorizzarli sarà statica array La struttura dati che naturalmente si adatta ai costrutti for è l’array, cioè la sequenza di valori organizzati insieme ed individuabili con un unico nome. Il nome dell’array è un identificatore, ed è possibile accedere ad ognuno degli elementi usando un indice (indirizzamento mediante registro indice) che parte da 0 Tutti gli elementi! hanno lo stesso! nome c)! c[0]! -45! c[1]! 6! c[2]! 0! c[3]! 72! c[4]! 1543! c[5]! -89! c[6]! 0! c[7]! 62! c[8]! -3! c[9]! 1! c[10]! 6453! c[11]! 78! Posizione! dell’elemento! nella array c! array 12 a[0] 24 31 101 55 71 a[1] un array è un insieme di locazioni di memoria con lo stesso nome e distinte da un numero detto indice (in inglese subscript). Gli array si dichiarano come le variabili ma sono seguiti da [n], dove n è una costante ed indica la dimension dell'array int a[6];! char testo[20];! Le singole locazioni di memoria si indicano con i simboli a[0],a[1],a[2],..., a[5]! Memoria per array contenuti indirizzi int pippo[3] 9, cioè1001 pippo 00000000 00000010 00000010 pippo[0] = 0 pippo[1] =2 pippo[2] = 2 & pippo[0] Dichiarazioni e assegnamenti array Es di dichiarazione: int s[6];! double t[4];! Es. di inizializzazione contestuale: int s[6] = {5, 0, -1, 2, 15, 2};! double t[4] = {0.0, 0.1, 0.2, 0.8};! int s[6] = {0}; assegna 0 a tutti gli elementi! int s[ ] = {5, 0, -1, 2, 15, 2}; calcola! la dimensione dai dati di inizializzazione Inizializzare mediante cicli Per inizializzare in modo regolare: int k; double gi[21];! for (k=0; k<= 20; k++)! gi[k] = k * 0.5;! se k supera 20 accede a posizioni di memoria fuori dell’array Per inizializzare mediante lettura : int k; double gi[21];! for (k=0; k<= 20; k++)! scanf (“%lf”, &gi[k]);! esempio #include <stdio.h>! /* programma che acquisisce 5 numeri in array e la stampa*/! main()! { int lista[5];! int contavolte = 0, letto = 0;! printf("Inserire 5 numeri tra 1 e 10\n");! /* questo ciclo while controlla la gestione dei 5 valori */! while ( contavolte < 5 )! { letto = 0;! /* questo ciclo while aspetta un numero fra 1 e 10*/! while (letto < 1 || letto > 10)! { printf("\n Inserisci il num. %d: ", contavolte + 1 );! scanf("%d", &letto );! }! lista[contavolte] = letto;! contavolte++;! }! for (contavolte = 0; contavolte < 5; contavolte++)! printf("\nVal. %d=%d", contavolte + 1, lista[contavolte]! );! }! /* Programma distanza - ogni punto è un array di due*/! ….! double lato1, lato2, distanza;! double punto1[2], punto2[2];! punto1[0] = 1; punto1[1] = 5;! punto2[0] = 4; punto2[1] = 7;! lato1= punto2[0] - punto1[0] ;! lato2= punto2[1] - punto1[1] ;! distanza=sqrt(lato1*lato1 + lato2*lato2);! /* visualizzazione! */! printf (“la distanza fra i due punti = %5.2lf\n”, distanza);! }! Estendere al caso 3D?! Ogni punto è array di 3 posizioni! Estendere a più punti?! Fare array rettangolare: ogni linea è un punto, ogni! colonna i valori di un asse! Esempio: stampa un istogramma #include <stdio.h>! #define SIZE 10! main()! {! int n[ SIZE ] = { 19, 3, 15, 7, 11, 9, 13, 5, 17, 1 };! int i, j;! printf( "%s%13s%17s\n", "Elemento", "Valore", “Istogramma! for ( i = 0; i <= SIZE - 1; i++ ) {! printf( "%7d%13d! ", i, n[ i ]) ;! for ( j = 1; j <= n[ i ]; j++ )! printf( "%c", '*' );! printf( "\n" );! }! } /* stampa una barra */! Output del programma Elemento! 0! 1! 2! 3! 4! 5! 6! 7! 8! 9! Valore! 19! 3! 15! 7! 11! 9! 13! 5! 17! 1! Istogramma! *******************! ***! ***************! *******! ***********! *********! *************! *****! *****************! *! massimo rivisto: Trovare il massimo di un array di 5 valori naturali, prendendo il primo come max provvisorio int max, i, corrente, valori[5];! /* lettura*/! for (i = 0; i<5; i++)! scanf ("%6d \n", &valori[i]);! /* calcolo */! max = valori[0];! for (i = 1; i<5; i++)! { if (valori[i] > max) max = valori[i]; }! printf ("il massimo è' %d \n", max);! ….! Esempio calcolo vettoriale Scrivere un programma che chiede all’utente di inserire due vettori e ne stampa il prodotto scalare e vettoriale. Vettore r, con componenti r1, r2, r3 Vettore s con componenti s1, s2, s3 Prodotto scalare r.s = r1*s1 + r2*s2 +r3*s3 Prodotto vettoriale c è un vettore c1, c2, c3 c1 = r2*s3 – r3*s2 c2 = r3*s1 – r1*s3 c3 = r1*s2 – r2*s1 calcolo vettoriale: pezzi della soluzione /* dichiarazioni*/! int comp; double scalare; float r[3], s[3], c[3] = {0.0};! /* lettura dati mediante ciclo for*/! /* calcolo prodotto scalare*/! scalare = 0.0;! for(comp=0;comp<3;comp++)! scalare = scalare + r[comp]*s[comp];! /* calcolo prodotto vettoriale modo diretto*/! c[0] = r[1]*s[2] – r[2]*s[1]! c[1] = r[2]*s[0] – r[0]*s[2]! c[2] = r[0]*s[1] – r[1]*s[0]! /* calcolo prodotto vettoriale: for e indici modulo3*/! for(comp=0;comp<3;comp++)! [comp]=! r[(comp+1)%3]*s[(comp+2)%3]-r[(comp+2)%3]*s[(comp+1)%3];! Array a più dimensioni c0! r0! r1! r2! c1! c2! c3! a[ 0 ][ 0 ] a[ 0 ][ 1 ] a[ 0 ][ 2 ] a[ 0 ][ 3 ]! a[ 1 ][ 0 ] a[ 1 ][ 1 ] a[ 1 ][ 2 ] a[ 1 ][ 3 ]! a[ 2 ][ 0 ] a[ 2 ][ 1 ] a[ 2 ][ 2 ] a[ 2 ][ 3 ]! Indice colonna! Nome array! Indice riga! int a[ 3 ][ 4]! Inizializzare int b[ 2 ][ 2 ] = { { 1, 2 }, { 3, 4 } };! Quello non specificato va a 0 int b[ 2 ][ 2 ] = { { 1 }, { 3, 4 } };! Richiamare un elemento Prima indice di riga, poi di colonna printf( "%d", b[ 0 ][ 1 ] );! Array a più dimensioni /* esempio: immagine*/! const int height = 256;! const int width = 256;! int i, j, image [height][width];! /* inizializzazione con 2 for: uno! per righe e l’interno per colonne*/! for(i=0;i< width;i++)! {! for(j=0;j<height;j++)! image[i][j] = i*j;! }! stringhe Stringhe sono array di caratteri “first” - array di char – costanti fra due apici! Dichiarazione e inizializzazione char string1[] = "first";! '\0' termina la stringa! string1 ha quindi 6 elementi! Equivalente a char string1[6] = { 'f', 'i', 'r', 's', 't', '\0' };! Per accedere al singolo carattere string1[ 3 ] is character ‘s’! Il nome dell’array è il suo indirizzo. & non si usa in scanf scanf( "%s", string1 );! esercizio: Media, mediana, modo su array Media – somma valori divisa per il numero occorrenze 1, 2, 3, 4 => la media è 2,5 Mediana – il numero nel mezzo di un insieme ordinato 1, 2, 3, 4, 5 => la mediana è 3 Modo – il numero che compare più spesso 1, 1, 1, 2, 3, 3, 4, 5 => 1 è il modo Array di strutture come gestire diversi concorsi? array di strutture struct concorso c[3];! Ogni elemento dell’array è una struttura conforme al template concorso l'array ha nome c, 3 elementi del tipo “struct concorso” Per accedere ai singoli elementi dell'array specificare il nome dell'array seguito dall'indice, tra quadre, dell'elemento da referenziare; usare l'operatore punto per accedere al campo voluto. #include <stdio.h>! struct concorso { int serie;! char organizzatore;! int partecipanti;};! main()! { int i; struct concorso c[3];! c[0].serie = 2; c[0].organizzatore = 'F';! c[0].partecipanti = 482;! c[1].serie = 0; c[1].organizzatore = 'G';! c[1].partecipanti = 33;! c[2].serie = 3; c[2].organizzatore = 'E';! c[2].partecipanti = 107;! for(i = 0; i < 3; i++)! printf("%d %c %d\n",c[i].serie,! c[i].organizzatore,c[i].partecipanti);}! Array come campo di struttura /*globale – stato del concorso*/! struct concorso { int serie;! char organizzatore;! int partecipanti;! char stato [2];};! main()! { int i; struct concorso mio;! mio.serie = 2;! mio.organizzatore = ’A';! mio.partecipanti = 15;! mio.stato[0] = ’T';! mio.stato[1] = ’F';! printf("%d %c %d\n",mio.serie,! mio.organizzatore,mio.partecipanti);}! for(i = 0; i < 2; i++)! printf("%s",mio.stato[i]);! }! serie organizzatore partecipanti s0 s1 Array come campo di struttura /*locale – stato del concorso*/! main()! {struct concorso { int serie;! char organizzatore;! int partecipanti;! char stato [2];};! int i; struct concorso mio;! mio.serie = 2;! mio.organizzatore = ’A';! mio.partecipanti = 15;! mio.stato[0] = ’T';! mio.stato[1] = ’F';! printf("%d %c %d\n",mio.serie,! mio.organizzatore,mio.partecipanti);}! for(i = 0; i < 2; i++)! printf("%s",mio.stato[i]);! @} Problemi di ricerca Esiste un certo dato in un array? Ricerca sequenziale (dall’inizio o dalla fine, l’unica se i dati non sono ordinati) Ricerca dicotomica (dal mezzo, su dati ordinati) Ricerca sequenziale #include <stdio.h>! #define MAXDIM 100 /* dimensione massima del! vettore */! main()! {int i,K,N;! int V[MAXDIM];! do{! printf("\n Inserire la dimensione del vettore! non superiore a %d\n",MAXDIM);! scanf("%d",&N);! }while(N>MAXDIM);! /* inserimento vettore */! for (i=0;i<N;i++)! {! printf("Inserire l'elemento %d : ",i+1);! scanf("%d",&V[i]);! }! /* Inserimento del valore da cercare ( chiave K! )*/! printf("Inserire l'elemento da cercare : ");! scanf("%d",&K);! /* scandire gli elementi del vettore partendo dal! primo V[0] e fermandosi se si trova K o se si! finisce l’array*/! i=0;! while( K != V[i] && i<N )! i = i + 1;! /*il risultato della ricerca dipende da quale! condizione di uscita è stata verificata*/! if ( i<N ) printf("Elemento trovato in posizione! %d\n", i+1);! else printf("Elemento non trovato\n");! }! Ricerca dicotomica 1) 2) 3) Si individua l’elemento che sta a metà del vettore; Si confronta la chiave K con tale elemento. Se l’elemento individuato non è uguale a quello cercato : • se K > elemento mediano la ricerca continua solo nel semivettore superiore • se K < elemento mediano la ricerca continua solo nel semivettore inferiore Il procedimento continua suddividendo i semivettori via via individuati. Esempio: 2 4 5 6 8 9 14 trovare 9 Confronto 9 con 6 - ripeti sul vettore 8 9 14 Confronta 9 con 9 - trovato Ricerca dicotomica #include <stdio.h>! #define MAXDIM 100! main()! {! int i,inf,sup,med,K,N; int V[MAXDIM];! do{! printf("\n Inserire la dimensione del vettore non! superiore a %d\n",MAXDIM);! scanf("%d",&N);! }while(N>MAXDIM);! /* inserimento del vettore ordinato */! for (i=0;i<N;i++)! {! printf("Inserire l'elemento %d : ",i+1);! scanf("%d",&V[i]);! }! /* Inserimento del valore da cercare K */! printf("Inserire l'elemento da cercare : ");! scanf("%d",&K);! /*inizializzazione degli indici */! inf = 0; sup = N-1; med = (inf + sup)/2;! /*accedi al mediano del vettore a ciascun passo */! while ( K != V[med] && inf<sup )! {! if ( K > V[med] ) /*vai nella parte alta*/! inf = med+1;! else! sup = med-1; /*vai nella parte bassa*/! med = (inf + sup)/2;! }! /*risultato della ricerca */! if ( V[med]== K )! printf("Elemento trovato in posizione %d\n", med+1);! else printf("Elemento non trovato\n");! }! Quale preferire? La Ricerca Sequenziale ricerca con successo:Nel caso migliore ho un solo confronto e in quello peggiore N Il numero medio di confronti risulta (N+1)/2 ricerca senza successo: L’algoritmo esamina sempre tutto il vettore, quindi il numero di confronti è sempre N La Ricerca dicotomica Ad ogni iterazione l'insieme è dimezzato, il numero di confronti è pari a quante volte N può essere diviso per 2 fino a ridurlo a 0. in un vettore di dimensione N = 2h, l’algoritmo deve compiere circa h = log2(N) passi (e quindi confronti) per la ricerca senza successo, nel caso medio il numero è leggermente inferiore mentre nel caso migliore è 1. Esempio : per cercare un elemento in un insieme di 1.000.000 elementi, nel caso pessimo con la Ricerca Sequenziale dovremmo eseguire circa 1.000.000 confronti, mentre con la Ricerca Binaria ne dobbiamo effettuare al massimo 21. Problemi di ordinamento 3 metodi: Selection Insertion Exchange Si parte da array iniziale con i valori disordinati, e si ordina nell’array stessa 32 Una passata per ordinare ogni posizione 24 Una passata31 per cercare101 il valore da55mettere in 71 quella posizione Selection sort Trovo il minimo fra gli N; poi il minimo fra gli N-1; etc e lo metto nella posizione da ordinare #define N 100! ….! main ()! {! int i, j, min, temp; int dati[N];! /*acquisisci gli N valori*/! ……! for (i = 0; i < N-1; i++) {! min = i;! for (j = i+1; j < N; j++) {! /* trovo l’indice in cui si trova il minimo */! if(dati[j]<dati[min])! min=j;! temp = dati[i];! dati[i]=dati[min]; /*metto il minimo a posto*/! dati[min]= temp;! }! }! Esempio selection 67345 37645 34675 34576 34567 inizio dopo for i=0 dopo for i =1 dopo for i=2 dopo for i = 3 Insertion sort ..{ int i, j; int dati[N];! for (i = 1; i <N; i++)! for (j = i; j > 0; j--)! if (dati[j]<dati[j-1])! {/*scambia*/;! temp = dati[j-1];! dati[j-1]=dati[j];! dati[j]= temp;! }}! Esempio insertion 67345 37645 34675 34576 34567 inizio dopo for i=0 dopo for i =1 dopo for i=2 dopo for i = 3 sort Bubble sort su array N passate Confronta un elemento con il successivo Se il primo è minore o uguale, nulla Se maggiore, scambia Repeat esempio: originale: passata 1: passata 2: passata 3: 34267 32467 23467 23467 Bubblesort – ordinare array a #include <stdio.h>! # define! N 10! main ()! { int pass, j, temp, a[N];! /* lettura di a*/! /* bubblesort a*/! for (pass = 1; pass <N; pass++)! for (j = 0; j <N-1; j++)! if a[j] > a[j+1]! {/* scambio*/! temp = a[j] ; a[j] = a[j+1] ; a[j+1]=temp;! } /* stampa di a*/! ….! } esercizi Calcolare la somma dei primi N numeri interi N(N+1)/2 N =1 Somma = 2/2 =1 N=2 Somma = 2(3)/2 = 3 cioè 1+2 Calcolare la somma dei primi N numeri pari N*N+N Es: N = 1 Somma=2 N=2 Somma = 2*2+2 = 6 cioè 2+4