Esercizi su file e strutture

Esercizi su file e strutture

Svilupperemo oggi degli esercizi su file e strutture in C, al fine di consolidare l’apprendimento delle funzioni sui file studiate finora.

In questi esercizi proporremo in particolar modo l’uso delle funzioni fopen, fwrite e fclose e tratteremo anche i file binari.


Esercizi su file e strutture in C

Il primo esercizio che vi voglio proporre è molto semplice.

Creare una struct alunno che contiene il nome, il cognome e il voto. Dopo inserire 5 studenti e memorizzarli in un file binario di nome archivio.txt.

Quindi apriamo in lettura il nostro file binario e diamo un messaggio di avviso qualora si dovessero presentare degli errori.

Dopo con un ciclo for inseriamo tutti i dati e con la funzione fwrite copiamo i dati nel nostro file binario.

#include<stdio.h>
#include <stdlib.h>

#define N 5

typedef struct{
	char nome[20];
	char cognome[20];
	int voto;
}studente;

int main(){
	FILE *fp;
	studente s;
	int i;

	if((fp=fopen("archivio.txt", "wb"))==NULL) {
		printf("Errore nell'apertura del file");
		exit(1);
	}

	for(i=0;i<N;i++){
		printf("Dati studente %d:\n", i+1);
		scanf("%s%s%d",&s.nome,&s.cognome,&s.voto);
                fwrite(&s,sizeof(studente),1,fp);
	}
	
	fclose(fp);
	
	return 0;
}

Potremmo variare l’esercizio permettendo che sia l’utente a decidere quando terminare l’inserimento, ad esempio facendo comparire un messaggio.

Quindi ogni volta che terminiamo l’inserimento di uno studente, chiediamo all’utente se vuole proseguire oppure no.

Ecco dunque il listato completo:

#include<stdio.h>
#include <stdlib.h>

#define N 5

typedef struct{
	char nome[20];
	char cognome[20];
	int voto;
}studente;

int main(){
	FILE *fp;
	studente s;
	int fine=0;

	if((fp=fopen("archivio2.txt", "wb"))==NULL) {
		printf("Errore nell'apertura del file");
		exit(1);
	}

	 while(!fine) {
   		printf("Dati studente:\n");
		scanf("%s%s%d",&s.nome,&s.cognome,&s.voto);
		fwrite(&s,sizeof(studente),1,fp);
	
		printf("\nVuoi terminare? (Si=1, No=0)");
		scanf("%d", &fine);
		} 
	
	fclose(fp);
	
	return 0;
}

Ma questa procedura è fastidiosa, pensate ad esempio di voler inserire 10 studenti o anche più, digitare ogni volta zero per continuare diventa noioso.

Allora potremmo far decidere all’utente di terminare l’inserimento digitando una parola, ad esempio stop.

Modifichiamo dunque il programma in questo modo:

#include<stdio.h>
#include <stdlib.h>

typedef struct{
	char nome[20];
	char cognome[20];
	int voto;
}studente;

int main(){
	FILE *fp;
	studente s;
	char name[10];

	if((fp=fopen("archivio3.txt", "wb"))==NULL) {
		printf("Errore nell'apertura del file");
		exit(1);
	}

	do{
		printf("\nNome:");
		scanf("%s", name);
		if(strcmp(name,"stop")!=0){
			strcpy(s.nome, name);
			printf("Cognome:");
			scanf("%s", s.cognome);
			printf("Voto:");
			scanf("%d", &s.voto);
			fflush(stdin);
			fwrite(&s, sizeof(s), 1, fp);
		}
	}while (strcmp(name, "stop")!=0);

	fclose(fp);
	
	return 0;
}

Chiaramente questi sono solo dei semplici esercizi, andando avanti nel tutorial proporremo altri esempi su file e strutture in C.

Alcuni link utili

Indice argomenti linguaggio C

La funzione fopen

Funzione fscanf

Allocazione dinamica della memoria con malloc

Strutture in C

Realizzare un menù di scelta in C

Strutture complesse in C

Come sommare gli elementi della cornice esterna

Come sommare due matrici

Prodotto tra matrici

