Está en la página 1de 27

Lenguaje de Programaciòn II

Ficheros

Objetivos:

• Manejar archivos en C mediante el concepto de flujo o canal.


• Realizar operaciones básicas de entrada y salida de archivos.

Contenido:
• Conceptos básicos.
• Flujos.
• Operaciones con archivos: abrir, cerrar, leer y escribir.

Presentado por: Ana Marìa Salgado Grillo.

1
Entrada/Salida con archivos
Todos los programas en C que hemos ejecutado hasta el momento requerían de ingreso de datos
por teclado para realizar determinadas tareas y luego mostrar resultados. Tales programas tienen
un gran defecto y es que los datos que se cargan desaparecen cuando el programa termina, por lo
tanto cada vez que se ejecuta el programa hay que cargar los datos nuevamente.

Para solucionar este problema debería de existir una forma de almacenar los datos que se ingresan
en un archivo que se almacena en el disco duro o memoria flash de forma de disponer de la
información en cualquier momento.

Desde el punto de vista informático un archivo es un conjunto de información que almacenamos


en un soporte magnético para poder manipularlo en cualquier momento.

Flujo
Un flujo (stream) es una abstracción que se refiere a un flujo o corriente de datos que fluyen entre
un origen o fuente (productor) y un destino o sumidero (consumidor). Entre el origen y el destino
debe existir una conexión o canal por la cual circulen los datos. La apertura de un archivo supone
establecer la conexión del programa con el dispositivo que contiene al archivo.

Hay tres flujos o canales abiertos automáticamente:


extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;

Estas tres variables se inicializan al comenzar la ejecución del programa y todas ellas admiten
secuencias de caracteres en modo texto. Tienen el siguiente cometido:
stdin asocia la entrada estándar (teclado) con el programa.
stdout asocia la salida estándar (pantalla) con el programa.
stderr asocia la salida de mensajes de error (pantalla) con el programa.

El acceso a los archivos se hace con un buffer intermedio. Se puede pensar en el buffer como un
array donde se van almacenando los datos dirigidos al archivo, o desde el archivo; el buffer se
vuelca cuando de una forma u otra se da la orden de vaciarlo.

2
Por ejemplo, cuando se llama a una función para leer del archivo una cadena, la función lee tantos
caracteres como quepan en el buffer. Luego, la primera cadena del buffer es la que se obtiene; una
siguiente llamada a la función obtendrá la siguiente cadena del buffer, así hasta que se quede vacío
y sea llenado con una posterior llamada a la función de lectura.

Los pasos fundamentales a la hora de operar con ficheros son los siguientes:

1. Declarar una variable tipo flujo, que representará el fichero.


2. Abrir el fichero y asociar la variable con ese fichero.
3. Leer/Escribir en el fichero.
4. Cerrar el fichero.

Pasaremos a describir cada uno de los pasos más detalladamente

Variables de flujo
La librería estándar de C tiene definido un tipo de datos, FILE * que representa un flujo de bytes.
Asociado a este flujo puede estar un archivo, una posición de memoria, el teclado, etc... La
declaración:

FILE *fich;

Declara que la variable fich representará un flujo de datos, que luego asociaremos.

Abrir el fichero
Una vez que tenemos declarada una variable de tipo FILE * tenemos que asociarla con el fichero
que queremos abrir. Esto se hace mediante la llamada fopen.

fopen admite varios modos de apertura de ficheros. Si quisiéramos abrir el fichero para lectura
(esto es, leer los datos que contiene y no modificarlo), utilizaríamos fopen de la siguiente
manera:

fich = fopen( "fichero.txt", "r" );

Si en cambio quisiéramos crear un nuevo fichero haríamos lo siguiente:


fich = fopen( "fichero.txt", "w" );

Por último es posible que necesitemos añadir datos al final de un fichero ya existente:
fich = fopen( "fichero.txt", "a" );

3
Leer y escribir en un fichero
Lectura

Leer un archivo que tenga un formato determinado es una tarea fácil utilizando la rutina fscanf,
que funciona de forma análoga a scanf.

Supongamos que queremos leer una línea del fichero notas.txt que contiene un listado de notas
de alumnos con el siguiente formato:

Nombre Apellido1 Apellido2 notaParcial1 NotaParcial2

El código que realizaría esta lectura sería el siguiente:


