CORSO DI PROGRAMMAZIONE  II
This presentation is the property of its rightful owner.
Sponsored Links
1 / 32

CORSO DI PROGRAMMAZIONE II Lezione 13 Uso dei puntatori prof. E. Burattini a.a. 2010-2011 PowerPoint PPT Presentation


  • 74 Views
  • Uploaded on
  • Presentation posted in: General

CORSO DI PROGRAMMAZIONE II Lezione 13 Uso dei puntatori prof. E. Burattini a.a. 2010-2011. STACK. Stack: zona di memoria che costituisce un’area di appoggio temporaneo. Heap: zona di memoria libera di essere utilizzata sul momento. HEAP. DATI.

Download Presentation

CORSO DI PROGRAMMAZIONE II Lezione 13 Uso dei puntatori prof. E. Burattini a.a. 2010-2011

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

CORSO DI PROGRAMMAZIONE II

Lezione 13

Uso dei puntatori

prof. E. Burattini

a.a. 2010-2011


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

STACK

Stack: zona di memoria che costituisce un’area di appoggio temporaneo

Heap: zona di memoria libera di essere utilizzata sul momento

HEAP

DATI

Dati: contiene tutte le variabili e le costanti definite nel programma

CODICE

Codice: contiene il codice macchina del programma

Puntatori e function

Così come il nome di un array rappresenta l’indirizzo del suo primo elemento, il nome di una function rappresenta l’indirizzo di partenza del suo codice.

Un puntatore a function contiene l’indirizzo di memoria della function; esso può essere passato o restituito da un’altra function e può essere assegnato ad un altro puntatore a function.

Il puntatore a function è molto utile quando è necessario, nel corso di un programma, scegliere tra più function.


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

STACK

Stack: zona di memoria che costituisce un’area di appoggio temporaneo

Heap: zona di memoria libera di essere utilizzata sul momento

HEAP

DATI

Dati: contiene tutte le variabili e le costanti definite nel programma

CODICE

Codice: contiene il codice macchina del programma

Puntatori e function

Supponiamo di avere due function, funz1 e funz2 del tipo

int funz1(char) e int funz2(char)

ed un’altra function funz

void funz(int, int)

A seconda delle varie opportunità, ci si vuole servire di funz1 o di funz2: il primo intero int può essere il risultato della prima (funz1), il secondo di funz2 o viceversa.

Come possiamo scrivere il codice in maniera tale che la function funz possa richiamare l’una o l’altra tra funz1 o funz2?


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

Utilizzando i puntatori a function possiamo scrivere il prototipo di funz in questo modo:

void funz(int (*)(char), int)

il primo parametro int da assegnare alla function deve essere il risultato di una function che ha un parametro char (potrebbe essere funz1 o funz2 o qualsiasi altra function che ha le stesse caratteristiche: stessa tipologia di parametri formali e stesso tipo di valore restituito).

L’implementazione della function funz deve avere un’intestazione del tipo

void funz(int (*puntafunz)(char), int n)

mentre la function funz può essere richiamata con una delle seguenti modalità

funz(funz1, m) funz(funz2, m)


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

ESEMPIO

Un esempio di utilizzo dei puntatori a function concerne l’ordinamento.

Supponiamo di voler ordinare un array A di interi.

Possiamo decidere di ordinarli sia in modo crescente che decrescente.

A questo scopo supponiamo di avere due function, chiamate crescente e decrescente, che restituiscono un valore booleano.

Come organizzare il programma in modo tale da passare la function che serve allo scopo?

Il puntatore a function risolve il problema.


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

Di seguito è riportato il codice che permette di scegliere fra il realizzare un ordinamento crescente o decrescente dei dati contenuti in un array di interi.

Le function interessate sono:

void ordinaB (int vet[], int N, bool (*confronta)(int,int))

bool crescente(int x, int y)

bool decrescente(int x, int y)

void scambia (int &x1, int &x2)


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

int main () {

char ch;

int a[100], n;

cout<<" Lunghezza vettore=";

cin>>n;

LeggeVettore ( a, n, 'a');

do {

cout<<" CRESCENTE "<<endl;

ordinaB(a,n,crescente);

StampaVettore (a, n,'a');

cout<<"\n DECRESCENTE "<<endl;

ordinaB(a,n,decrescente);

StampaVettore (a, n,'a');

cout<<"\n f per terminare ";

cin>>ch;

} while (ch!='f');

return 0;

}

#include <iostream>

#include <cstdlib>

#include "InsertArray.h"

using namespace std;

// PROTOTIPI

void ordinaB(int[ ], int, bool(*)(int,int));

bool crescente(int, int);

bool decrescente(int, int);

void scambia (int&, int&);


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

// implementazione delle procedure e function

void scambia (int &x1, int &x2)

{

int s;

s=x1;

x1=x2;

x2=s;

}

void ordinaB (int vet[], int N, bool (*confronta)(int,int))

{

int j, k;

for (k=0; k<N-1; k++)

for (j=k+1; j<N; j++)

if ((confronta)(vet[k], vet[j]))

{

scambia (vet[k],vet[j]);

}

}

bool crescente(int x, int y) {

return (x>y);

}

bool decrescente(int x, int y) {

return (x<y);

}

Allegato: funzPuntatori


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

Esercizio

Con i puntatori a funzione scrivere una function che valuti il valore massimo contenuto in un vettore di interi, il minimo e la somma di tutti gli elementi del vettore.

Con i puntatori a funzione scrivere una function che verifichi se assegnata una matrice di interi essa è unitaria, oppure simmetrica oppure con elementi tutti non negativi.

funzMinMax.cpp

funzMatrixPunt


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

Variabili dinamiche

Nel caso delle variabili statiche la memoria viene allocata nel momento in cui la variabile è definita;

per esempio le variabili

int x, a[10];

impegnano la memoria nel momento stesso in cui vengono definite, mentre vengono deallocate nel momento in cui il programma termina, se la variabile è globale; se, invece, la variabile è locale (cioé definita in una function) allora viene deallocata quando termina la function.

In molti casi, però, è più comodo avere un controllo completo sulla allocazione di memoria cioè decidere quando allocare o deallocare la variabile in un qualsiasi punto del programma.


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

Questo è il concetto chiave di gestione dinamica della memoria.

Il C++ mette a disposizione del programmatore due istruzioni:

new che serve per allocare memoria per una certa variabile durante l’esecuzione del programma

delete che serve a deallocare memoria (libera la zona di memoria occupata dall’oggetto definito con new).


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

Volendo definire due variabili dinamiche, ad esempio un intero ed un array di 100 interi, si procede in questo modo:

si definiscono due puntatori ad interi, int *P1, *P2;

si usa l’operatore new per indicare che è una variabile dinamica

sia per l’intero

P1=new int

che per l’array

P2=new int [100]

Se l’operatore new fallisce, ritorna il puntatore nullo NULL: ciò indica che, per qualche ragione, non è stato possibile allocare altra memoria.


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

Il programma può utilizzare i puntatori P1 e P2 nei suoi calcoli; può, inoltre, deallocarli in un qualsiasi momento con l’istruzione delete:

delete P1;// cancella dalla memoria heap l’intero di cui P1 contiene l’indirizzo

delete [ ] P2; // cancella dalla memoria heap l’array di cui P2 contiene l’indirizzo-base

Vediamo l’utilizzo delle variabili dinamiche per un algoritmo di selection sort


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

#include <iostream>

#include <cstdlib>

#include "InsertArraypunt.h"

using namespace std;

// PROTOTIPI

void SortSel(int*, const int);

void Scambia (int*, int*);// questa function usa puntatori che puntano ad interi NON ad array

// MAIN

int main() {

int N, *ap; //viene definito un puntatore ad un array

ap=new int[30]; // ap è un puntatore ad un array: è una variabile dinamica con al più 30 interi

if (ap==NULL) { //se ap è NULL allora non è possibile allocare memoria

cout<<"Non è possibile allocare memoria"<<endl;

return -1; } //il programma termina

cout<<”Numero valori da caricare in a =";

cin>>N;

LeggeVettore(ap,N,'a'); // in questa e nelle chiamate

successive si passa il puntatore ap all'array

SortSel(ap,N);

StampaVettore(ap,N,'a');

delete [ ] ap; //si libera la memoria a cui punta ap

system("pause");

}