Tavola pitagorica in C

Selection sort in C

Merge sort in C

Insertion Sort in C


Media dei numeri in un array

Media dei numeri in un array

Realizziamo in questa lezione un semplice algoritmo che calcola la media dei numeri in un array.

L’algoritmo è di facile implementazione, richiede all’utente di inserire 10 numeri e al termine del programma comunicare in output la media.


Sviluppo diagramma di flusso per la media dei numeri in un array

Per realizzare questo algoritmo iterativo e con l’uso degli array servono quindi le seguenti forme:

Ellisse per l’inizio e per la fine;

Parallelogramma per inserire l’input, ovvero in questo caso i 10 numeri dell’array e per visualizzare in output messaggi o risultati come ad esempio la media.

Rettangolo per effettuare le operazioni e gli assegnamenti;

Esagono per realizzare il ciclo for, nel quale si usa una variabile in tre parti della stessa istruzione: inizializzazione, condizione, aggiornamento.
Dove con inizializzazione si intente un assegnamento come ad esempio: i = 0.
Invece la condizione è una espressione booleana come ad esempio: i <10.
Infine l’aggiornamento è un assegnamento per calcolare ad esempio il valore successivo come: i=i+1. (attenzione non possiamo scrivere i++ come siamo abituati a fare nei linguaggi di programmazione).

Quindi inseriamo la costante N uguale a 10, perchè 10 sono gli elementi che si vogliamo inserire nell’array.

Inizializziamo la media a zero.

Dopo con un ciclo for inseriamo tutti gli elementi nell’array e li sommiamo nella variabile media. Potrei anche utilizzare due variabili diverse: somma e media, ma dato che la somma non viene utilizzata ulteriormente all’interno del programma, utilizzo solo la variabile media.

Poi calcolo la media dividendo il risultato della somma di tutti gli elementi per N.

Infine stampo in output il risultato.

Ecco dunque il diagramma a blocchi completo che rappresenta l’algoritmo per il calcolo della media dei numeri in un array.

media con diagrammi di flusso

Alcuni link utili

Indice argomenti diagramma a blocchi

Numeri primi da 1 a 100

Triangoli con algobuild

Fibonacci con algobuild

Serie buffa con algobuild

Area del cerchio con Algobuild

Numeri amicabili con algobuild

Numeri perfetti con algobuild

Massimo fra tre numeri

Minore fra tre numeri

Minore tra due numeri

Diagramma a blocchi

fwrite

fwrite

La funzione fwrite in C permette di scrivere su un file un blocco di dati di qualsiasi tipo, precedentemente aperto con la funzione fopen. La funzione fwrite consente quindi di scrivere i dati di un file binario. Per la scrittura a blocchi è necessario che il file sia stato aperto in modalità binaria (b).

La sintassi della funzione fwrite è dunque la seguente:

size_t fwrite(void *punt, size_t dim, size_t num, FILE *fp)

Punt rappresenta l’indirizzo della locazione di partenza su cui scrivere i dati, dim rappresenta la dimensione in byte del singolo dato e num rappresenta il numero degli elementi da scrivere nello stream. FILE *fp è il puntatore al file restituito dalla funzione fopen, così come nelle altre funzioni che abbiamo studiato finora.

Il valore di ritorno di fwrite indica il numero di elementi effettivamente memorizzati sul file. Nel caso in cui il valore di ritorno assume un valore negativo allora vuol dire che è stato commesso qualche errore. Un errore può essere ad esempio la non apertura di un file.

Se punt rappresenta un vettore, allora in esso verranno trasferiti i dati che devono essere memorizzati nel file fp.


Esempio di utilizzo di fwrite in C

Realizziamo quindi un programma in linguaggio C che acquisisce da tastiera una stringa e la memorizza all’interno di un file di nome nomi.txt.

Apriamo, al solito, il file con la funzione fopen per renderlo disponibile per la scrittura e controlliamo se il puntatore restituisce il valore NULL. In caso positivo restituiamo un messaggio di errore e usciamo dal programma, altrimenti continuiamo nel nostro programma.

Quindi utilizziamo fwrite(buffer, 1, num, fp);

