Esercizio n.1 – File sequenziale di Struct in C++

In questo articolo, un esercizio abbastanza articolato con le struct in C++, un tipo di dati record che permette al programmatore di personalizzare le strutture informative personalizzate sia a livello di memoria RAM con le tabelle, o su memoria di massa con i files strutturati.
L’esercizio prevede la gestione di un elenco di libri su un file binario composto da record logici.
Il codice C++ è:

// main.cpp
#include "funzioni.cpp"
using namespace std;
int main ()
{
	fstream f;
	int scelta;
	struct libro rlibro;
	while (true)
	{
	do 
	{
	cout << "\n Bemvemto nel programma di gestione della libreria\n";
	cout << "1- Aggiungi libri\n";
	cout << "2- Stampa Elenco libri\n";
	cout << "3- Uscita dal programma\n";
	cout << "\n Effettua la tua scelta 1-3 \n";
	cin >> scelta;
				if ((scelta<1)||(scelta >3))
						cout << "\n Errore nella scelta ripeti !";
		}	
	while ((scelta<1)||(scelta >3));
	switch (scelta){
		case 1: 
		{
			scrivi(f,rlibro);
			break;
		}
		case 2:
			{
				leggi(f,rlibro);
				break;
			}
		case 3:
		{
			cout << "\n Arrivederci\n";
			return 0;
		}
}}}

// funzioni.h header con implementazione delle funzioni
#include "file.h"
// implementazione delle funizioni richieste
void scrivi(fstream& f, libro l)
{
	f.open("dati.dat",ios::app | iso::bin);
	if (!f)
		{
			f.open("dati.dat",ios::out| ios::bin);
			cout << "\n Creato nuovo file\n";
		}
	cout << "\n Inserisci i dati del libro:";
	cout << "Codice ISBN 14 cifre\n";
	cin.ignore(80,'\n');
	cin.getline(l.isbn,14);
	cout << "Inserisci il titolo del libro\n";
	cin.getline(l.titolo,50);
	cout << "Inserisci gli autori del libro:\n";
	cin.ignore(1,'\n');
	cin.getline(l.autori,50);
	cout << "Inserisci l'editore del libro\n";
	cin.getline(l.editore,50);
	cout << "Insersici il prezzo del libro:\n";
	cin >> l.prezzo;
	cout << "Inserisci il numero di copie:\n";
	cin >> l.q;
	f.write((char *)&l,sizeof(l));
	f.close();
}
void leggi(fstream& f, libro l)
{
	char sep;
	f.open("dati.dat",ios::in| ios::bin);
	if (!f)
		{
			cout << "\n Errore nell'apertura del file\n";
			return;
	}
		while (f.read((char *)&l,sizepf(l)))
		{
		cout << "Dati dei libri:";
		cout << "Codice ISBB:\t" << l.isbn;
		cout << "\nAutori : \t"<< l.autori;
		cout << "\nTitolo:\t"<< l.titolo;
		cout << "\n Editore:\t"<< l.editore;
		cout << "\n Prezzo: \t"<< l.prezzo;	
		}
		f.close();}

// file.h
#include <iostream>
#include <fstream>
#include <string.h>
using namespace std;
// modello di dati;
struct libro 
{
	char isbn[14];
	char titolo[50];
	float prezzo;
	int q;
	char autori[50];
	char editore[50];
};
void scrivi(fstream &f, struct libro l);
void leggi(fstream &f,struct libro l);

Commento al codice C++

Il seguente programma in C++, si compone di tre file due header estensioni contenenti la dichiarazione della struct e le relative procedure e/o funzioni che sono poi implementate nel file “funzioni.cpp”.
Il programma crea un file composto da record logici appunto la struct composta a sua volta da i seguenti campi isbn, autore, titolo, editore, prezzo e quantità. Come dati di tipo stringa si è scelto di utilizzare array di char per bloccare le dimensioni massime di ciascun campo.
Le procedure “void” una scrive i dati raccolti in input da console su file e l’altra legge gli stesis dati e li stampa.
Nell’implementazione delle due procedure il file logico è passato per indirizzo ecco perché nell’intestazione delle procedure compare “fstream &f”. Il file è aperto in modo binario con il flag” ios::bin”. Per questa modalità che riguarda sempre file ad accesso sequenziale sono utilizzati i metodi “read” e “write” che leggono e scrivono dati in formato binario sotto forma di sequenza di byte.
In particolare per scrivere dati in byte l’argomento delle istruzioni read e write deve essere convertito in un array di byte mediante la sintassi:
(char *)&(nome variabile di tipo struct), sizeof(nome variabile di tipo struct). In questo modo viene allocato un blocco fisico di dati pari alla dimensione della variabile di tipo struct utilizzata, “castata” in byte i dati contenuti in essa e poi scritti sul supporto di memoria di massa. Nel ciclo di lettura l’istruzione “read” compare come condizione del ciclo while in modo da leggere i dati fin quanto sono presenti nel file.
Come ultima annotazione è utilizzata la funzione “ignore” nellla cin per ingnorare i caratteri di interruzione riga , e utilizzata l’istruzione “getline” per permettere la lettura di stringhe di lunghezza fissa.

Video sull’uso di struct e file binari in C++