From b9c399a948a2dc3256e6a5c2059ae1ac748662ae Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Mon, 25 Aug 2003 07:22:40 +0000 Subject: [PATCH] Se organiza mejor, separando el TP en varios archivos. --- Makefile | 8 ++- calculo.c | 39 +++++++++++ calculo.h | 50 ++++++++++++++ carga.c | 75 ++++++++++++++++++++ carga.h | 55 +++++++++++++++ general.h | 28 ++++++++ grafico.c | 83 ++++++++++++++++++++++ grafico.h | 66 ++++++++++++++++++ tipos.h | 44 ++++++++++++ tp1.c | 189 ++++++++++++--------------------------------------- tp1.h | 200 ------------------------------------------------------ 11 files changed, 489 insertions(+), 348 deletions(-) create mode 100644 calculo.c create mode 100644 calculo.h create mode 100644 carga.c create mode 100644 carga.h create mode 100644 general.h create mode 100644 grafico.c create mode 100644 grafico.h create mode 100644 tipos.h delete mode 100644 tp1.h diff --git a/Makefile b/Makefile index 33d8e28..e7ef152 100644 --- a/Makefile +++ b/Makefile @@ -18,12 +18,14 @@ CFLAGS=-ansi -pedantic -Wall -g3 # Programa a compilar. -TARGETS=tp1 +TARGETS=carga.o calculo.o grafico.o # Regla por defecto. -all: $(TARGETS) +all: tp1 + +tp1: $(TARGETS) # Regla para borrar. clean: @echo "Limpiando..." - @rm -fv $(TARGETS) *.o core + @rm -fv $(TARGETS) *.o core tp1 diff --git a/calculo.c b/calculo.c new file mode 100644 index 0000000..09f7bd1 --- /dev/null +++ b/calculo.c @@ -0,0 +1,39 @@ +/* vim: set et ts=4 sw=4 fdm=indent fdl=1 fdn=1 fo+=t: + * + * Taller de Programación (75.42). + * + * Ejercicio Número 1: + * Graficador de la solución de una ecuación diferencial por el método + * de Euler (explícito). + * + * Copyleft 2003 - Leandro Lucarella + * Puede copiar, modificar y distribuir este programa bajo los términos de + * la licencia GPL (http://www.gnu.org/). + * + * Creado: sáb ago 23 16:59:01 ART 2003 + * + * $Id$ + */ + +#include "calculo.h" + +size_t resultados_calcular(Resultados* res, Real paso, Real ti, Real tf, Real f0) { + /* Índice para iterar. */ + size_t i; + /* Calculo la cantidad de pasos necesarios según el tiempo inicial, el + * tiempo final y el "tamaño" del paso. */ + size_t pasos = (size_t)((tf - ti) / paso); + /* Respeto la cantidad máxima de pasos admitida. */ + if (pasos > ANCHO) { + pasos = ANCHO; + } + /* Agrego el valor inicial de la función (para empezar a iterar). */ + (*res)[0] = 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]); + } + return pasos; +} + diff --git a/calculo.h b/calculo.h new file mode 100644 index 0000000..d243838 --- /dev/null +++ b/calculo.h @@ -0,0 +1,50 @@ +/* vim: set et ts=4 sw=4 fdm=indent fdl=1 fdn=1 fo+=t: + * + * Taller de Programación (75.42). + * + * Ejercicio Número 1: + * Graficador de la solución de una ecuación diferencial por el método + * de Euler (explícito). + * + * Copyleft 2003 - Leandro Lucarella + * Puede copiar, modificar y distribuir este programa bajo los términos de + * la licencia GPL (http://www.gnu.org/). + * + * Creado: sáb ago 23 16:59:01 ART 2003 + * + * $Id$ + */ + +#ifndef H_CALCULO +#define H_CALCULO + +#include "tipos.h" + +/** + * \ref integracion "Calcula" el siguiente paso de la función numérica. + * Obtiene el siguiente valor de \f$ f \f$, integrando numéricamente la \ref + * funcion "ecuación diferencial" por el \ref metodo "método de euler". + * \f[ + * f_{t + step} = f_{(step, f_t)} = f_t + \frac{500 - f_t}{30} \cdot step + * \f] + * + * \note Se pone en un macro para poder reemplazar fácilmente la función sin la + * 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) + +/** + * \ref integracion "Calcula" todos los valores de la función. + * + * \param res Vector donde se guardan los resultados. + * \param paso Paso de iteración. + * \param ti Tiempo de inicio de la iteración. + * \param tf Tiempo final de la iteración. + * \param f0 Valor inicial de la función. + * + * \return Cantidad de pasos realizados. + */ +size_t resultados_calcular(Resultados* res, Real paso, Real ti, Real tf, Real f0); + +#endif diff --git a/carga.c b/carga.c new file mode 100644 index 0000000..6747088 --- /dev/null +++ b/carga.c @@ -0,0 +1,75 @@ +/* vim: set et ts=4 sw=4 fdm=indent fdl=1 fdn=1 fo+=t: + * + * Taller de Programación (75.42). + * + * Ejercicio Número 1: + * Graficador de la solución de una ecuación diferencial por el método + * de Euler (explícito). + * + * Copyleft 2003 - Leandro Lucarella + * Puede copiar, modificar y distribuir este programa bajo los términos de + * la licencia GPL (http://www.gnu.org/). + * + * Creado: sáb ago 23 16:59:01 ART 2003 + * + * $Id$ + */ + +#include "carga.h" +/* Para utilizar fprintf() y stderr */ +#include +/* Para utilizar strtod() */ +#include + +int argtod(const char* arg, Real* var, const char* nom) { + /* Puntero al último caracter bien interpretado por strtod. */ + char* err = NULL; + /* Realiza la conversión de un string a un Real */ + *var = strtod(arg, &err); + /* Si el caracter donde apunta endptr es 0 es porque se interpretó toda la + * cadena bien */ + if ((char)*err == '\0') { + return TRUE; + /* Si no, es que hubo error. */ + } else { + fprintf(stderr, "Error: El parámetro '%s' debe ser un número ", nom); + fprintf(stderr, "real. Usted ingresó '%s' pero '%s' no ", arg, err); + fprintf(stderr, "pudo ser interpretado.\n"); + return FALSE; + } +} + +int cargar_datos(int argc, const char** argv, Real* paso, Real* tf, Real* f0) { + switch (argc) { + /* Si no tiene parámetros usa los valores por omisión. */ + case 1: + break; + /* Si tiene de 1 a 3 parámetros, los lee y valida, saliendo con un + * mensaje de error en caso de haberlo. */ + case 4: + /* Hay 3 parámetros, lee el 3er parámetro. */ + if (!argtod(argv[3], f0, "f0")) { + return FALSE; + } + /* Continúa con el resto de los parámetros. */ + case 3: + /* Hay al menos 2 parámetros, lee el 2do parámetro. */ + if (!argtod(argv[2], tf, "tf")) { + return FALSE; + } + /* Continúa con el resto de los parámetros. */ + case 2: + /* Hay al menos 1 parámetro, lee el 1er parámetro. */ + if (!argtod(argv[1], paso, "paso")) { + return FALSE; + } + break; /* Finaliza el switch (no lee más parámetros). */ + /* Hay demasiados parámetros, sale con mensaje de error. */ + default: + fprintf(stderr, "Error: Demasiados parámetros.\n"); + return FALSE; + } + /* TODO Verificar que el paso no sea cero y que tf > ti. */ + return TRUE; +} + diff --git a/carga.h b/carga.h new file mode 100644 index 0000000..3763642 --- /dev/null +++ b/carga.h @@ -0,0 +1,55 @@ +/* vim: set et ts=4 sw=4 fdm=indent fdl=1 fdn=1 fo+=t: + * + * Taller de Programación (75.42). + * + * Ejercicio Número 1: + * Graficador de la solución de una ecuación diferencial por el método + * de Euler (explícito). + * + * Copyleft 2003 - Leandro Lucarella + * Puede copiar, modificar y distribuir este programa bajo los términos de + * la licencia GPL (http://www.gnu.org/). + * + * Creado: sáb ago 23 16:59:01 ART 2003 + * + * $Id$ + */ + +#ifndef H_CARGA +#define H_CARGA + +#include "tipos.h" + +/** + * Carga (validando) un dato real en una variable. + * Si al validar hay algún error, muestra un mensaje por la salida de error y + * devuelve false. + * + * \param arg Argumento a cargar (y validar). + * \param var Variable en donde cargar el real. + * \param nom Nombre de la variable que se quiere cargar (para el mensaje de + * error, en caso de haberlo). + * + * \return TRUE si se cargó bien, FALSE si no. + */ +int argtod(const char* arg, Real* var, const char* nom); + +/** + * 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. + * + * \param argc Cantidad de parámetros de línea de comandos ingresados. + * \param argv Parámetros de línea de comandos. + * \param paso Paso utilizado para las iteraciones. + * \param tf Tiempo final. + * \param f0 Valor inicial de la función. + * + * \return TRUE si se cargaron bien, FALSE si no. + * \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); + +#endif diff --git a/general.h b/general.h new file mode 100644 index 0000000..990144b --- /dev/null +++ b/general.h @@ -0,0 +1,28 @@ +/* vim: set et ts=4 sw=4 fdm=indent fdl=1 fdn=1 fo+=t: + * + * Taller de Programación (75.42). + * + * Ejercicio Número 1: + * Graficador de la solución de una ecuación diferencial por el método + * de Euler (explícito). + * + * Copyleft 2003 - Leandro Lucarella + * Puede copiar, modificar y distribuir este programa bajo los términos de + * la licencia GPL (http://www.gnu.org/). + * + * Creado: sáb ago 23 16:59:01 ART 2003 + * + * $Id$ + */ + +#ifndef H_GENERAL +#define H_GENERAL + +/** 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 + +#endif + diff --git a/grafico.c b/grafico.c new file mode 100644 index 0000000..173c955 --- /dev/null +++ b/grafico.c @@ -0,0 +1,83 @@ +/* vim: set et ts=4 sw=4 fdm=indent fdl=1 fdn=1 fo+=t: + * + * Taller de Programación (75.42). + * + * Ejercicio Número 1: + * Graficador de la solución de una ecuación diferencial por el método + * de Euler (explícito). + * + * Copyleft 2003 - Leandro Lucarella + * Puede copiar, modificar y distribuir este programa bajo los términos de + * la licencia GPL (http://www.gnu.org/). + * + * Creado: sáb ago 23 16:59:01 ART 2003 + * + * $Id$ + */ + +#include "grafico.h" +#include + +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'; +} + +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]; + } + } + return max; +} + +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]; + } + } + return min; +} + +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, ANCHO); + /* 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); + } +} + diff --git a/grafico.h b/grafico.h new file mode 100644 index 0000000..c3cea5b --- /dev/null +++ b/grafico.h @@ -0,0 +1,66 @@ +/* vim: set et ts=4 sw=4 fdm=indent fdl=1 fdn=1 fo+=t: + * + * Taller de Programación (75.42). + * + * Ejercicio Número 1: + * Graficador de la solución de una ecuación diferencial por el método + * de Euler (explícito). + * + * Copyleft 2003 - Leandro Lucarella + * Puede copiar, modificar y distribuir este programa bajo los términos de + * la licencia GPL (http://www.gnu.org/). + * + * Creado: sáb ago 23 16:59:01 ART 2003 + * + * $Id$ + */ + +#ifndef H_GRAFICO +#define H_GRAFICO + +#include "tipos.h" + +/** + * 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); + +/** + * Devuelve el valor máximo de los resultados. + * + * \param res Vector de resultados. + * \param pasos Cantidad de pasos a iterar. + * + * \return Máximo resultado. + */ +Real resultados_max(Resultados* res, size_t pasos); + +/** + * Devuelve el valor mínimo de los resultados. + * + * \param res Vector de resultados. + * \param pasos Cantidad de pasos a iterar. + * + * \return Mínimo resultado. + */ +Real resultados_min(Resultados* res, size_t pasos); + +/** + * 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); + +#endif diff --git a/tipos.h b/tipos.h new file mode 100644 index 0000000..19555d3 --- /dev/null +++ b/tipos.h @@ -0,0 +1,44 @@ +/* vim: set et ts=4 sw=4 fdm=indent fdl=1 fdn=1 fo+=t: + * + * Taller de Programación (75.42). + * + * Ejercicio Número 1: + * Graficador de la solución de una ecuación diferencial por el método + * de Euler (explícito). + * + * Copyleft 2003 - Leandro Lucarella + * Puede copiar, modificar y distribuir este programa bajo los términos de + * la licencia GPL (http://www.gnu.org/). + * + * Creado: sáb ago 23 16:59:01 ART 2003 + * + * $Id$ + */ + +#ifndef H_TIPOS +#define H_TIPOS + +#include "general.h" +#include + +/** Indica un valor verdadero */ +#define TRUE 1 + +/** Indica un valor falso */ +#define FALSE 0 + +/** + * Tipo de dato utilizado para medir el tiempo y el valor de la función. + * Se define como un tipo de dato propio para cambiar fácilmente la precisión. + */ +typedef float Real; + +/** + * Vector que representa los resultados. + * El índice del vector representa el número de iteración (que multiplicado por + * el paso da el tiempo, o eje X). El contenido es el valor de la + * \ref funcion "función" en ese instante. + */ +typedef Real Resultados[ANCHO]; + +#endif diff --git a/tp1.c b/tp1.c index 7706605..c004b88 100644 --- a/tp1.c +++ b/tp1.c @@ -15,9 +15,37 @@ * $Id$ */ -/* Cabecera del TP. */ -#include "tp1.h" +#include "carga.h" +#include "calculo.h" +#include "grafico.h" +/* Para utilizar printf() y stderr */ +#include +/* Para utilizar EXIT_SUCCES y EXIT_FAILURE */ +#include +/** Tiempo inicial. */ +#define T0 0.0 + +/** Tiempo final por omisión. */ +#define DEFAULT_TF 70.0 + +/** Valor inicial de la función por omisión. */ +#define DEFAULT_F0 0.0 + +/** Valor del pas de iteración por omisión. */ +#define DEFAULT_PASO 1.0 + +/** Caracter usado para dibujar un punto por omisión. */ +#define DEFAULT_PUNTO '*' + +/** Caracter usado para dibujar un punto blanco por omisión. */ +#define DEFAULT_BLANCO ' ' + +/** + * Imprime una explicación de como usar el programa. + * + * \param fh Archivo en donde imprimir el mensaje (ej: stdout o stderr). + */ void imprimir_uso(FILE* fh) { fprintf(fh, "\n"); fprintf(fh, "Modo de uso:\n"); @@ -30,166 +58,37 @@ void imprimir_uso(FILE* fh) { DEFAULT_F0); } -int argtod(const char* arg, Real* var, const char* nom) { - /* Puntero al último caracter bien interpretado por strtod. */ - char* err = NULL; - /* Realiza la conversión de un string a un Real */ - *var = strtod(arg, &err); - /* Si el caracter donde apunta endptr es 0 es porque se interpretó toda la - * cadena bien */ - if ((char)*err == '\0') { - return TRUE; - /* Si no, es que hubo error. */ - } else { - fprintf(stderr, "Error: El parámetro '%s' debe ser un número ", nom); - fprintf(stderr, "real. Usted ingresó '%s' pero '%s' no ", arg, err); - fprintf(stderr, "pudo ser interpretado.\n"); - return FALSE; - } -} - -int cargar_datos(int argc, const char** argv, Real* paso, Real* tf, Real* f0) { - switch (argc) { - /* Si no tiene parámetros usa los valores por omisión. */ - case 1: - break; - /* Si tiene de 1 a 3 parámetros, los lee y valida, saliendo con un - * mensaje de error en caso de haberlo. */ - case 4: - /* Hay 3 parámetros, lee el 3er parámetro. */ - if (!argtod(argv[3], f0, "f0")) { - return FALSE; - } - /* Continúa con el resto de los parámetros. */ - case 3: - /* Hay al menos 2 parámetros, lee el 2do parámetro. */ - if (!argtod(argv[2], tf, "tf")) { - return FALSE; - } - /* Continúa con el resto de los parámetros. */ - case 2: - /* Hay al menos 1 parámetro, lee el 1er parámetro. */ - if (!argtod(argv[1], paso, "paso")) { - return FALSE; - } - break; /* Finaliza el switch (no lee más parámetros). */ - /* Hay demasiados parámetros, sale con mensaje de error. */ - default: - fprintf(stderr, "Error: Demasiados parámetros.\n"); - return FALSE; - } - /* TODO Verificar que el paso no sea cero y que tf > ti. */ - return TRUE; -} - -size_t calcular(Resultados* res, Real paso, Real ti, Real tf, Real f0) { - /* Índice para iterar. */ - size_t i; - /* Calculo la cantidad de pasos necesarios según el tiempo inicial, el - * tiempo final y el "tamaño" del paso. */ - size_t pasos = (size_t)((tf - ti) / paso); - /* Respeto la cantidad máxima de pasos admitida. */ - if (pasos > MAX_PASOS) { - pasos = MAX_PASOS; - } - /* Agrego el valor inicial de la función (para empezar a iterar). */ - (*res)[0] = 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]); - } - return pasos; -} - -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]; - } - } - return max; -} - -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]; - } - } - 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); - } -} - +/** + * Programa principal. + * Este es el programa que se encarga de resolver el trabajo práctico. + * + * \param argc Cantidad de parámetros de línea de comandos ingresados. + * \param argv Parámetros de línea de comandos. + * + * \return EXIT_FAILURE si hubo un error, si no EXIT_SUCCESS. + */ int main(int argc, const char** argv) { - /* TODO: Declaración de variables. */ + /* Declaración de variables. (TODO: describir variables) */ Resultados resultados; size_t pasos; Real paso = DEFAULT_PASO; Real tf = DEFAULT_TF; Real f0 = DEFAULT_F0; - char punto = '*'; - char blanco = ' '; - + char punto = DEFAULT_PUNTO; + char blanco = DEFAULT_BLANCO; /* Obtención de datos. */ if (!cargar_datos(argc, argv, &paso, &tf, &f0)) { + /* Si hay error, imprime mensaje con modo de uso y sale con error. */ imprimir_uso(stderr); return EXIT_FAILURE; } - /* Cálculo de la solución, dejando en un array los valores de cada paso. */ - pasos = calcular(&resultados, paso, T0, tf, f0); + pasos = resultados_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. */ resultados_graficar(&resultados, pasos, punto, blanco); - return EXIT_SUCCESS; } diff --git a/tp1.h b/tp1.h deleted file mode 100644 index eb00948..0000000 --- a/tp1.h +++ /dev/null @@ -1,200 +0,0 @@ -/* vim: set et ts=4 sw=4 fdm=indent fdl=1 fdn=1 fo+=t: - * - * Taller de Programación (75.42). - * - * Ejercicio Número 1: - * Graficador de la solución de una ecuación diferencial por el método - * de Euler (explícito). - * - * Copyleft 2003 - Leandro Lucarella - * Puede copiar, modificar y distribuir este programa bajo los términos de - * la licencia GPL (http://www.gnu.org/). - * - * Creado: sáb ago 23 16:59:01 ART 2003 - * - * $Id$ - */ - -/************************ BIBLIOTECAS USADAS *******************************/ - -/* Para utilizar printf(), fprintf() y stderr */ -#include -/* Para utilizar strtod(), EXIT_SUCCES y EXIT_FAILURE */ -#include - - - -/***************************** CONSTANTES **********************************/ - -/** Indica un valor verdadero */ -#define TRUE 1 - -/** Indica un valor falso */ -#define FALSE 0 - -/** Máxima cantidad de pasos a calcular. */ -#define MAX_PASOS 70 - -/** 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 - -/** Tiempo final por omisión. */ -#define DEFAULT_TF 70.0 - -/** Valor inicial de la función por omisión. */ -#define DEFAULT_F0 0.0 - -/** Valor del pas de iteración por omisión. */ -#define DEFAULT_PASO 1.0 - - - -/******************************* MACROS ************************************/ - -/** - * \ref integracion "Calcula" el siguiente paso de la función numérica. - * Obtiene el siguiente valor de \f$ f \f$, integrando numéricamente la \ref - * funcion "ecuación diferencial" por el \ref metodo "método de euler". - * \f[ - * f_{t + step} = f_{(step, f_t)} = f_t + \frac{500 - f_t}{30} \cdot step - * \f] - * - * \note Se pone en un macro para poder reemplazar fácilmente la función sin la - * 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) - - - -/************************ TIPOS DE DATOS UTILIZADOS ************************/ - -/** - * Tipo de dato utilizado para medir el tiempo y el valor de la función. - * Se define como un tipo de dato propio para cambiar fácilmente la precisión. - */ -typedef float Real; - -/** - * Vector que representa los resultados. - * El índice del vector representa el número de iteración (que multiplicado por - * el paso da el tiempo, o eje X). El contenido es el valor de la - * \ref funcion "función" en ese instante. - */ -typedef Real Resultados[MAX_PASOS]; - - - -/********************************* FUNCIONES *******************************/ - -/** - * Imprime una explicación de como usar el programa. - * - * \param fh Archivo en donde imprimir el mensaje (ej: stdout o stderr). - */ -void imprimir_uso(FILE* fh); - -/** - * Carga (validando) un dato real en una variable. - * Si al validar hay algún error, muestra un mensaje por la salida de error y - * devuelve false. - * - * \param arg Argumento a cargar (y validar). - * \param var Variable en donde cargar el real. - * \param nom Nombre de la variable que se quiere cargar (para el mensaje de - * error, en caso de haberlo). - * - * \return TRUE si se cargó bien, FALSE si no. - */ -int argtod(const char* arg, Real* var, const char* nom); - -/** - * 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. - * - * \param argc Cantidad de parámetros de línea de comandos ingresados. - * \param argv Parámetros de línea de comandos. - * \param paso Paso utilizado para las iteraciones. - * \param tf Tiempo final. - * \param f0 Valor inicial de la función. - * - * \return TRUE si se cargaron bien, FALSE si no. - * \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); - -/** - * \ref integracion "Calcula" todos los valores de la función. - * - * \param res Vector donde se guardan los resultados. - * \param paso Paso de iteración. - * \param ti Tiempo de inicio de la iteración. - * \param tf Tiempo final de la iteración. - * \param f0 Valor inicial de la función. - * - * \return Cantidad de pasos realizados. - */ -size_t calcular(Resultados* res, Real paso, Real ti, Real tf, Real f0); - -/** - * Devuelve el valor máximo de los resultados. - * - * \param res Vector de resultados. - * \param pasos Cantidad de pasos a iterar. - * - * \return Máximo resultado. - */ -Real resultados_max(Resultados* res, size_t pasos); - -/** - * Devuelve el valor mínimo de los resultados. - * - * \param res Vector de resultados. - * \param pasos Cantidad de pasos a iterar. - * - * \return Mínimo resultado. - */ -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. - * Este es el programa que se encarga de resolver el trabajo práctico. - * - * \param argc Cantidad de parámetros de línea de comandos ingresados. - * \param argv Parámetros de línea de comandos. - * - * \return EXIT_FAILURE si hubo un error, si no EXIT_SUCCESS. - */ -int main(int argc, const char** argv); - -- 2.43.0