Dove, buffer indica dove sono trasferite le informazioni da memorizzare nel file, 1 indica il numero di elementi del vettore, num rappresenta invece la dimensione in byte di un elemento del vettore ed fp è il file su cui scrivere.

Ecco quindi il listato completo:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define N 100

int main()
{
   	FILE *fp;
   	char buffer[N];
   	int num;
   	   	
   	printf("Inserisci un nome: ");
        scanf("%s",buffer);
    
        num=strlen(buffer);

	if((fp=fopen("nomi.txt", "wb"))==NULL) {
		printf("Errore nell'apertura del file");
		exit(1);
	}
   	
   	fwrite(buffer, 1, num, fp);                        
   	fclose(fp); 
	     
   	return 0;
}


Chiaramente questo è un semplice esempio d’uso della funzione fwrite in C, più avanti proporrò tante altre esercitazioni.

Alcuni link utili

Indice argomenti linguaggio C

La funzione fopen

La funzione fclose

Funzione fprintf

Funzione fscanf

Allocazione dinamica della memoria con malloc

Array multidimensionali

Merge sort in C

Insertion Sort in C

fread

fread

La funzione fread in C permette di leggere su un file un blocco di dati di qualsiasi tipo, precedentemente aperto con la funzione fopen. La funzione fread consente quindi di leggere i dati di un file binario. Ricordiamo che un file binario memorizza dati di qualunque tipo, quindi anche dati che non sono caratteri (tipo vettori o strutture). Inoltre, per la lettura a blocchi è necessario che il file sia stato aperto in modalità binaria (b).

La sintassi della funzione fread è la seguente:

size_t fread(void *punt, size_t dim, size_t num, FILE *fp)

Dove punt rappresenta l’indirizzo della locazione di partenza da cui leggere i dati, dim rappresenta la dimensione in byte del singolo dato e num rappresenta il numero degli elementi da leggere nello stream.FILE *fp è il puntatore al file restituito dalla funzione fopen, così come nelle altre funzioni che abbiamo studiato finora.

Il valore di ritorno di fread indica il numero di elementi effettivamente letti dal file. In caso di successo il valore di ritorno deve coincidere con quello del parametro num passato alla funzione.

Se punt rappresenta un vettore, allora in esso verrano trasferite le informazioni lette dal file.

Un file può avere dimensioni elevate, quindi occorrono più chiamate ad fread. Pertanto la funzione ad ogni chiamata legge una limitata porzione di file.

Dopo l’apertura del file con fopen, il puntatore si trova all’inizio del file, ogni volta che viene chiamata fread il puntatore si sposta in avanti del numero di byte letti. Quando la funzione termina di leggere tutto il contenuto del file ritorna il valore 0 (indica quindi che il puntatore è posizionato alla fine).

Se si tenta nuovamente di leggere la funzione restituirà il valore 0 per indicare che il puntatore è a fine file.


Esempio di utilizzo di fread in C

Realizziamo un programma in linguaggio C che determini e visualizzi il numero delle occorrenze di uno specifico carattere fornito come argomento in un file di testo.

Apriamo il file con la funzione fopen e controlliamo se il puntatore restituisce il valore NULL. In caso positivo restituiamo un messaggio di errore e usciamo dal programma, altrimenti continuiamo nel nostro programma.

Quindi utilizziamo fread(buffer, sizeof(char), sizeof(buffer), fp);

Buffer dove sono trasferite le informazioni lette dal file, sizeof(buffer) indica il numero di elementi del vettore, sizeof(char) rappresenta la dimensione in byte di un elemento del vettore, fp è il file da leggere.

Inizializziamo a zero il contatore del carattere ricercato e lo incrementeremo ogni volta che verrà trovata l’occorrenza di quel carattere nel file.

Infine chiudiamo il file usando la funzione fclose e stampiamo il risultato ottenuto.

