/*************************************************************************/
/* ALTER: Eine einfache Datenverwaltung zur Demonstration der Verkettung */
/*        über Zeiger, der VERKETTETEN LISTEN                            */
/*-----------------------------------------------------------------------*/
/*                      (C) by Dirk Owerfeldt '89                        */
/*************************************************************************/

/*----------*/
/* Includes */
/*----------*/

#include <exec/types.h>
#include <stdio.h>

#define REG register
#define BOOLEAN BOOL
#define CHAR char

#define CLS   fputchar ( 0xc )
#define TASTE printf("-- Return --"); gets ( hilf )

/*---------------------------------*/
/* Funktionsprototypen fuer ANSI-C */
/*---------------------------------*/

extern VOID eingabe ( VOID );
extern VOID loesche( VOID );
extern VOID zeige( VOID );
extern VOID suche( VOID );


/*-------------------*/
/* Die Datenstruktur */
/*-------------------*/

char hilf[ 50 ];
 
typedef struct DATENBLATT
{
     BYTE name[40];
     WORD alter;

     struct DATENBLATT *link;

} DATENBLATT;

DATENBLATT *Liste;


/*-----------------------------------------------*/
/* Fügt neues Datenblatt am Anfang der Liste ein */
/*-----------------------------------------------*/

VOID create(name,alter)
char *name;
WORD alter;
{
   DATENBLATT *hp;

   hp = (DATENBLATT *) malloc(sizeof(DATENBLATT));  

   /* Inhalt in neues Datenblatt eintragen */

   hp->alter = alter;
   strcpy(hp->name,name);
         
   /* Neues Datenblatt am Anfang der */
   /* Liste einklinken               */

   hp->link = Liste;
   Liste    = hp;  
}




/*------------------------------------------------*/
/* Einfügen eines neuen Datenblattes (name,alter) */
/* hinter dem Listenelement, aus das p zeigt      */
/*------------------------------------------------*/

VOID insert(p,name,alter)
DATENBLATT *p;
char *name;
WORD alter;
{
   DATENBLATT *hp;

   hp = (DATENBLATT *) malloc(sizeof (DATENBLATT));

   hp->alter = alter;
   strcpy(hp->name,name);

   if(p!=NULL)
   {
      hp->link = p->link;
      p->link  = hp;
   }
   else
   {
      hp->link = Liste;
      Liste    = hp;
   }
}

/*----------------------------------------*/
/* Durchsucht Liste nach einem Namen      */
/* Liefert Pointer auf gefundenes Element */
/* oder NULL, wenn name nicht auffindbar  */
/*----------------------------------------*/

DATENBLATT *find(name)
char *name;
{
   DATENBLATT *hp;

   hp = Liste;

   while(hp!=NULL) 
   {
      if(!strcmp(name,hp->name))
         return(hp);

      hp = hp->link;
   }
   
   return(NULL);
}

/*------------------------------------*/
/* Löscht das Listenelement hinter cp */
/*------------------------------------*/

VOID delete(cp)
DATENBLATT *cp;
{
   DATENBLATT *free_p;

   if(cp==NULL)
   {
        free_p = Liste;               /* 1. Element löschen (SONDERFALL) */
        Liste  = Liste->link;   
   }
   else
   {
        free_p   = cp->link;          /* im Inneren löschen (Normalfall) */
        cp->link = cp->link->link;
   }

   free(free_p);
}

/***********************/
/* SORTIERTES EINFÜGEN */
/***********************/

DATENBLATT *sfind(name)
CHAR *name;
{
   register DATENBLATT *hp,*np;

   np=NULL;
   hp=Liste;

   while(hp!=NULL)
   {
      if(strcmp(name,hp->name)<0)
         return(np);

      np=hp;
      hp=hp->link;
   }
   
   return(np);
}

/*----------------------------------*/
/* Sortiertes Einfügen in die Liste */
/*----------------------------------*/

VOID sort_insert(name,alter)
CHAR *name;
WORD alter;
{
   insert( sfind(name),name,alter );
}


/*********************/
/* DAS HAUPTPROGRAMM */
/*********************/

