Code:
/***************************************************************************
** **
** ASSIGNMENT THREE ADVANCE PROCEDURAL PROGRAMMING (66121) **
** **
** NAME: Zane Jarvis (Q11215164) **
** DATE: 15th October 2001 **
** **
** **
****************************************************************************/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "adt.h"
#define clear printf("\033[2J\033[0;0f")
//****************************************************************************
//*************** F U N C T I O N D E F I N I T I O N S *******************
int menu(void);
void order_bill_by_number(node *Head, long int LowerNum,long int HighNum);
int get_unique_numbers(node *Head);
void sort_bill_by_number(node *Head);
void Produce_Report(void);
void grand_total_bill(node *Start, node *End);
void get_times(node *Array, int *Records, int *HourMinimum, int *MinuteMinimum,
int *HourMaximum, int *MinuteMaximum, char *MinDay, char *MaxDay);
//****************************************************************************
//****************************************************************************
//****************************************************************************
int main() {
node *Head=NULL,
*Tail=NULL;
int choice=0;
bool CheckOptionOne=false,CheckOptionTwo=false;
char billfile[FILENAME_MAX];
do {
choice = menu();
switch(choice) {
case 1:
clear;
printf("Enter The name of File which contains the bill details.\nFILE: ");
scanf(" %s", billfile);
//FREE MEMORY IF USER WISHES TO INPUT ANOTHER FILE
destroy_list(Tail);
Head = get_records(billfile);
if(Head == NULL){
break;
}
Tail = find_tailptr(Head);
CheckOptionOne=true; //SET FLAG TO TRUE FOR MENU OPTION TWO
break;
case 2:
// CHECK IF OPTION ONE HAS BEEN SELECTED YET
if(CheckOptionOne != true){
fprintf(stderr,"\n\tMust Get Records Before You Can Sort Them.\n");
printf("\tPress [ENTER] to continue.");
getchar();getchar();
}else{
sort_bill_by_number(Head);
CheckOptionTwo=true;
}
break;
case 3:
if (CheckOptionTwo != true){
fprintf(stderr, "\n\tMust Sort Records Before You Can Get A Number "
"Summary\n\tChoose Option Two First\n\tPress [ENTER] "
"to continue.");
getchar();getchar();
}else{
Produce_Report();
}
break;
case 4:
grand_total_bill(Head, Tail);
break;
}
}while(choice != 5);
destroy_list(Tail); //FREE MEMORY
exit(EXIT_SUCCESS);
}
//****************************************************************************
//----------------- E N D O F M A I N F U N C T I O N ------------------
//****************************************************************************
int menu(void){
int selection=0;
//CLEAR THE SCREEN
clear;
//PRINT VERTICAL TAB
puts("\v");
//PRINT MENU
printf("\t**********************************\n"
"\t* M E N U *\n"
"\t**********************************\n"
"\t* *\n"
"\t* 1) Enter bill from file. *\n"
"\t* 2) Sort Bill by Phone Number *\n"
"\t* 3) Produce Report *\n"
"\t* 4) Grand total *\n"
"\t* 5) Exit *\n"
"\t* *\n"
"\t**********************************\n");
printf("\tCHOICE: ");
do { //LOOP UNTIL A VALID SELECTION IS CHOSEN
scanf(" %d", &selection);
//CHECK IF INVALID CHOICE
if(selection != 1 && selection != 2 && selection != 3 && selection != 4 && selection != 5) {
printf("\n\tPlease Choose Only 1,2,3,4, or 5\n\tCHOICE: ");
if(!isdigit(selection)){ //CHECK IF CHOICE IS NOT A NUMBER
scanf(" %*[^\n]"); //GET JUNK
selection = 0; //RESET VARIABLE
}
}else{ //IF VALID NUMBER RETURN TO MAIN
return selection;
}
}while(1); //LOOP UNTIL VALID INPUT
}
//****************************************************************************
void grand_total_bill(node *Start, node *End){
// THIS FUNCTION GETS THE GRAND TO OF THE BILL.
// IT CALCULATES THE TOTAL COST IN DOLLARS AND CENTS, AND FINDS
// THE EARLIEST AND LATEST TIMES CALLS HAD BEEN MADE, ON THE
// FIRST AND LAST DAY OF THE BILL.
node *tempStart=Start,
*temp=NULL,
*tempEnd=End;
int minHour,
minMinutes,
maxHour,
maxMinutes,
NumberOfRecords=0;
char minTimeDay[3],
maxTimeDay[3],
MonthBegin[15],
DayBegin[3],
YearBegin[5],
MonthEnd[15],
DayEnd[3],
YearEnd[5];
float total_cost=0.0;
//GET FIRST DATE (ASSUMED BILL IS IN ORDER)
strcpy(DayBegin, tempStart->DETAILS.date);
strcpy(MonthBegin, tempStart->DETAILS.month);
strcpy(YearBegin, tempStart->DETAILS.year);
//GET LAST DATE (ASSUMED BILL IS IN ORDER)
strcpy(DayEnd, tempEnd->DETAILS.date);
strcpy(MonthEnd, tempEnd->DETAILS.month);
strcpy(YearEnd, tempEnd->DETAILS.year);
do{
++NumberOfRecords;
total_cost += tempStart->DETAILS.cost;
//FIND EARLIEST AND LATEST TIMES
get_times(tempStart, &NumberOfRecords, &minHour,&minMinutes, &maxHour,
&maxMinutes, minTimeDay, maxTimeDay);
temp = tempStart->next; // MOVE TO..
tempStart = temp; // ..NEXT NODE
}while(temp != NULL);
//***** THE FOLLOWING COLLECTION OF IF..ELSE IF...ELSE STATEMENTS
//***** PRINTS THE TIME AND BILL DETAILS TO THE SCREEN APPROPRIATELY
//***** IT DEPENDS ON THE TIME ON WHICH STATEMENT IT CHOOSES TO PRINT
//***** THEY ALL APPEAR THE SAME TO THE END USER THOUGH
if (strcmp(maxTimeDay ,"PM") == 0) {
if(strcmp(minTimeDay ,"AM") == 0){
if(minHour == 0){
clear;
printf("\vAll numbers: %d calls.\n$%.2f from %s %s %s to %s %s %s from %d:%.2d %s to %d:%.2d %s\n", NumberOfRecords, total_cost, DayBegin, MonthBegin, YearBegin, DayEnd, MonthEnd, YearEnd, minHour+12, minMinutes, minTimeDay, maxHour-12, maxMinutes, maxTimeDay );
printf("\vPress [ENTER] to continue.");
getchar();getchar();
}
else{
clear;
printf("\vAll numbers: %d calls.\n $%.2f from %s %s %s to %s %s %s from %d:%.2d %s to %d:%.2d %s\n", NumberOfRecords, total_cost, DayBegin, MonthBegin, YearBegin, DayEnd, MonthEnd, YearEnd, minHour, minMinutes, minTimeDay, maxHour-12, maxMinutes, maxTimeDay );
printf("\vPress [ENTER] to continue.");
getchar();getchar();
}
}
else if (strcmp(minTimeDay ,"PM") == 0){
if(minHour == 12){
clear;
printf("\vAll numbers: %d calls.\n $%.2f from %s %s %s to %s %s %s from %d:%.2d %s to %d:%.2d %s\n", NumberOfRecords, total_cost, DayBegin, MonthBegin, YearBegin, DayEnd, MonthEnd, YearEnd, minHour, minMinutes, minTimeDay, maxHour-12, maxMinutes, maxTimeDay );
printf("\vPress [ENTER] to continue.");
getchar();getchar();
}
else {
clear;
printf("\vAll numbers: %d calls.\n $%.2f from %s %s %s to %s %s %s from %d:%.2d %s to %d:%.2d %s\n", NumberOfRecords, total_cost, DayBegin, MonthBegin, YearBegin, DayEnd, MonthEnd, YearEnd, minHour-12, minMinutes, minTimeDay, maxHour-12, maxMinutes, maxTimeDay );
printf("\vPress [ENTER] to continue.");
getchar();getchar();
}
}
}
else if (strcmp(maxTimeDay ,"AM") == 0) {
clear;
printf("\vAll numbers: %d calls.\n $%.2f from %s %s %s to %s %s %s from %d:%.2d %s to %d:%.2d %s\n", NumberOfRecords, total_cost, DayBegin, MonthBegin, YearBegin, DayEnd, MonthEnd, YearEnd, minHour, minMinutes, minTimeDay, maxHour, maxMinutes, maxTimeDay );
printf("\vPress [ENTER] to continue.");
getchar();getchar();
}
} //END OF FUNCTION
//****************************************************************************
void get_times(node *Array, int *Records, int *HourMinimum, int *MinuteMinimum,
int *HourMaximum, int *MinuteMaximum, char *MinDay, char *MaxDay){
// THIS FUNCTION FINDS JUST THE EARLIEST AND LATEST TIMES
if(strcmp(Array->DETAILS.TimeOfDay, "AM") == 0) {
if(*Records == 1) { //GET FIRST RECORD
if (Array->DETAILS.hour == 12){
*HourMinimum = *HourMaximum = 0;
}
else {
*HourMinimum = *HourMaximum = Array->DETAILS.hour;
}
*MinuteMinimum = *MinuteMaximum = Array->DETAILS.min;
strcpy(MinDay, "AM");strcpy(MaxDay, "AM");
}
else {
if(Array->DETAILS.hour == 12){
*HourMinimum = 0;
*MinuteMinimum = Array->DETAILS.min;
strcpy(MinDay, "AM");
}
else if (Array->DETAILS.hour <= *HourMinimum){
if (Array->DETAILS.hour < *HourMinimum){
*HourMinimum = Array->DETAILS.hour;
*MinuteMinimum = Array->DETAILS.min;
strcpy(MinDay, "AM");
}
else if (Array->DETAILS.hour == *HourMinimum && Array->DETAILS.min < *MinuteMinimum){
*MinuteMinimum = Array->DETAILS.min;
strcpy(MinDay, "AM");
}
}
else if (Array->DETAILS.hour >= *HourMaximum){
if (Array->DETAILS.hour > *HourMaximum){
*HourMaximum = Array->DETAILS.hour;
*MinuteMaximum = Array->DETAILS.min;
strcpy(MaxDay, "AM");
}
else if (Array->DETAILS.hour == *HourMaximum && Array->DETAILS.min > *MinuteMaximum){
*MinuteMaximum = Array->DETAILS.min;
strcpy(MaxDay, "AM");
}
}
}
}
else if(strcmp(Array->DETAILS.TimeOfDay, "PM") == 0) {
if(*Records == 1) { //GET FIRST RECORD
if (Array->DETAILS.hour == 12){
*HourMinimum = *HourMaximum = Array->DETAILS.hour;
}
else{
*HourMinimum = *HourMaximum = (Array->DETAILS.hour + 12);
}
*MinuteMinimum = *MinuteMaximum = Array->DETAILS.min;
strcpy(MinDay, "PM");
strcpy(MaxDay, "PM");
}
else {
if(Array->DETAILS.hour == 12) {
if (Array->DETAILS.hour <= *HourMinimum) {
if (Array->DETAILS.hour < *HourMinimum){
*HourMinimum = Array->DETAILS.hour;
*MinuteMinimum = Array->DETAILS.min;
strcpy(MinDay, "PM");
}
else if (Array->DETAILS.hour == *HourMinimum && Array->DETAILS.min < *MinuteMinimum){
*MinuteMinimum = Array->DETAILS.min;
strcpy(MinDay, "PM");
}
}
else if (Array->DETAILS.hour >= *HourMaximum){
if (Array->DETAILS.hour > *HourMaximum){
*HourMaximum = Array->DETAILS.hour;
*MinuteMaximum = Array->DETAILS.min;
strcpy(MaxDay, "PM");
}
else if (Array->DETAILS.hour == *HourMaximum && Array->DETAILS.min > *MinuteMaximum) {
*MinuteMaximum = Array->DETAILS.min;
strcpy(MaxDay, "PM");
}
} //END OF "else if (Array->DETAILS.hour >= HourMaximum)"
} //END OF "if(Array->DETAILS.hour == 12)"
else if ((Array->DETAILS.hour + 12) <= *HourMinimum){
if (Array->DETAILS.hour < *HourMinimum){
*HourMinimum = (Array->DETAILS.hour + 12);
*MinuteMinimum = Array->DETAILS.min;
strcpy(MinDay, "PM");
}
else if ((Array->DETAILS.hour + 12) == *HourMinimum && Array->DETAILS.min < *MinuteMinimum){
*MinuteMinimum = Array->DETAILS.min;
strcpy(MinDay, "PM");
}
} //END OF "else if ((Array->DETAILS.hour + 12) <= HourMinimum)"
else if ((Array->DETAILS.hour + 12) >= *HourMaximum){
if ((Array->DETAILS.hour + 12) > *HourMaximum){
*HourMaximum = (Array->DETAILS.hour + 12);
*MinuteMaximum = Array->DETAILS.min;
strcpy(MaxDay, "PM");
}
else if ((Array->DETAILS.hour + 12) == *HourMaximum && Array->DETAILS.min > *MinuteMaximum) {
*MinuteMaximum = Array->DETAILS.min;
strcpy(MaxDay, "PM");
}
}
}
}// END OF "else if(strcmp(Array->DETAILS.TimeOfDay, "PM") == 0)"
} //END OF FUNCTION
//****************************************************************************
void sort_bill_by_number(node *Head){
char Sorted_phoneNumbers[50][11];
node *tempHead = Head, *tempNodeptr=NULL;
int Number_Of_PhNums=0, phone_counter=0;
//*** GET ONE COPY OF EVERY PHONE NUMBER
Number_Of_PhNums = get_unique_numbers(tempHead);
//*** GET PHONE NUMBERS FROM FILE
FILE *uniqueNumbers = fopen("tempSortNumbers.tmp", "r");
FILE *orderedBill = fopen("orderdBill_by_phone","w");
if (uniqueNumbers == NULL || orderedBill == NULL){
clear;
fprintf(stderr, "\n\nUnable to open neccessary file.\n\nPress [ENTER] to continue.");
getchar();getchar();
return;
}
while(fscanf(uniqueNumbers," %s",Sorted_phoneNumbers[phone_counter]) != EOF){
tempHead = Head;
while (tempHead != NULL){
if (strcmp(tempHead->DETAILS.number, Sorted_phoneNumbers[phone_counter])==0){
fprintf(orderedBill,"%s %s %s %s %d:%.2d %s %s %.2f\n", tempHead->DETAILS.year, tempHead->DETAILS.date, tempHead->DETAILS.month, tempHead->DETAILS.day, tempHead->DETAILS.hour, tempHead->DETAILS.min, tempHead->DETAILS.TimeOfDay, tempHead->DETAILS.number, tempHead->DETAILS.cost);
}
tempNodeptr = tempHead->next;
tempHead = tempNodeptr;
}
}
fclose(uniqueNumbers);
fclose(orderedBill);
}
//****************************************************************************
int get_unique_numbers(node *Head){
// THIS FUNCTION FINDS EVERY NUMBER AND ONLY RECORDS ONE RECORD OF IT.
// IT THEN SORTS THEM IN ASCENDING ORDER AND RETURNS THE NUMBER OF UNIQUE
// NUMBERS
node *tempHead,
*tempptr;
char tempNumber[11],
phoneNumbers[50][11];
int counter=0; //Counter
bool NumberFlag=false;
FILE *SortedNumbers = fopen("tempSortNumbers.tmp","w");
if (SortedNumbers == NULL){
fprintf(stderr, "Unable To Continue Program Exiting");
exit(EXIT_FAILURE);
}
tempHead = Head;
strcpy(phoneNumbers[counter], tempHead->DETAILS.number);
tempptr = tempHead->next;
tempHead = tempptr;
while(tempHead != NULL){
strcpy(tempNumber, tempHead->DETAILS.number);
for(int tempCount=0; tempCount <= counter+1; tempCount++){
if (atol(tempNumber) == atol(phoneNumbers[tempCount])){
NumberFlag = false;
break;
}else {
NumberFlag = true;
}
}
if (NumberFlag == true){
counter++;
strcpy(phoneNumbers[counter], tempNumber);
}
tempptr = tempHead->next;
tempHead = tempptr;
} //END OF WHILE LOOP
//*** BUBBLE SORT ***
// BUBBLE SORT THE NUMBERS INTO ASCENDING ORDER
for (int loop1=1; loop1 <= counter - 0; loop1++){
for (int loop2=0; loop2 <= counter - 1; loop2++){
if ( atol(phoneNumbers[loop2]) > atol(phoneNumbers[loop2+1])){
strcpy(tempNumber, phoneNumbers[loop2]);
strcpy(phoneNumbers[loop2], phoneNumbers[loop2+1]);
strcpy(phoneNumbers[loop2+1], tempNumber);
}
}
}
//*** WRITE SORTED NUMBERS TO FILE
for (int WriteLoop=0; WriteLoop <= counter; WriteLoop++){
fprintf(SortedNumbers, "%s\n", phoneNumbers[WriteLoop]);
}
//CLOSE THE FILE STREAM
fclose(SortedNumbers);
return counter;
}//END OF FUNCTION
//****************************************************************************
void Produce_Report(void){
// THIS FUNCTION PRODUCES A REPORT FOR EACH INDIVIDUAL NUMBER
// IT TOTALS THE NUMBER OF CALLS TO EACH NUMBER THE TOTAL COST
// AND THE EARLIEST AND LATEST DAYS AND TIMES FOR EACH NUMBER
// IT ALSO ASK THE USER WHICH NUMBER THEY WISH TO SEE AND OUTPUTS
// THE RESULTS TO THE SCREEN
FILE *OrderdBillptr = fopen("orderdBill_by_phone", "r");
FILE *reading_pointer;
float total_cost = 0;
int counter = 0,
x = 0,
y = 0,
z = 0,
CHECK_FLAG = 0;
char from_date[3],
from_year[5],
to_date[3],
to_year[5],
from_month[5],
to_month[5],
last_number[11],
phone_number[11];
int HourBegin,
MinutesBegin,
HOUR_24_temp,
Minutes_24_temp,
HourEnd_current,
MinutesEnd_current,
TotalCalls;
char early_period[3],
late_period[3],
ValidNumbers[11][500];
details bill,
temp[100];
fscanf(OrderdBillptr, "%s %s %s %s %d:%d %s %s %f", bill.year, bill.date, bill.month, bill.day, &bill.hour, &bill.min, bill.TimeOfDay, bill.number, &bill.cost);
printf("Please Choose a Phone number to show total for...\n");
printf("%d) %s\n", ++counter, bill.number);
strcpy(last_number, bill.number);
while (fscanf(OrderdBillptr, "%s %s %s %s %d:%d %s %s %f", bill.year, bill.date, bill.month, bill.day, &bill.hour, &bill.min, bill.TimeOfDay, bill.number, &bill.cost) != EOF){
if (strcmp(bill.number, last_number) == 0){
strcpy(last_number, bill.number);
}
else {
printf("%d) %s\n", ++counter, bill.number);
strcpy(ValidNumbers[x], bill.number);
strcpy(last_number, bill.number);
}
y++;
}
fclose(OrderdBillptr);
while (1){
z = 0;
printf("Enter Phone Number:> ");
scanf("%s", phone_number);
while (z != y){
if (strcmp(phone_number, ValidNumbers[z]) == 0){
CHECK_FLAG = 1;
break;
}
z++;
} // END OF WHILE(z != y) LOOP
if (CHECK_FLAG == 1){
CHECK_FLAG = 0;
break;
}
else {
printf("Invalid Phone Number Entered...\n");
}
}//END OF WHILE(1) LOOP
reading_pointer = fopen("orderdBill_by_phone", "r");
while (fscanf(OrderdBillptr, "%s %s %s %s %d:%d %s %s %f\n", bill.year, bill.date, bill.month, bill.day, &bill.hour, &bill.min, bill.TimeOfDay, bill.number, &bill.cost) != EOF){
if (strcmp(phone_number, bill.number) == 0){
strcpy(temp[x].year, bill.year);
strcpy(temp[x].date, bill.date);
strcpy(temp[x].month, bill.month);
strcpy(temp[x].day, bill.day);
temp[x].hour = bill.hour;
temp[x].min= bill.min;
strcpy(temp[x].TimeOfDay, bill.TimeOfDay);
strcpy(temp[x].number, bill.number);
temp[x].cost = bill.cost;
TotalCalls = x + 1;
x++;
}
}
x = 0;
while (x != TotalCalls){
total_cost = total_cost + temp[x].cost;
x++;
}
strcpy(from_date, temp[0].date);
strcpy(from_month, temp[0].month);
strcpy(from_year, temp[0].year);
strcpy(to_date, temp[x-1].date);
strcpy(to_month, temp[x-1].month);
strcpy(to_year, temp[x-1].year);
if (strcmp(temp[0].TimeOfDay, "PM") == 0){
if (temp[0].hour == 12){
HOUR_24_temp = temp[0].hour;
Minutes_24_temp = temp[0].min;
}
else {
HOUR_24_temp = temp[0].hour + 12;
Minutes_24_temp = temp[0].min;
}
}
else if (strcmp(temp[0].TimeOfDay, "AM") == 0){
if (temp[0].hour == 12){
HOUR_24_temp = 0;
Minutes_24_temp = temp[0].min;
}
else {
HOUR_24_temp = temp[0].hour;
Minutes_24_temp = temp[0].min;
}
}
HourEnd_current = HOUR_24_temp;
MinutesEnd_current = Minutes_24_temp;
if (HourEnd_current >= 12){
if (HourEnd_current == 12){
HourEnd_current = HourEnd_current;
}
else{
HourEnd_current = HourEnd_current - 12;
}
strcpy(late_period, "PM");
}
else if (HourEnd_current < 12){
if (HourEnd_current == 0){
HourEnd_current = 12;
}
strcpy(late_period, "AM");
}
HourBegin = HOUR_24_temp;
MinutesBegin = Minutes_24_temp;
if (HourBegin >= 12){
if (HourBegin == 12){
HourBegin = HourBegin;
}
else{
HourBegin = HourBegin - 12;
}
strcpy(early_period, "PM");
}
else if (HourBegin < 12){
if (HourBegin == 0){
HourBegin = 12;
}
strcpy(early_period, "AM");
}
x = 1;
while (x != TotalCalls){
if (strcmp(temp[x].TimeOfDay, "PM") == 0){
if (temp[x].hour == 12){
HOUR_24_temp = temp[x].hour;
Minutes_24_temp = temp[x].min;
}
else {
HOUR_24_temp = temp[x].hour + 12;
Minutes_24_temp = temp[x].min;
}
}
else if (strcmp(temp[x].TimeOfDay, "AM") == 0){
if (temp[x].hour == 12){
HOUR_24_temp = 0;
Minutes_24_temp = temp[x].min;
}
else{
HOUR_24_temp = temp[x].hour;
Minutes_24_temp = temp[x].min;
}
}
if ((HOUR_24_temp >= HourEnd_current) && (Minutes_24_temp > MinutesEnd_current)){
HourEnd_current = HOUR_24_temp;
MinutesEnd_current = Minutes_24_temp;
if (HourEnd_current >= 12){
if (HourEnd_current == 12){
HourEnd_current = HourEnd_current;
}
else {
HourEnd_current = HourEnd_current - 12;
}
strcpy(late_period, "PM");
}
else if (HourEnd_current < 12){
if (HourEnd_current == 0){
HourEnd_current = 12;
}
strcpy(late_period, "AM");
}
}
else if ((HOUR_24_temp <= HourBegin) && (Minutes_24_temp < MinutesBegin)){
HourBegin = HOUR_24_temp;
MinutesBegin = Minutes_24_temp;
if (HourBegin >= 12){
if (HourBegin == 12){
HourBegin = HourBegin;
}
else{
HourBegin = HourBegin - 12;
}
strcpy(early_period, "PM");
}
else if (HourBegin < 12){
if (HourBegin == 0){
HourBegin = 12;
}
strcpy(early_period, "AM");
}
}
x++;
}
if (TotalCalls == 0){
printf("Invalid Phone Number Entered, Returning to Main Menu...\n");
}
else{
clear;
printf("\v%s - %d calls, with a cost of$ %.2f.\nFrom %s %s %s to %s %s %s from %d:%.2d %s to %d:%.2d %s\r", phone_number, TotalCalls, total_cost, from_date, from_month, from_year, to_date, to_month, to_year, HourBegin, MinutesBegin, early_period, HourEnd_current, MinutesEnd_current, late_period);
printf("\vPress [ENTER] to continue.");
getchar(); getchar();
}
fclose(OrderdBillptr);
}
file: