/****************************************************************************
* File:
SLM.C
* Date:
17.7.17
* Version:
1.0
* Author
A.D. Johnson
* System:
Linux (Most/All versions?)
* Design Doc:
* Description:
Sales Logger and Monitor Program for the Advanced C
* Programming Course. Sets up
and maintains a simple
* database of customer
purchases.
* Supplied as is Warts 'n' all -
improve as you wish!
* Changes:
*
****************************************************************************/
/***
Further
comments:
This
programme is simply a "teaching aid" for C programming and would
probably
never
be used or developed in the context suggested by the description.
The
main programming features/methods it
attempts to illustrate are
1)
Use of a doubly-linked list.
2)
Use of Dynamic Memory allocation.
3)
Storing binary data in a file.
4)
Retrieving the binary data again
5)
A very simple menu-based user interface.
Though
the program is fully functional and well-debugged, major features are missing -
such as
a)
Ability to edit customer data.
b)
Ability to edit purchase records
c)
Ability to easily correct data entry errors.
As
the point of this demonstration program was to illustrate the use of some
simple data structures,
it
didn't seem worth adding the additional features to a program that would never
be used.
The
code here could be adapted to other purposes - mainly to do with storing
records in C linked
lists.
Modern
languages make this sort of task much simpler and far less error prone.
However, these
modern
languages may not be usable on the system you are developing code for.
*/
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
#include
<ctype.h>
#include
<float.h>
#include
<time.h>
#include
<termios.h> /* Linux System File
*/
/*
Purchase Record Definition */
struct
purchase_rec
{
long item_code;
int
quantity;
float
unit_price;
char date[30];
struct purchase_rec *next_purchase_ptr;
};
/*
Customer Record Definition. */
struct
customer_record
{
long
ref_no;
char
name[40];
char
address[3][50];
char
telephone[20];
float
amount_owing;
long
no_of_items_bought;
struct customer_record *next_cust_ptr;
struct customer_record *prev_cust_ptr;
struct purchase_rec *purchase_list_ptr;
};
/*
Declare a new type called “FUNCTION_PTR”. */
typedef
void (*FUNCTION_PTR)(void);
struct
menu_table_element
{
char
keypress; /*This
field will hold the keypress.*/
char
menu_item_text[50];
FUNCTION_PTR handler_function; /*This will
hold the function pointer. */
};
#define
MAIN_MENU_SIZE 7
//
We need function pre-declarations so we can build a table.
void
enter_customer();
void
display_customers();
void
delete_customer();
void
enter_purchase();
void
display_purchases();
void
finish();
/*
Build up a table of function addresses, with “ID's”. */
struct
menu_table_element menu_table[MAIN_MENU_SIZE] =
{
'1', "Enter New Customer",
enter_customer,
'2', "Display Customer List",
display_customers,
'3', "Delete Customer",
delete_customer,
'4', "Enter a New Purchase",
enter_purchase,
'5', "Display Customer Purchases",
display_purchases,
'6', "Enter
Payment",display_purchases,
'0', "Quit", finish
};
/*
Global pointer to start of customer list. */
struct
customer_record *customer_list_head, *prev_cust_ptr;
/*
Keep a current customer reference number. */
long
customer_no=1000;
char
*file_name_ptr,filename[80];
#define
CUSTOMERS_FILE_NAME "slm.dat"
/*************************************************************************
*
Function: gotoxy
*
Parameters: column - X, row - Y
*
Description: Moves printing position to
specified screen/window location
*
*
Returns: Nothing
**************************************************************************/
void
gotoxy(int x, int y)
{
// This uses what's called an ANSI escape
sequence to move the cursor
// to a particular location in the window.
printf("\033[%d;%dH", y, x);
}
/*************************************************************************
*
Function: clrscr
*
Parameters: none
*
Description: Clears the "screen"
(console printing area)
*
*
Returns: Nothing
**************************************************************************/
void
clrscr()
{
// This uses what's called an ANSI escape
sequence to clear the
// viewing portion of the terminal window.
printf ("\033c");
}
/*************************************************************************
*
Function: getch()
*
Parameters: none
*
Description: Waits for a single key to
be pressed, rather than needing
"Enter" or "Return"
to be pressed - hence the jiggery pokery
*
Returns: The key code that was
pressed.
**************************************************************************/
char
getch(void)
{
int c=0;
struct termios org_opts, new_opts;
int res=0;
//-----
store old IO settings in a structure -----------
res=tcgetattr(fileno(stdin),
&org_opts);
//Keep a copy:
new_opts = org_opts;
//Update the bits we're interested in
new_opts.c_lflag &= ~(ICANON | ECHO |
ECHOE | ECHOK | ECHONL | ECHOPRT | ECHOKE | ICRNL);
//Put the settings into the system.
tcsetattr(fileno(stdin), TCSANOW,
&new_opts);
//Check for a keypress
c=getchar();
//------
restore old settings ---------
res=tcsetattr(fileno(stdin), TCSANOW,
&org_opts);
//assert(res==0);
return(c);
}
/****************************************************************************
* Function:
delay
* Description:
Delay execution for a set time. We will use a Linux System
* function to delay execution
but use a value in milliseconds
****************************************************************************/
void
delay (long millisecs)
{
struct timespec time_val, result_val;
//Convert milliseconds to seconds and store
it in a structure field.
time_val.tv_sec = millisecs/1000;
time_val.tv_nsec = (millisecs%1000)*1000000;
//It seems overkill, but the system function
takes 2 structures as
//paramaters - and it's only the 1st one
we're interested in here.
nanosleep(&time_val, &result_val);
}
/****************************************************************************
* Function:
delete_purchases
* Description:
Free up all memory for a list of purchases.
****************************************************************************/
void
delete_purchases(struct purchase_rec *purchase_ptr)
{
struct purchase_rec *next_ptr;
/* Scan down purchase list. */
while (purchase_ptr)
{
next_ptr = purchase_ptr->next_purchase_ptr;
free (purchase_ptr);
purchase_ptr = next_ptr;
}
}
/**************************************************************************
* Function:
write_purchase_records
* Description:
Write all purchase records for a customer to the file
* Parameters:
file pointer, customer record pointer.
***************************************************************************/
void
write_purchase_records(FILE *file_ptr, struct customer_record *record_ptr)
{
long no_item_records, bytes_written;
struct purchase_rec *item_record_ptr;
/*Set up pointer to head of list of items.
*/
item_record_ptr =
record_ptr->purchase_list_ptr;
for (no_item_records = 0;
no_item_records <
record_ptr->no_of_items_bought;
no_item_records++)
{
/* Write the whole record to the output
file. */
bytes_written = fwrite ((char
*)item_record_ptr, 1,
sizeof (struct
purchase_rec), file_ptr);
/* Check and set a flag for end of file.
*/
if (bytes_written != sizeof (struct
purchase_rec))
{
printf ("\nFile write
error!\n");
}
item_record_ptr =
item_record_ptr->next_purchase_ptr;
}
}
/***************************************************************************
* Function:
write_disk_file
* Description:
Writes all customer details to a data file.
***************************************************************************/
void
write_disk_file(char *data_file_name)
{
FILE *file_ptr;
/*
Set up a value to hold the length of our record. */
int
record_length = sizeof (struct customer_record);
int
bytes_written;
long customer_count = 0;
struct customer_record *customer_ptr;
if ((!data_file_name) || (!*data_file_name))
{
data_file_name = CUSTOMERS_FILE_NAME;
}
/* Set things up ready to write the file -
use "file_ptr" to access it./
file_ptr = fopen
(data_file_name,"wb");
if (file_ptr == NULL)
{
printf ("*** Could not open %s!",
data_file_name);
}
else
{
/* Write the current max customer
number to file first. */
fwrite ((char *)&customer_no, 1,
sizeof (long), file_ptr);
/* Set to start of list. */
customer_ptr = customer_list_head;
/* Keep writing records using a
"do" loop. */
while (customer_ptr != NULL)
{
/* Read the whole record from the
input file. */
bytes_written = fwrite ((char
*)customer_ptr, 1,
sizeof (struct customer_record), file_ptr);
/* Check bytes actually written
to file. */
if (bytes_written !=
record_length)
{
printf ("\nFile write
error for %s (Disk Full?)\n",data_file_name);
}
/* Check for purchase records: */
if
(customer_ptr->no_of_items_bought)
{
/* Write the purchase records
for this customer. */
write_purchase_records
(file_ptr, customer_ptr);
}
/* Move to next record in list.
*/
customer_ptr =
customer_ptr->next_cust_ptr;
customer_count++;
}
/* Close the file we were using. */
fclose (file_ptr);
printf ( "\n\n%ld record(s)
written\n",customer_count);
}
delay (1500);
}
/****************************************************************************
* Function:
finish
* Description:
Free up all dynamically allocated memory, close files
* and exit.
****************************************************************************/
void
finish(void)
{
struct customer_record *next_cust_ptr,
*customer_ptr = customer_list_head;
write_disk_file(filename);
printf ("\nRecords saved.
Farewell!\n");
delay (1000);
/* Free all memory for purchase and customer
records....*/
while (customer_ptr)
{
next_cust_ptr =
customer_ptr->next_cust_ptr;
delete_purchases(customer_ptr->purchase_list_ptr);
free (customer_ptr);
customer_ptr = next_cust_ptr;
}
exit (0);
}
/****************************************************************************
* Function:
display_customer_record
* Description:
Display one customer's Details
* Parameters:
Pointer to Customer's Record
*
* Returns:
Nothing.
****************************************************************************/
void
display_cust_record (struct customer_record *record_ptr)
{
printf ("\nName:\t\t\%s\n",
record_ptr->name);
printf ("Ref No:\t\t%ld\n",
record_ptr->ref_no);
printf ("Address:\t%s\n",
record_ptr->address[0]);
printf ("\t\t%s\n",
record_ptr->address[1]);
printf ("\t\t%s\n",
record_ptr->address[2]);
printf ("Tel. \t\t%s\n",
record_ptr->telephone);
printf ("Credit /
Debit\t£%05.02f\n", record_ptr->amount_owing);
printf ("No of items:\t%ld",
record_ptr->no_of_items_bought);
}
/****************************************************************************
* Function:
display_purchase_record
* Description:
Display a customer's purchase record
* Parameters:
Pointer to purchase Record
*
* Returns:
Nothing.
****************************************************************************/
void
display_purchase_record (struct purchase_rec *record_ptr)
{
printf ("\nItem Code\t%ld\n",
record_ptr->item_code);
printf ("Quantity:\t%d\n",
record_ptr->quantity);
printf ("Unit Price:\t£%03.2f\n",
record_ptr->unit_price);
printf ("Date: %s\t\t",
record_ptr->date);
}
/****************************************************************************
* Function:
get_customer_record
* Description:
Gets a record pointer for a given customer number.
* Parameters:
none
*
* Returns:
Pointer to the customer's record.
****************************************************************************/
struct
customer_record *get_customer_record (void)
{
struct customer_record *record_ptr;
long ref_no;
char resp;
do
{
if (customer_list_head==NULL)
{
printf ("***No customers in the
database!\n");
delay (1000);
return 0;
}
clrscr();
fflush (stdin);
printf ("Enter reference number
>>>");
scanf ("%ld", &ref_no);
record_ptr = customer_list_head;
/* Scan through the linked list till we
find our reference number. */
do
{
if (record_ptr->ref_no == ref_no)
{
display_cust_record(record_ptr);
break;
}
else
{
/* Pass to next customer in list.
*/
record_ptr =
record_ptr->next_cust_ptr;
}
}
while (record_ptr != NULL);
/* Check to see if we found a customer.
*/
if (record_ptr ==NULL)
{
printf ("\n\n*** Error - no such
customer!\n");
delay (1000);
}
else
{
printf ("\nIs this correct? [Y/N]
");
fflush(stdin);
resp = getchar();
if (toupper (getchar()) != 'Y')
{
/* Force the loop round again. */
record_ptr = NULL;
}
}
}
while(record_ptr == NULL);
return (record_ptr);
}
/****************************************************************************
* Function:
read_customer_record
* Description:
Read in Customer details from keyboard.
* Parameters:
Pointer to Customer's Record
*
* Returns:
Nothing.
****************************************************************************/
void
read_customer_record (struct customer_record *record_ptr)
{
int i;
do
{
printf ("Enter the name
>>>");
gets (record_ptr->name);
for (i = 0; i < 3; i++)
{
printf ("Enter the
Address[%d]>>>",i+1);
gets (record_ptr->address[i]);
}
printf ("\nEnter Tel No.
>>>");
gets(record_ptr->telephone);
printf ("\nIs this correct? (Y =
Yes)");
}
while (toupper(getch())!='Y');
record_ptr->purchase_list_ptr = NULL;
/* Increment the reference number that we
are using. */
record_ptr->ref_no = customer_no++;
}
/****************************************************************************
* Function:
display_customers
* Description:
Display all customer details
* Parameters:
Pointer to Customer's Record
*
* Returns:
Nothing.
****************************************************************************/
void
display_customers()
{
struct customer_record *customer_ptr;
/* Set to start of list. */
customer_ptr = customer_list_head;
clrscr();
/* Keep writing records using a
"do" loop. */
while (customer_ptr != NULL)
{
display_cust_record(customer_ptr);
/* Move to next record in list. */
customer_ptr =
customer_ptr->next_cust_ptr;
printf ("\nPress Any Key to Advance...");
getch();
}
getch();
}
/**************************************************************************
* Function:
get_time_date
* description:
returns a pointer to a string with current time & date
***************************************************************************/
char
*get_time_date(void)
{
time_t t;
static char temp_buffer[30];
//Call the system function to get a time
value.
time(&t);
//Format the time value into a string.
strncpy (temp_buffer, ctime(&t), 24);
//Terminate the string so it can be
displayed.
temp_buffer[25] = 0;
return (temp_buffer);
}
/****************************************************************************
* Function:
read_purchase_record
* Description:
Read in purchase details from keyboard.
* Parameters:
Pointer to purchase Record
*
* Returns:
Nothing.
****************************************************************************/
void
read_purchase_record (struct purchase_rec *record_ptr)
{
char resp;
do
{
fflush (stdin);
printf ("Enter the item code >>>");
scanf
("%ld",&record_ptr->item_code);
printf ("Enter the quantity >>>");
scanf
("%d",&record_ptr->quantity);
printf ("Enter the unit price
>>> £");
scanf
("%f",&record_ptr->unit_price);
printf ("\nIs this correct? (Y =
Yes)");
resp = toupper(getchar());
}
while (resp=='Y');
/* Get time and date and store it in this
purchase record. */
strcpy (record_ptr->date,
get_time_date());
}
/**************************************************************************
* Function:
read_purchase_records
* Description:
Reads all purchase records for a customer from the file
* Parameters:
file pointer, customer record pointer.
***************************************************************************/
void
read_purchase_records(FILE *file_ptr, struct customer_record *record_ptr)
{
long no_item_records, bytes_read;
struct purchase_rec *item_record_ptr, *prev_record_ptr=NULL;
for (no_item_records = 0;
no_item_records <
record_ptr->no_of_items_bought;
no_item_records++)
{
/* Allocate memory to hold one customer
record. */
item_record_ptr = malloc (sizeof (struct
purchase_rec));
/* Set pointer field to NULL. */
item_record_ptr->next_purchase_ptr =
NULL;
if (item_record_ptr == NULL)
{
printf ("\nFailed to allocate
memory whilst reading disk file!!\n");
finish();
}
/* Set up pointer to this new record from
the previous record. */
if (prev_record_ptr!= NULL)
{
prev_record_ptr->next_purchase_ptr=item_record_ptr;
}
/* If this is the 1st purchase record
read,
set up the head of the list in the
customer record. */
if (no_item_records == 0)
{
record_ptr->purchase_list_ptr =
item_record_ptr;
}
/* Read the whole record from the input
file. */
bytes_read = fread ((char
*)item_record_ptr, 1,
sizeof (struct purchase_rec),
file_ptr);
if (bytes_read != sizeof (struct
purchase_rec))
{
printf ("\nFile read
error!\n");
finish();
}
prev_record_ptr = item_record_ptr;
}
}
/**************************************************************************
* Function:
read_disk_file
* Description:
Reads all customer details from a file.
***************************************************************************/
void
read_disk_file(char *data_file_name)
{
FILE *file_ptr;
/* Set up a value to hold the length of our
record. */
int
record_length = sizeof (struct customer_record);
int
bytes_read, end_of_file=0;
long customer_count = 0;
struct customer_record *customer_ptr,
*prev_ptr;
/* Set things up ready to read the input
file - use "file_ptr" to access it./
file_ptr = fopen
(data_file_name,"rb");
if (file_ptr == NULL)
{
printf ("*** Could not open
%s!", data_file_name);
}
else
{
/* Get the current max customer number - 1st
thing in file. */
fread ((char *)&customer_no, 1,
sizeof (long), file_ptr);
/* Keep reading records using a
"do" loop. */
do
{
/* Allocate memory to hold one
customer record. */
customer_ptr = malloc
(record_length);
if (customer_ptr == NULL)
{
printf ("\nFailed to
allocate memory whilst reading disk file!!\n");
finish();
}
else
{
/* Read the whole record from the
input file. */
bytes_read = fread ((char
*)customer_ptr, 1,
sizeof (struct
customer_record), file_ptr);
/* Check and set a flag for end
of file. */
end_of_file = feof (file_ptr);
if ((bytes_read != record_length)
&& !(end_of_file))
{
printf ("\nFile read
error for %s!\n",data_file_name);
finish();
}
/* Check for purchase records: */
if
((customer_ptr->no_of_items_bought) && (!end_of_file))
{
/* Read the purchase records
for this customer. */
read_purchase_records
(file_ptr, customer_ptr);
}
/* At end of file, we will have
erroneously created a customer
record, so delete it. */
if (end_of_file)
{
free (customer_ptr);
}
else
{
/* If this is the 1st record
read, set up
the head of the list. */
if (customer_count == 0)
{
customer_list_head =
customer_ptr;
customer_ptr->prev_cust_ptr=NULL;
}
else
{
/* Add record onto list
of customers. */
prev_ptr->next_cust_ptr = customer_ptr;
//Set previous record back from this one.
customer_ptr->prev_cust_ptr=prev_ptr;
}
prev_ptr = customer_ptr;
/* Set end of list. */
customer_ptr->next_cust_ptr = NULL;
customer_count++;
}
}
}
while (!feof(file_ptr));
/* Close the file we were using. */
fclose (file_ptr);
printf ( "\n\n%ld Records
read\n",customer_count);
}
delay (1500);
}
/****************************************************************************
* Function:
enter_customer
* Description: Allocate memory for a new
customer record and read details *
****************************************************************************/
void
enter_customer(void)
{
struct customer_record
*record_ptr,*current_ptr=NULL;
clrscr();
/*Allocate memory for new purchase record.
*/
record_ptr = malloc (sizeof (struct
customer_record));
/*Check we got it. */
if (record_ptr == NULL)
{
printf ("\n\n***Unable to allocate
memory for customer record!\n\n");
}
else
{
/*Set up "head" pointer now
that we have read a record. */
if (customer_list_head == NULL)
{
customer_list_head = record_ptr;
}
else
{
current_ptr = customer_list_head;
/* Add this record onto the list. */
while (current_ptr->next_cust_ptr)
{
current_ptr =
current_ptr->next_cust_ptr;
}
current_ptr->next_cust_ptr =
record_ptr;
}
record_ptr->next_cust_ptr = NULL;
/* Set list of purchases to be NULL.. */
record_ptr->purchase_list_ptr = NULL;
/* Set item details. */
record_ptr->amount_owing = 0;
record_ptr->no_of_items_bought = 0;
//Link back to the previous
record_ptr->prev_cust_ptr=current_ptr;
/* Now read in customer details. */
read_customer_record (record_ptr);
}
}
/****************************************************************************
* Function:
enter_purchase
* Description: get customer refernece number,
allocate memory and read
* details.
****************************************************************************/
void
enter_purchase(void)
{
struct customer_record *record_ptr;
struct purchase_rec *purchase_ptr,
*new_purchase_ptr;
//long ref_no;
record_ptr = get_customer_record();
if (record_ptr==NULL)
{
printf ("***No customers in the
database!\n");
return;
}
/*Allocate memory for new purchase record.
*/
new_purchase_ptr = malloc (sizeof (struct
purchase_rec));
if (!new_purchase_ptr)
{
printf ("\n\n***Could not allocate
memory for new purchase!\n");
}
else
{
/* Read in the details. */
read_purchase_record(new_purchase_ptr);
/* Set "next" field as this
record will now form end of list. */
new_purchase_ptr->next_purchase_ptr =
NULL;
/*Count the purchases for this customer.
*/
record_ptr->no_of_items_bought++;
/* Add on the amount owing. */
record_ptr->amount_owing +=
new_purchase_ptr->unit_price *
new_purchase_ptr->quantity;
/* Add this pruchase onto the list... */
purchase_ptr =
record_ptr->purchase_list_ptr;
/* If this is the 1st purchase, set head
of purchase list.*/
if (!purchase_ptr)
{
record_ptr->purchase_list_ptr=new_purchase_ptr;
}
else
{
/* Search to end of list. */
while
(purchase_ptr->next_purchase_ptr)
{
purchase_ptr =
purchase_ptr->next_purchase_ptr;
}
/* Add on the new purchase record...*/
purchase_ptr->next_purchase_ptr =
new_purchase_ptr;
}
}
}
/****************************************************************************
* Function:
enter_payment
* Description: Enter a payment made by a
customer.
* details.
****************************************************************************/
void
enter_payment(void)
{
struct customer_record *record_ptr;
float payment;
record_ptr = get_customer_record();
printf ("\n\nEnter amount of payment
>>>");
/*Get the amount paid. */
scanf ("%f", &payment);
/* Update the record accordingly. */
record_ptr->amount_owing -= payment;
}
/****************************************************************************
* Function:
display_purchases
* Description: Display list of purchases for a
given customer.
****************************************************************************/
void
display_purchases(void)
{
struct customer_record *customer_ptr;
struct purchase_rec *purchase_ptr;
char resp[10];
//long ref_no;
customer_ptr = get_customer_record();
if (customer_ptr)
{
/* Get pointer to purchase list. */
purchase_ptr =
customer_ptr->purchase_list_ptr;
}
else
{
purchase_ptr = NULL;
}
if (!purchase_ptr)
{
printf ("\nThis customer has not
made any purchases!\n");
delay (1000);
}
else
{
clrscr();
fflush(stdin);
/* Display the list of purchases, pausing
between each. */
while (purchase_ptr)
{
display_purchase_record(purchase_ptr);
purchase_ptr = purchase_ptr->next_purchase_ptr;
printf ("\n\n------\n\n");
}
fflush(stdin);
getch();
getch();
}
}
/****************************************************************************
* Function:
delete_customer
* Description: Deletes a customers details.
****************************************************************************/
void
delete_customer(void)
{
struct customer_record *record_ptr,
*prev_record_ptr,*next_record_ptr;
record_ptr = get_customer_record();
if
(record_ptr==NULL)
{
printf ("***No customers in the
database!\n");
return;
}
/*Remove the current customer from the
chain. */
if (record_ptr != customer_list_head)
{
//Get pointers to next and previous
records.
next_record_ptr =
record_ptr->next_cust_ptr;
prev_record_ptr =
record_ptr->prev_cust_ptr;
//Now set the pointers to remove the
current element from the list
prev_record_ptr->next_cust_ptr=next_record_ptr;
//Check if this is the last element of
the list.
if (next_record_ptr)
{
next_record_ptr->prev_cust_ptr=prev_record_ptr;
}
}
else
{
//Reset this the new record is the start
of the list.
customer_list_head =
customer_list_head->next_cust_ptr;
//Is the list now empty?
if (customer_list_head)
{
//Set the record properly as we're
at the start of the list
customer_list_head->prev_cust_ptr = NULL;
}
}
/* Delete the purchase list. */
delete_purchases
(record_ptr->purchase_list_ptr);
/* Free record's memory. */
free (record_ptr);
}
/****************************************************************************
* Function:
process_menu_option
* Description: Takes required action for
keypress.
****************************************************************************/
void
process_menu_option(char option)
{
int i;
//Scan through the table and check which
function needs to be called.
for (i=0;i<MAIN_MENU_SIZE;i++)
{
if (option == menu_table[i].keypress)
{
(*menu_table[i].handler_function)();
}
}
}
/****************************************************************************
* Function:
display_menu
* Description: Display the menu for the
program.
****************************************************************************/
void
display_menu(void)
{
int i;
clrscr();
gotoxy(25,3);
printf ("Sales Logger and
Monitor");
gotoxy(25,4);
printf
("------------------------");
for (i=0;i<MAIN_MENU_SIZE;i++)
{
printf ("\n\n\t\t%c.
%s",menu_table[i].keypress,menu_table[i].menu_item_text);
}
printf ("\n\n");
}
/****************************************************************************
* Function:
sign_on
* Description: Display sign on message.
****************************************************************************/
void
sign_on (void)
{
clrscr();
gotoxy (12,10);
printf ("Sales Logger and Monitor by
A.D. Johnson - VERSION 1.0.\n\n\n\n");
delay (1500);
}
/****************************************************************************
* Function:
main
* Description: The main program!
****************************************************************************/
int
main (int argument_count, char *argument_values[])
{
sign_on();
/* Has user supplied filename on command
line? */
if (argument_count > 1)
{
file_name_ptr = argument_values[1];
}
else
{
/* Assume a default filename. */
file_name_ptr = CUSTOMERS_FILE_NAME;
}
/* Read the records in from the supplied
file. */
read_disk_file(file_name_ptr);
do
{
display_menu();
process_menu_option(getch());
}
while (1);
}