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)==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 */
}
Related examples in the same category