//fscanf1.c

#include <stdio.h>
int main(void)
{
int c, n = 0;
FILE *fich;
char nombre[10], apellido1[10], apellido2[10];
float nota1,nota2;

if((fich=fopen("notas.txt", "r")) == NULL)


{
puts("ERROR EN LA OPERACION DE APERTURA");
return 1;
}

fscanf( fich, "%s %s %s %f %f\n", nombre, apellido1,apellido2,&nota1,&nota2 );


printf("Los datos leidos son:\n");
printf("%s %s %s %f %f\n",nombre, apellido1,apellido2,nota1,nota2);
fclose(fich);
return 0;
}

Contenido de notas.txt

4
Una necesidad común a la hora de leer de un archivo consiste en saber cuándo hemos llegado al
final del archivo. Esto se realiza con la rutina feof(), que devuelve un valor distinto de cero cuando
hemos llegado al final del archivo.

Otra opción a la hora de leer de un archivo es leer un número determinado de caracteres y


almacenarlos en un buffer para posterior proceso. Esto se puede realizar con la rutina fgets.

Escritura

Para escribir sobre un archivo tenemos disponibles las siguientes primitivas:

• fprintf: Escritura con formato. Funcionamiento similar a printf


• fputs: Escribe un buffer de caracteres en archivo especificado

Cerrar el fichero
Una vez que hemos terminado de operar con el fichero hay que realizar una operación de cierre
sobre la variable asociada, utilizando la rutina fclose(). Una vez que hemos cerrado un fichero
no podremos realizar ninguna operación de lectura/escritura sin antes volver a abrirlo.

Funciones para el manejo de ficheros

fopen
FILE *fopen(const char *nombre_fichero, const char *modo);

Abre el fichero de nombre ``nombre_fichero'', lo asocia con un flujo de datos y devuelve un


puntero al mismo. Si falla la llamada, devuelve un puntero nulo. Algunos de los caracteres
iniciales de ``modo'' son:
r Solo lectura
w Escritura desde el comienzo del archivo (Crearlo también)
a Escritura añadida al final del archivo.
r+ Lectura y escritura
w+ Escritura y lectura

fclose
int fclose(FILE *flujo);

5
Cierra el fichero asociado con ``flujo''. Devuelve 0 en caso de éxito y EOF (end of file) en caso
contrario.

fgetc
int fgetc(FILE *flujo);

Lee el siguiente carácter por ``flujo'', avanza el indicador de posición y devuelve int. Devuelve
EOF si pone a 1 el indicador de fin de fichero o el de error.

fgets
char *fgets(char *s, int n, FILE *flujo);

Lee caracteres por ``flujo'' y los almacena en elementos sucesivos del ``array'' que comienza en
``s'', continuando hasta que almacene ``n-1'' caracteres, almacene un carácter del nueva línea o
ponga a 1 los indicadores de error o de fin de fichero.

fputc
int fputc(int c, FILE *flujo);

Escribe el carácter c por ``flujo'', avanza el indicador de posición del fichero y devuelve int c .
En caso de error devuelve EOF.

fputs
int fputs(const char *s, FILE *flujo);

Escribe los caracteres de la cadena s por ``flujo''. No escribe el carácter nulo de terminación. En
caso de éxito, devuelve un valor no negativo; en caso de error devuelve EOF.

fscanf
int fscanf(FILE *flujo, const char *formato, ...);

Lee texto y convierte a la representación interna según el formato especificado en formato.


Devuelve el número de entradas emparejadas y asignadas, o EOF si no se almacenan valores antes
de que se active el indicador de error o de fin de fichero.

6
fprintf
int fprintf(FILE *flujo, const char *formato, ...);

Genera texto formateado, bajo el control de formato formato y escribe los caracteres generados
por flujo. Devuelve el número de caracteres generados o un valor negativo en caso de error.
A modo de resumen estas son las especificaciones de formato más comunes:
Formato Descripción
%d Entero con signo
%u Entero sin signo
%c Caracter
%s Puntero a cadena de caracteres

función feof(archivo)

Permite saber si el puntero está al final o no del archivo, esta devuelve el resultado 0 si
se encuentra en el final de archivo o #0 si se encuentra en cualquier otra parte del mismo.

fwrite
size_t fwrite(const void *buffer, size_t n, size_t c, FILE *flujo);

