UC3M

Grado en Ing. Telemática/Sist. Audiovisuales/Sist. de Comunicaciones

Arquitectura de Sistemas

Septiembre 2015 - Enero 2016

Operaciones de entrada/salida sobre fichero

Actividades previas

1. Convirtiendo (y copiando) un fichero a mayúsculas

Recursos

Plan de trabajo

  • Para leer de un fichero un número determinado de bytes existe la función fread: size_t fread(void *ptr, size_t tam, size_t nmiemb, FILE *flujo);. Esta función lee nmiemb elementos de datos, cada uno de tamaño tam bytes de largo, del flujo de datos apuntado por flujo, almacenándolos en el sitio apuntado por ptr.

    La función fread devuelve, si no ha ocurrido ningún error, el número de elementos leídos. Si ocurre un error o si se llega al final de fichero, devuelve el valor 0.

    Como la función fread no distingue entre estas dos circunstancias, se deberá usar la función feof() o la función ferror() para determinar qué ha ocurrido.

  • La función feof: int feof( FILE *flujo); inspecciona el indicador de fin-de-fichero para el flujo indicado por flujo, devolviendo no cero si está activado.

  • La función inversa a fread es la función fwrite: size_t fwrite( const void *ptr, size_t tam, size_t nmiemb, FILE *flujo);

    Esta función escribe nmiemb elementos de datos, cada uno de tamaño tam bytes de largo, al flujo de datos apuntado por flujo, obteniéndolos del sitio apuntado por ptr.

    La función fwrite devuelve, si no ha ocurrido ningún error, el número de bytes escritos. La función fwrite() devuelve un valor menor que nmiemb sólo si un ha ocurrido un error de escritura.

  • La función toupper convierte un carácter en su representación en mayúsculas: int toupper (int c);. El valor devuelto es el carácter c convertido a mayúsculas o c si no se pudo convertir. Esta función está incluida en la biblioteca ctype.h.

  1. Escribe un programa con nombre convert_to_uppercase.c que realice las siguientes:

    1. Compruebe que el programa se ejecuta con dos argumentos. En caso de que no sea así, imprime un mensaje y termina.

    2. Abre para lectura el fichero cuyo nombre es la cadena pasada como primer argumento. Si la operación falla, notificar mediante un mensaje y terminar la ejecución.

    3. Abre para escritura el fichero cuyo nombre es la cadena pasada como segundo argumento. Si la operación falla, notificar mediante un mensaje y terminar la ejecución.

    4. Lee TAMANHO bytes del fichero de entrada (primer argumento) usando fread y transforma cada uno de los bytes leídos en mayúsculas (deberás usar un bucle, teniendo cuidado de sólo transformar aquellos bytes que hayas leído).

      Escribe en el fichero de salida (segundo argumento) usando fwrite los bytes transformados.

      El programa deberá convertir todo el fichero a mayúsculas.

    5. Cierra los ficheros de entrada y de salida

¿Cuánto tiempo has dedicado a esta actividad? mins.

2. Trabajando con un fichero que contiene información sobre alumnos

Recursos

Plan de trabajo