ESEMPIO

Dal main si evince che viene creato lo spazio e caricato un array con N interi (Legge Vettore), successivamente vengono ordinati (SortSel) e stampati (StampaVettore) i dati e quindi viene liberato lo spazio di memoria


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

ESEMPIO

// DEFINIZIONI

void SortSel(int *vet, const int Nv) {

int minp;

for ( int i=0; i<Nv-1; i++) {

minp=i;

for ( int j=i+1; j<Nv; j++) {

if (*(vet+j) < *(vet+minp))

minp=j;

}

Scambia((vet+minp), (vet+i));

// Attenzione! La procedura Scambia richiede puntatori!!

}

}

void Scambia (int *x, int *y) {

int z;

z=*x; *x=*y; *y=z;

}

Si noti che gli elementi del vettore vengono individuati tramite i puntatori.

Allegato: SortPuntatori2


Esercizi

Esercizi

Assegnato un array A scrivere una funzione booleana ricorsiva che, operando con i puntatori, determini se i valori disposti nell’array sono simmetrici rispetto al centro.

Assegnato un array A scrivere una procedura ricorsiva che, operando con i puntatori, ordini l’array con l’algoritmo dell’inserction sort.


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

/*Assegnato un array A[10] scrivere una funzione booleana ricorsiva che,

operando con i puntatori, determini se i valori disposti nell’array sono

simmetrici rispetto al centro. */

#include <iostream>

#include <cstdlib>

#include "InsertArraypunt.h"

using namespace std;

//void StampaVettore(ap,N,'a');

bool simm(int*,int,int);

int main()

{

int *array;

int *lng;

array=new int[50];

lng= new int;

cout<<" Numero dati= ";cin>>*lng;cout<<"\n"<<endl;

for(int i=0;i<*lng;i++)

{ cout<<"A["<<i<<"]=";

cin>>array[i]; }

cout<<"\n CONTROLLO...\n"<<endl;

StampaVettore(array,*lng,'a');

if (simm(array,*lng-1,0)) cout<<"\n L'ARRAY E' SIMMETRICO\n"<<endl;

else cout<<"\n L'ARRAY NON E' SIMMETRICO\n"<<endl;

system("pause");

}

bool simm (int *array,int lng, int pos)

{ if(lng <= pos)

return true;

else

{

if(array[lng]==array[pos])

return simm (array,lng-1,pos+1);

else

return false;

}

}

arraySimmetrico


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

I puntatori e i record

Consideriamo il tipo

struct TPersona {

char cognome[20];

char nome[20];

Tdata nascita;

char luogo[20];

double reddito;

}

Definiamo due variabili

TPersona* puntP;

TPersona persona;

La variabile puntP non ha un nome in quanto il suo nome coincide con l’indirizzo;

Le variabili di questo tipo sono dette anonime; il loro contenuto può essere perso se non ne conosciamo più l’indirizzo.

STACK

HEAP

DATI

CODICE


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

Per memorizzare il contenuto cui punta puntP dobbiamo:

Usare new per allocare lo spazio nello Heap

puntP=new Tpersona

Inserire i dati

cout<<“Cognome=“;

cin>>puntP.cognome;

cout<<“Nome=“;

cin>>puntP.nome;

cout<<“Data Nascita=“;

cin>>puntP.nascita.giorno >>puntP.nascita.mese >>puntP.nascita.anno;

cout<<“Luogo Nascita=“;

cin>>puntP.luogo;

cout<<“Reddito=“;

cin>>puntP.reddito;

Una volta inseriti i dati questi si trovano nella memoria heap a cui è possibile accedere solo attraverso puntP e l’operatore “.”


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

Supponiamo siano assegnate due variabili

Abate

Luca

21 9 1976

Napoli

12000

Zurlo

Aldo

1 8 1966

Milano

37000

puntP1

puntP

Se poniamo puntP1=puntP si avrà

Abate

Luca

21 9 1976

