Elementi di Informatica A. A. 2016/2017 Ing. Nicola Amatucci Università degli studi di Napoli Federico II Scuola Politecnica e Delle Scienze di Base nicola.amatucci@unina.it
Programmazione C++ Parte 2
Da dove studiare? «Che C Serve», Capitolo 4
Dati Strutturati Una variabile appartenente ad un tipo semplice contiene un unico valore scelto nell'ambito del tipo Ad es. "int a;" può contenere solo un intero Più tipi semplici possono essere aggregati a formare un unico tipo strutturato Un Array è costituito da più componenti dello stesso tipo Un Record è un'informazione strutturata costituita da componenti di tipo diverso Ad es. una voce della rubrica telefonica è costituita da parole e numeri
Array Gli elementi di un Array (o Vettore) sono tutti dello stesso tipo hanno tutti lo stesso nome sono accessibili indicando la loro posizione nell'array (gli indici partono da 0) Un Array ha una dimensione predefinita (indicata da una costante) Permette di allocare locazioni di memoria consecutive L'etichetta (il nome del vettore) contiene la posizione in memoria del primo elemento
Dichiarazione di un Array Per dichiarare un Array si deve indicare Tipo Nome (o etichetta) Dimensione Esempio: int a[3]; float b[10]; char c[20]; tipo nome[dimensione];
Inizializzazione degli Array Per inizializzare un Array si utilizza una lista di tipi semplici rinchiusi tra parentesi graffe Ad esempio int a[3] = {1,2,3}; float b[2] = {-0.1, 0.1}; char ciao[5] = {'c', 'i', 'a', 'o', '\0'}; int tutti_zero[10] = {0}; Nell'ultimo caso, utilizzando {0} la memoria che contiene l'array viene inizializzata interamente a zero
Gli array: funzione di accesso Per accedere agli elementi bisogna utilizzare la posizione dell'elemento all'interno dell'array La posizione di memoria salvata all'interno dell'etichetta è quella del primo elemento esso si trova in posizione zero Il secondo elemento sarà in posizione 1 posizione in memoria del primo elemento più 1 Si arriva fino a N-1, dove N è la dimensione (o cardinalità) dell'array (il numero tra parentesi quadre)
Gli array: funzione di accesso int vettore[5] = {22, 12, 5, 13, 65}; vettore[0] vettore[1] vettore[2] vettore[3] vettore[4] 22 12 5 13 65
Array Multidimensionali Array Bidimensionale (o Matrice) Un elemento dell'array è a sua volta un Array dello stesso tipo Dichiarazione int matrice[4][3]; È una matrice di 4 righe e 3 colonne 1 3 5 22 24 7 11 6 49 37 61 25
Array Multidimensionali: Dichiarazione In generale, per dichiarare un array multi-dimensionale tipo nome[dimensione1] [dimensione2] [dimensione3]. [dimensionex]; Per identificare un elemento saranno necessarie tante posizioni quante sono quelle definite in fase di dichiarazione Se una matrice è un vettore di vettori, un array multidimensionale è un vettore di vettori di vettori di vettori
Array Multidimensionali: Inizializzazione int matrice[4][3] = { {1,3,5}, {22,24,7}, {11, 6, 49}, {37,61,25}}; 1 3 5 22 24 7 11 6 49 37 61 25 Se scrivo int matrice[4][3] = {0}; Inizializzo tutti gli elementi della matrice a zero
Array Multidimensionali: Accesso Per accedere ad un elemento di un vettore multidimensionale bisogna indicare le posizioni in tutte le dimensioni definite Ad esempio, per una matrice "int matrice[4][3];" matrice[0][0] = 1; matrice[0][1] = 3; matrice[1][0] = 22; 1 3 5 22 24 7 11 6 49 37 61 25
Memoria e Array Multidimensionali Per semplicità consideriamo un array bidimensionale (matrice) 1 3 5 22 24 7 11 6 49 37 61 25 In memoria avremo che la seconda riga comincia alla posizione di memoria 2 + 1 (ricordando che si parte da 0) matrice[0][0] matrice[0][1] matrice[0][2] matrice[1][0] matrice[1][1] matrice[1][2] 1 3 5 22 24 7
Memoria e Array Multidimensionali Sotto questo punto di vista è possibile vedere un array multidimensionale come un array monodimensionale molto grande Utilizzando più indici l'accesso alle singole posizioni viene "semplificato" Possiamo inoltre dichiarare un array multidimensionale omettendo le parentesi graffe int matrice[4][3] = { 1, 3, 5, 22, 24, 7, 11, 6, 49, 37, 61, 25}; Meno comprensibile di quando ci sono le parentesi graffe!
Array e Stringhe Un Array di char è anche detto stringa Un array di questo tipo, per poter essere utilizzato da C++ (ad es. in cout) deve avere un elemento detto terminatore '\0' Ad esempio char ciao[10] = {'c','i','a','o','\0'}; Si può anche usare una inizializzazione alternativa char ciao[10] = "ciao"; In questo caso '\0' è aggiunto automaticamente
Inizializzazione aggregata di Array Se l'array (monodimensionale) viene inizializzato, è possibile omettere la dimensione int vettore[] = {1,2,3}; la dimensione è definita in modo implicito attraverso il numero di valori forniti Da utilizzare con attenzione Preferibile l'uso di un carattere terminatore Molto utile nel caso di stringhe Implicitamente hanno un carattere terminatore Ad es. int ciao[] = "ciao"; Nel caso di array bidimensionali (matrici), è possibile omettere solo il primo indice Ad es. int matrice[][3] = = { {1,3,5}, {22,24,7}, {11, 6, 49}, {37,61,25}};
Errori Frequenti In C++ non è possibile assegnare un array ad un altro int a[3] = {1,2,3}; int b[3]; b = a; //errore! Il C++ non effettua il controllo sui limiti degli array Non c'è nulla che eviti lo sconfinamento alla fine di un array Sconfinare significa andare ad accedere ad aree di memoria ad esempio riservate altre variabili o vuote Il programmatore deve aggiungere un controllo di errore adeguato a seconda delle necessità
Esercizio Dati due vettori in ingresso, implementare il prodotto scalare trai due vettori Date due matrici, implementare la somma di matrici
Record Un Record (o Struttura) è una collezione di elementi di tipo diverso (o anche dello stesso), raggruppati sotto un unico nome Un elemento è detto campo Ogni campo ha un tipo ed un nome Il tipo può essere semplice o strutturato (array o record) Consente di aggregare informazioni che appartengono allo stesso "concetto" Esempio Studente Matricola (intero) Nome (array di char) Cognome (array di char)
Record in C++: Dichiarazione struct studente { int matricola; char nome[20]; char cognome[20]; }; Ogni campo della struttura è di un tipo semplice (int) o strutturato (array di char)
Record in C++: Dichiarazione In generale struct nome { tipo1 nome1; tipo2 nome2; }; Ogni campo termina per ; Dopo la parentesi graffa c'è ;
Record in C++: Dichiarazione Una volta definita una struct è possibile dichiarare variabili che siano del tipo definito struct studente { int matricola; char nome[20]; char cognome[20]; }; struct studente mario_rossi; struct studente gennaro_esposito;
Record in C++: Dichiarazione È possibile anche dichiarare delle variabili contemporaneamente alla struct struct studente { int matricola; char nome[20]; char cognome[20]; } mario_rossi, gennaro_esposito; In questo caso la "struct studente" non potrà essere usata per costruire altre variabili
Record in C++: Inizializzazione Definita una struttura, per inizializzare una variabile del tipo della struttura si inseriscono i valori tra parentesi graffa, separati da ',' come per un array struct nome_record variabile = {valore1, valore2, valorex};
Record in C++: Inizializzazione struct studente { int matricola; char nome[20]; char cognome[20]; }; struct studente mario_rossi = {34, "mario", "rossi"}; struct studente studente2 = {36, "gennaro", "esposito"};
Record in C++: Accesso ai campi Per accedere ai valori dei campi si utilizza la "dot notation" Si utilizza l'operatore '.' (punto) Lettura cout << mario_rossi.cognome; Assegnazione mario_rossi.matricola = 34; cin >> mario_rossi.matricola;
Esempio struct Data { int giorno, mese, anno; }; struct Persona { char nome[20]; char cognome[20]; Data data_di_nascita; }; //inizializzazione Persona mario = {"mario", "Rossi", {10,10,1990}}; //assegnazione mario.nome[0] = 'M'; mario.data_di_nascita.giorno = 15; //lettura int giorno = mario.data_di_nascita.giorno; cout << mario.nome;
Record in C++: Assegnamento Un record può essere copiato in un record dello stesso tipo NOTA: due tipi struttura che differiscono solo per il nome sono considerati diversi! struct Data { int giorno, mese, anno; }; struct DT { int giorno, mese, anno; }; struct Data oggi = {24,11,2016}; struct DT oggi1; oggi1 = oggi; //errore!
Record in C++: dichiarazione innestata struct studente { int matricola; char nome[20]; char cognome[20]; struct Data { int giorno, mese, anno; } data_di_nascita; }; In questo caso, la data di nascita è definita a sua volta come record
Record in C++: array di record È possibile dichiarare array di record utilizzando la stessa sintassi utilizzata per i tipi base struct Studente[10]; Sarà possibile accedere ad ogni struct utilizzando gli indici La memoria sarà riservata automaticamente da C++
Definizione di alias in C++: Typedef Utilizzando la parola chiave typedef in C++ è possibile definire alias per un altro tipo esistente typedef tipo alias; Consideriamo "char str[100]" vorremmo poter utilizzare un sinonimo più comprensibile e sintetico Ad es. "stringa str;" Per farlo possiamo definire un alias typedef char stringa[100]; Posso assegnare un alias anche ai tipi semplici typedef unsigned short int ushort; In questo caso possiamo scrivere "ushort variabile;", invece di scrivere per esteso "unsigned short int variabile;"
Typedef e Record Anche nel caso del tipo Record è possibile utilizzare la parola chiave typedef In particolare l utilizzo del typedef con la struct ha il seguente significato: prima si definisce una struttura anonima poi l'uso di typedef crea un alias per quel tipo struttura typedef struct { int matricola; char nome[20]; char cognome[20]; struct Data { int giorno, mese, anno; } data_di_nascita; } studente;
Esempio: Agendina Telefonica Date le seguenti dichiarazioni typedef char stringa[ns]; typedef struct { stringa nome; int cellulare; int fisso; } Contatto; typedef Contatto Contatti[N]; Vogliamo realizzare un'agendina con le seguenti funzionalità: inserisci Stampa Contatto Stampa Elenco Cerca da Numero di Telefono