Universidad Simón Bolívar
Departamento de Computación
CI2126 Computación II  

Gabriela Ochoa

Lectura y Escritura en Archivos Secuenciales

La clase de hoy cubre la creación, lectura y escritura de archivos. Adicionalmente veremos como pasar argumentos desde la linea de comandos al programa. Un aspecto importante de cualquier programa, es su habilidad de comunicarse con el mundo exterior. La lectura de archivos con datos de entrada, y la escritura de archivos de salida con los resultados, consituye una manera simple pero efectiva de comunicación.

Funciones de Libreria para la Entrada y Salida (E/S) de Archivos

Existen rutinas para abrir y cerrar archivos, y para leer y escribir en ellos utilizando datos formateados, de manera similar a como se hace el formato de datos para entrada y salida en pantalla.

La función fopen se utiliza para abir un archivo, y asociarle una variable apuntador a archivo con la cual el programa puede referirse a la fuente del archivo. El prototipo de fopen es:

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

fopen retorna un apundador al archivo si la llamada fue exitosa, y sino, retorna NULL. El apundador al archivo se utiliza para indentificar la fuente del mismo, se pasa como parámetro a las rutinas de escritura, lectura y manejo del archivo. El filename y modo son cadenas de caracteres. Los modos válidos son:

Modo
Uso
r
Abre para lectura
w
Abre o crea para escritura. Descarta (destruye) cualquier contenido previo
a
Abre o crea para escritura. Agrega a (escribe despues de) cualquier contenido previo
r+
Abre para modificaciones (lectura y escritura)
w+
Abre o crea para modificacion. Descarta (destruye) cualquier contenido previo
a+
Abre o crea para modificacion. Agrega a cualquier contenido previo

Para declarar una variable de tipo apuntador a archivo:

#include <stdlib.h>

FILE *fp;

Ejemplo de apertura de un archivo:

fp = fopen("datos.txt","w");

La funcion fflush se usa para fÍsicamente escribir (bajar) en el archivo cualquier data almacenada en el "buffer" intermedio. Para hacer los programas mas eficientes y reducir las llamadas aL sistema, los archivos mantienen un buffer (memoria) intermedia, una vez que el buffer esta lleno, los datos se escriben en el archivo. La rutina fflush fuerza a que el buffer sea escrito en el archivo asociado. Su prototipo es:

int fflush(FILE *fp);

Recibe un apuntador a archivo como parámetro. Retorna cero si la llamada fue exitosa y EOF si no lo fue. EOF es una constante especial que denota que se ha llegado al final del archivo.

Para cerrar los archivos se utiliza la funcion fclose. Su prototipo es:

int fclose(FILE *fp);

Fclose retorna cero si fue exitosa y EOF si hubo alguna falla.

Para escribir datos en un archivo se utiliza la fprintf. Esta función es muy similar a printf, que ya sabemos manejar bien. La única diferencia es que fprintf tiene un argumento adicional, el apundador a archivo que especifica la fuente donde queremos escribir. Su prototipo es:

int fprintf(FILE *fp, const char* format, ....);

fprintf retorna el número de caracteres que fueron escritos exitosamente o un número negativo en caso de falla.

Para leer datos de un archivo se utiliza la función fscanf. Esta función es muy similar a scanf, que ya sabemos manejar bien. La única diferencia es que fscanf tiene un argumento adicional, el apundador a archivo que especifica la fuente de donde queremos leer. Recuerden que los argumentos para guardar datos deben ser apuntadores (i.e, llevan & en caso de ser variables simples, y solo el nombre en caso de ser arreglos de caracteres). Su prototipo es:

int fscanf(FILE *stream, const char* format, ....);

Ejemplo

El siguiente programa abre un archivo que contiene un nombre y cedula de indentidad. Luego abre un archivo de salida y escribe estos datos (pero en orden invertido). El archivo de entrada fue creado con un editor de texto.

Archivo de entrada: entrada.txt

Pedro 18878798

#include <stdio.h>

