FUNDAMENTOS DE PROGRAMACIÓN BOLETÍN 12.3: Lenguaje C. Estructuras y ficheros Curso: 2012/13 Versión: 1.0.3 OBJETIVOS Aprender a usar registros (tipo struct) Aprender a utilizar funciones de lectura y escritura de ficheros de texto. EJERCICIOS (1ª PARTE): STRUCT EJERCICIO 1 – RACIONALES Con la organización de ficheros de los boletines anteriores (.h y .c) construya un proyecto denominado Racionales en el que se atienda a lo siguiente: 1. Defina un tipo llamado Racional mediante una estructura para almacenar el numerador y el denominador de un número racional. 2. Implemente una función de tipo void leeRacional que devuelva como parámetro de salida una variable de tipo Racional con sus valores introducidos por teclado (por ello defina un tipo PRacional como puntero a Racional). La función debe verificar si el denominador es cero, y en ese caso visualizar el mensaje “Denominador debe ser distinto de cero” y volver a pedirlo, hasta que sea distinto de cero. Complementariamente, si el racional tiene numerador y denominador de distinto signo, el valor negativo se aplicará al numerador; en otro caso, siempre serán positivos. 3. Implemente también las funciones suma, resta, producto y división, que recibiendo como parámetros de entrada dos variables de tipo Racional, devuelvan la suma, la resta, el producto o división de los parámetros de entrada, respectivamente. Tenga en cuenta que: a. Si en alguna de las funciones anteriores el numerador resultase ser cero, el denominador debe ser 1 (p.e: 1/2 -1/2 = 0/1) b. Si en el producto o división el denominador resultase negativo hay que cambiar de signo al numerador y denominador. Para resolver a y b apóyese en un método Racional cambiaDenominadorYSigno (Racional) c. En la división no se pueden multiplicar racionales con el numerador igual al cero en el segundo multiplicando (controle esta situación en el test y en su caso visualice “División imposible”). 4. Finalmente cree un fichero testRacionales en el que se implemente la función main para pedir por teclado dos racionales y visualizar respectivamente su suma, resta, producto y división. EJERCICIO 2 – ALUMNO Con la organización de ficheros conocida de .h y .c construya un proyecto denominado Alumnos en el que se atienda a lo siguiente: 1. Defina un tipo de datos Cadena con las características del boletín anterior. Defina un tipo llamado Alumno mediante una estructura para almacenar: a. El DNI, de tipo Cadena. b. El nombre, de tipo Cadena. c. Los apellidos, de tipo Cadena. Boletín 12.3: Lenguaje C. Estructuras y ficheros 2 d. La edad, de tipo entero. e. Un array con un máximo de 30 elementos de tipo Asignatura (que debe definir previamente mediante la constante TAM) donde cada elemento conste de dos campos: 1. Denominación de la asignatura, de tipo Cadena. 2. Nota obtenida, de tipo real. f. Número real de elementos del array de asignaturas. Asimismo defina Pint como puntero a int; PAsignatura como puntero a Asignatura; PAlumno como puntero a Alumno; y PCadena como puntero a Cadena. 2. Implemente una función void leeAlumno que devuelva como parámetro de salida una variable de tipo Alumno con los valores introducidos por teclado. 3. Para pedir los datos de tipo Cadena utilice las funciones apropiadas en las que se puedan insertar caracteres en blanco, por ejemplo: Luis Miguel, Fundamentos de Programación, etc. Para introducir las notas apóyese en una función void leeAsignaturas (PAsignatura, Pint) que pida el número real de asignaturas y notas a introducir y permita introducirlas. 4. Implemente una función void visualizaAlumno con una presentación similar a: Datos del alumno: DNI: 27259012A Nombre: Frasquito Apellidos: Pérez Muñoz Edad: 20 Fundamentos Programación: 7.000000 Cálculo: 8.100000 Sistemas Operativos: 9.800000 5. Construya una función para responder a cada una de las preguntas que se plantean a continuación (para realizar en casa): a. ¿Cuál es el promedio de notas de un alumno? Devuelva el resultado en la propia función. b. ¿Qué asignaturas del alumno han resultado aprobadas? Devuélvalas en un vector de Cadena, como parámetro de salida. 6. Visualice el resultado mediante el siguiente test: #include "alumnos.h" int main(void){ Alumno a; Cadena asigAprobadas[TAM]; int numAsigApr, i; leeAlumno(&a); visualizaAlumno(a); printf("\nMedia de notas: %lf", promedioNotas(a)); asignaturasAprobadas(a, asigAprobadas, &numAsigApr); printf("\nAsignaturas aprobadas"); for (i=0; i<numAsigApr; i++) printf("\n\t%s", asigAprobadas[i]); return 0; } Boletín 12.3: Lenguaje C. Estructuras y ficheros 3 EJERCICIOS (2ª PARTE): FICHEROS EJERCICIO 3 – LEYENDO Y ESCRIBIENDO FECHAS Cree un proyecto denominado Fechas que contendrá, como es habitual, dos ficheros de código fuente que denominará fechas.c y testFechas.c y un fichero de cabecera fechas.h con el siguiente contenido: #ifndef FECHAS_H_ #define FECHAS_H_ #include<stdio.h> #define TAM 25 #define MAX 255 typedef char Cadena[MAX]; typedef int* Pint; typedef struct{ int dia; int mes; int anyo; } Fecha; typedef Fecha ArrayFechas[TAM]; // A continuación se escribirán los prototipos de los ejercicios // … #endif // FECHAS_H _ Escriba la función void leeArrayFechas que lea las fechas contenidas en el fichero: “fechas.txt”. Dicho fichero deberá crearlo copiando lo siguiente con un editor de texto (puede utilizar el propio Eclipse): 29 12 11 26 11 02 09 12 07 02 2010 2009 2005 2007 2010 28 15 17 23 02 06 11 02 2010 2010 2005 24 05 2010 2009 A medida que vaya leyendo debe ir almacenando las fechas en una estructura apropiada. Esta función recibe como parámetros: a) El nombre del fichero a leer. b) Un array de fechas vacío, que devolverá cargado con las fechas leídas. Recuerde que siempre que se pasa un array como parámetro de salida a una función hay que acompañarlo de otra variable donde se almacenará el número real de elementos (nFechas). Para poder leer, abra el fichero con la función fopen(“nombreFichero”,”r”). Si el programa no consigue abrir el fichero (el puntero a fichero es NULL), visualice el mensaje “Fichero nombreFichero no encontrado” y devuelva como número real de elementos cargados en el array un cero (*nFechas =0). El código de esta lectura sería: Boletín 12.3: Lenguaje C. Estructuras y ficheros 4 int i = 0; FILE *f; f = fopen(nombreFichero,"r"); if (f == NULL) { printf("fichero %s no encontrado", nombreFichero); *nFechas = 0; } else { fscanf(f,"%d%d%d",&aF[i].dia,&aF[i].mes,&aF[i].anyo); while (!feof(f) && i < TAM-1) { i++; fscanf(f,"%d%d%d",&aF[i].dia,&aF[i].mes,&aF[i].anyo); } *nFechas = i; fclose(f); } Observe el esquema de lectura adelantada: la función feof( ) devuelve un valor verdadero cuando ya no quedan registros tras un intento de lectura. Use la función fscanf para leer cada una de las fechas del fichero y tenga en cuenta que en cada lectura deberá leer lo que representa una fecha. Defina la función escribeArrayFechas para que reciba el nombre de un fichero (por ejemplo: fechasSal.txt), un array de Fecha (este parámetro debe llevar la etiqueta const al tratarse de un array que no debe ser modificado en escribeArrayFechas) y el número real de elementos del array. Esta función debe escribir las fechas en el fichero de texto mediante fprintf( ) con el formato “aaaa/mm/dd” (pruebe con "%4d/%2d/%2d\n" como cadena especificadora de formato). Así mismo deberá usar en el modo de escritura en la función de apertura del fichero. Compruebe con un editor de texto el contenido del fichero de salida.