FONDAMENTI DI INFORMATICA II Ingegneria Gestionale a a

  • Slides: 28
Download presentation
FONDAMENTI DI INFORMATICA II Ingegneria Gestionale a. a. 2001 -2002 - 4° Ciclo Puntatori

FONDAMENTI DI INFORMATICA II Ingegneria Gestionale a. a. 2001 -2002 - 4° Ciclo Puntatori e Stringhe 1

PUNTATORI Definizione: Per puntatore s’intende una variabile che contiene l’indirizzo di un’altra variabile. Quest’ultima

PUNTATORI Definizione: Per puntatore s’intende una variabile che contiene l’indirizzo di un’altra variabile. Quest’ultima a sua volta può contenere un valore specifico. Rappresentazione grafica: var. Point var 1000 Variabile puntatore, di nome var. Point, contenente l’indirizzo della variabile di nome var Variabile di nome var contenente il valore specifico 1000 2

PUNTATORI Dichiarazione di puntatore: Tipo_Variabile …. , * Nome_Puntatore, ……. . Esempi: int *var.

PUNTATORI Dichiarazione di puntatore: Tipo_Variabile …. , * Nome_Puntatore, ……. . Esempi: int *var. Point; float *lat. Ptr, *long. Ptr; long *var. Ptr, var, ……; Inizializzazione di un puntatore: Si può inizializzare un puntatore con un puntamento a nessuna variabile in uno dei due seguenti modi. var. Point= NULL; var. Point=0; 3

PUNTATORI Operatore di indirizzo &: L’operatore di indirizzo & è un operatore unario che

PUNTATORI Operatore di indirizzo &: L’operatore di indirizzo & è un operatore unario che restituisce l’indirizzo del suo operando. L’operando di & deve essere un lvalue, ossia un oggetto a cui si può assegnare un valore. In modo simbolico si può scrivere: Tipo_Variabile …. , * Nome_Puntatore, …, Nome_Variabile, . . ; Nome_Puntatore= &Nome_Variabile; Esempio: int var, *var. Ptr; var. Ptr= &var; 4

