siasd
asked on
ADDING A SORT FUNCTION
I have written this address book program, but I can't figure out how to add a sort function. I have a very busy schedule at work and I don't have time to write the code. So I'm willing to give extra point to get the code written and working correctly. I'm also working on my class reunion and I wanted to write this program to simplifiy updating my old high school classmates addresses.
Can anyone help me. Thanks in advance. SIASD
* * * * * * * * * * * * *
/* Address Book */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <conio.h>
#define LIST 200 /* Max number of records in database */
#define TRUE 1
#define FALSE 0
#define NAME 13
#define STREET 22
#define CITY 12
#define STATE 3
#define ZIPCODE 6
#define PHONE 12
#define DEBUG FALSE
#define DEBUGFILE "debug.txt"
#define PRINTER_PORT "LPT1:"
struct namestr {
char fname[NAME + 1];
char lname[NAME + 1];
};
struct address {
unsigned short recordnum;
struct namestr PERSON;
char street[STREET + 1];
char city[CITY + 1];
char state[STATE + 1];
char zipcode[ZIPCODE + 1];
char phone[PHONE +1];
};
static int add(struct address BOOK[], int *count);
static void change(struct address BOOK[], int *count);
static void del(struct address BOOK[], int *count);
static void inputs(char *prompt, char *str, unsigned int max);
static void help();
static int load(struct address BOOK[], int *count, char *fname, int lastfile);
static char menu();
static void printlist(struct address BOOK[], int *count);
static void print_rec(int i, struct address BOOK[]);
static void save(struct address BOOK[], int *count, char *fname, int lastfile);
/*------------------------ ---------- ---------- ---------- ---------- ---------- ----
FUNCTION: main
PURPOSE: This function drives the entire program.
A menu is displayed, then a call to the appropriate function.
-------------------------- ---------- ---------- ---------- ---------- ---------- --*/
void main()
{
static struct address BOOK[LIST]; /* Array of address book records */
static int count = 0; /* Counter for number of records in list */
static char fname[20];
static int lastfile = FALSE;
for(;;)
{
printf("\n\nEnter the letter in brackets to activate your choice.");
printf("\n\n\t\tMenu\n");
switch( menu() ) /* Call to display menu, returns character */
{
case 'L':
printf("\n----- LOADING A FILE -----\n");
lastfile = load(BOOK, &count, fname, lastfile);
break;
case 'S':
printf("\n----- SAVING A RECORD -----\n");
save(BOOK, &count, fname, lastfile);
break;
case 'A':
printf("\n----- ADDING A NEW RECORD -----\n");
lastfile = add(BOOK, &count);
break;
case 'C':
printf("\n----- CHANGING A RECORD -----\n");
change(BOOK, &count);
break;
case 'D':
printf("\n----- DELETING A RECORD -----\n");
del(BOOK, &count);
break;
case 'P':
printf("\n----- PRINTING THE RECORDS -----\n");
printlist(BOOK, &count);
break;
case 'H':
//clrscr();
printf("\n----- HELP MENU -----\n");
help();
break;
case 'Q':
exit(0);
}
}
}
/*------------------------ ---------- ---------- ---------- ---------- ---------- ----
FUNCTION: add
PURPOSE: This function adds a record to the database.
First the record number is assigned,
then inputs is called passing the user prompt, destination, and
max string length.
-------------------------- ---------- ---------- ---------- ---------- ---------- --*/
static int add(struct address BOOK[], int *count)
{
if(*count > LIST) /* If too many records */
{
printf("\n\tList full! Save & Quit the program.");
}
else /* Else assign record to structure */
{
fflush(stdin);
BOOK[*count].recordnum = (unsigned short)(*count +1);
inputs("\n\tEnter first name: ", BOOK[*count].PERSON.fname, NAME);
inputs("\tEnter last name: ", BOOK[*count].PERSON.lname, NAME);
inputs("\tEnter street address: ", BOOK[*count].street, STREET);
inputs("\tEnter city: ", BOOK[*count].city, CITY);
inputs("\tEnter state: ", BOOK[*count].state, STATE);
inputs("\tEnter zipcode: ", BOOK[*count].zipcode, ZIPCODE);
inputs("\tEnter phone number: ", BOOK[*count].phone, PHONE);
(*count)++;
}
return TRUE;
}
/*------------------------ ---------- ---------- ---------- ---------- ---------- ----
FUNCTION: change
PURPOSE: This functions changes a database record.
The user is prompted for the record number to change.
Then a search for the record number is conducted.
If no match is found, the appropriate message is displayed.
If there is a match, then the record is displayed,
and the user is asked which element to change, or to return
to the main menu.
-------------------------- ---------- ---------- ---------- ---------- ---------- --*/
static void change(struct address BOOK[], int *count)
{
unsigned short chrec = 0;
char ch = ' ';
int i, quit = FALSE;
static int find = TRUE, change = FALSE;
char choice;
printf("Please enter the number of the record you wish to change: ");
scanf("%d", &chrec);
do
{
for(i = 0; i < *count; i++) /* Loop to search through all records */
{
if(BOOK[i].recordnum == chrec && quit != TRUE)/* If record number matches */
{
print_rec(i, BOOK); /* Display single record */
find = TRUE;
do
{ /* Ask with element user wants to change */
printf("\n\n\tWhich record do you wish to change?");
printf("\n\t(F)irst name\n\t(L)astname\n\t(A)d dress");
printf("\n\t(C)ity\n\t(S)t ate\n\t(Z) ipcode\n\t (P)hone\n\ t(R)eturn to menu");
printf("\n\n\tEnter your choice: ");
fflush(stdin);
gets(&choice);
} while( !strchr( "FLACSZPR", toupper(choice) ) );
switch( toupper(choice) ) /* Input and assign change */
{
case 'F':
inputs("\tEnter first name: ", BOOK[i].PERSON.fname, NAME);
change = TRUE;
break;
case 'L':
inputs("\tEnter last name: ", BOOK[i].PERSON.lname, NAME);
change = TRUE;
break;
case 'A':
inputs("\tEnter street address: ", BOOK[i].street, STREET);
change = TRUE;
break;
case 'C':
inputs("\tEnter city: ", BOOK[i].city, CITY);
change = TRUE;
break;
case 'S':
inputs("\tEnter state: ", BOOK[i].state, STATE);
change = TRUE;
break;
case 'Z':
inputs("\tEnter zip code: ", BOOK[i].zipcode, ZIPCODE);
change = TRUE;
break;
case 'P':
inputs("\tEnter telephone number: ", BOOK[i].phone, PHONE);
change = TRUE;
break;
case 'R':
quit = TRUE;
}
}
}
}while(quit != TRUE);
if(change == TRUE)
{
printf("\nThe change was successful...");
}
else
{
if(find == FALSE)
{
printf("\nRecord number not found.");
}
printf("\nNo changes were made...");
}
printf("\nPress enter to return to main menu...");
getch();
//clrscr();
fflush(stdin);
//scanf("%c", &ch);
}
/*------------------------ ---------- ---------- ---------- ---------- ---------- ----
FUNCTION: del
PURPOSE: This function flags a record for deletion,
and re-initialises the record numbers.
The user is asked which record to delete,
If there is a match, then confirmation is required,
If deletion is confirmed, record is flagged.
Appropriate messages are displayed after users options.
-------------------------- ---------- ---------- ---------- ---------- ---------- --*/
static void del(struct address BOOK[], int *count)
{
unsigned short chrec = 0;
int i, j, done = 0;
char answer;
printf("\n\nPlease enter the number of the record you wish to delete: ");
fflush(stdin);
scanf("%d", &chrec);
for(i = 0; i < *count, done == FALSE; i++)/* Loop to search through all records */
{
if(BOOK[i].recordnum == chrec) /* If record number matches */
{
print_rec(i, BOOK); /* Display single record */
do
{ /* Confirmation */
printf("\n\nYou have chosen to delete record number ");
printf("%d. Are you sure? Y or N: ", BOOK[i].recordnum);
fflush(stdin);
scanf("%c", &answer);
} while( !strchr( "YN", toupper(answer) ) );
if( toupper(answer) == 'Y') /* If answer is Y */
{
BOOK[i].recordnum = 0; /* Flag for deletion */
for(j = 0; j < *count; j++) /* Loop to include all records */
{
if(BOOK[j].recordnum != 0 && BOOK[j].recordnum > chrec)
{ /* Update record numbers */
BOOK[j].recordnum -= (unsigned short)1;
}
}
printf("\n\nThe record has been flagged for deletion...\nThe actual ");
printf("deletion will occur the next time the file is saved to disk");
done = TRUE;
}
else
{
printf("Okay, deletion has been cancelled, returning to menu...");
done = TRUE;
}
}
}
if(done == FALSE)
{
printf("record not found");
}
}
/*------------------------ ---------- ---------- ---------- ---------- ---------- ----
FUNCTION: help
PURPOSE: This function brings up a help menu for the user to explain
the features of this program.
-------------------------- ---------- ---------- ---------- ---------- ---------- --*/
static void help()
{
//char ch;
printf("Enter the letter in brackets to activate your choice.\n");
printf("What would you like help with?");
switch( menu() )
{
case 'L':
printf("\n----- LOADING A FILE -----\n");
printf("This option allows you to enter the name of a file which will then be");
printf("\nopened and read into memory.\n\n");
printf("You can use this option more than once in order to read several files into\n");
printf("the program, in which case the contents of each succeeding file are\n");
printf("added to the end of the same address book already in memory.\n");
break;
case 'S':
printf("\n----- SAVING A RECORD -----\n");
printf("This option allows you to write the contents if the address book from\n");
printf("memory to disk.\n\n");
printf("Any records that have been flagged for deletion will not be saved to disk.\n\n");
printf("When this option has been chosen, you will be asked if you wish to \n");
printf("overwrite the last filename that was opened. If you do not wish to do\n");
printf("this, you can enter the name of a new file which will then be the\n");
printf("destination of the updated address book.\n");
break;
case 'A':
printf("\n----- ADDING A NEW RECORD -----\n");
printf("This option allows you to enter new records which will be added to the\n");
printf("address book in memory.\n\n");
printf("You can enter new records either before or after file(s) have been loaded\n");
printf("into the address book.\n\n");
printf("You can create a new file by adding records with this option, then saving\n");
printf("them as a new file by using the SAVE FILE option, without having to load\n");
printf("any files.\n");
break;
case 'C':
printf("\n----- CHANGING A RECORD -----\n");
printf("Enter a record number, then you can change either name, address or both.\n\n");
printf("The record details for the requested record is displayed on the screen\n");
printf("and then you enter which type to change.\n\n");
printf("All change operations affect only the address book stored in memory - that\n");
printf("is, until the user saves the list to disk with the SAVE FILE option.\n");
break;
case 'D':
printf("\n----- DELETING A RECORD -----\n");
printf("After selecting this option, you can enter the record number you wish to\n");
printf("delete from the address book.\n\n");
printf("When the record number has been entered, the record details are\n");
printf("displayed on screen and you are requested for confirmation.\n");
printf("If you choose not not to delete, then you're returned to the main menu.\n");
printf("If you confirm deletion, the record number is set flagged for deletion.\n");
printf("The actual deletion occurs next time the file is saved to disk.\n");
break;
case 'P':
printf("\n----- PRINTING THE RECORDS -----\n");
printf("This option allows you to choice of sending the output to the screen, or\n");
printf("to the printer.\n");
break;
case 'H':
printf("\n----- THE HELP MENU -----\n");
printf("This option displays a help menu. When you enter a letter in brackets,\n");
printf("you can recieve info on the particular option.\n");
break;
case 'Q':
printf("\n----- QUITING THIS PROGRAM -----\n");
printf("This option allows you to exit this program.\n");
break;
}
fflush(stdin);
printf("\n\nPress enter to return to the main menu...");
getch();
//scanf("%c", &ch);
//clrscr();
}
/*------------------------ ---------- ---------- ---------- ---------- ---------- ----
FUNCTION: input
PURPOSE: This function displays a prompt, and validates the response
by length only.
Then string copys the valid response to the pointer passed.
-------------------------- ---------- ---------- ---------- ---------- ---------- --*/
static void inputs(char *prompt, char *str, unsigned int max)
{
char temp[80];
printf(prompt);
do
{
gets(temp);
if(strlen(temp) > max)
{
printf("\a\n\tToo long, please re-enter: ");
}
} while(strlen(temp) > max);
strcpy(str, temp);
}
/*------------------------ ---------- ---------- ---------- ---------- ---------- ----
FUNCTION: load
PURPOSE: This function loads a database into memory.
The user is asked for a file name, which is validated.
If this is not the first file to be loaded,
Then a new record number is assigned to be added to the current
database in memory.
Otherwise, the records are copied as is.
The process is validated, and appropriate errors display a message.
-------------------------- ---------- ---------- ---------- ---------- ---------- --*/
static int load(struct address BOOK[], int *count, char *fileptr, int lastfile)
{
FILE *fp;
static struct address TEMP;
char ch = ' ';
printf("\tEnter the name of the input file: ");
scanf("%s", fileptr);
if( (fp = fopen(fileptr, "rb") ) == NULL ) /* Open the file to read from */
{
fprintf(stderr, "\nFile open error on <%s>", fileptr);
}
else
{
if(lastfile == TRUE) /* If there are already records */
{
fread(&TEMP, sizeof(struct address), 1, fp);
while(!ferror(fp) && ! feof(fp) && *count < LIST)
{
BOOK[*count] = TEMP; /* Assign new record number */
BOOK[*count].recordnum = (unsigned short)(*count +1);
(*count)++;
fread(&TEMP, sizeof(struct address), 1, fp);
}
}
else
{
/* Read records from database one at a time */
/* and increment number of records in list */
fread(&BOOK[*count], sizeof(struct address), 1, fp);
while(!ferror(fp) && ! feof(fp) && *count < LIST)
{
(*count)++;
fread(&BOOK[*count], sizeof(struct address), 1, fp);
}
}
if( ferror(fp) )
{
fprintf(stderr, "File read error has occurred.");
}
else if(*count >= LIST) /* not all records may fit */
{
fprintf(stderr, "\n\tList full! Quit the program.");
}
else
{
printf("\n\tFile <%s> loaded into memory.", fileptr);
lastfile = TRUE;
}
fclose(fp);
}
printf("\nPress enter to continue...");
getch();
//clrscr();
fflush(stdin);
//scanf("%c", &ch);
return lastfile;
}
/*------------------------ ---------- ---------- ---------- ---------- ---------- ----
FUNCTION: menu
PURPOSE: Display menu options and validate input choices
-------------------------- ---------- ---------- ---------- ---------- ---------- --*/
static char menu()
{
static char ch;
do
{
printf("\n\t(L)oad a file");
printf("\n\t(S)ave a file");
printf("\n\t(A)dd a record");
printf("\n\t(C)hange a record");
printf("\n\t(D)elete a record");
printf("\n\t(P)rint file");
printf("\n\t(H)elp");
printf("\n\t(Q)uit");
printf("\n\n\tEnter your choice: ");
fflush(stdin);
scanf("%c", &ch);
if( !strchr( "LSACDPHQ", toupper(ch) ) )
{
printf("\nYou have entered an invalid key, please try again...");
}
} while( !strchr( "LSACDPHQ", toupper(ch) ) );
return (char)toupper(ch);
}
/*------------------------ ---------- ---------- ---------- ---------- ---------- ----
FUNCTION: printlist
PURPOSE: Prints database to screen or printer.
-------------------------- ---------- ---------- ---------- ---------- ---------- --*/
static void printlist(struct address BOOK[], int *count)
{
FILE *handle;
int i = 0, j = 0, printer = 0, counter = 0;
//char ch;
do
{
printf("\n Do you want to send output to the printer? ");
printf("\nType 0 to print screen, 1 to print to printer: ");
scanf("%d", &printer);
fflush(stdin);
if(printer == TRUE)
{
/* Open channel to printer */
handle = fopen("PRINTER_PORT", "wt");
#if DEBUG
freopen(DEBUGFILE, "wt", handle); /* Redirect the standard printer */
#endif /* stream to a file */
}
if(printer == FALSE)
{
handle = stdout; /* Assign handle to screen */
}
} while( printer != 0 && printer != 1);
/* Print title */
fprintf(handle, "\nREC # LAST FIRST ADDRESS");
fprintf(handle, " CITY STATE ZIPCODE TELEPHONE\n");
for(j = 0; j <92; j++)
{
fprintf(handle, "%c", '-');
}
for(j = 0; j < *count; j++) /* Loop to include all records */
{
if(counter >= 20) /* If end of page */
{
if(handle == stdout) /* If printing on screen */
{
printf("\n----- Press any key to continue -----\n");
getch();
fflush(stdin);
}
else
{
fputc('\f', handle); /* Else formfeed at end of page */
}
/* Print title */
fprintf(handle, "\nREC # LAST FIRST ADDRESS");
fprintf(handle, " CITY STATE ZIPCODE TELEPHONE\n");
for(i = 0; i < 92; i++)
{
fprintf(handle, "%c", '-');
}
counter = 0;
} /* Print body */
fprintf(handle, "\n%4d ", BOOK[j].recordnum);
fprintf(handle, "%-13s%-13s", BOOK[j].PERSON.lname,
BOOK[j].PERSON.fname);
fprintf(handle, "%-21s", BOOK[j].street);
fprintf(handle, "%-12s ", BOOK[j].city);
fprintf(handle, "%-5s", BOOK[j].state);
fprintf(handle, " %-1s", BOOK[j].zipcode);
fprintf(handle, " %s", BOOK[j].phone);
counter++;
}
if(printer == TRUE) /* If outputing to printer */
{
fputc('\f', handle); /* Form feed */
fclose(handle); /* Close stream to printer */
}
printf("\n\nReturning to menu, press enter to continue...\n");
getch();
//scanf("%c", &ch);
//clrscr();
}
/*------------------------ ---------- ---------- ---------- ---------- ---------- ----
FUNCTION: print_rec
PURPOSE: Prints a single record to the screen.
-------------------------- ---------- ---------- ---------- ---------- ---------- --*/
static void print_rec(int i, struct address BOOK[])
{
int j = 0;
printf("\nREC # LAST FIRST ADDRESS"); /* Print title */
printf( " CITY STATE ZIPCODE TELEPHONE\n");
for(j = 0; j < 92; j++)
{
printf("%c", '-');
} /* Print body */
printf("\n%4d ", BOOK[i].recordnum);
printf("%-13s%-13s", BOOK[i].PERSON.lname,
BOOK[i].PERSON.fname);
printf("%-21s", BOOK[i].street);
printf("%-12s", BOOK[i].city);
printf("%-5s", BOOK[i].state);
printf(" %-1s", BOOK[i].zipcode);
printf(" %s", BOOK[i].phone);
}
/*------------------------ ---------- ---------- ---------- ---------- ---------- ----
FUNCTION: save
PURPOSE: Rewrites database to disk.
-------------------------- ---------- ---------- ---------- ---------- ---------- --*/
static void save(struct address BOOK[], int *count, char *fileptr, int lastfile)
{
FILE *fp;
int i = 0, file_error = FALSE;
char answer = 0;
/* If lastfile is true and there's a file in memory */
if(lastfile == TRUE && *fileptr != '\0')
{
do
{ /* Confirmation */
printf("Do you wish to overwrite the last filename opened? Y or N: ");
fflush(stdin);
scanf("%c", &answer);
} while( !strchr( "YN", toupper(answer) ) );
}
if( toupper(answer) == 'Y') /* If answer is Y */
{
if( (fp = fopen(fileptr, "wb") ) == NULL) /* Open the file to write to */
{
fprintf(stderr, "\nFile open error on <%s>", *fileptr);
file_error = TRUE;
}
}
else
{
printf("\n\tEnter the new file to be saved: ");
scanf("%s", fileptr);
if( (fp = fopen(fileptr, "wb") ) == NULL) /* Open the file to write to */
{
fprintf(stderr, "\nFile open error on <%s>", *fileptr);
file_error = TRUE;
}
}
if(file_error == FALSE)
{
for(i = 0; i < *count; i++) /* Loop for all records */
{
if(BOOK[i].recordnum > 0)
{
fwrite(&BOOK[i], sizeof(struct address), 1, fp); /* Write records */
} /* to disk one at a time */
}
fprintf(stdout, "\nFile <%s> saved...\n", fileptr);
fclose(fp);
}
}
Can anyone help me. Thanks in advance. SIASD
* * * * * * * * * * * * *
/* Address Book */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <conio.h>
#define LIST 200 /* Max number of records in database */
#define TRUE 1
#define FALSE 0
#define NAME 13
#define STREET 22
#define CITY 12
#define STATE 3
#define ZIPCODE 6
#define PHONE 12
#define DEBUG FALSE
#define DEBUGFILE "debug.txt"
#define PRINTER_PORT "LPT1:"
struct namestr {
char fname[NAME + 1];
char lname[NAME + 1];
};
struct address {
unsigned short recordnum;
struct namestr PERSON;
char street[STREET + 1];
char city[CITY + 1];
char state[STATE + 1];
char zipcode[ZIPCODE + 1];
char phone[PHONE +1];
};
static int add(struct address BOOK[], int *count);
static void change(struct address BOOK[], int *count);
static void del(struct address BOOK[], int *count);
static void inputs(char *prompt, char *str, unsigned int max);
static void help();
static int load(struct address BOOK[], int *count, char *fname, int lastfile);
static char menu();
static void printlist(struct address BOOK[], int *count);
static void print_rec(int i, struct address BOOK[]);
static void save(struct address BOOK[], int *count, char *fname, int lastfile);
/*------------------------
FUNCTION: main
PURPOSE: This function drives the entire program.
A menu is displayed, then a call to the appropriate function.
--------------------------
void main()
{
static struct address BOOK[LIST]; /* Array of address book records */
static int count = 0; /* Counter for number of records in list */
static char fname[20];
static int lastfile = FALSE;
for(;;)
{
printf("\n\nEnter the letter in brackets to activate your choice.");
printf("\n\n\t\tMenu\n");
switch( menu() ) /* Call to display menu, returns character */
{
case 'L':
printf("\n----- LOADING A FILE -----\n");
lastfile = load(BOOK, &count, fname, lastfile);
break;
case 'S':
printf("\n----- SAVING A RECORD -----\n");
save(BOOK, &count, fname, lastfile);
break;
case 'A':
printf("\n----- ADDING A NEW RECORD -----\n");
lastfile = add(BOOK, &count);
break;
case 'C':
printf("\n----- CHANGING A RECORD -----\n");
change(BOOK, &count);
break;
case 'D':
printf("\n----- DELETING A RECORD -----\n");
del(BOOK, &count);
break;
case 'P':
printf("\n----- PRINTING THE RECORDS -----\n");
printlist(BOOK, &count);
break;
case 'H':
//clrscr();
printf("\n----- HELP MENU -----\n");
help();
break;
case 'Q':
exit(0);
}
}
}
/*------------------------
FUNCTION: add
PURPOSE: This function adds a record to the database.
First the record number is assigned,
then inputs is called passing the user prompt, destination, and
max string length.
--------------------------
static int add(struct address BOOK[], int *count)
{
if(*count > LIST) /* If too many records */
{
printf("\n\tList full! Save & Quit the program.");
}
else /* Else assign record to structure */
{
fflush(stdin);
BOOK[*count].recordnum = (unsigned short)(*count +1);
inputs("\n\tEnter first name: ", BOOK[*count].PERSON.fname,
inputs("\tEnter last name: ", BOOK[*count].PERSON.lname,
inputs("\tEnter street address: ", BOOK[*count].street, STREET);
inputs("\tEnter city: ", BOOK[*count].city, CITY);
inputs("\tEnter state: ", BOOK[*count].state, STATE);
inputs("\tEnter zipcode: ", BOOK[*count].zipcode, ZIPCODE);
inputs("\tEnter phone number: ", BOOK[*count].phone, PHONE);
(*count)++;
}
return TRUE;
}
/*------------------------
FUNCTION: change
PURPOSE: This functions changes a database record.
The user is prompted for the record number to change.
Then a search for the record number is conducted.
If no match is found, the appropriate message is displayed.
If there is a match, then the record is displayed,
and the user is asked which element to change, or to return
to the main menu.
--------------------------
static void change(struct address BOOK[], int *count)
{
unsigned short chrec = 0;
char ch = ' ';
int i, quit = FALSE;
static int find = TRUE, change = FALSE;
char choice;
printf("Please enter the number of the record you wish to change: ");
scanf("%d", &chrec);
do
{
for(i = 0; i < *count; i++) /* Loop to search through all records */
{
if(BOOK[i].recordnum == chrec && quit != TRUE)/* If record number matches */
{
print_rec(i, BOOK); /* Display single record */
find = TRUE;
do
{ /* Ask with element user wants to change */
printf("\n\n\tWhich record do you wish to change?");
printf("\n\t(F)irst name\n\t(L)astname\n\t(A)d
printf("\n\t(C)ity\n\t(S)t
printf("\n\n\tEnter your choice: ");
fflush(stdin);
gets(&choice);
} while( !strchr( "FLACSZPR", toupper(choice) ) );
switch( toupper(choice) ) /* Input and assign change */
{
case 'F':
inputs("\tEnter first name: ", BOOK[i].PERSON.fname, NAME);
change = TRUE;
break;
case 'L':
inputs("\tEnter last name: ", BOOK[i].PERSON.lname, NAME);
change = TRUE;
break;
case 'A':
inputs("\tEnter street address: ", BOOK[i].street, STREET);
change = TRUE;
break;
case 'C':
inputs("\tEnter city: ", BOOK[i].city, CITY);
change = TRUE;
break;
case 'S':
inputs("\tEnter state: ", BOOK[i].state, STATE);
change = TRUE;
break;
case 'Z':
inputs("\tEnter zip code: ", BOOK[i].zipcode, ZIPCODE);
change = TRUE;
break;
case 'P':
inputs("\tEnter telephone number: ", BOOK[i].phone, PHONE);
change = TRUE;
break;
case 'R':
quit = TRUE;
}
}
}
}while(quit != TRUE);
if(change == TRUE)
{
printf("\nThe change was successful...");
}
else
{
if(find == FALSE)
{
printf("\nRecord number not found.");
}
printf("\nNo changes were made...");
}
printf("\nPress enter to return to main menu...");
getch();
//clrscr();
fflush(stdin);
//scanf("%c", &ch);
}
/*------------------------
FUNCTION: del
PURPOSE: This function flags a record for deletion,
and re-initialises the record numbers.
The user is asked which record to delete,
If there is a match, then confirmation is required,
If deletion is confirmed, record is flagged.
Appropriate messages are displayed after users options.
--------------------------
static void del(struct address BOOK[], int *count)
{
unsigned short chrec = 0;
int i, j, done = 0;
char answer;
printf("\n\nPlease enter the number of the record you wish to delete: ");
fflush(stdin);
scanf("%d", &chrec);
for(i = 0; i < *count, done == FALSE; i++)/* Loop to search through all records */
{
if(BOOK[i].recordnum == chrec) /* If record number matches */
{
print_rec(i, BOOK); /* Display single record */
do
{ /* Confirmation */
printf("\n\nYou have chosen to delete record number ");
printf("%d. Are you sure? Y or N: ", BOOK[i].recordnum);
fflush(stdin);
scanf("%c", &answer);
} while( !strchr( "YN", toupper(answer) ) );
if( toupper(answer) == 'Y') /* If answer is Y */
{
BOOK[i].recordnum = 0; /* Flag for deletion */
for(j = 0; j < *count; j++) /* Loop to include all records */
{
if(BOOK[j].recordnum != 0 && BOOK[j].recordnum > chrec)
{ /* Update record numbers */
BOOK[j].recordnum -= (unsigned short)1;
}
}
printf("\n\nThe record has been flagged for deletion...\nThe actual ");
printf("deletion will occur the next time the file is saved to disk");
done = TRUE;
}
else
{
printf("Okay, deletion has been cancelled, returning to menu...");
done = TRUE;
}
}
}
if(done == FALSE)
{
printf("record not found");
}
}
/*------------------------
FUNCTION: help
PURPOSE: This function brings up a help menu for the user to explain
the features of this program.
--------------------------
static void help()
{
//char ch;
printf("Enter the letter in brackets to activate your choice.\n");
printf("What would you like help with?");
switch( menu() )
{
case 'L':
printf("\n----- LOADING A FILE -----\n");
printf("This option allows you to enter the name of a file which will then be");
printf("\nopened and read into memory.\n\n");
printf("You can use this option more than once in order to read several files into\n");
printf("the program, in which case the contents of each succeeding file are\n");
printf("added to the end of the same address book already in memory.\n");
break;
case 'S':
printf("\n----- SAVING A RECORD -----\n");
printf("This option allows you to write the contents if the address book from\n");
printf("memory to disk.\n\n");
printf("Any records that have been flagged for deletion will not be saved to disk.\n\n");
printf("When this option has been chosen, you will be asked if you wish to \n");
printf("overwrite the last filename that was opened. If you do not wish to do\n");
printf("this, you can enter the name of a new file which will then be the\n");
printf("destination of the updated address book.\n");
break;
case 'A':
printf("\n----- ADDING A NEW RECORD -----\n");
printf("This option allows you to enter new records which will be added to the\n");
printf("address book in memory.\n\n");
printf("You can enter new records either before or after file(s) have been loaded\n");
printf("into the address book.\n\n");
printf("You can create a new file by adding records with this option, then saving\n");
printf("them as a new file by using the SAVE FILE option, without having to load\n");
printf("any files.\n");
break;
case 'C':
printf("\n----- CHANGING A RECORD -----\n");
printf("Enter a record number, then you can change either name, address or both.\n\n");
printf("The record details for the requested record is displayed on the screen\n");
printf("and then you enter which type to change.\n\n");
printf("All change operations affect only the address book stored in memory - that\n");
printf("is, until the user saves the list to disk with the SAVE FILE option.\n");
break;
case 'D':
printf("\n----- DELETING A RECORD -----\n");
printf("After selecting this option, you can enter the record number you wish to\n");
printf("delete from the address book.\n\n");
printf("When the record number has been entered, the record details are\n");
printf("displayed on screen and you are requested for confirmation.\n");
printf("If you choose not not to delete, then you're returned to the main menu.\n");
printf("If you confirm deletion, the record number is set flagged for deletion.\n");
printf("The actual deletion occurs next time the file is saved to disk.\n");
break;
case 'P':
printf("\n----- PRINTING THE RECORDS -----\n");
printf("This option allows you to choice of sending the output to the screen, or\n");
printf("to the printer.\n");
break;
case 'H':
printf("\n----- THE HELP MENU -----\n");
printf("This option displays a help menu. When you enter a letter in brackets,\n");
printf("you can recieve info on the particular option.\n");
break;
case 'Q':
printf("\n----- QUITING THIS PROGRAM -----\n");
printf("This option allows you to exit this program.\n");
break;
}
fflush(stdin);
printf("\n\nPress enter to return to the main menu...");
getch();
//scanf("%c", &ch);
//clrscr();
}
/*------------------------
FUNCTION: input
PURPOSE: This function displays a prompt, and validates the response
by length only.
Then string copys the valid response to the pointer passed.
--------------------------
static void inputs(char *prompt, char *str, unsigned int max)
{
char temp[80];
printf(prompt);
do
{
gets(temp);
if(strlen(temp) > max)
{
printf("\a\n\tToo long, please re-enter: ");
}
} while(strlen(temp) > max);
strcpy(str, temp);
}
/*------------------------
FUNCTION: load
PURPOSE: This function loads a database into memory.
The user is asked for a file name, which is validated.
If this is not the first file to be loaded,
Then a new record number is assigned to be added to the current
database in memory.
Otherwise, the records are copied as is.
The process is validated, and appropriate errors display a message.
--------------------------
static int load(struct address BOOK[], int *count, char *fileptr, int lastfile)
{
FILE *fp;
static struct address TEMP;
char ch = ' ';
printf("\tEnter the name of the input file: ");
scanf("%s", fileptr);
if( (fp = fopen(fileptr, "rb") ) == NULL ) /* Open the file to read from */
{
fprintf(stderr, "\nFile open error on <%s>", fileptr);
}
else
{
if(lastfile == TRUE) /* If there are already records */
{
fread(&TEMP, sizeof(struct address), 1, fp);
while(!ferror(fp) && ! feof(fp) && *count < LIST)
{
BOOK[*count] = TEMP; /* Assign new record number */
BOOK[*count].recordnum = (unsigned short)(*count +1);
(*count)++;
fread(&TEMP, sizeof(struct address), 1, fp);
}
}
else
{
/* Read records from database one at a time */
/* and increment number of records in list */
fread(&BOOK[*count], sizeof(struct address), 1, fp);
while(!ferror(fp) && ! feof(fp) && *count < LIST)
{
(*count)++;
fread(&BOOK[*count], sizeof(struct address), 1, fp);
}
}
if( ferror(fp) )
{
fprintf(stderr, "File read error has occurred.");
}
else if(*count >= LIST) /* not all records may fit */
{
fprintf(stderr, "\n\tList full! Quit the program.");
}
else
{
printf("\n\tFile <%s> loaded into memory.", fileptr);
lastfile = TRUE;
}
fclose(fp);
}
printf("\nPress enter to continue...");
getch();
//clrscr();
fflush(stdin);
//scanf("%c", &ch);
return lastfile;
}
/*------------------------
FUNCTION: menu
PURPOSE: Display menu options and validate input choices
--------------------------
static char menu()
{
static char ch;
do
{
printf("\n\t(L)oad a file");
printf("\n\t(S)ave a file");
printf("\n\t(A)dd a record");
printf("\n\t(C)hange a record");
printf("\n\t(D)elete a record");
printf("\n\t(P)rint file");
printf("\n\t(H)elp");
printf("\n\t(Q)uit");
printf("\n\n\tEnter your choice: ");
fflush(stdin);
scanf("%c", &ch);
if( !strchr( "LSACDPHQ", toupper(ch) ) )
{
printf("\nYou have entered an invalid key, please try again...");
}
} while( !strchr( "LSACDPHQ", toupper(ch) ) );
return (char)toupper(ch);
}
/*------------------------
FUNCTION: printlist
PURPOSE: Prints database to screen or printer.
--------------------------
static void printlist(struct address BOOK[], int *count)
{
FILE *handle;
int i = 0, j = 0, printer = 0, counter = 0;
//char ch;
do
{
printf("\n Do you want to send output to the printer? ");
printf("\nType 0 to print screen, 1 to print to printer: ");
scanf("%d", &printer);
fflush(stdin);
if(printer == TRUE)
{
/* Open channel to printer */
handle = fopen("PRINTER_PORT", "wt");
#if DEBUG
freopen(DEBUGFILE, "wt", handle); /* Redirect the standard printer */
#endif /* stream to a file */
}
if(printer == FALSE)
{
handle = stdout; /* Assign handle to screen */
}
} while( printer != 0 && printer != 1);
/* Print title */
fprintf(handle, "\nREC # LAST FIRST ADDRESS");
fprintf(handle, " CITY STATE ZIPCODE TELEPHONE\n");
for(j = 0; j <92; j++)
{
fprintf(handle, "%c", '-');
}
for(j = 0; j < *count; j++) /* Loop to include all records */
{
if(counter >= 20) /* If end of page */
{
if(handle == stdout) /* If printing on screen */
{
printf("\n----- Press any key to continue -----\n");
getch();
fflush(stdin);
}
else
{
fputc('\f', handle); /* Else formfeed at end of page */
}
/* Print title */
fprintf(handle, "\nREC # LAST FIRST ADDRESS");
fprintf(handle, " CITY STATE ZIPCODE TELEPHONE\n");
for(i = 0; i < 92; i++)
{
fprintf(handle, "%c", '-');
}
counter = 0;
} /* Print body */
fprintf(handle, "\n%4d ", BOOK[j].recordnum);
fprintf(handle, "%-13s%-13s", BOOK[j].PERSON.lname,
BOOK[j].PERSON.fname);
fprintf(handle, "%-21s", BOOK[j].street);
fprintf(handle, "%-12s ", BOOK[j].city);
fprintf(handle, "%-5s", BOOK[j].state);
fprintf(handle, " %-1s", BOOK[j].zipcode);
fprintf(handle, " %s", BOOK[j].phone);
counter++;
}
if(printer == TRUE) /* If outputing to printer */
{
fputc('\f', handle); /* Form feed */
fclose(handle); /* Close stream to printer */
}
printf("\n\nReturning to menu, press enter to continue...\n");
getch();
//scanf("%c", &ch);
//clrscr();
}
/*------------------------
FUNCTION: print_rec
PURPOSE: Prints a single record to the screen.
--------------------------
static void print_rec(int i, struct address BOOK[])
{
int j = 0;
printf("\nREC # LAST FIRST ADDRESS"); /* Print title */
printf( " CITY STATE ZIPCODE TELEPHONE\n");
for(j = 0; j < 92; j++)
{
printf("%c", '-');
} /* Print body */
printf("\n%4d ", BOOK[i].recordnum);
printf("%-13s%-13s", BOOK[i].PERSON.lname,
BOOK[i].PERSON.fname);
printf("%-21s", BOOK[i].street);
printf("%-12s", BOOK[i].city);
printf("%-5s", BOOK[i].state);
printf(" %-1s", BOOK[i].zipcode);
printf(" %s", BOOK[i].phone);
}
/*------------------------
FUNCTION: save
PURPOSE: Rewrites database to disk.
--------------------------
static void save(struct address BOOK[], int *count, char *fileptr, int lastfile)
{
FILE *fp;
int i = 0, file_error = FALSE;
char answer = 0;
/* If lastfile is true and there's a file in memory */
if(lastfile == TRUE && *fileptr != '\0')
{
do
{ /* Confirmation */
printf("Do you wish to overwrite the last filename opened? Y or N: ");
fflush(stdin);
scanf("%c", &answer);
} while( !strchr( "YN", toupper(answer) ) );
}
if( toupper(answer) == 'Y') /* If answer is Y */
{
if( (fp = fopen(fileptr, "wb") ) == NULL) /* Open the file to write to */
{
fprintf(stderr, "\nFile open error on <%s>", *fileptr);
file_error = TRUE;
}
}
else
{
printf("\n\tEnter the new file to be saved: ");
scanf("%s", fileptr);
if( (fp = fopen(fileptr, "wb") ) == NULL) /* Open the file to write to */
{
fprintf(stderr, "\nFile open error on <%s>", *fileptr);
file_error = TRUE;
}
}
if(file_error == FALSE)
{
for(i = 0; i < *count; i++) /* Loop for all records */
{
if(BOOK[i].recordnum > 0)
{
fwrite(&BOOK[i], sizeof(struct address), 1, fp); /* Write records */
} /* to disk one at a time */
}
fprintf(stdout, "\nFile <%s> saved...\n", fileptr);
fclose(fp);
}
}
wow, if i had the time dude i'd help ya
I suggest you post your request at
http://www.rentacoder.com
I am sure somebody will do it for you for less than $10
http://www.rentacoder.com
I am sure somebody will do it for you for less than $10
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
To Koma666: I appreciate your efforts but, I have downloaded you addition to my program and I've tried it on several compilers and I can't get it to compile. What compiler did you use? SIASD
i used visual c++ 6.0
what error did you get ?
Order function included just compile, i have integrated the new functions in the menu.
Have fun :-)
/* Address Book */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <conio.h>
#define LIST 200 /* Max number of records in database */
#define TRUE 1
#define FALSE 0
#define NAME 13
#define STREET 22
#define CITY 12
#define STATE 3
#define ZIPCODE 6
#define PHONE 12
#define DEBUG FALSE
#define DEBUGFILE "debug.txt"
#define PRINTER_PORT "LPT1:"
struct namestr {
char fname[NAME + 1];
char lname[NAME + 1];
};
struct address {
unsigned short recordnum;
struct namestr PERSON;
char street[STREET + 1];
char city[CITY + 1];
char state[STATE + 1];
char zipcode[ZIPCODE + 1];
char phone[PHONE +1];
};
static int add(struct address BOOK[], int *count);
static void change(struct address BOOK[], int *count);
static void del(struct address BOOK[], int *count);
static void inputs(char *prompt, char *str, unsigned int max);
static void help();
static int load(struct address BOOK[], int *count, char *fname, int lastfile);
static char menu();
static void printlist(struct address BOOK[], int *count);
static void print_rec(int i, struct address BOOK[]);
static void save(struct address BOOK[], int *count, char *fname, int lastfile);
static int order(struct address BOOK[], int *count);
/*------------------------
FUNCTION: main
PURPOSE: This function drives the entire program.
A menu is displayed, then a call to the appropriate function.
--------------------------
int main(void)
{
static struct address BOOK[LIST]; /* Array of address book records */
static int count = 0; /* Counter for number of records in list */
static char fname[20];
static int lastfile = FALSE;
for(;;)
{
printf("\n\nEnter the letter in brackets to activate your choice.");
printf("\n\n\t\tMenu\n");
switch( menu() ) /* Call to display menu, returns character */
{
case 'L':
printf("\n----- LOADING A FILE -----\n");
lastfile = load(BOOK, &count, fname, lastfile);
break;
case 'S':
printf("\n----- SAVING A RECORD -----\n");
save(BOOK, &count, fname, lastfile);
break;
case 'A':
printf("\n----- ADDING A NEW RECORD -----\n");
lastfile = add(BOOK, &count);
break;
case 'C':
printf("\n----- CHANGING A RECORD -----\n");
change(BOOK, &count);
break;
case 'D':
printf("\n----- DELETING A RECORD -----\n");
del(BOOK, &count);
break;
case 'P':
printf("\n----- PRINTING THE RECORDS -----\n");
printlist(BOOK, &count);
break;
case 'H':
//clrscr();
printf("\n----- HELP MENU -----\n");
help();
break;
case 'O':
printf("\n----- SORTING THE RECORDS -----\n");
order(BOOK,&count);
break;
case 'Q':
exit(0);
}
}
return true;
}
static int order( struct address BOOK[], int *count)
{
static char ch;
do
{
printf("\n\t(C)ity");
printf("\n\t(F)irst name");
printf("\n\t(L)ast name");
printf("\n\t(S)tate");
printf("\n\n\tEnter your choice: ");
fflush(stdin);
scanf("%c", &ch);
if( !strchr( "CFLS", toupper(ch) ) )
{
printf("\nYou have entered an invalid key, please try again...");
}
} while( !strchr( "CFLS", toupper(ch) ) );
bool isFinished;
bool bigger;
struct address Temp;
int iPos;
switch( toupper(ch) ) /* Call to display menu, returns character */
{
case 'C':
printf("\n----- ORDER BY CITY -----\n");
break;
case 'F':
printf("\n----- ORDER BY FIRST NAME -----\n");
break;
case 'L':
printf("\n----- ORDER BY LAST NAME -----\n");
break;
case 'S':
printf("\n----- ORDER BY STATE -----\n");
break;
case 'R':
return 0;
}
do
{
isFinished = true;
for( iPos=0; iPos < ( *count - 1); iPos++ )
{
bigger = false;
switch( toupper(ch) ) /* Call to display menu, returns character */
{
case 'C':
//printf("\n----- ORDER BY CITY -----\n");
if( strcmp(BOOK[iPos].city,BOO
bigger=true;
break;
case 'F':
//printf("\n----- ORDER BY FIRST NAME -----\n");
if( strcmp(BOOK[iPos].PERSON.f
bigger=true;
break;
case 'L':
//printf("\n----- ORDER BY LAST NAME -----\n");
if( strcmp(BOOK[iPos].PERSON.l
bigger=true;
break;
case 'S':
//printf("\n----- ORDER BY STATE -----\n");
if( strcmp(BOOK[iPos].state,BO
bigger=true;
break;
}
if(bigger)
{
Temp = BOOK[iPos];
BOOK[iPos] = BOOK[iPos+1];
BOOK[iPos+1] = Temp;
isFinished = false;
}
}
} while( !isFinished );
printf("\nfinished");
return true;
}
/*------------------------
FUNCTION: add
PURPOSE: This function adds a record to the database.
First the record number is assigned,
then inputs is called passing the user prompt, destination, and
max string length.
--------------------------
static int add(struct address BOOK[], int *count)
{
if(*count > LIST) /* If too many records */
{
printf("\n\tList full! Save & Quit the program.");
}
else /* Else assign record to structure */
{
fflush(stdin);
BOOK[*count].recordnum = (unsigned short)(*count +1);
inputs("\n\tEnter first name: ", BOOK[*count].PERSON.fname,
inputs("\tEnter last name: ", BOOK[*count].PERSON.lname,
inputs("\tEnter street address: ", BOOK[*count].street, STREET);
inputs("\tEnter city: ", BOOK[*count].city, CITY);
inputs("\tEnter state: ", BOOK[*count].state, STATE);
inputs("\tEnter zipcode: ", BOOK[*count].zipcode, ZIPCODE);
inputs("\tEnter phone number: ", BOOK[*count].phone, PHONE);
(*count)++;
}
return TRUE;
}
/*------------------------
FUNCTION: change
PURPOSE: This functions changes a database record.
The user is prompted for the record number to change.
Then a search for the record number is conducted.
If no match is found, the appropriate message is displayed.
If there is a match, then the record is displayed,
and the user is asked which element to change, or to return
to the main menu.
--------------------------
static void change(struct address BOOK[], int *count)
{
unsigned short chrec = 0;
char ch = ' ';
int i, quit = FALSE;
static int find = TRUE, change = FALSE;
char choice;
printf("Please enter the number of the record you wish to change: ");
scanf("%d", &chrec);
do
{
for(i = 0; i < *count; i++) /* Loop to search through all records */
{
if(BOOK[i].recordnum == chrec && quit != TRUE)/* If record number matches */
{
print_rec(i, BOOK); /* Display single record */
find = TRUE;
do
{ /* Ask with element user wants to change */
printf("\n\n\tWhich record do you wish to change?");
printf("\n\t(F)irst name\n\t(L)astname\n\t(A)d
printf("\n\t(C)ity\n\t(S)t
printf("\n\n\tEnter your choice: ");
fflush(stdin);
gets(&choice);
} while( !strchr( "FLACSZPR", toupper(choice) ) );
switch( toupper(choice) ) /* Input and assign change */
{
case 'F':
inputs("\tEnter first name: ", BOOK[i].PERSON.fname, NAME);
change = TRUE;
break;
case 'L':
inputs("\tEnter last name: ", BOOK[i].PERSON.lname, NAME);
change = TRUE;
break;
case 'A':
inputs("\tEnter street address: ", BOOK[i].street, STREET);
change = TRUE;
break;
case 'C':
inputs("\tEnter city: ", BOOK[i].city, CITY);
change = TRUE;
break;
case 'S':
inputs("\tEnter state: ", BOOK[i].state, STATE);
change = TRUE;
break;
case 'Z':
inputs("\tEnter zip code: ", BOOK[i].zipcode, ZIPCODE);
change = TRUE;
break;
case 'P':
inputs("\tEnter telephone number: ", BOOK[i].phone, PHONE);
change = TRUE;
break;
case 'R':
quit = TRUE;
}
}
}
}while(quit != TRUE);
if(change == TRUE)
{
printf("\nThe change was successful...");
}
else
{
if(find == FALSE)
{
printf("\nRecord number not found.");
}
printf("\nNo changes were made...");
}
printf("\nPress enter to return to main menu...");
getch();
//clrscr();
fflush(stdin);
//scanf("%c", &ch);
}
/*------------------------
FUNCTION: del
PURPOSE: This function flags a record for deletion,
and re-initialises the record numbers.
The user is asked which record to delete,
If there is a match, then confirmation is required,
If deletion is confirmed, record is flagged.
Appropriate messages are displayed after users options.
--------------------------
static void del(struct address BOOK[], int *count)
{
unsigned short chrec = 0;
int i, j, done = 0;
char answer;
printf("\n\nPlease enter the number of the record you wish to delete: ");
fflush(stdin);
scanf("%d", &chrec);
for(i = 0; i < *count, done == FALSE; i++)/* Loop to search through all records */
{
if(BOOK[i].recordnum == chrec) /* If record number matches */
{
print_rec(i, BOOK); /* Display single record */
do
{ /* Confirmation */
printf("\n\nYou have chosen to delete record number ");
printf("%d. Are you sure? Y or N: ", BOOK[i].recordnum);
fflush(stdin);
scanf("%c", &answer);
} while( !strchr( "YN", toupper(answer) ) );
if( toupper(answer) == 'Y') /* If answer is Y */
{
BOOK[i].recordnum = 0; /* Flag for deletion */
for(j = 0; j < *count; j++) /* Loop to include all records */
{
if(BOOK[j].recordnum != 0 && BOOK[j].recordnum > chrec)
{ /* Update record numbers */
BOOK[j].recordnum -= (unsigned short)1;
}
}
printf("\n\nThe record has been flagged for deletion...\nThe actual ");
printf("deletion will occur the next time the file is saved to disk");
done = TRUE;
}
else
{
printf("Okay, deletion has been cancelled, returning to menu...");
done = TRUE;
}
}
}
if(done == FALSE)
{
printf("record not found");
}
}
/*------------------------
FUNCTION: help
PURPOSE: This function brings up a help menu for the user to explain
the features of this program.
--------------------------
static void help()
{
//char ch;
printf("Enter the letter in brackets to activate your choice.\n");
printf("What would you like help with?");
switch( menu() )
{
case 'L':
printf("\n----- LOADING A FILE -----\n");
printf("This option allows you to enter the name of a file which will then be");
printf("\nopened and read into memory.\n\n");
printf("You can use this option more than once in order to read several files into\n");
printf("the program, in which case the contents of each succeeding file are\n");
printf("added to the end of the same address book already in memory.\n");
break;
case 'S':
printf("\n----- SAVING A RECORD -----\n");
printf("This option allows you to write the contents if the address book from\n");
printf("memory to disk.\n\n");
printf("Any records that have been flagged for deletion will not be saved to disk.\n\n");
printf("When this option has been chosen, you will be asked if you wish to \n");
printf("overwrite the last filename that was opened. If you do not wish to do\n");
printf("this, you can enter the name of a new file which will then be the\n");
printf("destination of the updated address book.\n");
break;
case 'A':
printf("\n----- ADDING A NEW RECORD -----\n");
printf("This option allows you to enter new records which will be added to the\n");
printf("address book in memory.\n\n");
printf("You can enter new records either before or after file(s) have been loaded\n");
printf("into the address book.\n\n");
printf("You can create a new file by adding records with this option, then saving\n");
printf("them as a new file by using the SAVE FILE option, without having to load\n");
printf("any files.\n");
break;
case 'C':
printf("\n----- CHANGING A RECORD -----\n");
printf("Enter a record number, then you can change either name, address or both.\n\n");
printf("The record details for the requested record is displayed on the screen\n");
printf("and then you enter which type to change.\n\n");
printf("All change operations affect only the address book stored in memory - that\n");
printf("is, until the user saves the list to disk with the SAVE FILE option.\n");
break;
case 'D':
printf("\n----- DELETING A RECORD -----\n");
printf("After selecting this option, you can enter the record number you wish to\n");
printf("delete from the address book.\n\n");
printf("When the record number has been entered, the record details are\n");
printf("displayed on screen and you are requested for confirmation.\n");
printf("If you choose not not to delete, then you're returned to the main menu.\n");
printf("If you confirm deletion, the record number is set flagged for deletion.\n");
printf("The actual deletion occurs next time the file is saved to disk.\n");
break;
case 'P':
printf("\n----- PRINTING THE RECORDS -----\n");
printf("This option allows you to choice of sending the output to the screen, or\n");
printf("to the printer.\n");
break;
case 'H':
printf("\n----- THE HELP MENU -----\n");
printf("This option displays a help menu. When you enter a letter in brackets,\n");
printf("you can recieve info on the particular option.\n");
break;
case 'Q':
printf("\n----- QUITING THIS PROGRAM -----\n");
printf("This option allows you to exit this program.\n");
break;
case 'O':
printf("\n----- Sorting -----\n");
printf("This option allows you to sort your entries.\n");
break;
}
fflush(stdin);
printf("\n\nPress enter to return to the main menu...");
getch();
//scanf("%c", &ch);
//clrscr();
}
/*------------------------
FUNCTION: input
PURPOSE: This function displays a prompt, and validates the response
by length only.
Then string copys the valid response to the pointer passed.
--------------------------
static void inputs(char *prompt, char *str, unsigned int max)
{
char temp[80];
printf(prompt);
do
{
gets(temp);
if(strlen(temp) > max)
{
printf("\a\n\tToo long, please re-enter: ");
}
} while(strlen(temp) > max);
strcpy(str, temp);
}
/*------------------------
FUNCTION: load
PURPOSE: This function loads a database into memory.
The user is asked for a file name, which is validated.
If this is not the first file to be loaded,
Then a new record number is assigned to be added to the current
database in memory.
Otherwise, the records are copied as is.
The process is validated, and appropriate errors display a message.
--------------------------
static int load(struct address BOOK[], int *count, char *fileptr, int lastfile)
{
FILE *fp;
static struct address TEMP;
char ch = ' ';
printf("\tEnter the name of the input file: ");
scanf("%s", fileptr);
if( (fp = fopen(fileptr, "rb") ) == NULL ) /* Open the file to read from */
{
fprintf(stderr, "\nFile open error on <%s>", fileptr);
}
else
{
if(lastfile == TRUE) /* If there are already records */
{
fread(&TEMP, sizeof(struct address), 1, fp);
while(!ferror(fp) && ! feof(fp) && *count < LIST)
{
BOOK[*count] = TEMP; /* Assign new record number */
BOOK[*count].recordnum = (unsigned short)(*count +1);
(*count)++;
fread(&TEMP, sizeof(struct address), 1, fp);
}
}
else
{
/* Read records from database one at a time */
/* and increment number of records in list */
fread(&BOOK[*count], sizeof(struct address), 1, fp);
while(!ferror(fp) && ! feof(fp) && *count < LIST)
{
(*count)++;
fread(&BOOK[*count], sizeof(struct address), 1, fp);
}
}
if( ferror(fp) )
{
fprintf(stderr, "File read error has occurred.");
}
else if(*count >= LIST) /* not all records may fit */
{
fprintf(stderr, "\n\tList full! Quit the program.");
}
else
{
printf("\n\tFile <%s> loaded into memory.", fileptr);
lastfile = TRUE;
}
fclose(fp);
}
printf("\nPress enter to continue...");
getch();
//clrscr();
fflush(stdin);
//scanf("%c", &ch);
return lastfile;
}
/*------------------------
FUNCTION: menu
PURPOSE: Display menu options and validate input choices
--------------------------
static char menu()
{
static char ch;
do
{
printf("\n\t(L)oad a file");
printf("\n\t(S)ave a file");
printf("\n\t(A)dd a record");
printf("\n\t(C)hange a record");
printf("\n\t(D)elete a record");
printf("\n\t(P)rint file");
printf("\n\t(H)elp");
printf("\n\tS(o)rt");
printf("\n\t(Q)uit");
printf("\n\n\tEnter your choice: ");
fflush(stdin);
scanf("%c", &ch);
if( !strchr( "LSACDPOHQ", toupper(ch) ) )
{
printf("\nYou have entered an invalid key, please try again...");
}
} while( !strchr( "LSACDPOHQ", toupper(ch) ) );
return (char)toupper(ch);
}
/*------------------------
FUNCTION: printlist
PURPOSE: Prints database to screen or printer.
--------------------------
static void printlist(struct address BOOK[], int *count)
{
FILE *handle;
int i = 0, j = 0, printer = 0, counter = 0;
//char ch;
do
{
printf("\n Do you want to send output to the printer? ");
printf("\nType 0 to print screen, 1 to print to printer: ");
scanf("%d", &printer);
fflush(stdin);
if(printer == TRUE)
{
/* Open channel to printer */
handle = fopen("PRINTER_PORT", "wt");
#if DEBUG
freopen(DEBUGFILE, "wt", handle); /* Redirect the standard printer */
#endif /* stream to a file */
}
if(printer == FALSE)
{
handle = stdout; /* Assign handle to screen */
}
} while( printer != 0 && printer != 1);
/* Print title */
fprintf(handle, "\nREC # LAST FIRST ADDRESS");
fprintf(handle, " CITY STATE ZIPCODE TELEPHONE\n");
for(j = 0; j <92; j++)
{
fprintf(handle, "%c", '-');
}
for(j = 0; j < *count; j++) /* Loop to include all records */
{
if(counter >= 20) /* If end of page */
{
if(handle == stdout) /* If printing on screen */
{
printf("\n----- Press any key to continue -----\n");
getch();
fflush(stdin);
}
else
{
fputc('\f', handle); /* Else formfeed at end of page */
}
/* Print title */
fprintf(handle, "\nREC # LAST FIRST ADDRESS");
fprintf(handle, " CITY STATE ZIPCODE TELEPHONE\n");
for(i = 0; i < 92; i++)
{
fprintf(handle, "%c", '-');
}
counter = 0;
} /* Print body */
fprintf(handle, "\n%4d ", BOOK[j].recordnum);
fprintf(handle, "%-13s%-13s", BOOK[j].PERSON.lname,
BOOK[j].PERSON.fname);
fprintf(handle, "%-21s", BOOK[j].street);
fprintf(handle, "%-12s ", BOOK[j].city);
fprintf(handle, "%-5s", BOOK[j].state);
fprintf(handle, " %-1s", BOOK[j].zipcode);
fprintf(handle, " %s", BOOK[j].phone);
counter++;
}
if(printer == TRUE) /* If outputing to printer */
{
fputc('\f', handle); /* Form feed */
fclose(handle); /* Close stream to printer */
}
printf("\n\nReturning to menu, press enter to continue...\n");
getch();
//scanf("%c", &ch);
//clrscr();
}
/*------------------------
FUNCTION: print_rec
PURPOSE: Prints a single record to the screen.
--------------------------
static void print_rec(int i, struct address BOOK[])
{
int j = 0;
printf("\nREC # LAST FIRST ADDRESS"); /* Print title */
printf( " CITY STATE ZIPCODE TELEPHONE\n");
for(j = 0; j < 92; j++)
{
printf("%c", '-');
} /* Print body */
printf("\n%4d ", BOOK[i].recordnum);
printf("%-13s%-13s", BOOK[i].PERSON.lname,
BOOK[i].PERSON.fname);
printf("%-21s", BOOK[i].street);
printf("%-12s", BOOK[i].city);
printf("%-5s", BOOK[i].state);
printf(" %-1s", BOOK[i].zipcode);
printf(" %s", BOOK[i].phone);
}
/*------------------------
FUNCTION: save
PURPOSE: Rewrites database to disk.
--------------------------
static void save(struct address BOOK[], int *count, char *fileptr, int lastfile)
{
FILE *fp;
int i = 0, file_error = FALSE;
char answer = 0;
/* If lastfile is true and there's a file in memory */
if(lastfile == TRUE && *fileptr != '\0')
{
do
{ /* Confirmation */
printf("Do you wish to overwrite the last filename opened? Y or N: ");
fflush(stdin);
scanf("%c", &answer);
} while( !strchr( "YN", toupper(answer) ) );
}
if( toupper(answer) == 'Y') /* If answer is Y */
{
if( (fp = fopen(fileptr, "wb") ) == NULL) /* Open the file to write to */
{
fprintf(stderr, "\nFile open error on <%s>", *fileptr);
file_error = TRUE;
}
}
else
{
printf("\n\tEnter the new file to be saved: ");
scanf("%s", fileptr);
if( (fp = fopen(fileptr, "wb") ) == NULL) /* Open the file to write to */
{
fprintf(stderr, "\nFile open error on <%s>", *fileptr);
file_error = TRUE;
}
}
if(file_error == FALSE)
{
for(i = 0; i < *count; i++) /* Loop for all records */
{
if(BOOK[i].recordnum > 0)
{
fwrite(&BOOK[i], sizeof(struct address), 1, fp); /* Write records */
} /* to disk one at a time */
}
fprintf(stdout, "\nFile <%s> saved...\n", fileptr);
fclose(fp);
}
}