13 de septiembre de 2018

Consideraciones adicionales con archivos de texto.

   Todos los ejemplos anteriores relacionados con archivos han recorrido de principio a fin el archivo que procesan pero, ¿qué sucede si se necesita volver a procesar nuevamente los datos del archivo?

   Dentro de la información indispensable que se encuentra representada en la estructura FILE para el control del archivo asociado se encuentra, como se mencionó con anterioridad, un indicador de posición, el cual hace referencia a la posición del último dato procesado en el archivo.

   Cuando un archivo ha sido procesado de principio a fin, el indicador de posición se encontrará ubicado al final del mismo, de tal forma que si por alguna razón se procesara de nuevo el archivo para lectura por ejemplo, se estaría en la situación de una lectura vacía, dando la impresión de que el archivo no contiene datos aún cuando sí los tenga, debido precisamente a que el indicador de posición del archivo se encuentra al final.

   Una posible solución a la problemática anterior sería cerrar el archivo, abrirlo nuevamente y procesarlo; sin embargo, el abrir y cerrar un archivo sólo para regresar el indicador de posición a su posición inicial es, además de ineficiente, un pésimo enfoque de solución: ¿qué sucede si el archivo tendrá un uso intensivo?, ¿es práctico estarlo abriendo y cerrando frecuentemente?

   La función rewind coloca el indicador de posición del archivo al inicio del archivo. Así, un llamado como "rewind(archivoPtr);" coloca el indicador de posición del archivo referido por archivoPtr al inicio de éste, de tal forma que se puedan procesar nuevamente el conjunto de datos almacenados en él, tal y como si el archivo se hubiera abierto por primera vez.

   Se deja como ejercicio para el lector que modifique el programa del Ejemplo 9.3 para que presente en la salida estándar dos veces, una seguida de otra, el archivo procesado. La idea de este ejercicio es que pueda practicar el uso de la función rewind descrita brevemente con anterioridad.

   Finalmente, debido a que la función fprintf es equivalente a la función printf, quizá se haya preguntado si es posible escribir en un archivo de texto otros tipos de datos además de cadenas, esto es, ¿es posible escribir en un archivo de texto otros tipos de datos como los siguientes:

fprintf(archivoPtr, "%d\n%s\n%s\n%.2f\n", num, nombre, direccion, salario);

donde num es de tipo int, nombre y direccion son cadenas, y salario es de tipo float?

   La respuesta es sí. Sin embargo, debe tomar en cuenta que cualquier tipo de dato, al ser almacenado en un archivo de texto, pierde su representación como tipo de dato y pasa a ser sólo una sucesión de caracteres dentro del archivo, de tal forma que al leer num o salario por ejemplo, se podrían leer como cadenas, y esto sería igual de válido que leerlos como un int o como un float. Por lo tanto, las sentencias:

            fscanf(archivoPtr, "%d %s %s %f", &num, nombre, direccion, &salario);
           fscanf(archivoPtr, "%f %s %s %f", &numero, nombre, direccion, &salario);
            fscanf(archivoPtr, "%s %s %s %s", cad1, nombre, direccion, cad2);

serían igualmente válidas, suponiendo que numero fuera de tipo float y que cad1 y cad2 fueran cadenas; aunque la más congruente sería la primera, en función de los datos que, según la idea planteada en esta entrada, se escribieron en el archivo referido por archivoPtr.

   Cuando trabaje con archivos de texto, no olvide tener en cuenta todas las consideraciones mencionadas en esta entrada.


3 de agosto de 2018

Comentarios y sugerencias.

   Esta entrada tiene como intención principal, recolectar aquellos comentarios que los lectores deseen hacer acerca de algún punto o tema relacionado con el blog.

   En general he tratado de cuidar, en todo el blog, aquellos aspectos que hagan más accesible tanto la lectura como su correspondiente comprensión; sin embargo, es posible que algunas cosas que podrían parecer claras no lo sean del todo para la amplia diversidad de lectores, por lo que agradeceré de manera anticipada al lector bien intencionado, me informe de cualquier error identificado o sugerencia que permita mejorar el contenido.

   Dejo abierta la sección de comentarios para recibirlos y poder dar respuesta, en la medida de mis posibilidades, a cada uno de ellos.

   Quedo en deuda con todas las personas que me han escrito y ayudado a mejorar con sus comentarios, así como con los estudiantes que me han hecho valiosas aportaciones en más de un sentido.
 
    Agradezco particular y encarecidamente con el más profundo de mis afectos a la Ing. Thelma García Reyes, quien ha sido piedra angular tanto en el desarrollo inicial como en la revisión de lo que en su momento fue un libro y ahora un blog; sin su inestimable ayuda y entusiasmo cuando el desánimo se montaba en mis espaldas, seguiría atorado en los escollos del desarrollo y elaboración de imágenes, revisión, correcciones, y un largo etcétera. 
 
    En este mismo sentido agradezco y aprecio el apoyo del Dr. Tomás Balderas Contreras, quien no sólo me hizo el favor de escribir el prólogo del libro, sino que sus valiosos comentarios respecto a algunos de los aspectos técnicos del contenido, son insalvables.
 
    Aún con lo anterior, cualquier error que persista en este blog y en cualquier parte de su contenido es únicamente atribuible al autor.


27 de noviembre de 2017