Debes saber los siguientes conceptos:

  • Para leer de un fichero un número determinado de bytes existe la función fread: size_t fread(void *ptr, size_t tam, size_t nmiemb, FILE *flujo);. Esta función lee nmiemb elementos de datos, cada uno de tamaño tam bytes de largo, del flujo de datos apuntado por flujo, almacenándolos en el sitio apuntado por ptr.

    La función fread devuelve, si no ha ocurrido ningún error, el número de elementos leídos. Si ocurre un error o si se llega al final de fichero, devuelve el valor 0.

    Como la función fread no distingue entre estas dos circunstancias, se deberá usar la función feof() o la función ferror() para determinar qué ha ocurrido.

  • La función feof: int feof( FILE *flujo); inspecciona el indicador de fin-de-fichero para el flujo indicado por flujo, devolviendo no cero si está activado.

  • La función inversa a fread es la función fwrite: size_t fwrite( const void *ptr, size_t tam, size_t nmiemb, FILE *flujo);

    Esta función escribe nmiemb elementos de datos, cada uno de tamaño tam bytes de largo, al flujo de datos apuntado por flujo, obteniéndolos del sitio apuntado por ptr.

    La función fwrite devuelve, si no ha ocurrido ningún error, el número de bytes escritos. La función fwrite() devuelve un valor menor que nmiemb sólo si un ha ocurrido un error de escritura.

  • La función mkstemp: int mkstemp(char *template) genera un nombre de fichero temporal único a partir de template.

    Los últimos seis caracteres de template deben ser XXXXXX y éstos son reemplazados con una cadena que hace que el nombre no esté repetido. El fichero es entonces creado en modo de lectura/escritura.

    Ya que será modificada, template no debe ser una cadena constante sino que se debería declarar como un array de caracteres.

    La función mkstemp() devuelve el descriptor de fichero (fd) del fichero temporal creado o -1 en caso de error. Nótese que el descriptor de fichero es un int.

    Para poder abrir un fichero dado su descriptor de fichero se ha de usar la función fdopen: FILE *fdopen(int fildes, const char *mode)

  • Esta función se comporta como la función fopen, pero en vez de abrir un fichero dado su path, usa el identificador de fichero para abrirlo.

  • Para mover el indicador de posición de un flujo de datos, se deberá usar la función fseek: int fseek( FILE *flujo, long desplto, int origen);.

    Esta función, mueve el indicador de posición del fichero correspondiente al flujo de datos apuntado por flujo. La nueva posición, medida en bytes, se obtiene añadiendo desplto bytes a la posición especificada por origen. Si origen es SEEK_SET, SEEK_CUR, o SEEK_END, el desplazamiento es relativo al comienzo del fichero, a la posición actual, o al final del fichero, respectivamente.

  • La función rewind: void rewind( FILE *flujo), mueve el indicador de posición del fichero para el flujo apuntado por flujo al principio del fichero.

  • La función remove: int remove(const char *pathname), borra un nombre del sistema de ficheros.

  • La función rename: int rename(const char *oldpath, const char *newpath), renombra un fichero, moviéndolo entre directorios si así se requiere.

Se guardan los datos de las notas de una clase en un fichero. Este fichero tiene la siguiente estructura:

Figura 1. Estructura del fichero

Estructura del fichero

Donde id_c es el identificador de la clase (un entero de 4 bytes); id_s el identificador del alumno (un entero de 4 bytes); size_n el tamaño del nombre del alumno, incluyendo el cero final (un entero de 4 bytes);name, el nombre del alumno (incluyendo el cero);n_scores el número de notas guardadas para ese alumno (un entero de 4 bytes); score_i, la nota número i de ese alumno(un entero de 4 bytes).

Si n_scores es cero, el alumno no tendrá notas guardadas.

  1. Se pide:

    1. Define el tipo/tipos de datos necesarios para guardar esta información en una lista.

    2. Implementa una función que lea el fichero y guarde toda su información en una lista. Debes pasarle como parámetros la lista donde guardar la información y el nombre del fichero.

    3. Implementa una función que, dados los datos de un alumno (id y nombre), lo añada al principio del fichero. Esta función deberá comprobar si el alumno existe y si no existe añadirlo, indicando que tiene 0 notas. Como parámetros de entrada recibirá los datos del alumno y el fichero. Deberá hacer uso de la función mkstemp para crear un fichero temporal.

    4. Implementa una función que, dados los datos de un alumno (id y nombre), lo borre del fichero (todos sus datos, incluyendo notas, si las hubiera). Como parámetros de entrada recibirá los datos del alumno y el fichero. Deberá hacer uso de la función mkstemp para crear un fichero temporal.

¿Cuánto tiempo has dedicado a esta actividad? mins.