Structure C

/*
Beginning C, Third Edition
 By Ivor Horton
 ISBN: 1-59059-253-0
 Published: Apr 2004
 Publisher: apress
*/
/*
   You could link the PhoneRecord structures in a list by adding a pointer member.
   I chose to define a Node structure that is a node in a linked list. Each Node 
   structure will contain a pointer to a PhoneRecord structure and a pointer to
   the next Node structure. Memory for Node and PhoneRecord structures are allocated
   dynamically. You could extend this to allocate memory for names and numbers too.
*/
#include 
#include 
#include 
#include 
#define FIRST_NAME_LEN  31
#define SECOND_NAME_LEN 51
#define NUMBER_LEN      16
#define TRUE             1
#define FALSE            0
/* Structure defining a name */
struct Name
{
  char firstname[FIRST_NAME_LEN];
  char secondname[SECOND_NAME_LEN];
};
/* Structure defining a phone record */
struct PhoneRecord
{
  struct Name name;
  char number[NUMBER_LEN];
};
/* Structure defining a node in a linked list of PhoneRecord structures */
struct Node
{
  struct PhoneRecord *pRecord;     /* Pointer to a PhoneRecord structure   */
  struct Node *pNext;              /* Pointer to the next node in the list */
};
struct Name read_name();                /* Read a name from the keyboard      */               
void show(struct PhoneRecord *pRecord); /* Output a phone record              */
int has_name(struct PhoneRecord record, struct Name name); /* Test for a name */
struct Node* create_node();             /* Create a new list node             */
struct PhoneRecord* create_record();    /* Create a new phone record          */
void insert_node(struct Node *pNode);   /* Insert a node in the list          */
int compare_records(struct PhoneRecord *pFirst, struct PhoneRecord *pSecond);  /* Compare records */
int compare_names(struct Name first, struct Name second); /* Compare two names                     */
void list_numbers(struct Name name);    /* List all numbers for a Name structure */
struct Node *pStart = NULL;
void main()
{
  char answer = 'n';
  struct Node *pNode = NULL;                /* Pointer to a list node              */
  struct PhoneRecord *pRecord = NULL;       /* Pointer to a PhoneRecord structure  */
  int found = FALSE;                        /* Records when a name has been found  */
  int i = 0;                                /* Loop control variable               */
 
  /* Read an arbitrary number of phone records from the keyboard */  
  do
  {
    insert_node(create_node());      /* Create and insert new node */
    printf("Do you want to enter another(y or n)?: ");
    scanf(" %c", &answer);
  }while(tolower(answer) == 'y');
  /* Search the list of phone records for a number */
  do
  {
    printf("\nEnter a name for which you want the number.");
    list_numbers(read_name());
    printf("Do you want to search for another (y or n)? ");
    scanf(" %c" , &answer);
  }while(tolower(answer) == 'y');
  /* List all the records in the linked list */
  pNode = pStart;
  do
  {
    show(pNode->pRecord);
  }while((pNode = pNode->pNext) != 0);
  printf("\n");
  /* Don't forget to free the memory! */
  pNode = pStart;
  do
  {
    free(pNode->pRecord);    /* Free memory for the record from the current node */
    pStart = pNode;          /* Save current node address                        */
    pNode = pNode->pNext;    /* Get next node address                            */
    free(pStart);            /* Free memory for the current node                 */
  }while((pNode = pNode->pNext) != 0);
}
/* Read a name from the keyboard and store in a structure */
struct Name read_name()
{
  unsigned long inches = 0;
  struct Name name;
    printf("\nEnter a first name: ");
    scanf(" %s", &name.firstname);
    printf("Enter a second name: ");
    scanf(" %s", &name.secondname);
  return name;
}
/* Output a record */
void show(struct PhoneRecord *pRecord)
{
  printf("\n%s %s   %s", pRecord->name.firstname, pRecord->name.secondname, pRecord->number);
}
int has_name(struct PhoneRecord record, struct Name name)
{
  return (strcmp(name.firstname, record.name.firstname)==0 && strcmp(name.secondname, record.name.secondname)==0);
}
/* Create a new list node */
struct Node* create_node()
{
  struct Node *pNode = NULL;                         /* Pointer to the new node                 */
  pNode = (struct Node*)malloc(sizeof(struct Node)); /* Allocate memory for node                */
  pNode->pNext = NULL;                               /* No next node yet                        */
  pNode->pRecord = create_record();                  /* Create record and store address in node */
  return pNode;
}
/* Create a new phone record    */
struct PhoneRecord* create_record() 
{
  struct PhoneRecord *pRecord = NULL;             /* Pointer to the new record */
  pRecord = (struct PhoneRecord*)malloc(sizeof(struct PhoneRecord)); /* Allocate memory */
  pRecord->name = read_name();                    /* Read the name             */      
  /* Get the number for the name */
  printf("Enter the number for this name: ");
  scanf(" %[ 0123456789]",pRecord->number);       /* Read the number - including spaces */
  return pRecord;                                 /* Return the address of the record   */
}
/*
  Compare two PhoneRecord structures
  Returns -1 if the name for the first is < name for the second
  Returns  0 if the name for the first is equal to the name for the second
  Returns +1 if the name for the first is > name for the second
*/
int compare_records(struct PhoneRecord *pFirst, struct PhoneRecord *pSecond)
{
  return compare_names(pFirst->name, pSecond->name);
}
/* Compare two names
  Returns -1 if the  first is < the second
  Returns  0 if the first is equal to tthe second
  Returns +1 if the first is >  the second
  The comparison is by second name. If second names are equal,
  first names are compared.
*/
int compare_names(struct Name first, struct Name second)
{
  int result = 0;
  result = strcmp(first.secondname,second.secondname);
  return (result != 0 ? result : strcmp(first.firstname,second.firstname));
}
/* Insert a node into the list */
void insert_node(struct Node *pNode)
{
  struct Node *pCurrent = NULL;
  struct Node *pPrevious = NULL;
  struct Node *pTemp = NULL;
  /* Check for empty list */
  if(pStart == NULL)
  {
    pStart = pNode;   /* Store address of the node as the start node */
    return;
  }
  /* Find position to insert the new node */
  pCurrent = pStart;
  while(pCurrent != NULL)
  {
    if(compare_records(pNode->pRecord, pCurrent->pRecord) <= 0)
    {                          /* New node goes before current list node */
      pNode->pNext = pCurrent; /* Set new node next pointer to current   */
      if(pPrevious == NULL)    /* If pCurrent is the first node          */
      {                        
        pNode->pNext = pStart; /* New node next pointer points to current */
        pStart = pNode;        /* New node is the first node              */
      }
      else
      {                           /* Otherwise... */
        pPrevious->pNext = pNode; /* Previous node next pointer points to new node */
        pNode->pNext = pCurrent;  /* New node next pointer points to current       */
      }
      return;
    }
    pPrevious = pCurrent;         /* Previous node will be the current node */
    pCurrent = pCurrent->pNext;   /* Current node is now the next node      */   
  }
  /* If we reach here, add pNode to the end */
  pPrevious->pNext = pNode;
}
/* List the numbers for a name */
void list_numbers(struct Name name)
{
  struct Node *pNode = NULL;
  int found = FALSE;
  int result = 0;
  /* Go through the list comparing names */
  pNode = pStart;
  while(pNode != NULL)
  {
    result = compare_names(name, pNode->pRecord->name);
    if(result == 0)
    {
      if(!found)                                    /* If this is the first time      */
      {
        found = TRUE;                               /* Reset found flag               */
        printf("The numbers for this name are:\n"); /* and output the heading         */
      }
      printf("%s\n", pNode->pRecord->number);       /* Output the number for the name */
    }
   else if(result < 0)                              /* If name comes before current   */
      break;                                        /* we are done                    */
    pNode = pNode->pNext;                           /* Otherwise move to next node    */
  }
  if(!found)                                         /* If the name was not found */
    printf("No numbers found for this name.\n");     /* Say so                    */
}