From e8be4543c7b27b4f68517e8b12acc895388997f2 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Mon, 25 Aug 2003 06:23:39 +0000 Subject: [PATCH] =?utf8?q?Pr=C3=A1cticamente=20se=20finaliza=20el=20TP,=20?= =?utf8?q?s=C3=B3lo=20quedan=20pulir=20detalles.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- documentacion.h | 24 +++++++++++++++-- tp1.c | 72 ++++++++++++++++++++++++++++++++++++++----------- tp1.h | 37 +++++++++++++++++++++---- 3 files changed, 111 insertions(+), 22 deletions(-) diff --git a/documentacion.h b/documentacion.h index a5c1b2b..efae98d 100644 --- a/documentacion.h +++ b/documentacion.h @@ -69,13 +69,13 @@ \endverbatim \section resolucion Resolución. - El \ref main "programa principal" se divide en FIXME N tareas principales, + El \ref main "programa principal" se divide en 3 tareas principales, cada una realizada por una función particular. \subsection obtencion Obtención y validación de parámetros del usuario. Antes de comenzar a hacer cálculos es necesario obtener los valores de las \ref variables "variables" de la entrada del usuario (en este caso - a través de parámetros de línea de comandos). Esto es realizado + a través de parámetros de línea de comandos). Esta tarea es realizada por la función cargar_datos(). \subsection integracion Integración de la ecuación diferencial. @@ -97,5 +97,25 @@ función y almacenándolos en el \ref Resultados "vector de resultados", tarea realizada por la función calcular(). + \subsection impresion Impresión del gráfico por pantalla. + Finalmente todo lo que queda es graficar por pantalla el resultado de la + función. Para esto se va imprimiendo línea por línea, chequeando qué + punto de la función cae en cada rango de valores representados por una + línea. Esta tarea es realizada por la función resultados_graficar(). + +\section conclusiones Conclusiones. + Realmente no se me presentaron muchos problemas para resolver el TP. El + único problema que tuve fue realizando el \ref impresion "gráfico", en + ciertas circunstancias (por problemas de redondeo) el valor máximo de la + función no era graficado. Esto se solucionó incluyendo una línea más al + gráico, con el rango que va desde el máximo de la función (en realidad desde + el mínimo más 20 pasos verticales) hasta el máximo más un paso vertical. + Es por esto que en realidad se grafican 21 pasos. Podría haber graficado 20 + pasos pero el código quedaría menos claro (o tendría que poner la constante + \ref ALTO en 19 en vez de 20). + + Otro detalle que cabe ser mencionado es que para valores altos del + \ref variables "step" (mayores a 30), la solución se vuelve inestable. + */ diff --git a/tp1.c b/tp1.c index f8b7c86..7706605 100644 --- a/tp1.c +++ b/tp1.c @@ -79,8 +79,6 @@ int cargar_datos(int argc, const char** argv, Real* paso, Real* tf, Real* f0) { return FALSE; } /* TODO Verificar que el paso no sea cero y que tf > ti. */ - /* XXX - sacar */ - printf("paso = %f, tf = %f, f0 = %f\n", *paso, *tf, *f0); return TRUE; } @@ -99,16 +97,14 @@ size_t calcular(Resultados* res, Real paso, Real ti, Real tf, Real f0) { /* Itero paso a paso calculando el valor de la función. */ for (i = 1; i < pasos; i++) { /* f(t+paso) = FUNCION(paso, f(t)) */ - (*res)[i] = FUNCION(paso, (*res)[i-1]); - /* FIXME sacar!!!! */ - printf("i = %i, t = %.2f, f(t) = %.2f\n", i, (Real)i * paso, (*res)[i]); + (*res)[i] = FUNCION(paso, (*res)[i-1]); } return pasos; } -Real max(const Resultados* res, size_t pasos) { - size_t i; - Real max = (*res)[0]; +Real resultados_max(Resultados* res, size_t pasos) { + size_t i; + Real max = (*res)[0]; for (i = 1; i < pasos; i++) { if ((*res)[i] > max) { max = (*res)[i]; @@ -117,9 +113,9 @@ Real max(const Resultados* res, size_t pasos) { return max; } -Real min(const Resultados* res, size_t pasos) { - size_t i; - Real min = (*res)[0]; +Real resultados_min(Resultados* res, size_t pasos) { + size_t i; + Real min = (*res)[0]; for (i = 1; i < pasos; i++) { if ((*res)[i] < min) { min = (*res)[i]; @@ -128,13 +124,56 @@ Real min(const Resultados* res, size_t pasos) { return min; } +void inicializar_linea(char* linea, char caracter, size_t cant) { + size_t j; + for (j = 0; j < cant; j++) { + linea[j] = caracter; + } + linea[cant] = '\0'; +} + +void resultados_graficar(Resultados* res, size_t pasos, char punto, char blanco) { + /* Máximo valor de la función. */ + Real min; + /* Mínimo valor de la función. */ + Real max; + /* Paso utilizado para la representación de las líneasMínimo valor de la función. */ + Real pasoh; + int i; + int j; + char linea[ANCHO]; + min = resultados_min(res, pasos); + max = resultados_max(res, pasos); + pasoh = (max - min) / (ALTO); + printf("min: %f, max: %f, pasoh: %f\n", min, max, pasoh); + /* Inicializa la línea. */ + inicializar_linea(linea, blanco, MAX_PASOS); + /* Por cada línea a dibujar. */ + for (i = ALTO; i >= 0; i--) { + /* Se fija si hay algún punto que entre en el rango. */ + for (j = 0; j < pasos; j++) { + /* Si está entre en el rango a imprimir, se agrega un punto. */ + if (((min + pasoh * i) <= (*res)[j]) + && ((*res)[j] < (min + pasoh * (i + 1)))) { + linea[j] = punto; + /* Si no, se lo deja en blanco. */ + } else { + linea[j] = blanco; + } + } + printf("%8.2f _%s\n", min + pasoh * i, linea); + } +} + int main(int argc, const char** argv) { /* TODO: Declaración de variables. */ Resultados resultados; size_t pasos; - Real paso = DEFAULT_PASO; - Real tf = DEFAULT_TF; - Real f0 = DEFAULT_F0; + Real paso = DEFAULT_PASO; + Real tf = DEFAULT_TF; + Real f0 = DEFAULT_F0; + char punto = '*'; + char blanco = ' '; /* Obtención de datos. */ if (!cargar_datos(argc, argv, &paso, &tf, &f0)) { @@ -144,10 +183,13 @@ int main(int argc, const char** argv) { /* Cálculo de la solución, dejando en un array los valores de cada paso. */ pasos = calcular(&resultados, paso, T0, tf, f0); + /* XXX - sacar o poner más lindo. */ + printf("paso = %f, tf = %f, f0 = %f, pasos = %i\n", paso, tf, f0, pasos); /* TODO: Barrido de pantalla de arriba hacia abajo consultando el array * y dibujando los resultados pertinentes. */ - /* TODO: Liberación de memoria y otras limpiezas, en caso de ser necesario. */ + resultados_graficar(&resultados, pasos, punto, blanco); + return EXIT_SUCCESS; } diff --git a/tp1.h b/tp1.h index 8ae9410..eb00948 100644 --- a/tp1.h +++ b/tp1.h @@ -38,6 +38,9 @@ /** Altura (en líneas) utilizadas para dibujar el gráfico. */ #define ALTO 20 +/** Ancho (en líneas) utilizadas para dibujar el gráfico. */ +#define ANCHO 70 + /** Tiempo inicial. */ #define T0 0.0 @@ -66,7 +69,7 @@ * pérdida de velocidad que agrega la indirección de un llamado a una * función. */ -#define FUNCION(paso, ft) ((ft) + (500.0 - (ft)) / 30.0 * paso) +#define FUNCION(paso, ft) ((ft) + ((500.0 - (ft)) / 30.0) * paso) @@ -112,7 +115,7 @@ void imprimir_uso(FILE* fh); int argtod(const char* arg, Real* var, const char* nom); /** - * Carga los datos necesarios por el programai. + * Carga los datos necesarios por el \ref main "programa". * Obtiene los datos desde los parámetros de la línea de comandos, validándolos * y mostrando un mensaje de error en caso de haberlo. * @@ -123,7 +126,8 @@ int argtod(const char* arg, Real* var, const char* nom); * \param f0 Valor inicial de la función. * * \return TRUE si se cargaron bien, FALSE si no. - * \todo Verificar que el paso no sea cero y que tf > ti. + * \todo \b TODO Verificar que el paso no sea cero y que tf > ti. + * \todo \b TODO Agregar opciones para especificar caracter en blanco y de punto. */ int cargar_datos(int argc, const char** argv, Real* paso, Real* tf, Real* f0); @@ -148,7 +152,7 @@ size_t calcular(Resultados* res, Real paso, Real ti, Real tf, Real f0); * * \return Máximo resultado. */ -Real max(const Resultados* res, size_t pasos); +Real resultados_max(Resultados* res, size_t pasos); /** * Devuelve el valor mínimo de los resultados. @@ -158,7 +162,30 @@ Real max(const Resultados* res, size_t pasos); * * \return Mínimo resultado. */ -Real min(const Resultados* res, size_t pasos); +Real resultados_min(Resultados* res, size_t pasos); + +/** + * Rellena una cadena de caracteres con un caracter arbitrario. + * + * \param linea Cadena de caracteres. + * \param caracter Caracter utilizado para rellenar. + * \param cant Cantidad de caracteres a rellenar. + */ +void inicializar_linea(char* linea, char caracter, size_t cant); + +/** + * Imprime un gráfico de los resultados por pantalla. + * Realiza un gráfico de la función por pantalla, imprimiendo línea por línea. + * Cada línea representa un rango de valores. En cada línea se dibuja el + * caracter \e punto si la función en el tiempo evaluado está en el rango de esa + * línea. Si no lo está se dibuja el caracter \e blanco. + * + * \param res Vector de resultados a graficar. + * \param pasos Cantidad de pasos a graficar. + * \param punto Caracter utilizado para dibujar un punto de la función. + * \param blanco Caracter utilizado para dibujar un punto en blanco. + */ +void resultados_graficar(Resultados* res, size_t pasos, char punto, char blanco); /** * Programa principal. -- 2.43.0