Ejercicios selectos (matrices).

  1. Considere el Ejemplo 6.7. ¿Qué pasa si hay más inicializadores que elementos físicos? Pruebe dicha situación en los dos esquemas de inicialización planteados en el blog.
  2. Escriba un programa que pruebe la función suma del Ejemplo 6.8.
  3. Modifique la función leeMatriz del Ejemplo 6.7 para que almacene valores de tipo float en la matriz matriz. Una vez que haya probado su función, agréguela a la biblioteca de funciones del Ejemplo 6.8.
  4. Modifique la función imprimeMatriz del Ejemplo 6.7 para que imprima los valores de tipo float de la matriz matriz. Una vez que haya probado su función, agréguela a la biblioteca de funciones del Ejemplo 6.8.
  5. Escriba un programa que defina y pruebe una función con el siguiente prototipo: void resta(float a[ ][N], float b[ ][N], float c[ ][N], int m, int n). La función deberá calcular en la matriz c la resta de la matriz a menos la matriz b de manera análoga a como lo hace la función suma del Ejemplo 6.8.
  6. Agregue la función resta del ejercicio anterior, a la biblioteca de funciones del Ejemplo 6.8.
  7. Escriba un programa que defina y pruebe una función con el siguiente prototipo: void imprimeTranspuesta(float a[ ][N], int m, int n). La función deberá imprimir en la salida estándar la matriz transpuesta de a. La matriz transpuesta se genera convirtiendo los renglones en columnas y viceversa.
  8. Escriba un programa que defina y pruebe una función con el siguiente prototipo: void transpuesta(float a[ ][N], float aT[ ][N],int m, int n). La función deberá generar en la matriz aT la matriz transpuesta de a. La matriz transpuesta se genera convirtiendo los renglones en columnas y viceversa.
  9. Agregue la función transpuesta del ejercicio anterior a la biblioteca de funciones del Ejemplo 6.8.
  10. Escriba un programa que defina y pruebe una función con el siguiente prototipo: int esSimetrica(float a[ ][N], int n). La función deberá determinar si la matriz a es o no simétrica. Una matriz simétrica es aquella que es igual con su matriz transpuesta.
  11. Agregue la función esSimetrica del ejercicio anterior, a la biblioteca de funciones del Ejemplo 6.8.
  12. Escriba un programa que defina y pruebe una función con el siguiente prototipo: void producto(float a[ ][N], float b[ ][N], float c[ ][N], int m, int n, int l). La función debe calcular el producto de las matrices  a y b almacenando el resultado en c. Para poder realizar este ejercicio, investigue cómo se define y obtiene el producto de matrices.
  13. Agregue la función producto del ejercicio anterior a la biblioteca de funciones del Ejemplo 6.8.
  14. Escriba una función que determine la suma de los elementos de la diagonal principal de una matriz.
  15. Escriba una función que determine la suma de los elementos de la diagonal secundaria de una matriz.
  16. Un cuadrado mágico es una matriz de n x n donde n es impar, en donde se colocan números enteros en cada una de sus entradas y que además cumple con las siguientes características:
    • La suma de los números de cualquier línea (horizontal, vertical o diagonal) será siempre la misma. A esta suma se le denomina constante mágica.
    • Todos los números almacenados en un cuadrado mágico deben ser distintos.
    Con base en lo anterior, escriba una función con el siguiente prototipo:

    int cuadradoMagico(int c[ ][N], int n);

    Dado un cuadrado c de dimensiones lógicas n, la función determina si representa (regresa 1) o no (regresa 0) un cuadrado mágico. Ejemplo:

    4     9     2
    3     5     7
    8     1     6
    es un cuadrado mágico.
  17.  Haga un programa que implemente el juego del gato (tic tac toe). En este programa el usuario jugará en contra de la computadora. Utilice una matriz de tipo char e inicialícela con espacios en blanco. Utilice "O" para la computadora y "X" para el usuario. Haga su algoritmo tan elaborado como considere, no permita que el usuario gane fácilmente; sin embargo, una posibilidad es que cuando sea el turno de la computadora, simplemente recorra la matriz buscando una posición que no esté ocupada.
  18. Considere una implementación básica del Juego de la Vida con base en una matriz de 0's y 1's. El Juego de la Vida fue diseñado por el matemático británico John Horton Conway en 1970.
Arreglos de n dimensiones.
  1. Las figuras del arreglo tridimensional discutidas en el blog (Arreglos de dimensiones) muestran en gris algunos de los elementos del arreglo de tres dimensiones. Denote todos los elementos visibles (para ambas) de dicho arreglo siguiendo la nomenclatura del lenguaje C.
  2. De manera análoga a lo descrito en la entrada Arreglos de dos dimensiones, dibuje y describa la representación física en la memoria del arreglo tridimensional del ejercicio anterior. Sugerencia: la representación en memoria se realiza también de manera lineal: los renglones de la primera matriz, después los de la segunda matriz, etcétera, la representación de malla puede ayudarle a visualizar mejor la representación.
  3. Basándose en el Ejemplo 6.9, escriba un programa que generalice la idea planteada para definir, inicializar, e imprimir en la salida estándar un hipercubo.
  4. Basándose en el Ejemplo 6.9, escriba un programa que generalice la idea planteada para definir, inicializar, e imprimir en la salida estándar un arreglo de cinco dimensiones cada una con un tamaño distinto, por ejemplo: dos para la primera dimensión, tres para la segunda, cuatro para la tercera y así sucesivamente.