Using a linked list of structures representing a person’s name





/*

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 <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <ctype.h>



#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)==&& 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 != ? 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                    */

}



 



           

       

Tags: , , , , , ,

Leave a Reply