76 - Archivos binarios: identificar final de archivo (feof)


Hemos visto la función fread que nos permite recuperar datos de un archivo binario. Ahora veremos otra función disponible en stdio.h que nos permite luego de la ejecución de la función fread verificar si se ha llegado a fin de archivo:

int feof([nombre lógico del archivo])

Esta función devuelve 0 si no es fin de archivo y un valor distinto a 0 si se ha llegado al final de archivo.

Problema 1:

Confeccionar un programa con dos funciones:
1 - Creación de un archivo binario llamado "archivo4.dat" y almacenar valores enteros ingresados por teclado.
2 - Imprimir el archivo en forma completa.

Archivo: programa225.c

Ver video

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

void crearCargar()
{
    FILE *arch;
    arch=fopen("archivo4.dat","wb");
    if (arch==NULL)
        exit(1);
    int valor;
    do {
        printf("Ingrese valor entero (0 para finalizar):");
        scanf("%i",&valor);
        if (valor!=0)
            fwrite(&valor, sizeof(int), 1, arch);
    }  while (valor!=0);
    fclose(arch);
}

void imprimir()
{
    FILE *arch;
    arch=fopen("archivo4.dat","rb");
    if (arch==NULL)
        exit(1);
    printf("Todos los datos almacenados en el archivo.\n");
    int x;
    fread(&x, sizeof(int), 1, arch);
    while(!feof(arch))
    {
        printf("%i ",x);
        fread(&x, sizeof(int), 1, arch);
    }
    fclose(arch);
}


int main()
{
    crearCargar();
    imprimir();
    getch();
    return 0;
}

La primer función crea un archivo llamado "archivo4.dat" (si existe borra el anterior), luego entra en una estructura repetitiva para ingresar enteros por teclado y grabarlos en el archivo:

void crearCargar()
{
    FILE *arch;
    arch=fopen("archivo4.dat","wb");
    if (arch==NULL)
        exit(1);
    int valor;
    do {
        printf("Ingrese valor entero (0 para finalizar):");
        scanf("%i",&valor);
        if (valor!=0)
            fwrite(&valor, sizeof(int), 1, arch);
    }  while (valor!=0);
    fclose(arch);
}

Lo nuevo aparece en la función de impresión, no podemos disponer una estructura secuencial porque no sabemos cuantos enteros están almacenados en el archivo. Abrimos el archivo para lectura:

void imprimir()
{
    FILE *arch;
    arch=fopen("archivo4.dat","rb");

Procedemos a hacer la lectura del primer valor previo a la estructura repetitiva:

    int x;
    fread(&x, sizeof(int), 1, arch);

Luego de llamar a la función fread podemos llamar a la función feof (end of file) recordemos que esta función retorna 0 si no es final de archivo, esto nos permite disponer una estructura while que se repita mientra no se llega al final de archivo:

    while(!feof(arch))
    {
        printf("%i ",x);
        fread(&x, sizeof(int), 1, arch);
    }

El operador lógico "!" invierte el valor de la condición, es decir si feof retorna 0 luego el "!" lo convierte en "1" y con esto entra al while.

Dentro del while imprimimos el valor de la variable x y procedemos a leer del archivo el siguiente entero.

En algún momento cuando fread no puede leer más datos ya que se llegó al final de archivo la condición del while se verifica falso.

La llamada a la función fread previa al while y luego dentro del while se debe a que no podemos llamar a la función feof sin leer primero.

Problema propuesto

Solución

programa226.c

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

void crearCargar()
{
    FILE *arch;
    arch=fopen("archivo5.dat","wb");
    if (arch==NULL)
        exit(1);
    int final;
    printf("Grabar en el archivo los valores comprendidos entre 1 y:");
    scanf("%i",&final);
    int f;
    for (f=1;f<=final;f++)
       fwrite(&f, sizeof(int), 1, arch);
    fclose(arch);
}

void imprimir()
{
    FILE *arch;
    arch=fopen("archivo5.dat","rb");
    if (arch==NULL)
        exit(1);
    printf("Todos los datos almacenados en el archivo.\n");
    int x;
    fread(&x, sizeof(int), 1, arch);
    while(!feof(arch))
    {
        printf("%i ",x);
        fread(&x, sizeof(int), 1, arch);
    }
    fclose(arch);
}


int main()
{
    crearCargar();
    imprimir();
    getch();
    return 0;
}

Retornar