fseek in C

fseek in C

La funzione fseek in C consente di muovere il puntatore di lettura e/o scrittura in una posizione qualunque all’interno del file, dopo la sua apertura con fopen.

Finora l’accesso al file è stato di tipo sequenziale, ovvero per aggiungere o leggere un elemento ci siamo posizionati esattamente sotto tutti gli elementi precedenti.

Infatti, molte volte c’è la necessità di realizzare un accesso diretto o random ad un elemento di un file. Ecco dunque che la funzione fseek ritorna molto utile a questo scopo.

La sintassi della funzione fseek in C è quindi la seguente:

int fseek(FILE *fp, long distanza, int partenza)

Dove fp è il file pointer, distanza indica di quanti byte il file pointer deve essere spostato mentre partenza indica da quale posizione deve essere spostato.

La funzione fseek ritorna 0 se lo spostamento è avvenuto con successo, altrimenti un valore diverso da 0.

Allora definiamo il punto di partenza che può assumere solo uno di questi tre valori:

SEEK_SETinizio del file

SEEK_ENDfine del file

SEEK_CURposizione corrente dell’indicatore


Esempio d’uso della funzione fseek in C

Realizziamo dunque lo stesso esempio di prima con rewind con la funzione fseek in C, solo a scopo didattico per capirne il funzionamento.

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

#define N 100

int main() {
  FILE *fp;
  char buf[N];

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

	/* legge e stampa fino alla fine del file */
  	while(!feof(fp)) {
		fgets(buf,N,fp);
    	printf("%s", buf);
  	}

	/* riporta il file pointer all'inizio */
  	fseek(fp,0,SEEK_SET);
  	
  	printf("\nStampo la seconda volta\n");

    /* legge e stampa fino alla fine del file */
  	while(!feof(fp)) {
    	    fgets(buf,N, fp);
    	    printf("%s", buf);
  	}

        printf("\nStampo la terza volta\n");
  	fseek(fp,0,SEEK_CUR);
  	 /* legge e stampa fino dalla posizione corrente dell'indicatore che in questo caso è l'ultima riga*/
  	while(!feof(fp)) {
    	    fgets(buf,N, fp);
    	    printf("%s", buf);
  	}

  	fclose(fp);

  	return 0;
}

Le potenzialità della funzione fseek in C saranno trattate anche nelle prossime lezioni in maniera approfondita.

Alcuni link utili

Indice argomenti linguaggio C

La funzione fopen

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

Prodotto tra matrici

Ricerca elementi in una matrice

Quick sort in C

Insertion Sort in C


Esercizi sui file in C

Esercizi sui file in C

Proponiamo ancora degli esercizi sui file in C ed in particolare sulle funzioni fopen, fwrite, fread e fclose.

Propongo questo esempio a scopo di introdurre, prossimamente, altre funzioni che ci permetteranno di posizionarci in una posizione qualunque del file e che quindi garantiscono un accesso diretto e non più sequenziale.

Esercizi sui file in C – problema

In un file binario sono memorizzati i dati di un vettore che contiene al massimo 50 elementi. Stampare i dati di questo file, se presenti, altrimenti dare come messaggio: “Nessun dato presente!”. Dopo chiedere quanti dati si vogliono aggiungere al vettore e creare una funzione che consenta di farlo. Creare un’altra funzione per il salvataggio di questi dati nel vettore. Infine ristampare nuovamente i dati del file aggiornati con il nuovo inserimento.

Le funzioni/procedure utilizzate sono dunque 4. Notate come la funzione init deve restituire un intero che corrisponde al numero di elementi che vengono inseriti nel vettore. Mentre le altre procedure non ritornano alcun valore.

Quindi la funzione init ha il compito di aprire in lettura il file binario, utilizzando fopen, e se l’operazione ha successo legge gli elementi in esso presenti utilizzando la funzione fread. Se non ci sono dati verrà stampato un messaggio: Nessun dato presente! Dopo chiudiamo il file binario con la funzione fclose.

La procedura print stampa semplicemente i dati presenti senza restituire alcun valore. Prende come parametri il vettore e il numero degli elementi.

La procedura add ha il compito di aggiungere gli elementi e quindi ha la necessità di prendere come parametri non solo il vettore ma anche il puntatore all’ultimo elemento inserito. Quindi chiediamo quanti elementi inserire e li aggiungiamo a quelli precedenti. Potremmo fare anche un controllo per far in modo che non si inseriscano più elementi rispetto alla dimensione massima dichiarata, che in questo caso è 50.

Infine la procedura save si occupa di salvare i dati inseriti nel file.

Ecco dunque il listato completo:

#include <stdio.h>

#define N 50

