| prof. Nunzio Brugaletta |
C++:
programmazione e oggetti |
Una tabella è costituita da una successione di elementi detti record costituiti da due o più campi, il primo è chiamato chiave e distingue un record da un altro. Anche un vettore di tipi elementari, per esempio di int, può definirsi tabella, ma nella realtà delle applicazioni informatiche è comune trovare vettori contenenti strutture.
Sulle tabelle sono comuni due tipi di algoritmi: la ricerca (data una tabella, cercare la chiave associata ad un determinato record), la selezione (data una tabella, costruirne una nuova che contiene i record della prima tabella che soddisfano a determinati requisiti).
Il primo programma proposto (esempio di ricerca), data una tabella contenete i dipendenti di una azienda, cerca se una persona, di cui vengono forniti cognome e nome, è un dipendente dell'azienda e, in questo caso, visualizza i suoi dati:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
namespace azienda{ /*1*/
struct dipendente{
string reparto;
string cognome;
string nome;
float stipendio;
};
vector<dipendente> insertDip();
void insertCogNom(string&, string&);
int cerca(vector<dipendente>, string, string);
void stampa(string, float);
}
int main()
{
vector<azienda::dipendente> libropaga; /*2*/
azienda::dipendente tempdip; /*2*/
string cogncerca,nomcerca;
int pos;
// Inserimento dati dei dipendenti,
libropaga = azienda::insertDip(); /*3*/
// cognome e nome dipendente da cercare
azienda::insertCogNom(cogncerca,nomcerca); /*3*/
// Ricerca dipendente
pos = azienda::cerca(libropaga,cogncerca,nomcerca); /*4*/
// Visualizza dati dipendente
if(pos>=0){ /*5*/
tempdip = libropaga.at(pos); /*6*/
azienda::stampa(tempdip.reparto,tempdip.stipendio); /*7*/
}
else
cout << "Non risulta come dipendente" << endl;
return 0;
}
// Inserimento dipendenti
vector<azienda::dipendente> azienda::insertDip()
{
vector<azienda::dipendente> d;
azienda::dipendente tempdip;
int i;
cout << "Inserimento dati dei dipendenti" << endl;
for(i=0;;i++){ /*8*/
cout << "\nDipendente " << i << endl;
cout << "Reparto ";
getline(cin,tempdip.reparto); /*9*/
if(tempdip.reparto=="") /*10*/
break;
cout << "Cognome ";
getline(cin,tempdip.cognome); /*9*/
cout << "Nome ";
getline(cin,tempdip.nome); /*9*/
cout << "Stipendio ";
cin >> tempdip.stipendio; /*9*/
cin.ignore(); /*11*/
d.push_back(tempdip); /*12*/
}
return d;
}
// Cognome e nome dipendente da cercare
void azienda::insertCogNom(string& c,string& n)
{
cout << "Dipendente da cercare" << endl
<< "Cognome ";
getline(cin,c);
cout << "Nome ";
getline(cin,n);
}
// Ricerca
int azienda::cerca(vector<azienda::dipendente> d,string c,string n)
{
int i,p;
p=-1; /*13*/
for(i=0;i<d.size();i++){
if(c==d.at(i).cognome && n==d.at(i).nome){ /*14*/
p=i; /*15*/
break; /*16*/
}
}
return p; /*17*/
}
// Stampa dati dipendente trovato
void azienda::stampa(string r,float s)
{
cout << "\nReparto di appartenenza " << r << endl;
cout << "Stipendio " << s << endl;
}
Come in altri esempi, in 1 è definito uno spazio di nomi in cui dichiarare la struttura con i dati di interesse del dipendente e i prototipi delle funzioni.
Nella 2 viene dichiarato un vettore di tipo dipendente, tipo a sua volta definito in azienda.
Nelle 3 si chiamano le funzioni per l'input della tabella dei dipendenti e dei dati della persona da cercare.
Nella 4 viene chiamata la funzione di ricerca che restituisce il numero della riga (la chiave) della tabella che contiene le informazioni cercate. Se non esiste una riga della tabella che soddisfa i requisiti richiesti, la funzione, ritorna il valore -1. Il valore ritornato può essere testato (5) per il tipo di stampa da effettuare. Si deposita l'elemento della posizione trovata in una variabile temporanea (6) e si inviano, alla funzione stampa (7), i dati che interessa stampare.
Il ciclo che inizia in 8 acquisisce i dati dei dipendenti finché non si digita un Invio a vuoto sul campo reparto (10). Il ciclo non ha una condizione di uscita. L'uscita dal ciclo è effettuata dalla istruzione break eseguita di conseguenza ad un input vuoto su reparto.
Nella funzione di inserimento dei dati dei dipendenti, prima vengono conservati gli input in una struttura temporanea (9) e, quindi, l'elemento viene inserito nel vettore (12). La 11 svuota il buffer di tastiera del carattere Invio, lasciato dall'input numerico precedente, al fine di consentire il prossimo getline.
La funzione di ricerca inizializza al valore -1 la posizione (13), se, poi, il cognome e nome passati come parametri hanno gli stessi valori dei rispettivi della riga della tabella considerata (14), la posizione viene conservata (15) e si forza una uscita anticipata dal ciclo (16). La posizione trovata, il valore assegnato in 13 o quello assegnato in 15, viene restituito al chiamante (17). La notazione con il doppio punto della 14 qui è necessaria perché, a differenza dei casi in cui un vettore è formato da variabili elementari, il vettore contiene, in ogni elemento, una struttura di tipo dipendente composta da più variabili. È quindi necessario specificare quale parte della riga della tabella si vuole prendere in considerazione.
Il prossimo programma proposto effettua una selezione. Acquisita la tabella dei dipendenti e un reparto, viene generato e stampato l'elenco dei dipendenti che lavorano nel reparto.
Il programma è, in buona parte, uguale al precedente, cambiano solo poche funzioni che saranno riportate nel listato seguente. Le parti di codice uguali, per motivi di chiarezza, non sono riportate. La numerazione delle righe commentate è riportata in modo da evidenziare le differenze con il programma precedente:
...
namespace azienda{
...
string insertRep();
vector<dipendente> selezione(vector<dipendente>, string);
void stampa(vector<dipendente>);
}
...
int main()
{
vector<azienda::dipendente> libropaga,dipRep; /*2*/
string repcerca;
...
repcerca = azienda::insertRep(); /*3*/
...
dipRep = azienda::selezione(libropaga,repcerca); /*4*/
...
if(!dipRep.empty()) /*5*/
azienda::stampa(dipRep);
else
cout << "Non risultano dipendenti nel reparto" << endl;
return 0;
}
...
// Inserimento reparto da selezionare
string azienda::insertRep()
{
string r;
cout << "Reparto da selezionare" << endl;
getline(cin,r);
return r;
}
// Seleziona in base al reparto
vector<azienda::dipendente>
azienda::selezione(vector<azienda::dipendente> d1,string r)
{
vector<azienda::dipendente> d2;
int i;
for(i=0;i<d1.size();i++){
if(r==d1.at(i).reparto) /*12*/
d2.push_back(d1.at(i));
}
return d2;
}
// Stampa dipendenti del reparto cercato
void azienda::stampa(vector<azienda::dipendente> d2)
{
int i;
cout << "\nDipendenti che lavorano nel reparto" << endl;
for(i=0;i<d2.size();i++)
cout << d2.at(i).cognome << " "
<< d2.at(i).nome << " "
<< d2.at(i).stipendio << endl;
}
Nello spazio di nomi azienda la funzione insertCogNom è sostituita dalla insertRep, cerca è sostituita da selezione e la funzione stampa è modificata in modo da stampare non più singole informazioni ma un intero vettore. Così come le dichiarazioni di variabili della 2 si adattano alla nuova elaborazione: un nuovo vettore dipRep e la stringa repcerca.
La chiamata alla funzione di inserimento del reparto, della 3, ritorna un dato di tipo string.
La 4, rispetto al programma precedente, è modificata in modo da chiamare la nuova funzione. Il controllo in 5 non si deve più occupare dell'esistenza di una posizione, ma dell'esistenza di elementi contenuti in un vettore.
La funzione di selezione, dopo aver verificato nella 12 che il reparto è quello interessato, invia l'elemento al nuovo vettore.
| http://ennebi.solira.org |
ennebi@solira.org |