Prenotazione treno con struct, lista, file binari, malloc, menù

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

Lascia un commento