int init(int*V);
void print(int *V,int n);
void add(int *V,int *pn);
void save(int *V,int n);

void main(){ 
	int a[N],i,n;
	
	n=init(a);
	print(a,n);
	add(a,&n);
	save(a,n);
	printf("Ristampo i dati contenuti nel file con l'aggiunta");
	print(a,n);
}

int init(int *V){ 
	FILE *pf;
	int i=0;

	pf=fopen("vettori.dat","rb");

	if(pf)
	while(fread(&V[i],sizeof(int),1,pf)>0 && i<N)
		i++;	

	else 
		printf("Nessun dato presente!");
		
	fclose(pf);
	return i;
}

void print(int *V, int n){ 
	int i;
	printf("\nElementi totali presenti: %d\n", n);
	for(i=0;i<n;i++)
		printf("%d\n", V[i]);
}

void add(int *V,int *pos){ 
	int x,i;
	printf("Elementi da aggiungere (max %d): ", N-*pos);
	scanf("%d",&x);
	
	for(i=*pos;i<*pos+x;i++){
		printf("Numero %d: ", i+1);
		scanf("%d",&V[i]);
	};
	
	*pos+=x;
}

void save(int *V,int n){ 
	FILE *pf;
	
	pf=fopen("vettori.dat","wb");
	
	if(pf)
		fwrite(V,sizeof(int),n,pf);
	else 
		printf("Errore in scrittura\n");
}

Questi sono solo alcuni degli esercizi sui file in C che vi propongo in questo semplice tutorial.

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

Matrice trasposta in C

Prodotto tra matrici

Tavola pitagorica in C

Quick sort in C

Selection sort in C

Merge sort in C

Insertion Sort in C

File con vettori in C

File con vettori in C

Proponiamo oggi alcuni esercizi sui file con vettori in C. Utilizzeremo i file binari e le funzioni fclose, fopen, fread e fwrite.


Esempio sui file con vettori in C

Realizzare un semplice esempio che crea una procedura per l’inserimento dei dati in un vettore e poi la copia di questi dati su file. Creare anche una procedura per la stampa dei dati inseriti.

Innanzitutto chiediamo all’utente quanti numeri vuole inserire (n) e dunque invochiamo la procedura per inserire i dati nel vettore. Facciamo il controllo che n sia positivo e minore di 10 (abbiamo stabilito di voler inserire massimo 10 numeri e abbiamo memorizzato questo valore nella costante N).

Quindi apriamo il file binario vettori.dat in scrittura, con la funzione fopen, e se l’operazione ha successo memorizziamo i dati nel file con la funzione fwrite. Dopo aver fatto ciò chiudiamo il file.

Poi riapriamo lo stesso file binario in lettura, sempre con la funzione fopen, e utilizziamo la funzione fread per leggere i dati dal file. Invochiamo poi la funzione print per stampare i dati del vettore e infine chiudiamo il file.

lLa funzione fread permette quindi di leggere un array da file con una singola istruzione: fread(a,sizeof(int),n,pf). Infatti se notate passiamo n come terzo argomento, cioè diciamo alla funzione di leggere n dati.

Ecco dunque il listato completo sui file con vettori in C:

#include <stdio.h>

#define N 10

void insert(int *V,int n);
void print(int *V,int n);

void main(void){ 
	FILE *pf;
	int a[N],i,n;
	
	do{
		printf("Quanti numeri?\n");
		scanf("%d",&n);
	} while(n<=0 || n>N);
	
	insert(a,n);
	
	pf=fopen("vettori.dat","wb");
	if(pf){
		fwrite(a,sizeof(int),n,pf);
		fclose(pf);
	}
	else 
		printf("Errore in scrittura\n");
	
	pf=fopen("vettori.dat","rb");
	if(pf){
		fread(a,sizeof(int),n,pf);
		print(a,n);
		fclose(pf);
	}
	else 
		printf("Errore in lettura");
}
	
      void insert(int *V,int n){
	    int i;
	    for(i=0;i<n;i++){
		printf("Numero %d: ", i+1);
		scanf("%d",&V[i]);}
}

       void print(int *V,int n){
	    int i; 
	    for(i=0;i<n;i++)
		printf("Numero %d: %d\n",i+1,V[i]);
}

Ecco dunque un esempio sui file con vettori in C, continuate a seguire il tutorial, proporrò ancora tanti altri esempi con spiegazione dettagliata.

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

Matrice trasposta in C

Prodotto tra matrici

Esercizi su file e strutture in C

Esercizi su file e strutture in C

Proponiamo oggi alcuni esercizi su file e strutture in C. Utilizzeremo i file binari e le funzioni fclose, fopen, fread e fwrite.