La rutina fwrite permite escribir c elementos de longitud n bytes almacenados en el buffer


apuntado por ``flujo''

fread
size_t fread(const void *buffer, size_t n, size_t c, FILE *flujo);

La rutina fread permite leer c elementos de longitud n bytes del fichero apuntado por ``flujo'' y
los almacena en el buffer especificado.
7
Acceso aleatorio:
❖ ftell( ) : Permite obtener la posición en el fichero del puntero de L/E
❖ rewind( ): Coloca el localizador de posición del archivo al principio del mismo.

❖ fseek:

int fseek(FILE *fp, long num_bytes, int origen);


establece el localizador de posicion en un byte especifico
num_byte : numero de bytes desde el origen a alcanzar la nueva
posicion

origen :
comienzo del archivo SEEK_SET 0
posicion actual SEEK_CUR 1
fin de archivo SEEK_END 2

#include <stdio.h>
#define SIZE 20
main()
{
FILE *fp;
char ch;

if((fp = fopen("texto", "rb")) == NULL){


puts("Error en apertura de archivo");
exit(1);
}
fseek(fp, SIZE, 0);
ch = getc(fp);
putchar(ch);
fclose(fp);
}

Detección de errores:

❖ ferror( ): Verifica si se ha producido un error en las operaciones con ficheros.


int ferror(FILE *pf);
Devuelve un cero si no hay error o un valor diferente de cero si hay error.
❖ clearerr( ): Pone a 0 los bits de error que estén a 1, incluido el bit de fin de fichero, en el
miembro flag de la estrutura FILE.
void clearerr(FILE *pf);

8
Ejemplo:
if(ferror(pf))
{
printf(“Error: No se puede realizar la operación sobre el archivo”);
clearerr(pf);
}

❖ perror( ): Permite escribir en la salida estándar de mensajes de error (stderr), el mensaje


que especifique el programador, seguido de dos puntos, seguidos del mensaje de error
dado por el sistema, terminado con ‘\n’

Si en el siguiente fragmento de código en C no se puede abrir el archivo datos.txt


if((pf = fopen(“a:\\datos.txt”,”r”)) = = NULL)
{
perror(“No se puede abrir el fichero”);
exit(1);
}

Se obtiene como salida:

No se puede abrir el fichero: No such file o directory

El mensaje en inglés se corresponde al código de error número 2

EJERCICIOS:

fputc()

Se desea crear un archivo SALIDA.TXT con los caracteres introducidos por teclado.
Una vez abierto el archivo, un bucle while no sea fin de archivo(macro EOF) lee
carácter a carácter y se escribe en el archivo asociado al puntero FILE.

//fputc1.c

#include <stdio.h>
int main()
{
int c;
FILE *pf;
char salida[] = "SALIDA.TXT";

9
if((pf=fopen(salida,"w")) == NULL)
{
puts("ERROR EN LA OPERACION DE APERTURA");
return 1;
}

printf("Introduzca texto. Termine con Ctrl+z\n");


while((c=getchar())!=EOF)
{
fputc(c,pf);
}

fclose(pf);
return 0;
}

fgetc() :

El archivo SALIDA.TXT creado en el problema anterior, se desea leer para mostrarlo


por pantalla y contar las líneas que tiene.
Una vez abierto el archivo de texto en modo lectura, un bucle mientras no sea fin de
fichero(macro EOF) lee carácter a carácter y se escribe en pantalla. En el caso de leer el
carácter de fin de línea se debe saltar a la línea siguiente y contabilizar una línea más.

//fgetc1.c