Ecco dunque il listato completo:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char* argv[]) {
 	FILE* fp;
 	char c='d';
 	char buffer[64];
 	int i, n, count = 0;
 	
	if((fp=fopen("alunni.dat", "rb"))==NULL) {
		printf("Errore nell'apertura del file");
		exit(1);
	}

 	while(!feof(fp)){
	   	n = fread(buffer, sizeof(char), sizeof(buffer), fp);
	   	for (i=0; i<n; i++)
	      	         if (buffer[i] == c)
		   		count++;
      }
	fclose(fp);
 	printf("Il carattere \"%c\" e' presente nel file %d volte\n", c, count);
 	return 1;
}

Potevamo anche chiedere all’utente quale carattere ricercare nel file facendo una semplice modifica nell’algoritmo.

Questo è un semplice esempio d’uso della funzione fread in C, più avanti ci eserciteremo ancora.

Alcuni link utili

Indice argomenti linguaggio C

La funzione fopen

La funzione fclose

Funzione fprintf

Funzione fscanf

Allocazione dinamica della memoria con malloc

Strutture in C

Typedef struct in C

Esercitazione sulle struct in C

Matrice trasposta

Array multidimensionali

Quick sort in C


fputs

fputs

La funzione fputs in C permette di scrivere in un file delle stringhe, precedentemente aperto con la funzione fopen.

La fputs ha la seguente sintasssi:

int fputs(char *stringa, FILE *fp)

Quindi la funzione invia una stringa e la memorizza nella locazione di memoria puntata da stringa. FILE *fp è il puntatore al file restituito dalla funzione fopen, così come nelle altre funzioni che abbiamo studiato finora.

La funzione ritorna zero se non si verificano errori, altrimenti ritorna un valore diverso da zero o la costante EOF.


Esempio di utilizzo di fputs in C

Facciamo dunque un semplice esempio che permette di aprire un file in lettura e copiare riga per riga il contenuto di questo file in uno nuovo.

Facciamo l’esempio richiedendo in input entrambi i file.

Inizializziamo a zero il contatore della riga, nr, per conoscere quante righe sono state copiate.

Chiediamo in input i nomi dei file e apriamo il file con la funzione fopen. Visualizziamo un messaggio di errore se ci sono problemi nell’apertura dei file.

Dopo utilizziamo un ciclo while con la funzione fgets, che come abbiamo spiegato nella lezione precedente, prende tre parametri: la stringa, il numero di caratteri e il puntatore al file. Finché non arriviamo a leggere tutte le stringhe presenti nel file in lettura, copiamo con la funzione fputs ciascuna stringa nel nuovo file aperto in scrittura.

Infine chiudiamo il file usando la funzione fclose e stampiamo il risultato ottenuto.

Ecco dunque il listato completo:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define N 100

int main()
{
   	FILE *fpin, *fpout;
	char nome_in[FILENAME_MAX], nome_out[FILENAME_MAX], r[N];
   	int nr=0;

   	printf("Nome del file da copiare:");
   	gets(nome_in);
   	
   	printf("Nome del nuovo file:");
   	gets(nome_out);

   	if ((fpin=fopen(nome_in,"rt"))==NULL) {
		printf("Errore nell'apertura del file");
		exit(1);
   	}
   	
   	if ((fpout=fopen(nome_out,"wt"))==NULL) {
		printf("Errore nell'apertura del file");
		exit(1);
   	}

   	while(fgets(r,N,fpin) != NULL) {
           nr++;
           fputs(r, fpout);
   	}                                    
   
   	fclose(fpin);
   	fclose(fpout);
   	printf("Totale righe copiate: %d\n", nr);
   
   	return 0;
}

A questo semplice esempio sulla funzione fputs in C seguiranno tanti altri esempi al fine di consolidarne l’uso.

Alcuni link utili

Indice argomenti linguaggio C

La funzione fopen

La funzione fclose

Funzione fprintf

Funzione fscanf

Allocazione dinamica della memoria con malloc

Strutture in C

Typedef struct in C

Esercitazione sulle struct in C

Realizzare un menù di scelta in C

Strutture complesse in C

Come sommare gli elementi della cornice esterna

Come sommare due matrici

Matrice trasposta

Prodotto tra matrici

Ricerca elementi in una matrice

Tavola pitagorica in C

Array multidimensionali

Quick sort in C

Selection sort in C

Merge sort in C

Insertion Sort in C