utiles.h |
#include<stdio.h> #ifndef __UTILES__ #define __UTILES__ char * sgets(void); void spause(void); int confirmar(char * indicacion); char * pedir(const char * indicacion); #ifdef __ISDEVC__ #define BORRAR "cls" int strcasecmp(const char * big, const char * little); #else #define BORRAR "clear" #include<termios.h> char getch(void); #endif #endif |
utiles.c |
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<ctype.h> #include "utiles.h" /* sgets() has different implementations in Unix and elsewhere, hence our first step is to determine just what the underlying OS is */ #ifdef __ISDEVC__ /* This is not Unix, hence no fgetln() and sgets() is somewhat less safe. We hope the user will not input more than 1024 characteres at a time. */ char * sgets(void) { int MAXCHARS = 1024; char * temp = (char *)malloc(MAXCHARS); char * resultado; fgets(temp,MAXCHARS,stdin); resultado = (char *)malloc(strlen(temp)); strcpy(resultado, temp); resultado[strlen(resultado)-1] = '\0'; free(temp); return resultado; } /* strcasecmp() is not defined, hence we try to produce a reasonable facsimile */ int strcasecmp(const char * big, const char * little) { int i,n; char * _big = (char *)malloc(sizeof(char)*(strlen(big)+1)); char * _little = (char *)malloc(sizeof(char)*(strlen(little)+1)); int result; /* Store the original values */ strcpy(_big, big); strcpy(_little,little); /* Translate into lowercase both _big and _little */ n = strlen(_big); for(i=0;i<n;i++) _big[i] = tolower(_big[i]); n = strlen(_little); for(i=0;i<n;i++) _little[i] = tolower(_little[i]); /* Find out whether little and big are equal after translating into lowercase */ result = strcmp(_big,_little); /* No leaks! */ free(_big); free(_little); /* And tell what happened */ return result; } #else /* This is Unix, hence fgetln() is available but getch() is not. We produce a reasonable implementation of sgets() and of getch() */ char * sgets(void) { char * puntero_linea; size_t longitud_linea; char * resultado; puntero_linea = fgetln(stdin, &longitud_linea); resultado = (char *)malloc(longitud_linea+2); memcpy(resultado,puntero_linea,longitud_linea); resultado[longitud_linea-1] = '\0'; return resultado; } char getch(void) { struct termios conf_vieja, conf_nueva; char c; tcgetattr(0,&conf_vieja); conf_nueva = conf_vieja; conf_nueva.c_lflag &= (~ICANON); conf_nueva.c_cc[VTIME] = 0; conf_nueva.c_cc[VMIN] = 1; tcsetattr(0,TCSANOW,&conf_nueva); c = getchar(); tcsetattr(0,TCSANOW,&conf_vieja); return c; } #endif /* Once we have sgets() and getch() at our disposal, we build further useful functions like pedir (ask) and confirmar (confirm). All these functions are shared between platforms. */ char * pedir(const char * indicacion) { char * resultado; printf("%s ", indicacion); resultado = sgets(); return resultado; } void spause(void) { char * temp; printf("\n\nPulse <INTRO> para continuar\n\n"); temp = sgets(); free(temp); return; } int confirmar(char * indicacion) { char * respuesta; printf("%s (s/n): ", indicacion); respuesta = sgets(); return toupper(respuesta[0]) == 'S'; } |
main.h |
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<ctype.h> #ifndef __PROGRAMAPRINCIPAL__ #define __PROGRAMAPRINCIPAL__ #include "utiles.h" #define MAX_REGISTROS 10 struct Registro { char nombre[20]; int edad; float talla; }; typedef struct Global { struct Registro bdd[MAX_REGISTROS]; } Global; typedef void (*pfuncion)(Global *); void dispatcher( char * pm, char * ov[], struct Global * pg, pfuncion pf[]); void iniciacion(Global * pg, int argc, char * argv[]); void terminacion(Global * pg); void ayuda(Global * pg); void altas(Global * pg); void bajas(Global * pg); void modificaciones(Global * pg); void informes(Global * pg); void salir(Global * pg); void mostrar(struct Registro * p); void rellenar(struct Registro * p); #endif |
main.c |
#include "main.h" /****************************************************************/ int main(int argc, char * argv[]) { Global * pg = (Global *)malloc(sizeof(Global)); char menu[] = "A)ltas B)ajas M)odificaciones I)nformes H)Ayuda S)alir"; char * opcionesvalidas[] = { "A", /* Ojo: el orden de opciones tiene que */ "B", /* ser igual al orden de funciones */ "M", "I", "H", "S" }; pfuncion pfun[] = { &altas, /* Ojo: el orden de funciones tiene que ser */ &bajas, /* igual al orden de opciones */ &modificaciones, &informes, &ayuda, &salir, NULL /* Marcador de fin de lista al estilo de las cadenas */ }; /* Las opciones válidas pueden ser tanto caracteres individuales como palabras completas. */ iniciacion(pg, argc, argv); dispatcher( menu, opcionesvalidas, pg, pfun); terminacion(pg); puts("\n\nThat's all folks!\n"); return 0; } /****************************************************************/ void mostrar(struct Registro * p) { printf("%20s %4d %6.2f\n", p->nombre, p->edad, p->talla); } void rellenar(struct Registro * p) { char * n; do { printf("\nEscriba el nombre: "); n = sgets(); strcpy(p->nombre, n); free(n); /* No hay fuga de memoria */ } while (0 == strlen(p->nombre)); do { printf("\nEscriba la edad: "); n = sgets(); p->edad = strtol(n, NULL, 10); free(n); } while (p->edad <1 || p->edad >100); do { printf("\nEscriba la talla (cm): "); n = sgets(); p->talla = strtof(n, NULL); free(n); } while (p->talla <=100.0 || p->talla >=230); } void iniciacion(Global * pg, int argc, char * argv[]) { int i; for(i=0;i<MAX_REGISTROS;i++) { strcpy(pg->bdd[i].nombre,""); pg->bdd[i].edad = 0; pg->bdd[i].talla = 0.0; } } void altas(Global * pg) { int i,n; n = -1; printf("\n\nAltas\n\n"); for(i=0;i<MAX_REGISTROS;i++) if (0 == pg->bdd[i].edad) { n = i; break; } if(-1 != n) rellenar(&(pg->bdd[n])); else printf("Base de datos llena!%c\n", 7); spause(); } void bajas(Global * pg) { int i,n; char * s; for(i=0;i<MAX_REGISTROS; i++) { if (0 != pg->bdd[i].edad) { mostrar(&(pg->bdd[i])); } } printf("\nEscriba el índice del registro que desea eliminar: "); s = sgets(); n = strtol(s, NULL, 10); free(s); pg->bdd[n].edad = 0; spause(); } void modificaciones(Global * pg) { int i,n; char * s; for(i=0;i<MAX_REGISTROS; i++) if (0 != pg->bdd[i].edad) mostrar(&(pg->bdd[i])); printf("\nModificaciones\n\nEscriba el índice del registro que desea modificar: "); s = sgets(); n = strtol(s, NULL, 10); free(s); /* no hay fuga */ rellenar(&(pg->bdd[n])); spause(); } void informes(Global * pg) { int i,n; char * s; printf("\nInformes\n\nEscriba la edad que desea buscar: "); s = sgets(); n = strtol(s, NULL, 10); free(s); /* No hay fuga */ printf("\nLista de registros hallados\n\n"); for(i=0;i<MAX_REGISTROS; i++) { if (n == pg->bdd[i].edad) { mostrar(&(pg->bdd[i])); } } printf("\n\nFin de la lista de registros hallados\n\n"); spause(); } void ayuda(Global * pg) { printf("\n\nAyuda\n\n"); spause(); } void terminacion(Global * pg) { int i; puts("\nEl contenido de la base de datos es:\n\n"); for(i=0;i<MAX_REGISTROS;i++) mostrar(&(pg->bdd[i])); printf("\n\nFin del listado\n\n"); } /****************************************************************/ void dispatcher( char * pm, char * ov[], Global * pg, pfuncion pf[]) { char * temp = NULL; /* Para leer la instrucción */ int instruccion; /* dada por el usuario */ int num_opciones = 0; int i; /* Recuento de opciones */ while(pf[num_opciones] != NULL) num_opciones++; /* Bucle principal de ejecución */ do { printf("%s ", pm); temp = sgets(); instruccion = -1; for(i=0;i<num_opciones;i++) if(0==strcasecmp(ov[i],temp)) { instruccion = i; break; } system(BORRAR); if (-1 != instruccion) pf[instruccion](pg); else printf("%c", 7); free(temp); /* Se libera la memoria reservada por sgets() */ } while (&salir != pf[instruccion]); } /* Fin de dispatcher() */ /****************************************************************/ void salir(struct Global * pg) { return; } |
makefile |
OBJECTS = main.o utiles.o CC = gcc #FLAGS = -D__ISWINDOWS__ FLAGS = -D__ISUNIX__ program: $(OBJECTS) $(CC) $(FLAGS) $(OBJECTS) -o program utiles.o: utiles.c utiles.h $(CC) $(FLAGS) -c utiles.c -o utiles.o main.o: main.c utiles.h main.h $(CC) $(FLAGS) -c main.c clean: rm *.o rm program windows_clean: del *.o del program.exe |
utiles.h |
#include<stdio.h> #ifndef __UTILES__ #define __UTILES__ char * sgets(void); void spause(void); int confirmar(char * indicacion); char * pedir(const char * indicacion); #ifdef __ISDEVC__ #define BORRAR "cls" int strcasecmp(const char * big, const char * little); #else #define BORRAR "clear" #include<termios.h> char getch(void); #endif #endif |
utiles.c |
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<ctype.h> #include "utiles.h" /* sgets() has different implementations in Unix and elsewhere, hence our first step is to determine just what the underlying OS is */ #ifdef __ISDEVC__ /* This is not Unix, hence no fgetln() and sgets() is somewhat less safe. We hope the user will not input more than 1024 characteres at a time. */ char * sgets(void) { int MAXCHARS = 1024; char * temp = (char *)malloc(MAXCHARS); char * resultado; fgets(temp,MAXCHARS,stdin); resultado = (char *)malloc(strlen(temp)); strcpy(resultado, temp); resultado[strlen(resultado)-1] = '\0'; free(temp); return resultado; } /* strcasecmp() is not defined, hence we try to produce a reasonable facsimile */ int strcasecmp(const char * big, const char * little) { int i,n; char * _big = (char *)malloc(sizeof(char)*(strlen(big)+1)); char * _little = (char *)malloc(sizeof(char)*(strlen(little)+1)); int result; /* Store the original values */ strcpy(_big, big); strcpy(_little,little); /* Translate into lowercase both _big and _little */ n = strlen(_big); for(i=0;i<n;i++) _big[i] = tolower(_big[i]); n = strlen(_little); for(i=0;i<n;i++) _little[i] = tolower(_little[i]); /* Find out whether little and big are equal after translating into lowercase */ result = strcmp(_big,_little); /* No leaks! */ free(_big); free(_little); /* And tell what happened */ return result; } #else /* This is Unix, hence fgetln() is available but getch() is not. We produce a reasonable implementation of sgets() and of getch() */ char * sgets(void) { char * puntero_linea; size_t longitud_linea; char * resultado; puntero_linea = fgetln(stdin, &longitud_linea); resultado = (char *)malloc(longitud_linea+2); memcpy(resultado,puntero_linea,longitud_linea); resultado[longitud_linea-1] = '\0'; return resultado; } char getch(void) { struct termios conf_vieja, conf_nueva; char c; tcgetattr(0,&conf_vieja); conf_nueva = conf_vieja; conf_nueva.c_lflag &= (~ICANON); conf_nueva.c_cc[VTIME] = 0; conf_nueva.c_cc[VMIN] = 1; tcsetattr(0,TCSANOW,&conf_nueva); c = getchar(); tcsetattr(0,TCSANOW,&conf_vieja); return c; } #endif /* Once we have sgets() and getch() at our disposal, we build further useful functions like pedir (ask) and confirmar (confirm). All these functions are shared between platforms. */ char * pedir(const char * indicacion) { char * resultado; printf("%s ", indicacion); resultado = sgets(); return resultado; } void spause(void) { char * temp; printf("\n\nPulse <INTRO> para continuar\n\n"); temp = sgets(); free(temp); return; } int confirmar(char * indicacion) { char * respuesta; printf("%s (s/n): ", indicacion); respuesta = sgets(); return toupper(respuesta[0]) == 'S'; } |
main.h |
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<ctype.h> #ifndef __PROGRAMAPRINCIPAL__ #define __PROGRAMAPRINCIPAL__ #include "utiles.h" #define MAX_REGISTROS 10000 struct Registro { char nombre[20]; int edad; float talla; }; typedef struct Global { struct Registro bdd[MAX_REGISTROS]; } Global; typedef void (*pfuncion)(Global *); void dispatcher( char * pm, char * ov[], struct Global * pg, pfuncion pf[]); void iniciacion(Global * pg, int argc, char * argv[]); void terminacion(Global * pg); void ayuda(Global * pg); void altas(Global * pg); void bajas(Global * pg); void modificaciones(Global * pg); void informes(Global * pg); void salir(Global * pg); void mostrar(struct Registro * p); void rellenar(struct Registro * p); void abrir(Global * p); void guardar(Global * p); #endif |
main.c |
#include "main.h" /****************************************************************/ int main(int argc, char * argv[]) { Global * pg = (Global *)malloc(sizeof(Global)); char menu[] = "O)Abrir G)uardar A)ltas B)ajas M)odificaciones I)nformes H)Ayuda S)alir"; char * opcionesvalidas[] = { "O", "G", "A", /* Ojo: el orden de opciones tiene que */ "B", /* ser igual al orden de funciones */ "M", "I", "H", "S" }; pfuncion pfun[] = { &abrir, &guardar, &altas, /* Ojo: el orden de funciones tiene que ser */ &bajas, /* igual al orden de opciones */ &modificaciones, &informes, &ayuda, &salir, NULL /* Marcador de fin de lista al estilo de las cadenas */ }; /* Las opciones válidas pueden ser tanto caracteres individuales como palabras completas. */ iniciacion(pg, argc, argv); dispatcher( menu, opcionesvalidas, pg, pfun); terminacion(pg); puts("\n\nThat's all folks!\n"); return 0; } /****************************************************************/ void mostrar(struct Registro * p) { printf("%20s %4d %6.2f\n", p->nombre, p->edad, p->talla); } void rellenar(struct Registro * p) { char * n; do { printf("\nEscriba el nombre: "); n = sgets(); strcpy(p->nombre, n); free(n); /* No hay fuga de memoria */ } while (0 == strlen(p->nombre)); do { printf("\nEscriba la edad: "); n = sgets(); p->edad = strtol(n, NULL, 10); free(n); } while (p->edad <=0 || p->edad >100); do { printf("\nEscriba la talla (cm): "); n = sgets(); p->talla = strtof(n, NULL); free(n); } while (p->talla <=1.0 || p->talla >=230); } void iniciacion(Global * pg, int argc, char * argv[]) { int i; for(i=0;i<MAX_REGISTROS;i++) { strcpy(pg->bdd[i].nombre,""); pg->bdd[i].edad = 0; pg->bdd[i].talla = 0.0; } } void altas(Global * pg) { int i,n; n = -1; printf("\n\nAltas\n\n"); for(i=0;i<MAX_REGISTROS;i++) if (0 == pg->bdd[i].edad) { n = i; break; } if(-1 != n) rellenar(&(pg->bdd[n])); else printf("Base de datos llena!%c\n", 7); spause(); } void bajas(Global * pg) { int i,n; char * s; for(i=0;i<MAX_REGISTROS; i++) if (0 == pg->bdd[i].edad) mostrar(&(pg->bdd[i])); printf("\nEscriba el índice del registro que desea eliminar: "); s = sgets(); n = strtol(s, NULL, 10); pg->bdd[n].edad = 0; spause(); } void modificaciones(Global * pg) { int i,n; char * s; for(i=0;i<MAX_REGISTROS; i++) if (0 != pg->bdd[i].edad) mostrar(&(pg->bdd[i])); printf("\nModificaciones\n\nEscriba el índice del registro que desea modificar: "); s = sgets(); n = strtol(s, NULL, 10); free(s); /* no hay fuga */ rellenar(&(pg->bdd[n])); spause(); } void informes(Global * pg) { int i,n; char * s; printf("\nInformes\n\nEscriba la edad que desea buscar: "); s = sgets(); n = strtol(s, NULL, 10); free(s); /* No hay fuga */ printf("\nLista de registros hallados\n\n"); for(i=0;i<MAX_REGISTROS; i++) if (n == pg->bdd[i].edad) mostrar(&(pg->bdd[i])); printf("\n\nFin de la lista de registros hallados\n\n"); spause(); } void ayuda(Global * pg) { printf("\n\nAyuda\n\n"); spause(); } void terminacion(Global * pg) { int i; puts("\nEl contenido de la base de datos es:\n\n"); for(i=0;i<MAX_REGISTROS;i++) mostrar(&(pg->bdd[i])); printf("\n\nFin del listado\n\n"); } /****************************************************************/ void dispatcher( char * pm, char * ov[], Global * pg, pfuncion pf[]) { char * temp = NULL; /* Para leer la instrucción */ int instruccion; /* dada por el usuario */ int num_opciones = 0; int i; /* Recuento de opciones */ while(pf[num_opciones] != NULL) num_opciones++; /* Bucle principal de ejecución */ do { printf("%s ", pm); temp = sgets(); instruccion = -1; for(i=0;i<num_opciones;i++) if(0==strcasecmp(ov[i],temp)) { instruccion = i; break; } system(BORRAR); if (-1 != instruccion) pf[instruccion](pg); else printf("%c", 7); free(temp); /* Se libera la memoria reservada por sgets() */ } while (&salir != pf[instruccion]); } /* Fin de dispatcher() */ /****************************************************************/ void salir(struct Global * pg) { return; } void abrir(Global * pg) { FILE * fp; fp = fopen("datos.bin", "rb"); fread(pg->bdd, sizeof(pg->bdd), 1, fp); fclose(fp); } void guardar(Global * pg) { FILE * fp; fp = fopen("datos.bin", "wb"); fwrite(pg->bdd, sizeof(pg->bdd), 1, fp); /* fwrite(pg->bdd, sizeof(struct Registro), MAX_REGISTROS, fp); */ fclose(fp); } |
makefile |
OBJECTS = main.o utiles.o program: $(OBJECTS) cc $(OBJECTS) -o program utiles.o: utiles.c utiles.h cc -c utiles.c -o utiles.o main.o: main.c utiles.h main.h cc -c main.c clean: rm utiles.o rm *.o rm program |
utiles.h |
#include<stdio.h> #ifndef __UTILES__ #define __UTILES__ char * sgets(void); void spause(void); int confirmar(char * indicacion); char * pedir(const char * indicacion); #ifdef __ISDEVC__ #define BORRAR "cls" int strcasecmp(const char * big, const char * little); #else #define BORRAR "clear" #include<termios.h> char getch(void); #endif #endif |
utiles.c |
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<ctype.h> #include "utiles.h" /* sgets() has different implementations in Unix and elsewhere, hence our first step is to determine just what the underlying OS is */ #ifdef __ISDEVC__ /* This is not Unix, hence no fgetln() and sgets() is somewhat less safe. We hope the user will not input more than 1024 characteres at a time. */ char * sgets(void) { int MAXCHARS = 1024; char * temp = (char *)malloc(MAXCHARS); char * resultado; fgets(temp,MAXCHARS,stdin); resultado = (char *)malloc(strlen(temp)); strcpy(resultado, temp); resultado[strlen(resultado)-1] = '\0'; free(temp); return resultado; } /* strcasecmp() is not defined, hence we try to produce a reasonable facsimile */ int strcasecmp(const char * big, const char * little) { int i,n; char * _big = (char *)malloc(sizeof(char)*(strlen(big)+1)); char * _little = (char *)malloc(sizeof(char)*(strlen(little)+1)); int result; /* Store the original values */ strcpy(_big, big); strcpy(_little,little); /* Translate into lowercase both _big and _little */ n = strlen(_big); for(i=0;i<n;i++) _big[i] = tolower(_big[i]); n = strlen(_little); for(i=0;i<n;i++) _little[i] = tolower(_little[i]); /* Find out whether little and big are equal after translating into lowercase */ result = strcmp(_big,_little); /* No leaks! */ free(_big); free(_little); /* And tell what happened */ return result; } #else /* This is Unix, hence fgetln() is available but getch() is not. We produce a reasonable implementation of sgets() and of getch() */ char * sgets(void) { char * puntero_linea; size_t longitud_linea; char * resultado; puntero_linea = fgetln(stdin, &longitud_linea); resultado = (char *)malloc(longitud_linea+2); memcpy(resultado,puntero_linea,longitud_linea); resultado[longitud_linea-1] = '\0'; return resultado; } char getch(void) { struct termios conf_vieja, conf_nueva; char c; tcgetattr(0,&conf_vieja); conf_nueva = conf_vieja; conf_nueva.c_lflag &= (~ICANON); conf_nueva.c_cc[VTIME] = 0; conf_nueva.c_cc[VMIN] = 1; tcsetattr(0,TCSANOW,&conf_nueva); c = getchar(); tcsetattr(0,TCSANOW,&conf_vieja); return c; } #endif /* Once we have sgets() and getch() at our disposal, we build further useful functions like pedir (ask) and confirmar (confirm). All these functions are shared between platforms. */ char * pedir(const char * indicacion) { char * resultado; printf("%s ", indicacion); resultado = sgets(); return resultado; } void spause(void) { char * temp; printf("\n\nPulse <INTRO> para continuar\n\n"); temp = sgets(); free(temp); return; } int confirmar(char * indicacion) { char * respuesta; printf("%s (s/n): ", indicacion); respuesta = sgets(); return toupper(respuesta[0]) == 'S'; } |
main.h |
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<ctype.h> #ifndef __PROGRAMAPRINCIPAL__ #define __PROGRAMAPRINCIPAL__ #include "utiles.h" #define MAX_REGISTROS 10000 struct Registro { char nombre[20]; int edad; float talla; }; typedef struct Global { struct Registro *bdd; int num_registros; } Global; typedef void (*pfuncion)(Global *); void dispatcher( char * pm, char * ov[], struct Global * pg, pfuncion pf[]); void iniciacion(Global * pg, int argc, char * argv[]); void terminacion(Global * pg); void ayuda(Global * pg); void altas(Global * pg); void bajas(Global * pg); void modificaciones(Global * pg); void informes(Global * pg); void salir(Global * pg); void mostrar(struct Registro * p); void rellenar(struct Registro * p); void abrir(Global * p); void guardar(Global * p); #endif |
main.c |
#include "main.h" /****************************************************************/ int main(int argc, char * argv[]) { Global * pg = (Global *)malloc(sizeof(Global)); char menu[] = "O)Abrir G)uardar A)ltas B)ajas M)odificaciones I)nformes H)Ayuda S)alir"; char * opcionesvalidas[] = { "O", "G", "A", /* Ojo: el orden de opciones tiene que */ "B", /* ser igual al orden de funciones */ "M", "I", "H", "S" }; pfuncion pfun[] = { &abrir, &guardar, &altas, /* Ojo: el orden de funciones tiene que ser */ &bajas, /* igual al orden de opciones */ &modificaciones, &informes, &ayuda, &salir, NULL /* Marcador de fin de lista al estilo de las cadenas */ }; /* Las opciones válidas pueden ser tanto caracteres individuales como palabras completas. */ iniciacion(pg, argc, argv); dispatcher( menu, opcionesvalidas, pg, pfun); terminacion(pg); puts("\n\nThat's all folks!\n"); return 0; } /****************************************************************/ void mostrar(struct Registro * p) { printf("%20s %4d %6.2f\n", p->nombre, p->edad, p->talla); } void rellenar(struct Registro * p) { char * n; do { printf("\nEscriba el nombre: "); n = sgets(); strcpy(p->nombre, n); free(n); /* No hay fuga de memoria */ } while (0 == strlen(p->nombre)); do { printf("\nEscriba la edad: "); n = sgets(); p->edad = strtol(n, NULL, 10); free(n); } while (p->edad <=0 || p->edad >100); do { printf("\nEscriba la talla (cm): "); n = sgets(); p->talla = strtof(n, NULL); free(n); } while (p->talla <=1.0 || p->talla >=230); } void iniciacion(Global * pg, int argc, char * argv[]) { int i; pg->bdd = NULL; } void altas(Global * pg) { int i,n; n = -1; printf("\n\nAltas\n\n"); for(i=0;i<pg->num_registros;i++) if (0 == pg->bdd[i].edad) { n = i; break; } if(-1 != n) rellenar(&(pg->bdd[n])); else printf("Base de datos llena o inexistente%c\n", 7); spause(); } void bajas(Global * pg) { int i,n; char * s; int num_posibles_bajas = 0; for(i=0;i<pg->num_registros; i++) if (0 != pg->bdd[i].edad) { mostrar(&(pg->bdd[i])); num_posibles_bajas++; }; if(0 == num_posibles_bajas) { printf("\n\nBase de datos vacía\n\n"); } else { printf("\nEscriba el índice del registro que desea eliminar: "); s = sgets(); n = strtol(s, NULL, 10); pg->bdd[n].edad = 0; } spause(); } void modificaciones(Global * pg) { int i,n; char * s; int num_posibles_modificaciones = 0; for(i=0;i<pg->num_registros; i++) if (0 != pg->bdd[i].edad) { mostrar(&(pg->bdd[i])); num_posibles_modificaciones++; } if (0 == num_posibles_modificaciones) { printf("\n\nBase de datos vacía o inexistente\n\n"); } else { printf("\nModificaciones\n\nEscriba el índice del registro que desea modificar: "); s = sgets(); n = strtol(s, NULL, 10); free(s); /* no hay fuga */ rellenar(&(pg->bdd[n])); } spause(); } void informes(Global * pg) { int i,n; char * s; if (0 == pg->num_registros) { printf("\n\nBase de datos vacía.\n\n"); } else { printf("\nInformes\n\nEscriba la edad que desea buscar: "); s = sgets(); n = strtol(s, NULL, 10); free(s); /* No hay fuga */ printf("\nLista de registros hallados\n\n"); for(i=0;i<pg->num_registros; i++) if (n == pg->bdd[i].edad) mostrar(&(pg->bdd[i])); printf("\n\nFin de la lista de registros hallados\n\n"); } spause(); } void ayuda(Global * pg) { printf("\n\nAyuda\n\n"); spause(); } void terminacion(Global * pg) { int i; if (0 == pg->num_registros) { printf("\n\nBase de datos vacía.\n\n"); } else { puts("\nEl contenido de la base de datos es:\n\n"); for(i=0;i<pg->num_registros;i++) if (0 != pg->bdd[i].edad) mostrar(&(pg->bdd[i])); printf("\n\nFin del listado\n\n"); free(pg->bdd); } } /****************************************************************/ void dispatcher( char * pm, char * ov[], Global * pg, pfuncion pf[]) { char * temp = NULL; /* Para leer la instrucción */ int instruccion; /* dada por el usuario */ int num_opciones = 0; int i; /* Recuento de opciones */ while(pf[num_opciones] != NULL) num_opciones++; /* Bucle principal de ejecución */ do { printf("%s ", pm); temp = sgets(); instruccion = -1; for(i=0;i<num_opciones;i++) if(0==strcasecmp(ov[i],temp)) { instruccion = i; break; } system(BORRAR); if (-1 != instruccion) pf[instruccion](pg); else printf("%c", 7); free(temp); /* Se libera la memoria reservada por sgets() */ } while (&salir != pf[instruccion]); } /* Fin de dispatcher() */ /****************************************************************/ void salir(struct Global * pg) { if (confirmar("Desea guardar los cambios?")) guardar(pg); else printf("\n\nNo se han guardado los cambios.\n\n"); return; } void abrir(Global * pg) { FILE * fp; struct Registro registro = {"", 0, 0.0 }; int i; fp = fopen("datos.bin", "rb"); if (NULL == fp) { /* la base de datos no existe, la creamos */ fp = fopen("datos.bin", "wb"); for(i=0;i<MAX_REGISTROS;i++) fwrite(®istro, sizeof(struct Registro),1,fp); fclose(fp); printf("\n\nBase de datos creada... por favor, arranque de nuevo.\n\n"); exit(0); } else { /* Calculamos el número de registros que hay en el archivo */ fseek(fp,0,SEEK_END); pg->num_registros = ftell(fp)/sizeof(struct Registro); printf("\n\nSe han leído %d registros\n", pg->num_registros); /* Creamos un bloque de tamaño adecuado */ pg->bdd = calloc(pg->num_registros,sizeof(struct Registro)); /* Ponemos el puntero de archivo al principio */ fseek(fp,0,SEEK_SET); fread(pg->bdd, sizeof(struct Registro), pg->num_registros, fp); fclose(fp); } } void guardar(Global * pg) { FILE * fp; if (0 != pg->num_registros) { fp = fopen("datos.bin", "wb"); fwrite(pg->bdd, sizeof(struct Registro), pg->num_registros, fp); fclose(fp); } else { printf("\n\nLa base de datos está vacía y no se ha guardado.\n\n"); } } |
makefile |
OBJECTS = main.o utiles.o program: $(OBJECTS) cc $(OBJECTS) -o program utiles.o: utiles.c utiles.h cc -c utiles.c -o utiles.o main.o: main.c utiles.h main.h cc -c main.c clean: rm utiles.o rm *.o rm program |