#include <stdio.h>
int main(void)
{
int c, n = 0;
FILE *pf;
char nombre[]="SALIDA.TXT";

if((pf=fopen(nombre,"r")) == NULL)
{
puts("ERROR EN LA OPERACION DE APERTURA");
return 1;
}

10
while((c=fgetc(pf))!=EOF)
{
if(c == '\n')
{
n++;
printf("\n");
}
else
putchar(c);
}

printf("\nNumero de lineas del archivo: %d",n);


fclose(pf);
return 0;

Otro ejemplo de fputc:

Lee una línea de texto en minúscula y la almacena en mayúscula en un archivo de datos.

//fputc2.c

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

void main(void)
{
FILE *fpt;
char c;

fpt=fopen("muestra.dat","w");

printf("Introduzca una linea de texto en minusculas.\n");


printf("Para terminar presione ENTER\n");

do
fputc(toupper(c=getchar() ),fpt);
while(c!='\n');

fclose(fpt);
}
11
El siguiente programa lee una línea de texto del archivo muestra.dat, carácter a
carácter y muestra el texto en la pantalla.

//fgetc2.c

#include <stdio.h>
void main(void)
{
FILE *fpt;
char c;

if((fpt=fopen("muestra.dat","r")) == NULL)
printf("\nError - No se puede abrir el archivo indicado\n");
else
do
putchar(c=fgetc(fpt));
while(c!='\n');
fclose(fpt);
}

Ejemplo de fgets y fputs

Este programa copia el contenido de un fichero de texto en otro fichero con nombre distinto. El
programa pedirá en primer lugar el nombre de un fichero ya existente; una vez introducido dicho
nombre pedirá otro nombre que será el del nuevo fichero donde irá la copia. Con estos datos, el
programa realizará una copia del texto contenido en el primer fichero en otro fichero con el segundo
nombre en el mismo directorio.

Nota: La resolución del problema es muy sencilla: basta con abrir dos ficheros: uno de lectura y
otro de escritura, que contengan respectivamente el fichero original y el fichero copia. Una vez
abiertos estos ficheros, se leen las cadenas del fichero original y se copian en el fichero copia., Para
ello se emplea el bucle while.

/* fichero copiar.c */
#include <stdio.h>
#include <stdlib.h>
//fgets1.c

void main()
{
char ch[80];
char file1[13], file2[13];
12
FILE *f1, *f2;

printf("Teclea el nombre de fichero original:");


scanf("%s", &file1);
printf("\ny ahora el nombre de fichero de copia:\n");
scanf("%s", &file2);
f1 = fopen(file1, "r");
f2 = fopen(file2, "w");
if(!f1)
printf("Fichero %s no existe!!", file1);
else
while ((fgets(ch,80,f1)) != NULL)
fputs(ch,f2);
fclose(f1);
fclose(f2);
}

El mismo ejemplo anterior pero ahora con añadir:

//fgets2.c
#include <stdio.h>
#include <stdlib.h>
void main()
{
char ch[80];
char file1[13], file2[13];
FILE *f1, *f2;

printf("Teclea el nombre de fichero original:");


scanf("%s", &file1);
printf("\ny ahora el nombre de fichero de copia:\n");
scanf("%s", &file2);
f1 = fopen(file1, "r");

f2 = fopen(file2, "a");
if(!f1)
printf("Fichero %s no existe!!", file1);
else
while ((fgets(ch,80,f1)) != NULL)
fputs(ch,f2);
fclose(f1);
fclose(f2);
}
13
Ejemplo de fprintf:

//fprintf1.c
#include <stdio.h>

int main(void)
{
int cuenta;
char nombre[30];
float saldo;
FILE *cfptr;

if((cfptr = fopen("clients.txt","w")) == NULL)


printf("El archivo no pudo ser abierto\n");

else
{
printf("Introduzca el numero de cuenta, nombre y saldo en una sola linea.\n");
printf("Introduzca EOF para terminar de introducir los datos\n");
scanf("%d %s %f",&cuenta, nombre, &saldo);

while(!feof(stdin))
{
fprintf(cfptr,"%d %s %.2f\n",cuenta, nombre, saldo);
scanf("%d %s %f",&cuenta, nombre, &saldo);
}

fclose(cfptr);
}
return 0;
}

Ejemplo de fscanf:
//fscanf1.c

#include <stdio.h>

int main(void)
{
int cuenta;
char nombre[30];
float saldo;
FILE *cfptr;
14
if((cfptr = fopen("clients.txt","r")) == NULL)
printf("El archivo no pudo ser abierto\n");
else
{
printf("%-10s %-13s %s\n","Cuenta","Nombre","Saldo");
fscanf(cfptr,"%d %s %f",&cuenta, nombre, &saldo);

while(!feof(cfptr))
{
printf("%-10d %-13s %7.2f\n",cuenta, nombre, saldo);
fscanf(cfptr,"%d %s %f",&cuenta, nombre, &saldo);
}
fclose(cfptr);
}
return 0;
}

OTRO EJEMPLO DE FPRINTF:

Este programa crea un archivo para una serie de registros de cliente. La estrategia
general será dar la fecha actual y entrar en un bucle que procesará una serie de registros
de cliente. Para cada cliente se leerá el nombre del cliente, la calle, la ciudad, el número
de cuenta, el saldo inicial(anteriorsaldo), el pago realizado y el saldo actual. A
continuación la fecha actual se asigna a ultimopago. Cada registro de cliente se escribirá
en un archivo de sólo escritura llamado registro.txt. El proceso continuará hasta que el
nombre de un cliente comience con los caracteres FIN(tanto en mayúscula como en
minúscula). Cuando se encuentre FIN, se escribirá en el archivo de datos indicando una
condición de fin de archivo.

//fprintf2.c

#include <stdio.h>
#include <string.h>
#define CIERTO 1

/*crear un archivo de datos conteniendo registros de clientes*/


struct fecha
{
int mes;
int dia;
int anno;
};

15
typedef struct
{
char nombre[80];
char calle[80];
char ciudad[80];
int cuen_no; /*entero positivo */
char cuen_tipo; /*C(al día), O(retrasada), M(Moroso) */
float anteriorsaldo; /* cantidad no negativa */
float pago; /*cantidad no negativa*/
float nuevosaldo; /* cantidad no negativa */
struct fecha ultimopago;
}registro;

FILE *fpt;

int main(void)
{
int indicador=CIERTO;
registro cliente;
registro leerpantalla(registro cliente);
void escribirarchivo(registro cliente);

/*abrir un archivo nuevo solo para escritura */


fpt = fopen("registro.txt","w");

/* introducir datos y asignar valores iniciales */


printf("SISTEMAS DE CUENTAS DE CLIENTES - INICIALIZACION \n\n");
printf("Introduzca la fecha actual (mm/dd/aaaa):");
scanf("%d/%d/%d",&cliente.ultimopago.mes, &cliente.ultimopago.dia,
&cliente.ultimopago.anno);

/*bucle principal*/
while(indicador)
{
/* introducir el nombre del cliente y escribirlo en el archivo */
fflush(stdin);
printf("\nNombre(introducir FIN para terminar):");
scanf("%[^\n]",cliente.nombre);
fprintf(fpt,"\n%s\n",cliente.nombre);
/*comprobacion de condicion de parada */
if(strcmpi(cliente.nombre,"FIN") == 0)
break;

cliente=leerpantalla(cliente);
16
escribirarchivo(cliente);
}
fclose(fpt);
return 0;
}

registro leerpantalla(registro cliente) /* leer el resto de los datos */


{
fflush(stdin);
printf("Calle: ");
scanf("%[^\n]",cliente.calle);
fflush(stdin);
printf("Ciudad: ");
scanf("%[^\n]",cliente.ciudad);
fflush(stdin);
printf("Cuenta numero: ");
scanf("%d",&cliente.cuen_no);
fflush(stdin);
printf("Tipo de cuenta: C(al dIa), O(retrasada), M(Moroso): ");
fflush(stdin);
cliente.cuen_tipo = getchar();
printf("Saldo actual:");
scanf("%f",&cliente.anteriorsaldo);
printf("Abono:");
scanf("%f",&cliente.pago);
cliente.nuevosaldo = cliente.anteriorsaldo - cliente.pago;
return(cliente);
}

void escribirarchivo(registro cliente) /* escribir el resto de los datos al archivo*/


{
fprintf(fpt,"%s\n",cliente.calle);
fprintf(fpt,"%s\n",cliente.ciudad);
fprintf(fpt,"%d\n",cliente.cuen_no);
fprintf(fpt,"%c\n",cliente.cuen_tipo);
fprintf(fpt,"%.2f\n",cliente.anteriorsaldo);
fprintf(fpt,"%.2f\n",cliente.pago );
fprintf(fpt,"%.2f\n",cliente.nuevosaldo);
fprintf(fpt,"%d/%d/%d\n",cliente.ultimopago.mes, cliente.ultimopago.dia,
cliente.ultimopago.anno);
return;
}

17
Ejercicio con fwrite

/*** Escribir datos en un fichero registro a registro ***/


/* fwrite.c
*/
#include <stdio.h>
#include <stdlib.h>

typedef struct
{
int numcuenta;
char nombre[40];
char apellido[40];
float saldo;
} registro; // tipo registro

int existe(char *nombreFichero);


void crearFichero(char *nombreFichero);

main()
{
char nombreFichero[30]; // nombre del fichero
char resp = 's';

// Solicitar el nombre del fichero


printf("Nombre del fichero: ");
gets(nombreFichero);

// Verificar si el fichero existe


if (existe(nombreFichero))
{
printf("El fichero existe ¿desea sobrescribirlo? (s/n) ");
resp = getchar();
fflush(stdin);
}
if (resp == 's')
{
crearFichero(nombreFichero);
}
}

18
int existe(char *nombreFichero)
{
FILE *pf = NULL;
// Verificar si el fichero existe
int exis = 0; // no existe
if ((pf = fopen(nombreFichero, "r")) != NULL)
{
exis = 1; // existe
fclose(pf);
}
return exis;
}

void crearFichero(char *nombreFichero)


{
FILE *pf = NULL; // identificador del fichero
registro reg; // definir un registro
char resp;
char saldo[10];

// Abrir el fichero nombreFichero para escribir "w"


if ((pf = fopen(nombreFichero, "w")) == NULL)
{
printf("El fichero no puede abrirse.");
exit(1);
}

// Leer datos de la entrada estándar y escribirlos en el fichero


do
{
printf("Numero de cuenta: ");
scanf("%d",&reg.numcuenta);
fflush(stdin);
printf("nombre: "); gets(reg.nombre);
fflush(stdin);
printf("apellido: "); gets(reg.apellido);
fflush(stdin);
printf("saldo: "); gets(saldo);
reg.saldo=atof(saldo);
fflush(stdin);

19
// Almacenar un registro en el fichero
fwrite(&reg, sizeof(reg), 1, pf);
if (ferror(pf))
{
perror("Error durante la escritura");
exit(2);
}

printf("¿desea escribir otro registro? (s/n) ");


resp = getchar();
fflush(stdin);
}
while (resp == 's');
}

Ejercicio con fseek


/**************** Acceso aleatorio a un fichero ****************/
/* fseek2.c
*/
#include <stdio.h>
#include <stdlib.h>

typedef struct
{
int numcuenta;
char nombre[40];
char apellido[40];
float saldo;
} registro; // tipo registro

void mostrarReg(FILE *pf, int numcuenta);


void modificarReg(FILE *pf, int numcuenta);

main()
{
FILE *pf = NULL; // puntero a un flujo
int totalreg = 0; // número total de registros
int nreg = 0; // número de registro
char nombreFichero[30]; // nombre del fichero
int c = 0, respuesta = 0;

20
// Solicitar el nombre del fichero
printf("Nombre del fichero: ");
gets(nombreFichero);

// Abrir el fichero para leer y escribir "r+"


if ((pf = fopen(nombreFichero, "r+")) == NULL)
{
printf("Error: no se puede abrir el fichero\n");
exit(1);
}

// Calcular el nº total de registros del fichero


fseek(pf, 0L, SEEK_END);
totalreg = (int)ftell(pf)/sizeof(registro);

// Presentar un registro en pantalla y modificarlo si procede


do
{
printf("Nº cuenta entre 1 y %d (0 para salir): ", totalreg);
c = scanf("%d", &nreg);
fflush(stdin);
if (c && (nreg >= 1) && (nreg <= totalreg))
{
mostrarReg(pf, nreg);
// Preguntar si se desea modificar el registro seleccionado
do
{
printf ("¿Desea modificar este registro? (s/n) ");
respuesta = getchar();
fflush(stdin);
}
while (tolower(respuesta != 's') && tolower(respuesta) != 'n');

if (respuesta == 's')
modificarReg(pf, nreg);
}
}
while (nreg);
fclose(pf);
}

void mostrarReg(FILE *pf, int nreg)


{
long desp = 0; // desplazamiento en bytes
21
registro reg; // variable de tipo registro
int bytesPorReg = sizeof(registro);

// Visualizar un registro
desp = (long)(nreg - 1) * bytesPorReg;
fseek(pf, desp, SEEK_SET);
fread(&reg, bytesPorReg, 1, pf);
if (ferror(pf))
{
printf("Error al leer un registro del fichero.\n");
return;
}
printf("Numero de cuenta: %d\n", reg.numcuenta);
printf("Nombre: %s\n", reg.nombre);
printf("Apellido: %s\n\n", reg.apellido);
printf("Saldo: %f\n",reg.saldo);
}

void modificarReg(FILE *pf, int numcuenta)


{
long desp = 0; // desplazamiento en bytes
registro reg; // variable de tipo registro
int bytesPorReg = sizeof(registro);
fflush(stdin);
printf("Numero de cuenta: ");
scanf("%d",&reg.numcuenta);
fflush(stdin);
printf("Nombre: "); gets(reg.nombre);
fflush(stdin);
printf("Apellido: "); gets(reg.apellido);
fflush(stdin);
printf("Saldo: ");
scanf("%f",&reg.saldo);

// Escribir un registro en el fichero


fseek(pf, -bytesPorReg, SEEK_CUR);
fwrite (&reg, bytesPorReg, 1, pf);
if (ferror(pf))
{
printf("Error al escribir un registro en el fichero.\n");
return;
}
}

22
Archivos temporales

Además de las funciones de procesamiento de archivos estudiadas, la biblioteca estándar


también tiene la función tmpfile, que abre un archivo temporal en modo “wb+”. Este fichero
es automáticamente borrado cuando el fichero es cerrado o cuando el programa termina
normalmente. Aunque este es un modo de archivo binario, algunos sistemas procesan los
archivos temporales como archivos de texto. Un archivo temporal es aquel que se crea durante
la ejecución del programa y se destruye, como muy tarde, al finalizar la ejecución del mismo.
Existe sólo hasta que es cerrado con fclose(), o bien hasta que el programa termina.

#include <stdio.h>
FILE *tmpfile(void);

La función tmpfile devuelve un puntero al fichero temporal creado o un puntero nulo si no es


posible crearlo. Por ejemplo:

FILE *pf;
if((pf = tmpfile() ) = = NULL)
printf(“No se puede crear un fichero temporal\n”);

El siguiente programa sustituye los tabuladores existentes en un archivo por espacios. El


programa solicita al usuario que escriba el nombre del archivo a modificarse. Si tanto el archivo
escrito por el usuario como el archivo temporal son abiertos con éxito, el programa lee
caracteres del archivo a modificarse, y los escribe en el archivo temporal. Si el carácter leído
es un tabulador , será reemplazado por un espacio y será escrito al archivo temporal. Cuando
se llegue al fin del archivo bajo modificación, utilizando rewind los apuntadores de archivo
para cada archivo serán reposicionados al principio de cada uno. A continuación, el archivo
temporal se copia al archivo original, carácter por carácter. Con el fin de confirmar que los
caracteres escritos son correctos, el programa imprime el archivo original conforme copia
caracteres al archivo temporal, así como imprime el nuevo archivo conforme copia caracteres
del archivo temporal al archivo original.

//temporal.c
/*Usando archivos temporales */

#include <stdio.h>
void main(void)
{
FILE *filePtr, *tempFilePtr;
int c;
char fileName[30];
printf("Este programa cambia los tabuladores a espacios en blanco.\n");
printf("Introduzca un nombre de archivo a ser modificado:");

23
scanf("%s",fileName);

if((filePtr=fopen(fileName,"r+"))!=NULL)
if((tempFilePtr=tmpfile() )!=NULL)
{
printf("\nEl archivo antes de la modificacion es:\n");
while((c=fgetc(filePtr)) !=EOF)
{
putchar(c);
fputc(c=='\t' ? ' ':c,tempFilePtr);
}
rewind(tempFilePtr);
rewind(filePtr);
printf("\nEl archivo después de la modificacion es:\n");
while((c=fgetc(tempFilePtr))!=EOF)
{
putchar(c);
fputc(c,filePtr);
}
}
else
printf("No se puede abrir el archivo temporal\n");
else
printf("No se puede abrir %s\n",fileName);
}

Salida:

24
Ejercicios propuestos

1. Hacer un programa que lea n líneas de texto de un fichero, cuente las vocales de cada línea
e imprima el número de la línea y el número de vocales que tiene.

2. Escribir un programa que genere un archivo conteniendo la lista de países y sus


correspondientes capitales. Colocar el nombre de cada país y su capital correspondiente en una
estructura. Tratar cada estructura como un registro separado. Ejecutar el programa creando un
archivo para usarlo en el siguiente problema. Use fwrite() o fread().

3. Escribir un programa interactivo en C, guiado por menús, que acceda al archivo generado
en el problema anterior y permita ejecutar una de las siguientes operaciones:
❖ Determinar la capital de un país especificado.
❖ Determinar el país cuya capital se especifica.
❖ Terminar la computación.

4. Escriba un programa para concatenar archivos. Los nombres de los archivos han de estar
en la línea de órdenes, el nuevo archivo resultante de la concatenación ha de ser el último
argumento de la línea de órdenes. El número mínimo de argumentos ha de ser 4: nombre del
programa ejecutable, primer archivo, segundo archivo y el archivo nuevo. El programa debe de
comprobar este hecho. Para copiar un archivo se usa la función fgets() que lee una línea del archivo
de entrada, y la función fputs() que escribe la línea en el archivo de salida. En una función
copia_archivo(), se realiza la operación de copia.

5. Los estudiantes de una clase consiguieron las siguientes puntuaciones en 6 exámenes de un


curso de Programación en C:

Nombre Puntuación

López Juan 45 80 80 95 55 75
Sánchez Carlos 60 50 70 75 55 80
Aráuz Eugenia 40 30 10 45 60 55
Gómez Marcio 0 5 5 0 10 5
Centeno Pedro 90 85 100 95 90 90
Zapata Sandra 95 90 80 95 85 80

a) Escribir un programa que genere un archivo conteniendo las notas de exámenes de los
estudiantes presentados. Cada componente del archivo será una estructura que contenga el
nombre y las notas de los exámenes para un estudiante. Utilice la función fprintf( ) para
escribir datos en el archivo. Ejecutar el programa para usar dicho fichero en el siguiente
inciso.