Napoli

12000

puntP

La zona di memoria a cui puntava

puntP1 resta occupata ma irraggiungibile

in quanto ne abbiamo perso l’indirizzo.

puntP1

Si crea così garbage o spazzatura e non

serve a nulla porre puntP1=NULL


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

Passaggio dei puntatori ad una function.

Tenendo presente che il puntatore è una variabile che fornisce l’indirizzo di un’altra variabile, analizziamo alcune situazioni-tipo.

Abbiamo un programma principale contenente due puntatori ad un intero; esso richiama due procedure: nella prima la variabile intera è passata per valore, nella seconda per riferimento.

Il programma principale è lo stesso, mentre faremo variare le due procedure.


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

#include <iostream>

#include <cstdlib>

using namespace std;

void CallVal(int*);

void CallRif(int* &);

int main () {

int *p1, *p2;

p1=new int;

p2=new int;

*p1=5; *p2=5;

CallVal(p1);

CallRif(p2);

system("pause");

}

Di seguito si mostra il codice e l’output del programma che opera chiamate dei puntatori sia per valore che per riferimento.


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

int main () {

int *p1, *p2;

p1=new int;

p2=new int;

*p1=5; *p2=5;

cout<<"indirizzo p1 pre-CalVal "<<p1<<" valore "<<*p1<<endl<<endl;

CallVal(p1);

cout<<"indirizzo p1 post-CalVal "<<p1<<" valore "<<*p1<<endl<<endl;

cout<<"indirizzo p2 pre-CalRif "<<p2<<" valore "<<*p2<<endl<<endl;

CallRif(p2);

cout<<"indirizzo p2 post-CalRif "<<p2<<" valore "<<*p2<<endl<<endl;

}

void CallVal(int* xp) {

xp=new int;

*xp=7;

cout<<"indirizzo p1 in-CalVal "<<xp<<" valore "<<*xp<<endl<<endl;}

void CallRif(int* &xp) {

xp=new int;

*xp=7;

cout<<"indirizzo p2 in-CalRif "<<xp<<" valore "<<*xp<<endl<<endl;}


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

void CallVal(int* xp) {

xp=new int;

*xp=7;

}

// indirizzo p1 in CalVal 0x3d2508 valore 7

void CallRif(int* &xp) {

xp=new int;

*xp=7;

}

// indirizzo p2 in CalRif 0x3d2518 valore 7

int main () {

int *p1, *p2;

p1=new int;

p2=new int;

*p1=5; *p2=5;

CallVal(p1);

CallRif(p2);

}

// indirizzo p1 pre-CalVal 0x3d2490 valore 5

// indirizzo p1 post-CalVal 0x3d2490 valore 5

// indirizzo p2 pre-CalRif 0x3d24f8 valore 5

Allegato: funzDinamPuntatori 3

// indirizzo p2 post-CalRif 0x3d2518 valore 7


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

Nell’esempio che segue il programma va in errore perché la procedura CallRif(p2) restituisce un puntatore p2=NULL che quindi non può essere stampato come richiesto.


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

// NON FUNZIONA

int main () {

int *p1, *p2;

p1=new int;

p2=new int;

*p1=5; *p2=5;

cout<<"indirizzo p1 pre-CalVal "<<p1<<" valore "<<*p1<<endl<<endl;

CallVal(p1);

cout<<"indirizzo p1 post-CalVal "<<p1<<" valore "<<*p1<<endl<<endl;

cout<<"indirizzo p2 pre-CalRif "<<p2<<" valore "<<*p2<<endl<<endl;

CallRif(p2);// restituisce un errore perché in uscita p2 punta a NULL!!

cout<<"indirizzo p2 post-CalRif "<<p2<<" valore "<<*p2<<endl<<endl;

system("pause");

}

void CallVal(int* xp) {

xp=NULL; }

void CallRif(int* &xp) {

xp=NULL; }

Allegato: funzDinamPunt2


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

Assegnato un Array contenete dati anagrafici mostrare a video i dati ordinati per cognome, luogo di nascita e data di nascita.

struct Tpdata {

int giorno;

int mese;

int anno;

};

