]> git.llucax.com Git - z.facultad/75.42/calculadora.git/blob - tp2.c
Últimos retoques.
[z.facultad/75.42/calculadora.git] / tp2.c
1 /* vim: set et sts=4 sw=4 fdm=indent fdl=1 fdn=0 fo+=t:
2  *
3  * Taller de Programación (75.42).
4  *
5  * Ejercicio Número 2:
6  * Programa calculadora.
7  *
8  * Copyleft 2003 - Leandro Lucarella <llucare@fi.uba.ar>
9  * Puede copiar, modificar y distribuir este programa bajo los términos de
10  * la licencia GPL (http://www.gnu.org/).
11  *
12  * Creado: mar sep 16 04:07:49 ART 2003
13  *
14  * $Id$
15  */
16
17 #include "dllist.h"
18 #include "parseerror.h"
19 #include "parser_variable.h"
20 #include "parser_equation.h"
21 #include "variable_list.h"
22 #include "equation_list.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "memdebug_debugger.h"
29
30 /** Tamaño del buffer de lectura de archivos. */
31 #define BUFFER_SIZE 4096
32
33 /**
34  * Imprime una explicación de como usar el programa.
35  *
36  * \param fh Archivo en donde imprimir el mensaje (ej: stdout o stderr).
37  */
38 void print_help(FILE* fh) {
39     fprintf(fh, "\n");
40     fprintf(fh, "Modo de uso:\n");
41     fprintf(fh, "  tp2 <arch_variables> <arch_ecuaciones>\n");
42 }
43
44 /**
45  * Dibuja el menú en pantalla.
46  */
47 void print_menu(void) {
48     printf("Menu:\n");
49     printf("      1. Listar variables.\n");
50     printf("      2. Listar ecuaciones.\n");
51     printf("      3. Evaluar ecuaciones.\n");
52     printf("      4. Listar memoria.\n");
53     printf("      5. Salir.\n");
54 }
55
56 /**
57  * Obtiene la selección del menú del usuario.
58  */
59 char get_entrada(void) {
60     char buff[BUFFER_SIZE];
61     printf("Elija una opción: ");
62     fgets(buff, BUFFER_SIZE, stdin);
63     return buff[0];
64 }
65
66 /**
67  * Menú de opciones.
68  */
69 void menu_loop(DLList* var_list, DLList* eq_list) {
70     char entrada;
71     print_menu();
72     entrada = get_entrada();
73     /* Mientras no sea '5' (salir), se mantiene en el loop. */
74     while (entrada != '5') {
75         /* Mientras la entrada sea inválida, muestra mensaje de error. */
76         while ((entrada < '1') || (entrada > '5')) {
77             printf("\n\n\n");
78             print_menu();
79             printf("Debe elegir un número entre 1 y 5!\n");
80             entrada = get_entrada();
81         }
82         printf("\n");
83         switch (entrada) {
84             case '1': /* Listar variables */
85                 printf("Lista de variables:\n");
86                 DLList_variable_print(var_list, stdout);
87                 break;
88             case '2': /* Listar ecuaciones */
89                 printf("Lista de ecuaciones:\n");
90                 DLList_equation_print(eq_list, stdout);
91                 break;
92             case '3': /* Evaluar ecuaciones */
93                 printf("Lista de variables después de evaluar:\n");
94                 DLList_equation_eval(var_list, eq_list, stderr);
95                 DLList_variable_print(var_list, stdout);
96                 break;
97             case '4': /* Listar memoria */
98                 printf("Lista de memoria alocada:\n");
99                 memdebug_list_print(stdout);
100                 break;
101             case '5': /* Sale */
102                 continue;
103         }
104         printf("\n\n");
105         print_menu();
106         entrada = get_entrada();
107     }
108 }
109
110 /**
111  * Programa principal.
112  * Este es el programa que se encarga de resolver el trabajo práctico.
113  *
114  * \param argc Cantidad de parámetros de línea de comandos ingresados.
115  * \param argv Parámetros de línea de comandos.
116  *
117  * \return EXIT_FAILURE si hubo un error, si no EXIT_SUCCESS.
118  */
119 int main(int argc, const char** argv) {
120     /* Declaración de variables. */
121     DLList* var_list = NULL;
122     DLList* eq_list = NULL;
123     ParseError* error;
124     char buff[BUFFER_SIZE];
125     int i;
126     FILE* fp;
127
128     if (argc != 3) {
129         print_help(stderr);
130         return EXIT_FAILURE;
131     }
132
133     /* Inicializo ParseError. */
134     if (!(error = ParseError_new())) {
135         fprintf(stderr, "Error: No se pudo alocar la memoria para el manejo "
136                 "de error.\n");
137         return EXIT_FAILURE;
138     }
139
140     /* Inicializo la lista de variables. */
141     if (!(var_list = DLList_new())) {
142         fprintf(stderr, "Error: No se pudo alocar la memoria para la lista "
143                 "de variables.\n");
144         return EXIT_FAILURE;
145     }
146     /* Abro archivo. */
147     fp = fopen(argv[1], "r");
148     if (!fp) {
149         fprintf(stderr, "Error: No se pudo abrir el archivo '%s'.\n", argv[1]);
150         return EXIT_FAILURE;
151     }
152     /* Parseo cada línea, mostrando mensaje por pantalla si hay error. */
153     for (i = 1; fgets(buff, BUFFER_SIZE, fp); i++) {
154         if (!parser_variable(buff, strlen(buff) - 1, var_list, error)) {
155             error->line = i;
156             fprintf(stderr, "%s: ", argv[1]);
157             ParseError_print(error, stderr);
158         }
159     }
160     /* Cierro archivo. */
161     fclose(fp);
162
163     /* Inicializo la lista de ecuaciones. */
164     if (!(eq_list = DLList_new())) {
165         fprintf(stderr, "Error: No se pudo alocar la memoria para la lista "
166                 "de ecuaciones.\n");
167         return EXIT_FAILURE;
168     }
169     /* Abro archivo. */
170     fp = fopen(argv[2], "r");
171     if (!fp) {
172         fprintf(stderr, "Error: No se pudo abrir el archivo '%s'.\n", argv[2]);
173         return EXIT_FAILURE;
174     }
175     /* Parseo cada línea, mostrando mensaje por pantalla si hay error. */
176     for (i = 1; fgets(buff, BUFFER_SIZE, fp); i++) {
177         if (!parser_equation(buff, strlen(buff) - 1, eq_list, error)) {
178             error->line = i;
179             fprintf(stderr, "%s: ", argv[2]);
180             ParseError_print(error, stderr);
181         }
182     }
183     /* Cierro archivo. */
184     fclose(fp);
185
186     /* Elimino el error de interpretación. */
187     ParseError_delete(error);
188
189     menu_loop(var_list, eq_list);
190
191     /* Elimino listas. */
192     DLList_variable_delete(var_list);
193     DLList_equation_delete(eq_list);
194
195     /* Veo si quedo memoria sin desalocar. */
196     memdebug_end();
197
198     /* Salió todo ok. */
199     return EXIT_SUCCESS;
200 }
201