+
+/************************ 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) {
+ fprintf(fh, "\n");
+ fprintf(fh, "Modo de uso:\n");
+ fprintf(fh, " tp1 [paso [tf [f0]]]\n");
+ fprintf(fh, "\n");
+ fprintf(fh, "Donde:\n");
+ fprintf(fh, " paso: Paso a utilizar (%.2f por omisión).\n", DEFAULT_PASO);
+ fprintf(fh, " tf: Tiempo final (%.2f por omisión).\n", DEFAULT_TF);
+ fprintf(fh, " f0: Valor inicial de la función (%.2f por omisión).\n",
+ DEFAULT_F0);
+}
+
+/**
+ * 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) {
+ /* 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;
+ }
+}
+
+/**
+ * Carga los datos necesarios por el programai.
+ * 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 Verificar que el paso no sea cero y que tf > ti.
+ */
+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. */
+ /* XXX - sacar */
+ printf("paso = %f, tf = %f, f0 = %f\n", *paso, *tf, *f0);
+ return TRUE;
+}
+
+/**
+ * \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) {
+ /* Í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]);
+ /* FIXME sacar!!!! */
+ printf("i = %i, t = %.2f, f(t) = %.2f\n", i, (Real)i * paso, (*res)[i]);
+ }
+ return pasos;
+}
+
+/**
+ * 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 max(const 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;
+}
+
+/**
+ * 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 min(const 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;
+}
+
+/**
+ * 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. */
+ Resultados resultados;
+ size_t pasos;
+ Real paso = DEFAULT_PASO;
+ Real tf = DEFAULT_TF;
+ Real f0 = DEFAULT_F0;
+
+ /* Obtención de datos. */
+ if (!cargar_datos(argc, argv, &paso, &tf, &f0)) {
+ 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);
+
+ /* 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. */
+ return EXIT_SUCCESS;
+}
+