struct Tpersona {

char cognome[30];

char nome[20];

Tpdata nascita;

char luogo[20];

};

typedef Tpersona* Ppersona;

//Ppersona è un nuovo tipo: puntatore a Tpersona

const char Nomefile[]="persone.dat";

// PROTOTIPI

void Stampa(Ppersona[],int);

void bubble(Ppersona [] ,int,int(*)(Ppersona ,Ppersona));

int cognome(Ppersona,Ppersona);

int luogo(Ppersona,Ppersona);

int nascita(Ppersona ,Ppersona );


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

main () {

Tpersona persona1;

Ppersona PuntaP1[101], PuntaP2[101], PuntaP3[101];

const int Lrec=sizeof(Tpersona);

fstream filepers;

filepers.open(Nomefile,ios::in|ios::out|ios::binary|ios::ate);

int NumPers;

if (!filepers) {

filepers.open("persone.dat",ios::out|ios::binary|ios::trunc);

return 1;}

NumPers=filepers.tellg()/Lrec;

cout<<NumPers;

filepers.seekg(0,ios::beg);

for (int i=0; i<NumPers; i++) {

//leggi I dati della persona

filepers.read((char*) &persona1, Lrec);

PuntaP1[i] = new Tpersona;

// Inserisci i dati letti in PuntaP1[i]

*PuntaP1[i] = persona1;

PuntaP2[i] = PuntaP1[i];

PuntaP3[i] = PuntaP1[i];

}


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

cout<<" STAMPA DATI "<<endl<<endl<<endl;

cout<<" INIZIALE"<<endl;

Stampa(PuntaP1,NumPers);

cout<<"\n COGNOME"<<endl;

bubble(PuntaP1,NumPers,cognome);

Stampa(PuntaP1,NumPers);

cout<<"\n LUOGO"<<endl;

bubble(PuntaP2,NumPers,luogo);

Stampa(PuntaP2,NumPers);

cout<<"\n NASCITA"<<endl;

bubble(PuntaP3,NumPers,nascita);

Stampa(PuntaP3,NumPers);

system("pause");

return 0;

}


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

void bubble(Ppersona vet[],int N,int(*confronta)(Ppersona ,Ppersona))

{ int j, k;

Ppersona s;

for (k=0; k<N-1; k++)

{ for (j=N-2; j>=k; j--)

{if (confronta(vet[j], vet[j+1])>=1)

{ s=vet[j];

vet[j]=vet[j+1];

vet[j+1]=s;

} } } }

int cognome(Ppersona Px , Ppersona Py)

{ return ((strcmp(Px->cognome, Py->cognome))); }

int luogo(Ppersona Px , Ppersona Py)

{return ((strcmp(Px->luogo, Py->luogo)));}

int nascita(Ppersona Px , Ppersona Py)

{ double data1,data2;

data1=(Px->nascita.anno)*10000+(Px->nascita.mese)*100+(Px->nascita.giorno);

data2=Py->nascita.anno*10000+Py->nascita.mese*100+Py->nascita.giorno;

return (data1-data2);}


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

int cognome(Ppersona Px , Ppersona Py)

{ return ((strcmp(Px->cognome, Py->cognome))); }

int luogo(Ppersona Px , Ppersona Py)

{return ((strcmp(Px->luogo, Py->luogo)));}

int nascita(Ppersona Px , Ppersona Py)

{ double data1,data2;

data1=(Px->nascita.anno)*10000+(Px->nascita.mese)*100+(Px->nascita.giorno);

data2=Py->nascita.anno*10000+Py->nascita.mese*100+Py->nascita.giorno;

return (data1-data2);}

ArrayPuntRec3


Corso di programmazione ii lezione 13 uso dei puntatori prof e burattini a a 2010 2011

ESERCIZIO

Sia K un intero positivo ed R una matrice mxn di interi. Si scriva una funzione ricorsiva che stabilisca se R contenga al suo interno una serie di almeno K elementi consecutivi allineati in uno qualsiasi dei tre versi orizzontale, verticale oppure diagonale. Utilizzare i puntatori.

Esempio per K=3

R=


  • Login