Corso di Programmazione 1 a.a.2006/2007 Prof.ssa Chiara Petrioli Corso di Laurea in Informatica Università degli Studi “La Sapienza” (lezioni 16-19) Strutture, Unioni e Liste Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Strutture Le strutture sono collezioni di variabili correlate sotto un unico nome Possono contenere variabili di diversi tipi di dato Esempio Etichetta di una struttura Definisce un tipo di dato struttura struct card{ struct card costituita da due campi char *face; un campo face stringa che dice che carta è quella corrente: asso, due,…,re char *suit; un campo suit stringa che dice il seme della }; carta corrente (cuori,…,fiori) Membri di una struttura Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Esempio Il recordi di un impiegato struct impiegato{ char *nome; La struttura consente di raggruppare Informazioni correlate, in questo caso char *cognome; Relative ad un singolo impiegato int eta; char sesso; float stipendio; }; Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Dichiarazione di variabili struct struct card a, deck[52], *cPtr; a è una variabile di tipo struct card viene allocata memoria per due campi puntatori deck è un vettore di strutture. Contiene 52 elementi. Ciascun elemento è una struttura costituita da due campi face e suit cPtr è un puntatore ad una struttura (contiene l’iundirizzo della locazione di memoria in cui è memorizzato un elemento di tipo struct card) Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Dichiarazione di variabili struct struct card a, deck[52], *cPtr; a è una variabile di tipo struct card ALTERNATIVA viene allocata memoria per due campi puntatori struct card{ *face; deck è un vettore char di strutture. Contiene 52 elementi. Ciascun elementochar è una*suit; struttura costituita da due campi face e suit }a,deck[52],*cPtr; cPtr è un puntatore ad una struttura (contiene l’iundirizzo della locazione di memoria in cui è memorizzato un elemento di tipo struct card) Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Operazioni su strutture Assegnare variabili struct a variabili struct dello stesso tipo di struttura Determinare in che locazione di memoria è memorizzata una struttura Accedere ai membri di una struttura (per leggere o scrivere il loro valore) Con l’operatore sizeof determinare la dimensione di una struttura (cosa che serve ad esempio per sapere quanta memoria deve essere allocata a ciascun elemento di quel tipo di dato struttura) Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Operazioni illecite Due elementi di tipo struttura non possono essere confrontati – Ci possono essere dei bit con valore indeterminato nelle locazioni di memoria allocate ad una struttura – Ad esempio Buco. In questo byte potrebbe essere contenuto qualsiasi valore struct example{ impossibile confrontare sample1 e char c; sample2 direttamente. Bisogna int i; confrontare i valori dei vari membri delle due strutture. } sample1,sample2; Un computer con una parola di 2byte potrebbe richiedere l’allineamento all’inizio della parola successiva per membri successivi della struttura 01100001 00000000 Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 01100001 Inizializzazione di strutture struct card{ char *face; char *suit; }; struct card a={“Asso”,”Fiori”}; Se il valore di un membro non è indicato tra le parentesi graffe è inizializzato automaticamente a 0 (o a NULL se è di tipo puntatore). Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Come si accede ai membri di una struttura Operatore membro di struttura (operatore punto .) – accede ad un membro della struttura attraverso il nome della variabile di struttura Esempio printf(“%s”, a.suit); Stampa il campo suit della variabile a, di tipo struct card Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Come si accede ai membri di una struttura Operatore puntatore a struttura -> – accede ad un membro della struttura attraverso un puntatore alla stessa Esempio printf(“%s”, cPtr->suit); Stampa il campo suit della struttura puntata da cPtr. cPtr è un puntatore ad una struttura di tipo struct card Risolve il riferimento e accede al membro suit della struttura usando l’operatore membro di struttura cPtr->suit equivale a (*cPtr).suit le parentesi sono necessarie perché l’operatore membro di struttura ha priorità maggiore di * Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Un esempio #include<stdio.h> struct card{ char *face; char *suit; }; main() { struct card a; struct card *aPtr; a.face =“Asso”; a.suit=“Picche”; aPtr=&a; printf(“%s di %s\n%s di %s\n %s di %s \n”, a.face, a.suit, aPtr->face, aPtr->suit, (*aPtr).face, (*aPtr).suit); return 0; } Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Asso di Picche Asso di Picche Asso di Picche Usare le strutture con le funzioni Le strutture possono essere passate alle funzioni fornendo i singoli membri, l’intera struttura o un puntatore ad una struttura. Vettori di strutture sono passati per riferimento. Per passare una struttura per Passati per valore riferimento si deve passare alla funzione l’indirizzo di memoria dove è memorizzata la struttura. Le funzioni possono restituire strutture Può consentire ad una funzione di restituire Prof.ssa Chiara Petrioli -- corso di più valori programmazione 1, a.a. 2006/2007 Un esempio Si scriva una funzione che dato un vettore restituisca il più piccolo elemento del vettore ed il più grande elemento del vettore Definiamo: struct min_max{ int min; int max; }; Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Soluzione struct min_max minmax_v (int vett[ ], int n) { struct min_max temp; La funzione minmax_v prende if (n==1) in input un vettore di interi vett { e la sua dimensione n temp.min=vett[0]; restituisce in output una struttura temp.max=vett[0]; di tipo min_max che contiene nei return temp; suoi membri il minimo ed il massimo } tra gli elementi del vettore else { temp=minmax_v(vett,n-1); if (vett[n-1]<temp.min) temp.min=vett[n-1]; if (vett[n-1]>temp.max) temp.max=vett[n-1]; return temp; } } Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Come si può passare per valore un vettore Dobbiamo creare una struttura che contenga come membro il vettore Dato che una struttura o i membri della struttura sono passati per valore il vettore verrà passato nello stesso modo (basta passare alla funzione il membro della struttura che contiene il vettore) – Verrà quindi fatta una copia del vettore e si opererà su tale copia Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 typedef La parola chiave typedef consente di creare pseudonimi per i tipi di dato precedentemente definiti, tipicamente per abbreviare i nomi di tali tipi di dato typedef struct card Card; dice che nel seguito del programma quando si troverà scritto Card di farà riferimento al tipo struct card Card deck[52]; Card NON è un nuovo tipo di dato, è un sinonimo per struct card ! Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Esempio Mescolatore di carte (variante ad alta efficienza di quello precedentemente visto) Vettore di tipo Card fillDeck inizializzato in modo da contenere le carte ordinate dall’asso al re per ogni seme La funzione shuffle che mescola il mazzo riceverà come input un vettore di 52 strutture di tipo Card, scorrerà le carte e per ogni carta sceglierà un numero casuale tra 0 e 51 (carta con cui la carta esaminata sarà scambiata). Mescola effettuando scambi, non potendo portare ad attese lunghe o indefinite per il completamento. Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Codice #include <stdio.h> #include<stdlib.h> #include<time.h> struct card { char *face; char *suit; }; typedef struct card Card; void fillDeck (Card *,char *[ ], char *[ ]); void shuffle(Card *); void deal(Card *); Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Codice main() Deck è un vettore di strutture { Card deck[52]; char *face[ ]={“Asso”, “Due”, “Tre”, “Quattro”, “Cinque”, “Sei”, “Sette”, “Otto”, “Nove”, “Dieci”, “Fante”, “Donna”, “Re”}; char *suit[ ]={“Cuori”, “Quadri”, “Picche”, “Fiori”}; srand(time(NULL)); fillDeck(deck, face, suit); shuffle(deck); deal(deck); return 0; } Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Codice void fillDeck(Card *wDeck, char *wFace[ ], char *wSuit[ ]) { int i; Inizializziamo al for (i=0;i<=51;i++) caso in cui per { ciascun seme le carte sono ordinate wDeck[i].face=wFace[i%13]; wDeck[i].suit=wSuit[i/13]; } } Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Codice void shuffle(Card *wDeck) { int i,j; Card temp; for (i=0;i<=51;i++){ j=rand()%52; temp=wDeck[i]; wDeck[i]=wDeck[j]; wDeck[j]=temp; } } Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Codice void deal (Card *wDeck) { int i; for (i=0;i<=51;i++) printf(“%s of %s \n, wDeck[i].face, wDeck[i].suit); } Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007