Esercizi su file e strutture in C

Il primo esercizio che svolgeremo è una variazione dell’esercizio precedente, proponiamo in aggiunta l’uso delle funzioni, così da approfondirne l’uso.

Creare una struct studente che contiene la matricola, il nome, il cognome e il voto. Creare una funzione/procedura per l’inserimento dei dati e un’altra per la stampa degli studenti inseriti. I dati saranno inseriti e letti in un file binario di nome student.dat.

Innanzitutto creiamo la struct come richiesta nel problema sopra. Dopo creiamo i prototipi delle funzioni che utilizzeremo per inserire e stampare i dati. Entrambe le funzioni prendono come parametro il file pointer, cioè il puntatore al file restituito dalla funzione fopen.

Apriamo il file binariostudent.dat in scrittura e se non ci sono problemi nell’apertura richiamiamo la procedura insert che si occupa di richiedere e registrare i dati in input.

Dopo occorre riaprire il file binario in lettura e verificare che l’apertura non abbia prodotto problemi. Quindi si invoca la procedura print che provvederà a stampare i campi inseriti precedentemente in input.

Notate che la chiusura del file, con fclose, avviene ovviamente sia dopo aver inserito i dati, sia dopo la stampa dei dati. Infatti il file viene aperto due volte, prima in scrittura e poi in lettura.

Ecco dunque il listato completo:

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

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

void insert(FILE *pf); //prototipo funzione
void print(FILE *pf); //prototipo funzione

void main(void){ 
	FILE *pf;

	pf=fopen("student.dat","wb");
	if(pf){  
		insert(pf);
		fclose(pf);
	}
	else 
		printf("Errore in scrittura\n");
		
	pf=fopen("student.dat","rb");
	if(pf)  { 
		print(pf);
		fclose(pf);
	}
	else 
		printf("Errore in lettura");
}

void insert(FILE *pfile){
	studente s;
	printf("\nInserisci Matricola:");
	scanf("%d",&s.id);
	printf("Inserisci il cognome:");
	scanf("%s",s.cognome);
	printf("Inserisci il nome:");
	scanf("%s",s.nome);
	printf("Inserisci il voto:");
	scanf("%d",&s.voto);
	fwrite(&s,sizeof(s),1,pfile);
}

void print(FILE *pfile){
	studente st;
	fread(&st,sizeof(studente),1,pfile);
	printf("\nMatricola: %d\n",st.id);
	printf("Cognome: %s\n",st.cognome);
	printf("Nome: %s\n",st.nome);
	printf("Voto: %d\n",st.voto);
}

Questo era uno degli esercizi su file e strutture in C, nella prossima lezione ne proporrò degli altri.

Alcuni link utili

Indice argomenti linguaggio C

La funzione fopen

Funzione fscanf

Allocazione dinamica della memoria con malloc

Realizzare un menù di scelta in C

Strutture complesse in C

Come sommare gli elementi della cornice esterna

Insertion Sort in C

File di record con numeri random

File di record con numeri random

Ci eserciteremo oggi sui file di record con numeri random, per il momento con accesso sequenziale.

Anche in questa lezione riprenderemo le funzioni fread, fwrite, fopen e fclose che abbiamo già studiato nelle lezioni precedenti.

Riprendiamo l’esercizio della lezione precedente, introducendo un campo matricola che verrà assegnato random dal sistema in modo tale che sia unico.


Esempi di file di record con numeri random

Creare una struct studente che contiene la matricola, il nome, il cognome e il voto. Il campo matricola dovrà essere generato dal sistema come numero random ad esempio tra 1000 e 1999. Quindi inserire 10 studenti e memorizzarli in una tabella s di tipo studente. Infine copiare i dati in un file binario di nome archivi.txt.

Quindi creaimo un struttura studente e una tabella s che contiene 10 studenti. Generiamo dei numeri casuali con la funzione rand() in modo tale che non ci siano ripetizioni. Per evitare ripetizioni inserisco un altro ciclo for interno che scandisce con un indice j il vettore dall’inizio fino alla posizione in cui si è arrivati con l’indice i. Ovviamente ci possono essere altri metodi per evitare ripetizioni, provate a pensare una soluzione alternativa e inseritela pure nei commmenti sotto.

Stampiamo, solo per controllare i dati inseriti, il nostro vettore e poi ne inseriamo il contenuto nel file archivi.txt utilizzando la funzione fwrite.

Chiaramente prima il file deve essere aperto con la funzione fopen.

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

#define N 10

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

studente s[N];

