]> git.llucax.com Git - z.facultad/75.42/euler.git/blob - tp1.c
7706605c055fde519a2db327ae1032970854adac
[z.facultad/75.42/euler.git] / tp1.c
1 /* vim: set et ts=4 sw=4 fdm=indent fdl=1 fdn=1 fo+=t:
2  *
3  * Taller de Programación (75.42).
4  *
5  * Ejercicio Número 1:
6  * Graficador de la solución de una ecuación diferencial por el método
7  * de Euler (explícito).
8  *
9  * Copyleft 2003 - Leandro Lucarella <llucare@fi.uba.ar>
10  * Puede copiar, modificar y distribuir este programa bajo los términos de
11  * la licencia GPL (http://www.gnu.org/).
12  *
13  * Creado: sáb ago 23 16:59:01 ART 2003
14  *
15  * $Id$
16  */
17
18 /* Cabecera del TP. */
19 #include "tp1.h"
20
21 void imprimir_uso(FILE* fh) {
22     fprintf(fh, "\n");
23     fprintf(fh, "Modo de uso:\n");
24     fprintf(fh, "  tp1 [paso [tf [f0]]]\n");
25     fprintf(fh, "\n");
26     fprintf(fh, "Donde:\n");
27     fprintf(fh, "  paso: Paso a utilizar (%.2f por omisión).\n", DEFAULT_PASO);
28     fprintf(fh, "  tf:   Tiempo final (%.2f por omisión).\n", DEFAULT_TF);
29     fprintf(fh, "  f0:   Valor inicial de la función (%.2f por omisión).\n",
30             DEFAULT_F0);
31 }
32
33 int argtod(const char* arg, Real* var, const char* nom) {
34     /* Puntero al último caracter bien interpretado por strtod. */
35     char* err = NULL;
36     /* Realiza la conversión de un string a un Real */
37     *var = strtod(arg, &err);
38     /* Si el caracter donde apunta endptr es 0 es porque se interpretó toda la
39      * cadena bien */
40     if ((char)*err == '\0') {
41         return TRUE;
42     /* Si no, es que hubo error. */
43     } else {
44         fprintf(stderr, "Error: El parámetro '%s' debe ser un número ", nom);
45         fprintf(stderr, "real. Usted ingresó '%s' pero '%s' no ", arg, err);
46         fprintf(stderr, "pudo ser interpretado.\n");
47         return FALSE;
48     }
49 }
50
51 int cargar_datos(int argc, const char** argv, Real* paso, Real* tf, Real* f0) {
52     switch (argc) {
53         /* Si no tiene parámetros usa los valores por omisión. */
54         case 1:
55             break;
56         /* Si tiene de 1 a 3 parámetros, los lee y valida, saliendo con un
57          * mensaje de error en caso de haberlo. */
58         case 4:
59             /* Hay 3 parámetros, lee el 3er parámetro. */
60             if (!argtod(argv[3], f0, "f0")) {
61                 return FALSE;
62             }
63             /* Continúa con el resto de los parámetros. */
64         case 3:
65             /* Hay al menos 2 parámetros, lee el 2do parámetro. */
66             if (!argtod(argv[2], tf, "tf")) {
67                 return FALSE;
68             }
69             /* Continúa con el resto de los parámetros. */
70         case 2:
71             /* Hay al menos 1 parámetro, lee el 1er parámetro. */
72             if (!argtod(argv[1], paso, "paso")) {
73                 return FALSE;
74             }
75             break; /* Finaliza el switch (no lee más parámetros). */
76         /* Hay demasiados parámetros, sale con mensaje de error. */
77         default:
78             fprintf(stderr, "Error: Demasiados parámetros.\n");
79             return FALSE;
80     }
81     /* TODO Verificar que el paso no sea cero y que tf > ti. */
82     return TRUE;
83 }
84
85 size_t calcular(Resultados* res, Real paso, Real ti, Real tf, Real f0) {
86     /* Índice para iterar. */
87     size_t i;
88     /* Calculo la cantidad de pasos necesarios según el tiempo inicial, el
89      * tiempo final y el "tamaño" del paso. */
90     size_t pasos = (size_t)((tf - ti) / paso);
91     /* Respeto la cantidad máxima de pasos admitida. */
92     if (pasos > MAX_PASOS) {
93         pasos = MAX_PASOS;
94     }
95     /* Agrego el valor inicial de la función (para empezar a iterar). */
96     (*res)[0] = f0;
97     /* Itero paso a paso calculando el valor de la función. */
98     for (i = 1; i < pasos; i++) {
99         /* f(t+paso) = FUNCION(paso, f(t)) */
100         (*res)[i]    = FUNCION(paso, (*res)[i-1]);
101     }
102     return pasos;
103 }
104
105 Real resultados_max(Resultados* res, size_t pasos) {
106     size_t i;
107     Real   max = (*res)[0];
108     for (i = 1; i < pasos; i++) {
109         if ((*res)[i] > max) {
110             max = (*res)[i];
111         }
112     }
113     return max;
114 }
115
116 Real resultados_min(Resultados* res, size_t pasos) {
117     size_t i;
118     Real   min = (*res)[0];
119     for (i = 1; i < pasos; i++) {
120         if ((*res)[i] < min) {
121             min = (*res)[i];
122         }
123     }
124     return min;
125 }
126
127 void inicializar_linea(char* linea, char caracter, size_t cant) {
128     size_t j;
129     for (j = 0; j < cant; j++) {
130         linea[j] = caracter;
131     }
132     linea[cant] = '\0';
133 }
134
135 void resultados_graficar(Resultados* res, size_t pasos, char punto, char blanco) {
136     /* Máximo valor de la función. */
137     Real min;
138     /* Mínimo valor de la función. */
139     Real max;
140     /* Paso utilizado para la representación de las líneasMínimo valor de la función. */
141     Real pasoh;
142     int  i;
143     int  j;
144     char linea[ANCHO];
145     min = resultados_min(res, pasos);
146     max = resultados_max(res, pasos);
147     pasoh = (max - min) / (ALTO);
148     printf("min: %f, max: %f, pasoh: %f\n", min, max, pasoh);
149     /* Inicializa la línea. */
150     inicializar_linea(linea, blanco, MAX_PASOS);
151     /* Por cada línea a dibujar. */
152     for (i = ALTO; i >= 0; i--) {
153         /* Se fija si hay algún punto que entre en el rango. */
154         for (j = 0; j < pasos; j++) {
155             /* Si está entre en el rango a imprimir, se agrega un punto. */
156             if (((min + pasoh * i) <= (*res)[j])
157                     && ((*res)[j] < (min + pasoh * (i + 1)))) {
158                 linea[j] = punto;
159             /* Si no, se lo deja en blanco. */
160             } else {
161                 linea[j] = blanco;
162             }
163         }
164         printf("%8.2f _%s\n", min + pasoh * i, linea);
165     }
166 }
167
168 int main(int argc, const char** argv) {
169     /* TODO: Declaración de variables. */
170     Resultados  resultados;
171     size_t      pasos;
172     Real        paso    = DEFAULT_PASO;
173     Real        tf      = DEFAULT_TF;
174     Real        f0      = DEFAULT_F0;
175     char        punto   = '*';
176     char        blanco  = ' ';
177
178     /* Obtención de datos. */
179     if (!cargar_datos(argc, argv, &paso, &tf, &f0)) {
180         imprimir_uso(stderr);
181         return EXIT_FAILURE;
182     }
183
184     /* Cálculo de la solución, dejando en un array los valores de cada paso. */
185     pasos = calcular(&resultados, paso, T0, tf, f0);
186     /* XXX - sacar o poner más lindo. */
187     printf("paso = %f, tf = %f, f0 = %f, pasos = %i\n", paso, tf, f0, pasos);
188
189     /* TODO: Barrido de pantalla de arriba hacia abajo consultando el array
190      *       y dibujando los resultados pertinentes. */
191     resultados_graficar(&resultados, pasos, punto, blanco);
192
193     return EXIT_SUCCESS;
194 }
195