PUNTATORI Operatore * di risoluzione dei riferimenti: L’operatore * di risoluzione dei riferimenti (detto

PUNTATORI Operatore * di risoluzione dei riferimenti: L’operatore * di risoluzione dei riferimenti (detto anche di deferenziazione) è un operatore unario su operandi di tipo puntatore che restituisce un alias della variabile puntata. L’alias permette di acquisire il valore della variabile o di assegnargli un nuovo valore. Tipo_Variabile …. , * Nome_Puntatore, . . Nome_Var. A, . . Nome_Var. B; ……………. . Nome_Puntatore= &Nome_Var. A; ……………. . Nome_Var. B = * Nome_Puntatore: Esempio: intero. A, intero. B , *var. Ptr; intero. A= 10; var. Ptr= &intero. A; intero. B= *var. Ptr; //Assegna il valore di intero. A a intero. B 5

PUNTATORI Associatività Gli operatori & e * associano da destra verso sinistra. Ossia se

PUNTATORI Associatività Gli operatori & e * associano da destra verso sinistra. Ossia se si considera l’espressione che segue in cui var. Ptr è un puntatore a cui è stato assegnato l’indirizzo della variabile var &*var. Ptr tutto va come se si dovesse applicare l’operatore & a ciò che viene restituito da *var. Ptr. Poiché *var. Ptr restituisce var, l’applicazione dell’operatore & restituisce l’indirizzo di var. Nel caso inverso: *&var. Ptr tutto va come se si dovesse applicare l’operatore * a ciò che viene restituito da &var. Ptr. Poiché &var. Ptr restituisce l’indirizzo di var. Ptr, l’applicazione dell’operatore * restituisce il contenuto di var. Ptr, ossia proprio l’indirizzo di var. Gli operatori & e * sono quindi l’uno l’inverso dell’altro. 6

PUNTATORI Chiamata per riferimento con argomenti di tipo puntatore Un puntatore può essere passato

PUNTATORI Chiamata per riferimento con argomenti di tipo puntatore Un puntatore può essere passato come argomento di una chiamata a funzione. In questo caso il prototipo della funzione deve contenere la dichiarazione del puntatore: . . Nome_Funzione (…, Tipo_Variabile *, …. ); L’invocazione della funzione deve contenere in corrispondenza un puntatore (o un valore di puntatore): Nome_Funzione (…. , Nome_Puntatore, ……); L’implementazione della funzione deve contenere in corrispondenza la dichiarazione della variabile puntatore locale: …Nome_Funzione (…. . , Tipo_Variabile *Nome_Variabile, …. ) { …. // Deferenziando Nome_variabile si accede al contenuto della variabile puntata da Nome_Puntatore nell’invocazione della funzione. } 7

PUNTATORI Esempio di argomenti di tipo puntatore: void funct (int *); // Prototipo della

PUNTATORI Esempio di argomenti di tipo puntatore: void funct (int *); // Prototipo della funzione int var ………… funct (&var); // Invocazione della funzione ………. . void funct (int *local. Var) // Implementazione della funzione { ……. *local. Var ……. . // Accesso al contenuto di var } Nota: questo esempio e le notazioni simboliche della pagina precedente fanno riferimento al caso di un passaggio di puntatore non costante a dati non costanti. In altre parole sia i puntatori che i dati puntati possono essere modificati. Per evitare che il valore di una variabile sia modificato si deve utilizzare il qualificatore const. 8

PUNTATORI Utilizzo dell’attributo const: • Dichiarazione di puntatore costante a dati non costanti. Tipo_Variabile

PUNTATORI Utilizzo dell’attributo const: • Dichiarazione di puntatore costante a dati non costanti. Tipo_Variabile *const Nome_Puntatore; • Dichiarazione di puntatore non costante a dati costanti: const Tipo_Variabile *Nome _Puntatore; • Dichiarazione di puntatore costante a dati costanti: const Tipo_Variabile *const Nome _Puntatore; Nota: Le dichiarazioni suddette inserite come dichiarazioni di parametri corrispondenti nel prototipo e nell’implementazione di una funzione permettono di rendere nell’ambito del codice della funzione i puntatori e/o i dati da essi puntati di tipo a sola lettura (read only). 9

PUNTATORI Esempio di passaggio di puntatore non costante a dati costanti: void funct (const

PUNTATORI Esempio di passaggio di puntatore non costante a dati costanti: void funct (const int *); //Prototipo della funzione int kappa; funct (&kappa); //Invocazione della funzione ………………. . Void funct (const int *var. Ptr) //Implementazione della funzione { ……. . //Non è ammesso fare un’assegnazione del tipo: *var. Ptr= 100; } 10

PUNTATORI Restituzione di una variabile puntatore da una funzione: Una chiamata a funzione può

PUNTATORI Restituzione di una variabile puntatore da una funzione: Una chiamata a funzione può restituire una variabile puntatore. In questo caso il prototipo della funzione deve contenere la dichiarazione del tipo di puntatore in restituzione: Tipo_Variabile *Nome_Funzione (………. ); L’invocazione della funzione può quindi essere assegnata ad una variabile puntatore del tipo dichiarato nel prototipo: Tipo_Variabile *Nome_Variabile_Puntatore, …. ; Nome_Variabile_Puntatore = Nome_Funzione (……); L’implementazione della funzione deve ripetere la dichiarazione del tipo di puntatore in restituzione (uguale a quella del prototipo) e la parola riservata Return deve essere seguita da un valore o variabile puntatore sempre dello stesso tipo: Tipo_Variabile *Nome_Funzione (………. . ) {………. return Nome_Variabile_Puntatore; } 11

PUNTATORI Esempio di funzione che restituisce un puntatore: …………. . float *Calcola (float, int);

PUNTATORI Esempio di funzione che restituisce un puntatore: …………. . float *Calcola (float, int); //Prototipo …………. . float *ret. Ptr, ret. Calc; ret. Ptr= Calcola (7. 5, 10); //Invocazione ……………. . float *Calcola (float dato. F, int dato. I) //Implementazione {…………. . float *local. Ptr; …………… return local. Ptr; } 12

PUNTATORI Operatore sizeof: L’operatore unario sizeof restituisce la dimensione in byte dell’operando che può

PUNTATORI Operatore sizeof: L’operatore unario sizeof restituisce la dimensione in byte dell’operando che può essere un array o un dato qualsiasi. L’operando di sizeof deve essere racchiuso tra parentesi tonde se è il nome di un tipo di dato (come int, float, . . ) altrimenti non è necessario. La seguente operazione: . . sizeof Nome_Array/sizeof (Tipo_Dato_Array) restituisce la lunghezza dell’array in elementi. 13

PUNTATORI Esempio di applicazione di sizeof: ………………. . int beta [ ]= {10, 20,

PUNTATORI Esempio di applicazione di sizeof: ………………. . int beta [ ]= {10, 20, 30, 40, 50}; int dim; ………………. dim= sizeof beta/sizeof(int); //Assegna il valore 5 a dim ………………. 14

PUNTATORI Aritmetica dei puntatori: I casi considerati sono quelli di puntatori ad elementi di

PUNTATORI Aritmetica dei puntatori: I casi considerati sono quelli di puntatori ad elementi di array, di tipo qualsiasi, e quindi di lunghezza in byte dipendente dal tipo. Operazione sul puntatore: Indirizzo risultante: Incremento (++) Punta all’elemento successivo Decremento (--) Punta all’elemento precedente Somma di un intero n Punta all’elemento dopo n elementi Sottrazione di un intero n Punta all’elemento precedente di n elementi Si possono anche fare differenze tra puntatori, purché dello stesso array e, in tal caso, il risultato è un numero intero corrispondente alla distanza tra i due puntatori in numero di elementi dell’array. 15

PUNTATORI Assegnazione tra puntatori: Si può assegnare un puntatore ad un altro dello stesso

PUNTATORI Assegnazione tra puntatori: Si può assegnare un puntatore ad un altro dello stesso tipo o, in generale, usando l’operatore cast, ad un altro di tipo diverso. Puntatore di tipo void Tutti i tipi di puntatore possono essere assegnati ad un puntatore di tipo void (void *), che è un tipo generico, ma non è vero il contrario. Un puntatore di tipo void non può nemmeno essere deferenziato Puntatori ed operatori relazionari Gli operatori relazionari possono essere utilizzati per confrontare i puntatori, ma ciò ha normalmente senso per puntatori ad elementi di uno stesso array. 16

PUNTATORI Correlazione tra puntatori e array La dichiarazione di un array, come la seguente:

PUNTATORI Correlazione tra puntatori e array La dichiarazione di un array, come la seguente: Tipo_Variabile …. , Nome_Array [Dimensione_Array], … comporta la dichiarazione di un puntatore costante al primo elemento dell’array di nome Nome_Array. In base a ciò l’accesso ad un elemento dell’array può ottenersi con uno dei seguenti modi: Indicizzazione dell’array: Nome_Array [Variabile _Indice] Nome dell’array e offset: *(Nome_Array + Variabile_Indice) Indicizzazione di puntatore: Puntatore_1°_Elemento [Variabile_Indice] Puntatore e offset: *(Puntatore _1°_Elemento + Variabile_Indice) 17

PUNTATORI Esempi di modi di accesso ad un array: float. Array [10], *float. Ptr,

PUNTATORI Esempi di modi di accesso ad un array: float. Array [10], *float. Ptr, float. Var; int index; float. Ptr= float. Array; //Equivalente a: float. Ptr= &float. Array[0]; index= 5; float. Var= float. Array [index]; float. Var= float. Array [5]; float. Var= *(float. Array + index); float. Var= float. Ptr [index]; float. Var= *(float. Ptr + index); 18

Puntatori a Funzioni PUNTATORI Una funzione può accettare in input un puntatore ad un’altra

Puntatori a Funzioni PUNTATORI Una funzione può accettare in input un puntatore ad un’altra funzione. Ciò è possibile perché il nome di una funzione è un puntatore alla funzione stessa. Il prototipo assume l’aspetto: …. Nome _Funzione_A (…, Tipo_Restituito (*) (Lista_Tipi), …. ); La corrispondente invocazione di funzione è: Nome_Funzione_A (…. , Nome_Funzione_B, ……. . ); dove Nome_Funzione_B deve corrispondere ad una funzione che ha il Tipo_Restituito e la Lista_Tipi identici a quelli indicati nel prototipo: possono esistere più funzioni con queste caratteristiche. L’implementazione è infine: . . Nome_Funzione_A (. . , Tipo_Restituito(*Nome_Funzione_Locale) (Lista_Tipi), …. . ) { ……. (*Nome_Funzione_Locale) (Lista_Argomenti); ……. . } 19

PUNTATORI Esempio di passaggio di puntatore a funzione: void funz. A (int, int (*)(float,

PUNTATORI Esempio di passaggio di puntatore a funzione: void funz. A (int, int (*)(float, int), float); //Prototipo della funzione int funz. B (float, int); //Prototipi delle funzioni che possono essere int funz. C (float, int); //passate come parametri con il loro puntatore ……………. . funz. A (3, 5, funz. C, 3. 5) //Invocazione della funzione ……………. . //Implementazione della funzione: funz. A (int var 1, int var 2, int (*local. Funz) (float, int), float var 3) { ………//Invocazione della funzione passata con un puntatore: (*local. Funz) (var 3, 6); ………………. . . } 20

STRINGHE Costanti carattere: Una costante carattere è un carattere racchiuso tra apici singoli e

STRINGHE Costanti carattere: Una costante carattere è un carattere racchiuso tra apici singoli e corrisponde ad un numero intero che è il codice ASCII di quel carattere. Sono costanti carattere: ‘a’, ‘b’, …’z’, ‘n’. Quest’ultimo è il valore intero di new line. Costanti stringa: Una costante stringa è una sequenza di caratteri racchiusi tra doppi apici che vengono trattati come un’entità singola. Una costante stringa è: “abcde”. Stringhe: Una stringa è un array di caratteri che termina con il carattere nullo (‘’). Il valore di una stringa è quindi l’indirizzo costante del suo primo carattere. 21

STRINGHE Dichiarazione ed inizializzazione di una stringa: In base alla definizione di stringa la

STRINGHE Dichiarazione ed inizializzazione di una stringa: In base alla definizione di stringa la sua dichiarazione ed inizializzazione si può ottenere come segue: char Nome_Stringa [ ]= {‘a’, ‘b’, ‘c’, … ‘z’, ‘’}; oppure, ricorrendo alle costanti stringa, nel modo seguente: char Nome_Stringa[ ]= “abcd…z”; in questo caso l’array di caratteri che compone la stringa conterrà un ultimo carattere in più, rispetto a quelli della costante stringa, automaticamente impostato a: ‘’. Una stringa può anche essere inizializzata senza assegnargli un nome, ma dichiarando solo il puntatore al suo primo carattere con la dichiarazione: char *Puntatore_alla_Stringa= “abcd…. z”; 22

STRINGHE Input di stringhe: L’input di una stringa in un array di caratteri si

STRINGHE Input di stringhe: L’input di una stringa in un array di caratteri si può ottenere con l’operatore di estrazione dallo stream e cin nel modo seguente: char Nome_Array [Dimensione_Array]; //Dichiarazione array cin >> Nome_Array; //Input stringa L’input termina alla digitazione di: spazio, tabulazione, new line o end of file. Non c’è controllo al superamento dell’ultimo posto dell’array. Ciò si può invece ottenere con l’operatore setw, che termina l’input dopo il carattere del penultimo posto e pone ‘’ nell’ultimo: cin >> setw(Dimensione_Array) >> Nome_Array; L’input di righe di testo complete si ottiene con la funzione: cin. getline (Nome_Array, Dimensione_Array, n); per la quale l’input termina se si riempie il penultimo posto dell’array (nell’ultimo si pone: ‘’), oppure si digita new line o end of file. 23

STRINGHE Funzioni di libreria per le stringhe Quelli che seguono sono i prototipi di

STRINGHE Funzioni di libreria per le stringhe Quelli che seguono sono i prototipi di funzioni di libreria che manipolano stringhe, confrontano stringhe, ricercano caratteri, segmentano stringhe, ne determinano la lunghezza, . . ecc. char *strcpy (char *s 1, const char *s 2); char *strcat (char *s 1, const char *s 2); char *strncpy (char *s 1, const char *s 2, size_t n); char *strncat (char *s 1, const char *s 2 , size_t n); int strcmp (const char *s 1, const char *s 2); int strncmp (const char *s 1, const char *s 2 , size_t n); char *strtok (char *s 1, const char *s 2); size_t strlen (const char *s): 24

RICHIAMI AI RIFERIMENTI Chiamata a funzione con argomenti di tipo riferimento: Un riferimento può

RICHIAMI AI RIFERIMENTI Chiamata a funzione con argomenti di tipo riferimento: Un riferimento può essere passato come argomento di una chiamata a funzione. In questo caso il prototipo della funzione deve contenere la dichiarazione del riferimento: …. . Nome_Funzione (…. , Tipo_Variabile &, …); L’invocazione della funzione deve contenere in corrispondenza un nome di variabile che in tal caso viene passata per riferimento (ossia potrà essere direttamente riferita) invece che per valore: …… Nome_Funzione (…. . , Nome_Variabile, …); L’implementazione della funzione deve contenere in corrispondenza la dichiarazione del riferimento locale che si comporta come alias della variabile passata: … Nome_Funzione (…. , Tipo_Variabile &Nome_Locale_Variabile, …) {……. //Attraverso il Nome_Locale_Variabile si accede direttamente in lettura/scrittura alla variabile passata nell’invocazione della funzione ……. . } 25

RICHIAMI AI RIFERIMENTI Esempio di argomento di tipo riferimento: void funct (int &); //

RICHIAMI AI RIFERIMENTI Esempio di argomento di tipo riferimento: void funct (int &); // Prototipo della funzione int var; ………… funct (var); // Invocazione della funzione ………. . void funct (int &local. Var) // Implementazione della funzione { ……. local. Var = 10; // Accesso al contenuto di var } 26

RICHIAMI AI RIFERIMENTI Restituzione di un riferimento da una funzione: Una chiamata a funzione

RICHIAMI AI RIFERIMENTI Restituzione di un riferimento da una funzione: Una chiamata a funzione può restituire un riferimento al un alias. In questo caso il prototipo della funzione deve contenere la dichiarazione del tipo di riferimento in restituzione: Tipo_Variabile &Nome_Funzione (……); L’invocazione della funzione può quindi essere assegnata ad una variabile riferimento del tipo dichiarato nel prototipo: Tipo_Variabile ……. , &Nome_Variabile, . . ; Nome_Variabile = Nome_funzione (……. . ); L’implementazione della funzione deve ripetere la dichiarazione del tipo di riferimento in restituzione (uguale a quella del prototipo) e la parola riservata return deve essere seguita dal nome di una variabile, sempre dello stesso tipo: Tipo_variabile &Nome_Funzione (………. ) {……. . return Nome_Variabile; } 27

RICHIAMI AI RIFERIMENTI Esempio di funzione che restituisce un riferimento: …………. . float &Calcola

RICHIAMI AI RIFERIMENTI Esempio di funzione che restituisce un riferimento: …………. . float &Calcola (float, int); //Prototipo …………. . float &ret. Calc; ret. Calc= Calcola (7. 5, 10); //Invocazione ret. Calc= 10; //Accesso a local. Var ! ……………. . float &Calcola (float dato. F, int dato. I) //Implementazione {…………. . float local. Var; …………… return local. Var; } 28