int main(){
	int i,j;
	FILE *fp;

	for(i=0;i<N;i++) {
		s[i].id=rand()%1000+1000;
    	        for(j=0;j<i;j++) {
                    if(s[i].id==s[j].id){
                         i--;
                         break;
        	    }
    	        }
	
               printf("\nInserisci il nome:");
	       scanf("%s",s[i].nome);
	       printf("Inserisci il cognome:");
	       scanf("%s",s[i].cognome);
	       printf("Inserisci il voto:");
	       scanf("%d",&s[i].voto);
       }

       for(i=0;i<N;i++) {
		printf("%d %s %s %d\n",s[i].id, s[i].nome, s[i].cognome,s[i].voto);
       }
	if((fp=fopen("archivi.txt", "wb"))==NULL) {
		printf("Errore nell'apertura del file");
		exit(1);
	}
	
	fwrite(&s,sizeof(studente),N,fp);
	fclose(fp);
	
	return 0;
}

Realizziamo adesso un altro programma che legge un file binario archivi.txt come quello appena creato.

Apriamo il file binario in lettura con la funzione fopen, poi con la funzione fread leggiamo il nostro file binario stampando a video i valori.

Ecco dunque il listato completo:

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

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

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

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

	while(fread(&s, sizeof(studente),1, fp)>0)
		printf("%d\t%s\t%s\t%d\n",s.id,s.nome,s.cognome,s.voto);

	fclose(fp);
	
	return 0;
}

Ecco dunque alcuni esempi sui file di record con numeri random, andando avanti nel tutorial ne affronteremo degli altri.

In questi esercizi per il momento stiamo omettendo i controlli dell’input che in seguito faremo opportunamente.

Alcuni link utili

Indice argomenti linguaggio C

La funzione fopen

Funzione fscanf

Allocazione dinamica della memoria con malloc

Come sommare gli elementi della cornice esterna

Quick sort in C

Selection sort in C

Merge sort in C

Insertion Sort in C


File di record

File di record

Realizziamo alcuni esempi sui file di record, al fine di consolidare le funzioni sui file studiate finora. Faremo l’accesso in maniera sequenziale, mentre più avanti studieremo l’accesso diretto. Ricordiamo inoltre che sui file di record le operazioni vengono effettuate un record alla volta.

In modo particolare approfondiremo oggi le funzioni fread e fwrite per la lettura e scrittura sui file binari. Impareremo anche a scrivere il contenuto di un vettore di record su un file binario.

Esempi su file di record

Creare una struct studente che contiene il nome, il cognome e il voto. Dopo inserire 5 studenti e memorizzarli in una tabella s di tipo studente. Infine copiare i dati in un file binario di nome archivi.txt.

Quindi definiamo una struttura studente come descritta nel problema e creiamo la tabella s di tipo studente che conterrà 5 elementi.

Dopo con un semplice ciclo for inizializziamo la tabella s con i dati inseriti dall’utente. Visualizziamo anche il contenuto del record, semplicemente come prova dell’inserimento, non sarebbe infatti necessario. Poi apriamo il file binario archivi.txt in scrittura e controlliamo eventuali messaggi di errore.

Infine copiamo il contenuto del record nel file binario utilizzando la funzione fwrite.

Ecco dunque il listato completo:

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

#define N 2
typedef struct { 
	char nome[20];
	char cognome[20];
	int voto;
} studente;

studente s[N];

main(){
	int i;
	FILE *file;

	for(i=0;i<N;i++) {
		printf("\nInserisci il nome:");
		scanf("%s",s[i].nome);
		printf("Inserisci il cognome:");
		scanf("%s",s[i].cognome);
		printf("Inserisci il voto:");
		scanf("%d",&s[i].voto);
}

/*visualizzo il contenuto del record*/
	for(i=0;i<N;i++) {
		printf("%s %s %d\n",s[i].nome, s[i].cognome,s[i].voto );
}

	if((file=fopen("archivi.txt", "wb"))==NULL) {
		printf("Errore nell'apertura del file");
		exit(1);
	}
	
	fwrite(&s,sizeof(studente),N,file);
	fclose(file);
}

Adesso creiamo un altro programma per leggere il file binario appena creato, chiaramente si poteva integrare anche nell’esempio sopra, inserendo solo l’operazione di lettura.

Per leggere dal file binario utilizzo la funzione fread.

Allego quindi il listato completo:

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

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

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

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

	while(fread(&s, sizeof(studente),1, fp)>0)
		printf("%s\t%s\t%d\n",s.nome,s.cognome,s.voto);

	fclose(fp);
	
	return 0;
}

Nella prossima lezione approfondiremo ancora i file di record e altre funzioni sui file 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

Matrice trasposta

Quick sort in C

Selection sort in C

Merge sort in C

Insertion Sort in C