Esercizio cumulativo con molte tecnologie del C/C++, destinato ad approfondimenti nelle scuole superiori e più indicativamente adatto ad un percorso universitario avanzato. Usiamo la lettura dei parametri da esecuzione per leggere un nome file. Dal file carichiamo i dati inerenti a prenotazioni di posti su treni su una lista dinamica; quindi consentiamo di aggiungere uno o più prenotazioni alla lista precaricata e scriviamo i dati su file, tutto con un menu interattivo con l’utente.
L’approccio del codice è ibrido C/C++ visto che per la gestione della memoria usiamo la funzione malloc invece del new. Questa scelta non è sempre indicata, poiché il costrutto new permette di gestire meglio alcuni aspetti propri della gestione della memoria del C++, le string ad esempio invece dei char[] e l’inizializzazione dei vari puntatori. Il lettore potrà però facilmente riconvertire il codice al C puro semplicemente sostituendo la gestione degli input/output e dei file, decisamente più comodi in C++. Vediamo il codice commentato.
/**
Esercizio cumulativo con molte tecnologie del C/C++, destinato ad approfondimenti nelle scuole superiori
e più indicativamente adatto ad un percorso universitario avanzato. Usiamo la lettura dei parametri da esecuzione
per leggere un nome file. Dal file carichiamo i dati inerenti a prenotazioni di posti su treni su una lista dinamica;
quindi consentiamo di aggiungere uno o più prenotazioni alla lista pre-caricata e scriviamo i dati su file
tutto con un menu interattivo con l'utente.
L'approccio del codice è ibrido C/C++ visto che per la gestione della memoria usiamo la funzione malloc invece del new
*/
#include <iostream>
#include <fstream>
#include <string.h>
using namespace std;
/**
Strutture dati e definizioni di tipi
*/
struct data
{
int gg;
int mm;
int aaaa;
};
typedef data Data;
struct posto
{
int treno;
int carrozza;
int posto;
char nome[20];
char cognome[20];
Data dd;
struct posto *next;
};
typedef posto Posto;
/**
Dichiarazione delle funzioni
*/
void visualizza(Posto *p)
{
int i=1;
while (p != NULL)
{
cout << "---------Prenotazione "<< i << "---------- " << endl;
cout << "Treno #" << p->treno << endl;
cout << "Carrozza: " << p->carrozza << endl;
cout << "Posto: " << p->posto << endl;
cout << "Passeggero:" << p->cognome << " " << p->nome << endl;
cout << "Data prenotazione: " << p->dd.gg << "/"<< p->dd.mm <<"/"<< p->dd.aaaa <<endl;
cout << "---------------------------------" << endl << endl;
p = p->next;
i++;
}
}
Posto *aggiungi(Posto *p)
{
Posto *buffer = NULL;
Posto *radice = NULL;
buffer = (Posto *)malloc(sizeof(Posto));
//anologamente buffer=(struct posto *)malloc(sizeof(struct posto));
//oppure new Posto();
buffer->next = NULL;
cout << "---------------------------- " << endl;
cout << "Treno #";
cin >> buffer->treno;
cout << "Carrozza: ";
cin >> buffer->carrozza;
cout << "Posto: ";
cin >> buffer->posto;
cout << "Cognome passeggero: ";
cin >> buffer->cognome;
cout << "Nome passeggero: ";
cin >> buffer->nome;
cout << "Data prenotazione: " << endl;
cout << "Giorno: ";
cin >> buffer->dd.gg;
cout << "Mese: ";
cin >> buffer->dd.mm;
cout << "Anno: ";
cin >> buffer->dd.aaaa;
cout << "---------------------------- " << endl << endl;
if (p == NULL)
{
//sto aggiungendo il primo elemento della lista
//cout << "DEBUG - aggiungo in testa" << endl;
radice = buffer;
p = radice;
}
else
{
//cout << "DEBUG - aggiungo in coda" << endl;
//mi assicuro di arrivare all'ultimo elemento della lista
radice = p;
while(p->next != NULL)
{
p = p->next;
}
if (p != NULL)
{
p->next = buffer;
p = p ->next;
}
}
return radice;
}
void scriviSuFile(Posto *p, char *f)
{
int i=0;
ofstream file;
file.open (f, ios::out | ios::binary);
if (file.fail())
{
cout << "ERRORE: impossibile aprire il file..." << endl;
exit(0);
}
while(p != NULL)
{
file.write((char*)p, 1*sizeof(Posto));
p = p->next;
i++;
}
file.flush();
file.close();
cout << "Scritti " << i << " record" << endl;
}
Posto *leggiDaFile(char *f)
{
int i=0;
ifstream file;
Posto *p = NULL;
Posto *radice = NULL;
Posto *buffer = NULL;
file.open (f, ios::in | ios::binary);
if (file.fail())
{
cout << "ERRORE: impossibile aprire il file..." << endl;
return radice;
}
while(!file.eof())
{
//preparo un buffer per leggere un elemento da file
buffer = (Posto *)malloc(sizeof(Posto));
//file.seekg(sizeof(Posto)*1); // edit to get desired record
file.read((char*)buffer, sizeof(Posto));
buffer->next = NULL;
//se l'elemento è valido lo aggiungo ad una lista
if (file && buffer != NULL)
{
//è il primo elemento della lista?
if (i == 0)
{
cout << "DEBUG - Leggi 2" << endl;
radice= buffer;
p = radice;
}
else
{
//successivi elementi
cout << "DEBUG - Leggi 3" << endl;
p->next = buffer;
p = p->next;
}
i++;
}
}
file.close();
cout << "Letti " << i << " record" << endl;
return radice;
}
/**
Programma principale
*/
int main(int argc, char * argv[])
{
char *nome_file_dati; //da passare come parametro da console es. programma.exe nomefile.dat
char scelta; //per il menu di scelta utente
Posto *radice = NULL;
// Controllo input del file per le operazione i I/O
if(argc-1 != 1)
{
cout << "Inserire il nome del file dati" << endl;
exit(1);
}
else
{
nome_file_dati = argv[1];
}
//precarico eventuali prenotazioni da file
cout << "Caricamento prenotazioni già registrate... " << endl;
radice=leggiDaFile(nome_file_dati);
cout << "Fatto!" << endl;
//Controllo e stampo i dati del file
if(radice==NULL)
{
cout << "Attenzione il file dati non ha prenotazioni" << endl;
}
else
{
cout << "Precedenti prenotazioni già registrate" << endl;
visualizza(radice);
}
scelta = 'a';
while(scelta != 'q')
{
cout << "Scegli e digita la lettera corrispondente:" << endl;
cout << "a -> aggiungi prenotazione" << endl;
cout << "v -> visualizza prenotazioni" << endl;
cout << "q -> esci" << endl;
cin >> scelta;
switch (scelta)
{
case 'q':
continue;
break;
case 'a':
radice = aggiungi(radice);
break;
case 'v':
visualizza(radice);
break;
}
}
scriviSuFile(radice, nome_file_dati);
return 0;
}
Ultima modifica 30 Maggio 2023