calculadora.c

   1 /**
   2  * calculadora.c
   3  *
   4  * @author Luis Alejandro Bernal Romero
   5  *
   6  * Una calculadora sencilla, de cuatro operaciones para aprender a
   7  * programar en GTK.
   8  *
   9  * Para compilar este programa digite en la línea de comando:
  10  *
  11  *  gcc -Wall -pedantic -o calculadora calculadora.c `pkg-config --cflags --libs gtk+-2.0`
  12  *
  13  * Que falta?: 
  14  *
  15  * - Hacer que el Label pantalla aline el texto a la derecha.
  16  *
  17  * - No violar el pricipio de ocultamiento al crear el Label pantalla.
  18  *
  19  * - Más pruebas, no se si funciona del todo.
  20  */
  21 
  22 #include <stdlib.h> 
  23 #include <string.h>
  24 #include <gtk/gtk.h>
  25 
  26 /*Estructura calculadora */
  27 
  28 #define abs(n) (((n)>=0)?(n):-(n))
  29 
  30 gdouble delta = 0.00000000000000001; /* Un número que es casi cero. */
  31 
  32 struct {
  33   GtkWidget *pantalla;
  34   gdouble acumulador; 
  35   gchar *ultimaOperacion;
  36   gboolean hayPunto; /* El punto fue digitado. */
  37   gboolean borrarPantalla;
  38 } cal;
  39 
  40 void cal_borrar_pantalla(){
  41   gtk_label_set_text(GTK_LABEL(cal.pantalla), "");
  42   cal.borrarPantalla = FALSE;
  43 }
  44 
  45 void cal_mod_pantalla(char *cad){
  46   gtk_label_set_text(GTK_LABEL(cal.pantalla), cad);
  47 }
  48 
  49 void cal_pantalla_adic_digito(const gchar *digito){
  50   char etiqueta[100 + 1];
  51   if(cal.borrarPantalla){
  52     cal_borrar_pantalla();
  53   }
  54   sprintf(etiqueta, "%s%s", gtk_label_get_text(GTK_LABEL(cal.pantalla)), digito);
  55   gtk_label_set_text(GTK_LABEL(cal.pantalla), etiqueta);
  56 }
  57 
  58 void cal_pantalla_adic_punto(){
  59   if(cal.borrarPantalla){
  60     cal_borrar_pantalla();
  61   }
  62   if( ! cal.hayPunto){
  63     char etiqueta[100 + 1];
  64 
  65     sprintf(etiqueta, "%s,", gtk_label_get_text(GTK_LABEL(cal.pantalla)));
  66     gtk_label_set_text(GTK_LABEL(cal.pantalla), etiqueta);
  67     cal.hayPunto = TRUE;
  68   }
  69 }
  70 
  71 gdouble cal_obt_ultimoOperando(){
  72   gdouble ultimoOperando;
  73   sscanf(gtk_label_get_text(GTK_LABEL(cal.pantalla)),"%lf", &ultimoOperando);
  74   return ultimoOperando;  
  75 }
  76 
  77 void cal_ini(){
  78   cal_borrar_pantalla();
  79   cal.acumulador = 0.0;
  80   cal.ultimaOperacion = NULL;
  81   cal.hayPunto = FALSE;
  82   cal.borrarPantalla = FALSE;
  83 }
  84 
  85 void cal_mod_ultimaOperacion(const gchar *operacion){
  86   cal.ultimaOperacion = (gchar *)operacion;
  87 }
  88 
  89 void cal_operar(){
  90   gchar cad[100 + 1];
  91 
  92   cal.borrarPantalla = TRUE;
  93   if(cal.ultimaOperacion == NULL){
  94     cal.acumulador = cal_obt_ultimoOperando();
  95     return;
  96   }
  97   if(strcmp(cal.ultimaOperacion, "+") == 0){
  98     cal.acumulador += cal_obt_ultimoOperando();
  99   }
 100   else if(strcmp(cal.ultimaOperacion, "-") == 0){
 101     cal.acumulador -= cal_obt_ultimoOperando();
 102   }
 103   else if(strcmp(cal.ultimaOperacion, "*") == 0){
 104     cal.acumulador *= cal_obt_ultimoOperando();
 105   }
 106   else if(strcmp(cal.ultimaOperacion, "/") == 0){
 107     if(abs(cal_obt_ultimoOperando()) < delta){
 108       cal_mod_pantalla("Error");
 109       cal.ultimaOperacion = NULL;
 110       cal.hayPunto = FALSE;
 111       cal.borrarPantalla = TRUE;
 112       return;
 113     }
 114     else{
 115       cal.acumulador /= cal_obt_ultimoOperando();
 116     }
 117   }
 118   sprintf(cad, "%g", cal.acumulador);
 119   cal_mod_pantalla(cad);
 120   cal.ultimaOperacion = NULL;
 121   cal.hayPunto = FALSE;
 122 }
 123 
 124 /* Manejadores de eventos. */
 125 
 126 static gboolean cerrar(GtkWidget *ventana, GdkEvent *evento, gpointer datos){
 127   gtk_main_quit();
 128   return FALSE;
 129 }
 130 
 131 static void al_oprimir_teclaNumerica(GtkWidget *tecla, gpointer datos){
 132   cal_pantalla_adic_digito(gtk_button_get_label(GTK_BUTTON(tecla)));
 133 }
 134 
 135 static void al_oprimir_teclaPunto(GtkWidget *teclaPunto, gpointer datos){
 136   cal_pantalla_adic_punto();
 137 }
 138 
 139 static void al_oprimir_teclaCe(GtkWidget *tecla, gpointer datos){
 140   cal_borrar_pantalla();
 141 }
 142 
 143 static void al_oprimir_teclaC(GtkWidget *tecla, gpointer datos){
 144   cal_ini();
 145 }
 146 
 147 static void al_oprimir_teclaIgual(GtkWidget *tecla, gpointer datos){
 148   cal_operar();
 149 }
 150 
 151 static void al_oprimir_teclaOperacion(GtkWidget *tecla, gpointer datos){
 152   cal_operar();
 153   cal_mod_ultimaOperacion(gtk_button_get_label(GTK_BUTTON(tecla)));
 154 }
 155 
 156 /* Pricipal */
 157 
 158 int main(int argc, char *argv[]){
 159   GtkWidget *ventana;
 160   GtkWidget *tabla;
 161   GtkWidget *tecla[10]; /* Teclas numéricas. */
 162   GtkWidget *teclaPunto;
 163   GtkWidget *teclaIgual;
 164   GtkWidget *teclaMas;
 165   GtkWidget *teclaMenos;
 166   GtkWidget *teclaPor;
 167   GtkWidget *teclaDiv;
 168   GtkWidget *teclaC;
 169   GtkWidget *teclaCe;
 170   int x, y , k;
 171   gchar etiqueta[2];  /* Etiquetas de la teclas numéricas. */
 172 
 173   cal_ini();
 174   gtk_init(&argc, &argv);
 175   ventana = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 176   g_signal_connect(G_OBJECT(ventana), "delete_event", G_CALLBACK(cerrar), NULL);
 177   tabla = gtk_table_new(5, 5, TRUE);
 178   gtk_container_add(GTK_CONTAINER(ventana), tabla);
 179   cal.pantalla = gtk_label_new("");
 180 
 181   gtk_table_attach_defaults(GTK_TABLE(tabla), cal.pantalla, 0, 5, 0, 1);
 182   gtk_widget_show(cal.pantalla);
 183 
 184   /* Crear las tecla numéricas */
 185   for(k = 0; k < 10; k++){
 186     etiqueta[0] = k + '0';
 187     etiqueta[1] = '\0';
 188     tecla[k] = gtk_button_new_with_label(etiqueta);
 189     g_signal_connect(G_OBJECT(tecla[k]), "clicked", G_CALLBACK(al_oprimir_teclaNumerica), NULL);
 190   }
 191 
 192   /* Crear la otras teclas.*/
 193   teclaPunto = gtk_button_new_with_label(".");
 194   teclaIgual = gtk_button_new_with_label("=");
 195   teclaMas = gtk_button_new_with_label("+");
 196   teclaMenos = gtk_button_new_with_label("-");
 197   teclaPor = gtk_button_new_with_label("*");
 198   teclaDiv = gtk_button_new_with_label("/");
 199   teclaC = gtk_button_new_with_label("C");
 200   teclaCe= gtk_button_new_with_label("CE");
 201 
 202   /* Posicionar la teclas numéricas en la tabla, desde la uno. */
 203   k = 1;
 204   for(y = 3; y >= 1; y--){
 205     for(x = 0; x <= 2; x++){
 206       gtk_table_attach_defaults(GTK_TABLE(tabla), tecla[k], x, x + 1, y, y + 1);
 207       gtk_widget_show(tecla[k++]);
 208     }
 209   }
 210 
 211   /* Posicionar las otras teclas. */
 212   gtk_table_attach_defaults(GTK_TABLE(tabla), tecla[0], 0, 1, 4, 5);
 213   gtk_widget_show(tecla[0]);
 214   gtk_table_attach_defaults(GTK_TABLE(tabla), teclaPunto, 1, 2, 4, 5);
 215   g_signal_connect(G_OBJECT(teclaPunto), "clicked", G_CALLBACK(al_oprimir_teclaPunto), NULL);
 216   gtk_widget_show(teclaPunto);
 217   gtk_table_attach_defaults(GTK_TABLE(tabla), teclaCe, 3, 4, 1, 2);
 218   g_signal_connect(G_OBJECT(teclaCe), "clicked", G_CALLBACK(al_oprimir_teclaCe), NULL);
 219   gtk_widget_show(teclaCe);
 220   gtk_table_attach_defaults(GTK_TABLE(tabla), teclaC, 4, 5, 1, 2);
 221   g_signal_connect(GTK_OBJECT(teclaC), "clicked", G_CALLBACK(al_oprimir_teclaC), NULL);
 222   gtk_widget_show(teclaC);
 223   gtk_table_attach_defaults(GTK_TABLE(tabla), teclaPor, 3, 4, 2, 3);
 224   g_signal_connect(G_OBJECT(teclaPor), "clicked", G_CALLBACK(al_oprimir_teclaOperacion), NULL);
 225   gtk_widget_show(teclaPor);
 226   gtk_table_attach_defaults(GTK_TABLE(tabla), teclaDiv, 4, 5, 2, 3);
 227   g_signal_connect(G_OBJECT(teclaDiv), "clicked", G_CALLBACK(al_oprimir_teclaOperacion), NULL);
 228   gtk_widget_show(teclaDiv);
 229   gtk_table_attach_defaults(GTK_TABLE(tabla), teclaMas, 3, 4, 3, 4);
 230   g_signal_connect(G_OBJECT(teclaMas), "clicked", G_CALLBACK(al_oprimir_teclaOperacion), NULL);
 231   gtk_widget_show(teclaMas);
 232   gtk_table_attach_defaults(GTK_TABLE(tabla), teclaMenos, 4, 5, 3, 4);
 233   g_signal_connect(G_OBJECT(teclaMenos), "clicked", G_CALLBACK(al_oprimir_teclaOperacion), NULL);
 234   gtk_widget_show(teclaMenos);
 235   gtk_table_attach_defaults(GTK_TABLE(tabla), teclaIgual, 3, 5, 4, 5);
 236   g_signal_connect(G_OBJECT(teclaIgual), "clicked", G_CALLBACK(al_oprimir_teclaIgual), NULL);
 237   gtk_widget_show(teclaIgual);
 238   
 239   gtk_widget_show(tabla);
 240   gtk_widget_show(ventana);
 241   gtk_main();
 242 
 243   return 0;
 244 }

CategoryLenguajeC | CategoryProgramacion

LenguajeC/Programas/calculadora.c (last edited 2008-04-20 14:38:20 by localhost)