Ejercicios Resueltos







Una base de datos sencilla
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



Una base de datos con soporte en un archivo binario
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



Una base de datos dinámica con soporte binario
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(&registro, 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