25
b) Escribir un programa orientado a archivo que procese las notas de exámenes dadas . Leer
los datos del archivo creado en el problema anterior haciendo uso de la función fscanf( ).
Crear un informe que contenga el nombre, las notas de los exámenes y la media de ellas
para cada estudiante. Escribir la salida en un fichero nuevo.

6. Para el sector de ventas de una empresa se necesita realizar un programa con las
siguientes características
En el archivo producto.dat se deben guardar todos los productos que existen para la venta y los
datos que se ingresan para cada producto son los siguientes:
Código de artículo 6 caracteres de longitud y el primer carácter debe ser X
Descripción Puede tener un máximo de 20 caracteres
Precio Precio del producto
Cantidad Cantidad en existencia del producto

En el archivo ventas.dat se deben guardar las ventas realizadas y los datos que se guardan en este
archivo son:
Código de artículo
Cantidad vendida
Fecha de venta

El programa debe contar con un menú de opciones que tenga Carga de productos, Venta de
productos y Salir del programa

Carga de productos: Se ingresan los datos relativos a cada producto y se guarda en el archivo
producto.dat , si el código ya existe en el archivo se debe informar al usuario y no se debe guardar
y si el código no existe se debe agregar al final. Todos los datos ingresados deben ser validados
por funciones.

Venta de productos: Se ingresa el código de producto que se desea vender y la cantidad a vender.
Se busca el código en el archivo producto.dat y si la cantidad existente es suficiente se realiza la
venta escribiendo en el archivo ventas.dat el código , la cantidad vendida y la fecha. Por otra parte
se debe actualizar la cantidad existente en el archivo producto.dat.
Si la cantidad en existencia es insuficiente se debe mostrar un mensaje de error y no se realizará
la venta.

26
Bibliografía:

✓ Ceballos Francisco Javier. Curso de Programación C/C++. Tercera Edición. Madrid.


Editorial RAMA, 2007.

✓ Cairó Osvaldo. Fundamentos de programación. Piensa en C. Primera edición. México.


Pearson, Prentice Hall. 2006.

✓ Joyanes Aguilar Luis, Zahonero Martínez Ignacio. Programación en C. Metodología,


algoritmos y estructura de datos. Segunda edición. España. Mc Graw Hill. 2005.

✓ Gottfried Byron S. Programación en C. Primera edición. México. McGraw Hill.1991.

✓ Deitel H.M., Deitel P. J. Cómo Programar en C/C++ y Java. Cuarta Edición. México.
Prentice Hall. 2004.

27

También podría gustarte