VOID main( VOID )
{
   BOOLEAN  schleife=TRUE;

   /*----------------------*/
   /* Liste initialisieren */
   /*----------------------*/

   Liste = NULL;

   /*-----------*/
   /* Hauptmenü */
   /*-----------*/

   while(schleife)
    {
      CLS;

      printf("** Verkettete Listen **\n");
      printf("** by Dirk Owerfeldt **\n\n\n");

      printf("1) sortierte Liste anlegen\n");
      printf("2) Eintrag löschen\n");
      printf("3) Name suchen\n");
      printf("4) Liste ausgeben\n");
      printf("9) Ende\n\n");

      printf("Ihre Wahl: ");
      gets( hilf ); 

      printf("\n\n\n");

      CLS;
      switch( hilf[ 0 ] )
      {
        case '1': eingabe();
                  break;

        case '2': loesche();
                  break;

        case '3': suche();
                  break;

        case '4': zeige();
                  break;

        case '9': schleife=FALSE;
                  break;
      }
   }
}



/*---------------------------------------------*/
/* Neue Elemente einlesen, bis name='ende' ist */
/*---------------------------------------------*/

VOID eingabe( )
{
   CHAR name[40],alter[20];

   printf("** Eingabe, Abbruch durch 'ende'\n\n\n");

   while(TRUE)
   {
        printf("\nName : "); gets(name);
        if(!strcmp(name,"ende")) break;   
    
        printf("Alter: "); gets(alter);
        sort_insert(name,atoi(alter));
   }
}

/*---------------------------*/
/* Namen aus Liste entfernen */
/*---------------------------*/

VOID loesche( )
{
   REG DATENBLATT *hp,*np;
   CHAR    name[40];
   BOOLEAN gefunden;

   printf("** Name löschen **\n\n\n");

   if(Liste==NULL)
   {
      printf("Die Liste ist bereits leer!\n");
      TASTE;
      return;
   }

   printf("\nZu löschender Name: "); gets(name);

   /*--------------------------------------------------------------*/
   /* Etwas modifizierte Funktion sfind(), da genau geprüft werden */
   /* muž, ob der Name schon vorhanden ist.                        */
   /*--------------------------------------------------------------*/

   np       = NULL;
   hp       = Liste;
   gefunden = FALSE;

   while(hp!=NULL)
   {
      if(!strcmp(name,hp->name))
      {
                  gefunden=TRUE;
          break;
      }

      np=hp;
      hp=hp->link;
   }

   /*---------------------------------------*/
   /* Nur wenn diese Bedingung erfüllt ist, */ 
   /* kann wirklich gelöscht werden...      */
   /*---------------------------------------*/

   if(gefunden)
   {
     printf("Name: %s mit Alter %d gelöscht!\n\n",hp->name,hp->alter);
     delete(np);
   }
   else
      printf("Name nicht in der Liste vorhanden!\n");

   TASTE;
}

/*-----------------------------*/
/* Suche Namen bis name='ende' */
/*-----------------------------*/

VOID suche( )
{
   DATENBLATT *p;
   CHAR name[40];

   printf("** Name suchen, Abbruch durch 'ende'\n\n\n");

   while(TRUE)
   {
        printf("\nSuchen nach : "); gets(name);
        if(!strcmp(name,"ende")) return;   

        if((p=find(name))!=NULL)
           printf("Name gefunden! Das Alter ist: %d\n",p->alter);
        else
           printf("Name nicht in der Liste vorhanden!\n\n");         
   }
   TASTE;
}

/*----------------------------------------------*/
/* Ausgabe aller Namen in der verketteten Liste */
/*----------------------------------------------*/

VOID zeige( )
{
   struct DATENBLATT *hp;

   printf("\n** Alle Namen der Liste **\n\n\n");

   hp=Liste;              
   while(hp!=NULL)        /* bis Liste zuende ist */
   {
      printf(hp->name);     /* Ausgabe des Namens   */
      printf ( "\n" );
      hp = hp->link;      /* hp zeigt jetzt auf   */    
   }                      /* nächstes Elemant     */
                          /* (oder enthält NULL)  */
   TASTE;                           
}
