1
Struct
Al fine di illustrare l’uso del tipo struct, utilizzando le struct
descritte nella lezione precedente, mostriamo come si scrive un
programma che permette di gestire in memoria un numero massimo
di 30 persone.
Il programma deve consentire l’inserimento dei dati, la ricerca di un
dato conoscendo il cognome di una persona e la stampa su video di
tutte le persone inserite ed eventualmente ordinate per data di nascita.
2
Struct
Il programma, oltre a contenere le definizioni delle strutture
Tpersona e Tpdata, deve proporre un semplice menù
Gestione Dati
12334-
struct TPersona {
char cognome[20];
char nome[20];
Tpdata nascita;
char luogo[20];
};
Inserimento
Ricerca
Stampa dati
Stampa dati ordinati x data nascita
Fine
struct Tpdata {
int giorno;
int mese;
int anno;
};
3
Lo pseudo-codice consta di quattro possibili alternative, oltre ad una
quinta di fine lavoro.
12345-
do {
scelta= opzione del menù
switch (scelta)
{
case 1: // Inserimento
Inserimento persona
Gestione Dati
break
Inserimento
case 2: // Ricerca
Ricerca
Inserire Cognome da ricercare
Stampa dati
Stampa dati ordinati x data nascita
Ricerca la persona e la stampa
Fine
break
case 3: // Stampa dati
Stampa tutti i dati
break
case 4: // Stampa dati ordinati x data nascita
Stampa i dati ordinati x data di nascita
}
}
4
while (scelta>0 && scelta<5);
Dallo pseudo-codice risulta la necessità di definire 5 function che
risolvano i seguenti problemi:
•un menù che restituisca il numero dell’opzione prescelta: è una
funzione che non ha input e deve restituire un intero;
•una procedura che consenta l’inserimento dei dati e li restituisca;
•una funzione che, assegnata una stringa rappresentante il cognome
di una persona, restituisca tutti gli altri dati relativi alla stessa;
•una procedura che, data una struttura determinata, ne stampi tutti i
dati.
•una procedura che, data una struttura determinata, ne stampi tutti i
dati ordinati per un determinato campo.
5
Introduciamo i prototipi delle function:
MenuScelta, non ha input e restituisce un int.
La procedura Inserimento, restituisce il record di tipo Tpersona ed
un carattere che potrà essere ‘s‘ ( il dato può essere conservato perché
esente da errori ) o ‘n’ ( il dato non può essere conservato).
La procedura, Stampa, stampa a video i dati di una persona; poiché
tali dati non possono essere cambiati dalla procedura, il tipo è
preceduto dalla parola chiave const.
// PROTOTIPI
int MenuScelta();
void Inserimento(Tpersona&, char&);
void Stampa(const Tpersona&);
int Ricerca( char[], Tpersona[],const int);
double dataNum(Tpdata x);
void ordinaBubble(Tpersona [] , int n);
void scambia (double&, double&); 6
La procedura, ordinaBubble, ordina, per cognome, i record contenuti
in un array.
La funzione, Ricerca, restituisce un intero che rappresenta l’indice
dell’elemento trovato. Essa ha in input il cognome da ricercare, che è
un array di caratteri, un array di strutture di tipo Tpersona ed un
intero costante che rappresenta la sua lunghezza.
// PROTOTIPI
int MenuScelta();
void Inserimento(Tpersona&, char&);
void Stampa(const Tpersona&);
int Ricerca( char[], Tpersona[],const int);
void ordinaBubble(Tpersona [] , int n);
double dataNum(Tpdata x);
void scambia (double&, double&);
7
Vi sono poi due function ausiliarie:
La funzione, dataNum, che trasforma una data espressa in GG MM
AAAA in un intero per effettuare confronti semplicemente.
La procedura, scambia, richiamata dalla procedura ordinaBubble per
effettuare gli scambi tra gli elementi di un vettore sottoposto ad
ordinamento.
// PROTOTIPI
int MenuScelta();
void Inserimento(Tpersona&, char&);
void Stampa(const Tpersona&);
int Ricerca( char[], Tpersona[],const int);
void ordinaBubble(Tpersona [] , int n);
double dataNum(Tpdata x);
void scambia (double&, double&);
8
La prima parte del programma include tutte le definizioni delle
strutture e la dichiarazione dell’array Persone che può contenere al
massimo 30 elementi.
#include <iostream>
using namespace std;
struct Tpdata {
int giorno;
int mese;
int anno;
};
struct Tpersona {
char cognome[20];
char nome[20];
Tpdata nascita;
char luogo[20];
};
Tpersona Persone[30];
………………………………………
9
Il main inizia con le dichiarazioni delle variabili
persona1 di tipo Tpersona,
corrente, che rappresenta l’indice corrente dell’array,
NumPers, che rappresenta il numero attuale di persone memorizzate.
scelta denota l’operazione da eseguire volta per volta,
ch e cognome2 sono le variabili di input delle function Inserimento e
Ricerca.
int main () {
Tpersona persona1;
int corrente,NumPers;
int scelta;
char ch;
char cognome2[20];
NumPers=0;
……………….. } 10
Il main contiene un ciclo do… while (il ciclo deve essere eseguito almeno una volta)
al cui interno appare l’istruzione switch che gestisce i seguenti casi:
caso 1 si inseriscono i dati; se l’utente preme ‘s’ i dati della persona vengono aggiunti
all’array Persone e la variabile NumPers è incrementata di uno;
caso 2 si assegna il cognome da ricercare e si richiama la funzione Ricerca: se il
valore restituito di corrente è maggiore di -1, si stampano tutti i dati, altrimenti si
avverte l’utente che il dato non è stato trovato;
caso 3 si esegue un ciclo for per stampare tutte le persone memorizzate
caso 4 si esegue un ciclo for per stampare tutte le persone ordinate per data di nascita.
do {
scelta= opzione del menù
switch (scelta)
{
case 1: Inserimento persona
break
case 2: Ricerca la persona e la stampa
break
case 3: Stampa tutti i dati
break
case 4: Stampa i dati ordinati x data di nascita
}
}
while (scelta>0 && scelta<5);
11
do {
scelta=MenuScelta();
cout<<"Numero Persone =" <<NumPers<<endl;
switch (scelta)
{
case 1:
Inserimento (persona1,ch);
if (ch=='s')
Persone[NumPers++]=persona1;
break;
case 2:
cout<<"Cognome da ricercare=";
cin>>cognome2;
corrente=Ricerca(cognome2, Persone,NumPers);
if (corrente>-1)
Stampa(Persone[corrente]);
else
cout<<"Dati non trovati"<<endl;
break;
int main ()
{
Tpersona persona1;
int corrente,NumPers;
int scelta;
char ch;
char cognome2[20];
NumPers=0;
………………..
}
12
int main ()
case 3:
{
Tpersona persona1;
cout << " STAMPA DATI "<<endl;
int corrente,NumPers;
for(corrente=0;corrente<NumPers;corrente++)
int scelta;
Stampa(Persone[corrente]);
char ch;
char cognome2[20];
break;
NumPers=0;
………………..
case 4:
}
cout << " STAMPA DATI ORDINATI PER DATA"<<endl;
ordinaBubble(Persone, NumPers);
for(corrente=0;corrente<NumPers;corrente++)
Stampa(Persone[corrente]);
break;
}
} while (scelta>0 && scelta<5);
} return 0;
13
La funzione MenuScelta deve mostrare sul monitor tutte le opzioni
disponibili dando all’utente la possibilità di inserire soltanto un intero
.
compreso tra 1 e 5. La funzione, dopo aver controllato che il valore
rispetta tali limiti, deve restituirlo al programma chiamante.
int MenuScelta() {
int sc;
do {
cout <<" GESTIONE PERSONE "<< endl;
cout <<" \n";
cout <<"1 - INSERIMENTO"<<endl;
cout <<"2 - RICERCA"<<endl;
cout <<"3 - STAMPA TUTTI "<<endl;
cout <<"4 - STAMPA ORDINATI PER NASCITA "<<endl;
cout <<"5 - FINE"<<endl;
cout <<" Scelta=";
cin >>sc;
}
while (sc<1 || sc>5);
return sc;
}
14
Si noti che dal MenuScelta può essere restituito anche il valore 5
che passato al main provoca la terminazione del programma.
int MenuScelta() {
int sc;
do {
cout <<" GESTIONE PERSONE "<< endl;
cout <<"1 - INSERIMENTO"<<endl;
cout <<"2 - RICERCA"<<endl;
cout <<"3 - STAMPA TUTTI "<<endl;
cout <<"4 - STAMPA ORDINATI PER NASCITA "<<endl;
cout <<"5 - FINE"<<endl;
cout <<" Scelta=";
cin >>sc; }
while (sc<1 || sc>5);
return sc; }
case 4:
cout << " STAMPA DATI ORDINATI PER DATA"<<endl;
ordinaBubble(Persone, NumPers);
for(corrente=0;corrente<NumPers;corrente++)
Stampa(Persone[corrente]);
break;
}
} while (scelta>0 && scelta<5);
} return 0;
do {
scelta=MenuScelta();
cout<<"Numero Persone =" <<NumPers<<endl;
switch (scelta)
{
case 1:
Inserimento (persona1,ch);
if (ch=='s')
Persone[NumPers++]=persona1;
break;
case 2:
cout<<"Cognome da ricercare=";
cin>>cognome2;
corrente=Ricerca(cognome2, Persone,NumPers);
if (corrente>-1)
Stampa(Persone[corrente]);
else
cout<<"Dati non trovati"<<endl;
break;
case 3:
cout << " STAMPA DATI "<<endl;
for(corrente=0;corrente<NumPers;corrente++)
Stampa(Persone[corrente]);
break;
15
La procedura Inserimento restituisce la struttura persona in pers1 e la
variabile carattere ch che può contenere il carattere ‘s’ o ‘n’. Le
istruzioni della procedura si limitano ad acquisire i dati da tastiera.
void Inserimento (Tpersona& pers1, char& ch)
{
cout << " INSERIMENTO PERSONE "<<endl;
cout << "Cognome =";
cin >> pers1.cognome;
cout << "Nome =";
cin >>pers1.nome;
cout << "Data di nascita GG MM AAAA =";
cin >> pers1.nascita.giorno>>pers1.nascita.mese >>pers1.nascita.anno;
cout <<"Luogo di nascita:";
cin >>pers1.luogo;
cout<<"Salva (s/n)=";
cin>>ch;
}
16
La procedura Stampa visualizza sul monitor la struttura persona
contenuta in pers1 con la clausola const ; essa ha lo scopo di non
consentire la variazione dei dati membri della struttura.
void Stampa(const Tpersona& pers1)
{
cout << "Cognome :"<< pers1.cognome<< "\n Nome:"<<pers1.nome<<endl;
cout << "Luogo ="<<pers1.luogo << "\n Data di nascita :";
cout<<pers1.nascita.giorno<<'/'<<pers1.nascita.mese<<'/'<<pers1.nascita.anno;
cout<<endl;
}
17
La funzione, Ricerca, verifica se la persona richiesta dall’utente è
presente tra i dati inseriti. Il cognome inserito da tastiera viene inviato
alla funzione che, attraverso una ricerca lineare, restituisce vero se la
persona è stata trovata
falso nel caso in cui quel cognome non esiste nel file.
18
int Ricerca(char cognome2[], Tpersona pers[],const int NumPers) {
int i=0;
bool trovato=false;
while (i<NumPers && !trovato) {
if (strcmp(pers[i].cognome,cognome2)==0) {
trovato=true;
return i;
}
else i++;
}
if (!trovato)
return -1;
}
19
int Ricerca(char cognome2[], Tpersona pers[],const int NumPers)
{ int i=0;
while (i<NumPers && !(strcmp(pers[i].cognome,cognome2)==0))
i++;
return i;
}
case 2:
cout<<"\n\tCognome da ricercare=";
cin>>cognome2;
corrente=Ricerca(cognome2, Persone,NumPers);
if (corrente<NumPers)
Stampa(Persone[corrente]);
else
cout<<"\nDati non trovati"<<endl;
break;
20
La procedura ordinaBubble ordina i dati che preventivamente
sono stati inseriti in un array denominato vet.
void ordinaBubble (Tpersona vet[], const int N)
{
int j, k;
Tpdata nasc1,nasc2;
for (k=0; k<N-1; k++)
for (j=N-2; j>=k; j--)
{ nasc1=vet[j].nascita;
nasc2=vet[j+1].nascita;
if ( dataNum(nasc1) > dataNum(nasc2) )
scambia (vet[j],vet[j+1]);
}
}
21
La procedura scambia viene utilizzata dalla procedura
ordinaBubble per scambiare tra loro due record.
void scambia (Tpersona &x1, Tpersona &x2)
{
Tpersona s;
s=x1;
x1=x2;
x2=s;
}
22
La procedura dataNum serve per trasformare una data
espressa come GG MM AA in un intero al fine di permettere
confronti rapidi.
double dataNum(Tpdata x)
{
return x.anno*10000+x.mese*100+x.giorno;
}
Eser_rec_ord
Eser_rec_ord2
orario1
23
/* Esempio di lettura, confronto e scrittura in un array contenuto in un
record a sua volta contenuto in un array di record*/
struct Tdati {
int numeri[4];
char lettere[5];
};
Tdati dati[30];
numeri[4]
dati[30]
2
3
1
lettere[5]
6
A B
G D K
24
/* Esempio di lettura, confronto e scrittura in un array contenuto in un record a
sua volta contenuto in un array di record*/
struct Tdati {
int main () {
char lettere[20];
cout<<"\nCarica interi per riga ";
int numeri[4]; };
Inserimento (dati, elemArray);
Tdati dati[30];
Stampa(dati, elemArray);
// PROTOTIPI
confronta(dati, elemArray);
void Inserimento(Tdati [], int);
system("pause");
void Stampa(const Tdati [], int);
}
void confronta(Tdati [], int);
int elemArray=4;
void Inserimento (Tdati dat1[], int ndat)
{ for (int j=0;j<ndat;j++)
{ cout<<endl;
for (int i=0;i<ndat;i++)
{cout<<" A["<<j<<"]= ";cin>>dat1[j].numeri[i]; }
cout << "lettere ="; cin >> dat1[j].lettere;
}
}
25
/* Esempio di lettura, confronto e scrittura in un array contenuto in un record a
sua volta contenuto in un array di record*/
struct Tdati {
char lettere[20];
int main () {
int numeri[4]; };
cout<<"\nCarica interi per riga ";
Tdati dati[30];
Inserimento (dati, elemArray);
// PROTOTIPI
Stampa(dati, elemArray);
void Inserimento(Tdati [], int);
confronta(dati, elemArray);
void Stampa(const Tdati [], int);
system("pause");
void confronta(Tdati [], int);
}
int elemArray=4;
void Stampa(const Tdati dat1[], int ndat) {
for (int j=0;j<ndat;j++)
{cout<<"\n riga "<<j<<--"<<dat1[j].lettere<<" ** ";
for (int i=0;i<ndat;i++)
{ cout<<dat1[j].numeri[i]<<" "; }
}
}
26
void confronta(Tdati dat1[], int ndat)
int main () {
{
cout<<"\nCarica interi per riga "
char lettere2[20]; int ass[ndat];
Inserimento (dati, elemArray);
bool flag; int cont=0;
Stampa(dati, elemArray);
cout <<"\n\n Lista numeri da confrontare "<<endl; confronta(dati, elemArray);
for (int y=0;y<ndat;y++) cin>>ass[y];
system("pause");
cout<<"\n\nlettere da confrontare ";cin>>lettere2; }
for (int j=0;j<ndat;j++)
{ if (strcmp(dat1[j].lettere,lettere2)==0)
cout<<"\n La lettere in posizione "<<j<<" coincide con quella assegnata"<<endl;
else cont++;
flag=true;
int i=0;
while ((i<ndat)&&(flag==true))
{ if (dat1[j].numeri[i]!=ass[i])flag=false;
i++; }
if (flag==true)
cout<<" riga "<<j<<" numeri uguali "<<endl;
if (cont==ndat)cout<<" non ci sono stringhe uguali "<<endl;
}
if (flag==true) cout<<" non ci sono sequenze di numeri uguali "<<endl;
27
array
rec1
}
Esercizi
1) Utilizzando la struttura Tpersona, definita nell’esempio aggiungere
al menù la voce cancellazione di un record: la function da scrivere
deve prima ricercare l’elemento da cancellare (con la funzione Ricerca)
e, successivamente, cancellarlo dall’array di record .
2) Definire la struttura impiegato che, oltre a tutti i dati già contenuti in
Tpersona, ha:
data di assunzione;
livello ( operaio, impiegato, dirigente, ….);
stipendio annuo percepito l’anno precedente.
Utilizzando il programma proposto nell’esempio, apportare le
necessarie modifiche per gestire i dati della struttura impiegato (
inserimento, ricerca, stampa ).
28
Esercizi
3) Utilizzando la struttura Tpdata già definita, scrivere una procedura,
SommaData che, assegnata una data ed un numero di giorni,
restituisca, in formato gg mm aa, la somma tra la data ed il numero di
giorni (si supponga che i mesi siano tutti di 31gg).
Ad esempio
SommaData applicata alla data 13 5 03 e 124 giorni deve restituire la
data 13 9 03
29
Esercizi
.
4) Definire una struttura Orario che comprenda giorni, ore ( da 0 a 23 ),
minuti e secondi rappresentato nel formato seguente: gg hh mm ss.
Scrivere due procedure, SommaTempo e SottraiTempo, che, assegnati
due tempi espressi in termini di numero di giorni, ore, minuti ed
secondi, restituiscano, in formato coerente, rispettivamente la somma e
la sottrazione tra i due tempi (sottraenso il tempo più lungo da quello
più breve).
Ad esempio
SommaSecondi applicata all’orario 13 45 23 e 224 secondi deve
restituire l’orario
13 49 7
SottraiSecondi applicata all’orario 13 45 23 e 204 secondi deve
restituire l’orario
orario2
13 41 59
30
.
Scarica

ppt