struct Family *get_person(void); /* Prototype for input function */
char related(struct Family *pmember1, struct Family *pmember2);
char set_ancestry(struct Family *pmember1, struct Family *pmember2);
/* Structure defining a name */
struct Name
{
char firstname[FIRST_NAME_LENGTH];
char secondname[SECOND_NAME_LENGTH];
};
/* Structure defining a phone record */
struct PhoneRecord
{
struct Name name;
char number[NUMBER_LENGTH];
};
/* Function prototypes */
struct PhoneRecord read_phonerecord(); /* Read a name and number from the keyboard */
struct Name read_name(); /* Read a name from the keyboard */
void show_record(struct PhoneRecord record); /* Output name and number from a phone record */
struct PhoneRecord find_numbers(struct Name name); /* Find numbers corresponding to a given name */
void add_record(); /* Add a new name and number */
void delete_records(struct Name name); /* Delete records for a given name */
void list_records(); /* List all the records in the file */
void show_operations(); /* Displays operations supported by the program */
int equals(struct Name name1, struct Name name2); /* Compare two names for equality */
/* Global variables */
FILE *pFile = NULL; /* File pointer */
char *filename = "C:\\records.bin"; /* Name of the file holding the records */
char answer = 'n'; /* Stores input responses */
struct Date
{
int day;
int month;
int year;
};
struct Family /* Family structure declaration */
{
struct Date dob;
char name[20];
char father[20];
char mother[20];
struct Family *next; /* Pointer to next structure */
struct Family *previous; /* Pointer to previous structure */
struct Family *p_to_pa; /* Pointer to father structure */
struct Family *p_to_ma; /* Pointer to mother structure */
};
int main()
{
struct Family *first = NULL; /* Pointer to first person */
struct Family *current = NULL; /* Pointer to current person */
struct Family *last = NULL; /* Pointer to previous person */
char more = '\0'; /* Test value for ending input */
for( ; ; )
{
printf("\nDo you want to enter details of a%s person (Y or N)? ",
first != NULL?"nother " : "" );
scanf(" %c", &more);
if(tolower(more) == 'n')
break;
current = get_person();
if(first == NULL)
{
first = current; /* Set pointer to first Family */
last = current; /* Remember for next iteration */
}
else
{
last->next = current; /* Set next address for previous Family */
current->previous = last; /* Set previous address for current */
last = current; /* Remember for next iteration */
}
}
current = first;
while(current->next != NULL) /* Check for relation for each person in */
{ /* the list up to second to last */
int parents = 0; /* Declare parent count local to this block */
last = current->next; /* Get the pointer to the next */
while(last != NULL) /* This loop tests current person */
{ /* against all the remainder in the list */
if(related(current, last)) /* Found a parent ? */
if(++parents == 2) /* Yes, update count and check it */
break; /* Exit inner loop if both parents found */
last = last->next; /* Get the address of the next */
}
current = current->next; /* Next in the list to check */
}
/* Now tell them what we know */
/* Output Family data in correct order */
current = first;
while (current != NULL) /* Output Family data in correct order */
{
printf("\n%s was born %d/%d/%d, and has %s and %s as parents.",
current->name, current->dob.day, current->dob.month,
current->dob. year, current->father, current->mother);
if(current->p_to_pa != NULL )
printf("\n\t%s's birth date is %d/%d/%d ",
current->father, current->p_to_pa->dob.day,
current->p_to_pa->dob.month,
current->p_to_pa->dob.year);
if(current->p_to_ma != NULL)
printf("and %s's birth date is %d/%d/%d.\n ",
current->mother, current->p_to_ma->dob.day,
current->p_to_ma->dob.month,
current->p_to_ma->dob.year);
current = current->next; /* current points to next in list */
}
/* Now free the memory */
current = first;
while(current->next != NULL)
{
last = current; /* Save pointer to enable memory to be freed */
current = current->next; /* current points to next in list */
free(last); /* Free memory for last */
}
}
/* Function to input data on Family members */
struct Family *get_person(void)
{
struct Family *temp; /* Define temporary structure pointer */
/* Allocate memory for a structure */
temp = (struct Family*) malloc(sizeof(struct Family));
printf("\nEnter the name of the person: ");
scanf("%s", temp -> name ); /* Read the Family's name */
printf("\nEnter %s's date of birth (day month year); ", temp->name);
scanf("%d %d %d", &temp->dob.day, &temp->dob.month, &temp->dob.year);
printf("\nWho is %s's father? ", temp->name );
scanf("%s", temp->father ); /* Get the father's name */
printf("\nWho is %s's mother? ", temp -> name );
scanf("%s", temp -> mother ); /* Get the mother's name */
temp->next = temp->previous = NULL; /* Set pointers to NULL */
temp->p_to_pa = temp->p_to_ma = NULL; /* Set pointers to NULL */
return temp; /* Return address of Family structure */
}
char set_ancestry(struct Family *pmember1, struct Family *pmember2)
{
if(strcmp(pmember1->father, pmember2->name) == 0)
{
pmember1->p_to_pa = pmember2;
return 1;
}
/* Fill in pointers for mother or father relationships */
char related (struct Family *pmember1, struct Family *pmember2)
{
return set_ancestry(pmember1, pmember2) ||
set_ancestry(pmember2, pmember1);
}
//---------------------------------------------------------------------------------------------------------------------
// menu file data
int x()
{
show_operations(); /* Display the available operations */
for( ; ; )
{
printf("\nEnter a letter to select an operation: ");
scanf(" %c", &answer);
switch(toupper(answer))
{
case 'A': /* Add a new name and number record */
add_record();
break;
case 'D': /* Delete records for a given name */
delete_records(read_name());
break;
case 'F': /* Find the numbers for a given name */
find_numbers(read_name());
break;
case 'L': /* List all the name/number records */
list_records();
break;
case 'Q':
/* Quit the program */
default:
printf("\nInvalid selection try again.");
show_operations();
break;
}
}
}
/* Reads a name and number from the keyboard and creates a PhoneRecord structure */
struct PhoneRecord read_phonerecord()
{
struct PhoneRecord record;
record.name = read_name();
printf("Enter the number: ");
scanf(" %[ 0123456789]",record.number); /* Read the number - including spaces */
return record;
}
/* Outputs the name and number from a phone record */
void show_record(struct PhoneRecord record)
{
printf("\n%s %s %s", record.name.firstname,record.name.secondname, record.number);
}
/* Add a new name and number */
void add_record()
{
struct PhoneRecord record;
if((pFile = fopen(filename, "a+")) == NULL) /* Open/create file to be written in append mode */
{
printf("Error opening %s for writing. Program terminated.", filename);
abort();
}
record = read_phonerecord(); /* Read the name and number */
fwrite(&record, sizeof record, 1, pFile);
fclose(pFile); /* Close file */
printf("\nNew record added.");
}
/* Read a name from the keyboard and create a Name structure for it */
struct Name read_name()
{
struct Name name;
printf("Enter a first name: ");
scanf(" %s", &name.firstname);
printf("Enter a second name: ");
scanf(" %s", &name.secondname);
return name;
}
/* Delete records for a given name */
/* To delete one or more records we can copy
the contents of the existing file to a new
file, omitting the records that are to be
deleted. We can then delete the old file and
rename the new file to have the old file
name.
*/
void delete_records(struct Name name)
{
FILE *pNewFile = NULL;
char *pnewfilename = NULL;
struct PhoneRecord record;
if((pFile = fopen(filename, "r")) == NULL) /* Open current file to read it */
{
printf("Error opening %s for reading. Program terminated.", filename);
abort();
}
pnewfilename = tmpnam(NULL); /* Create temporary file name */
if((pNewFile = fopen(pnewfilename, "w")) == NULL) /* Open temporary file to write it */
{
printf("Error opening %s for writing. Program terminated.", pnewfilename);
fclose(pFile);
abort();
}
/* Copy existing file contents to temporary file, omitting deleted records */
for(;;)
{
fread(&record, sizeof record, 1, pFile); /* Read a record */
if(feof(pFile)) /* End of file read ? */
break; /* Yes-quit copy loop */
if(equals(name, record.name)) /* Is the record this name ? */
{
printf("\nFound a record:"); /* Ys, so it's a delete candidate */
show_record(record);
printf("\nDo you really want to delete it(y or n)? ");
scanf(" %c", &answer);
if(tolower(answer) == 'y') /* If it's to be deleted */
continue; /* Skip the copying */
}
fwrite(&record, sizeof record, 1, pNewFile); /* copy current record */
}
fclose(pFile);
fclose(pNewFile);
if((pNewFile = fopen(pnewfilename, "r")) == NULL) /* Open temporary file to read it */
{
printf("Error opening %s for reading. Program terminated.", pnewfilename);
abort();
}
if((pFile = fopen(filename, "w"))==NULL) /* Open original file to write it */
{
printf("Error opening %s for writing. Program terminated.", filename);
abort();
}
/* Copy contents of new temporary file back to old file */
/* This overwrites the original contents because the mode is "w" */
for(;;)
{
fread(&record, sizeof record, 1, pNewFile); /* Read temporary file */
if(feof(pNewFile)) /* If we read EOF */
break; /* We are done */
fwrite(&record, sizeof record, 1, pFile); /* Write record to original file */
}
fclose(pFile); /* Close the original file */
fclose(pNewFile); /* Close the temporary file */
remove(pnewfilename); /* Delete the temporary file */
printf("Delete complete.");
}
/* List all the records in the file */
void list_records()
{
struct PhoneRecord record;
int file_empty = TRUE; /* File empty flag */
if((pFile = fopen(filename, "r")) == NULL) /* Open the file to read it */
{
printf("Error opening %s for reading. Program terminated.", filename);
abort();
}
/* List the file contents */
for(;;)
{
fread(&record, sizeof record, 1, pFile);
if(feof(pFile))
break;
file_empty = FALSE; /* We got a record so set empty flag false */
show_record(record); /* output the record */
}
fclose(pFile); /* Close the file */
/* Check whether there were any records */
if(file_empty)
printf("The file contains no records.\n");
else
printf("\n");
}
/* Displays the operations that are supported by the program */
void show_operations()
{
printf("The operations available are:"
"\nA: Add a new name and number entry."
"\nD: Delete all existing entries for a name."
"\nF: Find the number(s) for a given name."
"\nL: List all the entries in the file."
"\nQ: Quit the program.");
}
/* Find numbers corresponding to a given name */
struct PhoneRecord find_numbers(struct Name name)
{
struct PhoneRecord record;
int name_found = FALSE; /* Name found flag */
if((pFile = fopen(filename, "r")) == NULL) /* Open the file to read it */
{
printf("Error opening %s for reading. Program terminated.", filename);
abort();
}
/* Search the records read from the file */
for(;;)
{
fread(&record, sizeof record, 1, pFile); /* Read a record */
if(feof(pFile))
break;
if(equals(name,record.name)) /* Is it the name requested? */
{
if(!name_found) /* Is this the first time we found it? */
{
name_found = TRUE; /* Yes so set flag to true */
printf("The numbers for this name are:"); /* Output initial message */
}
printf("\n%s",record.number); /* Output the number */
}
}
fclose(pFile); /* Close the file */
/* Check for name not found */
if(!name_found)
printf("The name was not found.\n");
else
printf("\n");
}
/* Compare two names for equality */
int equals(struct Name name1, struct Name name2)
{
return (strcmp(name1.firstname, name2.firstname)==0) && (strcmp(name1.secondname, name2.secondname)==0);
}