int main()
{ 
   char ifilename[] = "entrada.txt";
   char ofilename[] = "salida.txt";
   char name[30];
   int idNum;

   FILE *ofp, *ifp;                    /* Declara apuntadores a archivo */
   ifp = fopen(ifilename,"r");         /* Abre archivo de entrada */
   fscanf(ifp,"%s %d",name,&idNum); 	/* Lee datos de entrada */
   ofp = fopen(ofilename,"w");         /* Abre archivo de salida */
   fprintf(ofp,"%d %s\n",idNum, name); /* Escribe los datos */
   fclose(ifp); fclose(ofp);           /* Cierra los archivos */
   return 0;
} 
Archivo de salida: salida.txt

18878798 Pedro

Ejercicio de Practica

Extender el ejercicio anterior para que sea capaz de leer y escribir múltiples pares de nombres y cédulas. Sugerencia: Crear un ciclo y chequear cuando la rutina scanf retorna EOF.

Solucion:

#include <stdio.h>
int main(){
char ifilename[] = "c:/entrada.txt";
char ofilename[] = "c:/salida.txt";
char name[30];
int idNum;
FILE *ofp, *ifp;
ifp = fopen(ifilename,"r");   /* Abrir archivo entrada     */
ofp = fopen(ofilename,"w");   /* Abrir archivo salida      */
while (fscanf(ifp,"%s %d",name,&idNum) != EOF) {/*Leer datos */
     fprintf(ofp,"%d %s\n",idNum, name);   /* Escribir datos */
}
fclose(ifp); fclose(ofp);     /* Cerrar archivos */
return 0;

} 

Otras Rutinas Utiles

int fgetc(FILE *fp); Retorna el siguiente caracter del archivo referenciado por fp, o EOF si se ha llegado al final del archivo. El tipo de retorno es int en lugar de char, debido a que el caracter EOF debe ser manejado.

int *fgets(char *s, int n, FILE *fp); Retorna un apuntador a la cadena de caracteres leida si resulta exitoso, o NULL si se llega al final del archivo o si ocurre un error. La cadena es también almacenada en el arreglo de caracteres especificado como argumento. Un máximo de n-1 caracteres seran leídos. Lo cual da espacio para guardar el carácater de fin de cadena '\0'.

int fputs(const char s*, FILE *fp); Escribe una cadena de caracteres en el archivo, retorna EOF si hubo alguna falla.

int fputc(int c, FILE *fp); Escribe un caracter solo en el archivo, si hubo algun problema devuelve EOF.

int sprintf(char *buffer, const char *format, ...); Esta función es similar a fprintf, excepto que los datos son escritos en un arrreglo (o buffer) de caracteres en lugar de en un archivo de salida.

int sscanf(char *buffer, const char *format, ...); Esta función es similar a fscanf, excepto que los datos son leidos de un arrreglo (o buffer) de caracteres en lugar de un archivo de entrada.

Argumentos de Línea de Comando

C provee un mecanismo para pasar argumentos desde la línea de comandos al programa que se va a ejecutar. Cuando el programa comieza su ejecución, la rutina main es llamada con dos argumentos: un contador y un apuntador a un arreglo de cadenas de caracteres. El contador es llamdo por convención argc y el apuntador argv. El uso de de argv es un poco truculento. Dado que argv es un apundador a un arreglo de cadenas de caracteres, la primera cadena de caracteres es referenciada por argv[0] (o *argv). La segunda cadena is referenciada por argv[1] (o *(argv + 1)), la tercera por argv[2], y así sucesivamente. La primera cadena de caracteres, argv[0], contiene el nombre del programa. Los argumentos comienzan realmente con argv[1].

Un ejemplo de llamada de un programa llamado copia, que copie un archivo en otro archivo seria: copia fuente.txt destino.txt. Esto es, el nombre del programa mas dos argumentos que corresponderian a los nombres de los archivos fuente y destino.

Veamos un ejemplo que simplemente muestra los argumentos de un programa.

#include <stdio.h>

int main(int argc, char *argv[])
{
   int i;
   fprintf("The number of command line arguments is %d\n", argc);
   fprintf("The program name is %s\n",argv[0]);
   for (i = 1; i < argc; i++) {
      fprintf("%s",argv[i]);
   }
   fprintf("\n");
   return 0;
}

Referencias

Tutorial de Programación en C , conciso y bien escrito, con elances a muchos otros recursos para la programación en C y C ++.


Ir a Pagina del Curso