/******************************************************
* MT285 TMA03 q4a.cpp
* for Q4 (a), (b) and (c)
* IDD Billing report program
* associated files: customer.txt, rate.txt, log.txt
* programming by Allen Lam (99043953)
* compiled by bcb, for DOS only
* Mar 2001
******************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
/**********************************************
Miscellaneous function for presentation purposes
*/
void dashline(){
int i;
for (i=0; i<80; i++) printf("=");
}
void headline(){
clrscr(); printf("IDD phone bill daily report\n");
dashline();
}
void moreline(){
gotoxy(1,24); dashline();
printf("Press any key to continue...");
getch();
}
void quitline(){
gotoxy(1,24); dashline();
printf("End of report. Press any key to quit...");
getch();
}
/**********************************************
Rate Table ADT
*/
/* Size of the Table Array */
#define RT_SIZE 16
struct RT_RateCell {
int rateType;
float rate; /* dollar per MINUTE */
};
struct RT_RateCell RT_rateTable[RT_SIZE];
int RT_count; /* number of rate types loaded from the file */
/**********************************************
This function initialize the rateTable array by
setting its counter (RT_count) and loading the data
from the rate data file (rate.txt).
*/
void RT_initialize() {
FILE* fp;
RT_count = 0;
/* opening the file for reading and error checking */
if ((fp = fopen("rate.txt.", "r")) == NULL) {
fprintf(stderr, "Error in reading rate.txt.\n");
fprintf(stderr, "Please make sure the file is in the local directory.\n");
exit(1);
}
/* reading the rate file by each pair of data*/
while (fscanf(fp, "%d %f", &(RT_rateTable[RT_count].rateType),
&(RT_rateTable[RT_count].rate)) != EOF) {
RT_count++;
if (RT_count >= RT_SIZE)
break;
}
fclose(fp); /* close the file for cleanliness */
}
/**********************************************
This function returns the rate of a given rateType.
If the rateType does not exist in the table, it returns 0.
*/
float RT_getRate(int rateType) {
/* it loops through the array one by one and look for
a record with the desired rateType. */
for (int i=0; i<RT_count; i++) {
if (RT_rateTable[i].rateType == rateType)
return RT_rateTable[i].rate;
}
return 0;
}
/**********************************************
This function calculates the cost of a call,
given the rateType, and duration in seconds
Requirement of Q4a is implemented here
======================================
*/
float RT_calculateCallCost(int rateType, int duration) {
float rate, total;
rate = RT_getRate(rateType);
if (duration<=6) duration = 0; /* failed call */
else if (duration<60) duration = 60; /* round up */
else if (duration%60<=20 && duration%60>0)
duration -= duration%60; /* round down */
else if (duration%60>20) duration += (60 - duration%60); /* round up */
total = rate * (float)duration / 60;
if (total>0.0) total += 0.2;
return total;
}
/**********************************************
This function prints the rate schedule nicely as
a table.
*/
void RT_printRates() {
headline();
printf("RateType Rate($)\n");
printf("--------------------\n");
for (int i=0; i<RT_count; i++) {
printf("%5.d %10.2f\n", RT_rateTable[i].rateType,
RT_rateTable[i].rate);
}
}
/***************************************************************************/
/**********************************************
Customer Table ADT
*/
#define ID_MAXLENGTH 8
#define NAME_MAXLENGTH 64
/* forward declaration (so it can be used as a field in the following decl */
struct CT_CustomerCell;
/* a customer record */
struct CT_CustomerCell {
char customerID[ID_MAXLENGTH]; /* id of this customer record */
char name[NAME_MAXLENGTH]; /* name of this customer record */
struct CT_CustomerCell* next; /* pointing to the next node in the linked-list */
};
struct CT_CustomerCell* CT_head; /* pointing to the first node in the linked-list */
/**********************************************
Question 4(b) Customer Table ADT function
=========================================
Initialize the ADT.
Open and read file customer.txt. Built a linked-list of CT_CustomerCell.
*/
void CT_initialize(){
FILE* fp;
CT_CustomerCell* p;
CT_CustomerCell* tail;
if ((fp = fopen("customer.txt", "r"))==NULL){
puts("Error in opening file CUSTOMER.TXT"); exit(1);
}
if ((tail = CT_head =
(CT_CustomerCell*)malloc(sizeof(CT_CustomerCell)))==NULL){
puts("Error in initializing customer table."); exit(1);
}
while (!feof(fp)){
if ((p = (CT_CustomerCell*)malloc(sizeof(CT_CustomerCell)))==NULL){
puts("Error in initializing customer table."); exit(1);
}
fscanf(fp, "%s %s", p->customerID, p->name);
p->next = NULL;
tail->next = p;
tail = p;
}
fclose(fp);
free(p); free(tail);
}
/**********************************************
Question 4(b) Customer Table ADT function
=========================================
Determine if the customerID exists in the table. Return True or False
*/
int CT_existCustomer(char* customerID) {
CT_CustomerCell* p; /* linked-list pointer */
p = CT_head;
while (p->next!=NULL){
p = p->next;
if (!strcmp(p->customerID, customerID)) return 1;
}
return 0;
}
/**********************************************
Question 4(b) Customer Table ADT function
=========================================
Returns the name of the customer with customerID.
Returns NULL if customerID not exists.
*/
char* CT_getName(char* customerID) {
CT_CustomerCell* p; /* linked-list pointer */
p = CT_head;
while (p->next!=NULL){
p = p->next;
if (!strcmp(p->customerID, customerID)) return p->name;
}
return NULL;
}
/**********************************************
Question 4(c)
=============
Read data from log.txt, compute the daily spending of each customer,
printout a summary list showing ID, name and $.
*/
/* an ADT for customer spending summary */
typedef struct CUST{
char id[ID_MAXLENGTH]; /* ID of customer */
char name[NAME_MAXLENGTH]; /* name of customer */
float amount; /* daily spending */
struct CUST* next; /* pointer to next item in linked-list */
} cust;
cust* head; /* head of linked-list */
cust* tail; /* tail of linked-list */
cust* p; /* a sharable temporary pointer */
/* initialize cust linked-list */
void initSummary(){
tail = head = (cust*)malloc(sizeof(cust));
head->next = NULL;
}
/* determine if id already exist in linked-list,
return pointer of id if found; return NULL if not found */
cust* idSearch(char* id){
p = head;
while (p->next!=NULL){
p = p->next;
if (!strcmp(id, p->id)) return p;
}
return NULL;
}
/* if id exist in linked-list, add amount to it,
else add new item in linked-list */
void addSummaryItem(char* id, char* name, float amount){
if (idSearch(id)==NULL){
if ((p = (cust*)malloc(sizeof(cust)))==NULL){
puts("Insufficient memory!"); exit(1);
}
strcpy(p->id, id); strcpy(p->name, name); p->amount = amount;
p->next = NULL;
tail->next = p;
tail = p;
}
else p->amount += amount;
}
void displaySummary(){
p = head;
while (p->next!=NULL){
p = p->next;
printf(" %s %s%10.2f\n", p->id, p->name, p->amount);
/* new page */
if (wherey()>=24){
moreline(); headline();
}
}
quitline();
}
/* lengthen str to length of len, return str */
char* lengthen(char* str, int len){
int i;
int extra; /* number of extra spaces need to append */
char blank[NAME_MAXLENGTH]; /* a blank string */
extra = len - strlen(str);
for (i=0; i<extra; i++) blank[i] = ' ';
blank[extra] = '\0';
strcat(str, blank);
return str;
}
/* main function of Q4c, process log.txt and print summary */
void LogProcessor() {
FILE* fp;
char time[5]; /* time making the call (not used) */
char id[ID_MAXLENGTH]; /* customer ID */
int rateType; /* rate type of call */
int duration; /* duration of call in second */
float amount; /* $ spent in a call */
char name[NAME_MAXLENGTH]; /* local copy of customer name */
if ((fp = fopen("log.txt", "r"))==NULL){
puts("Error in opening log.txt"); return;
}
initSummary();
puts("");
puts("Customer ID Name Daily Spending($)");
puts("=========== ==== =================");
while (!feof(fp)) {
fscanf(fp, "%s %s %d %d", time, id, &rateType, &duration);
amount = RT_calculateCallCost(rateType, duration);
if (amount>0 && CT_existCustomer(id)){
strcpy(name, CT_getName(id));
lengthen(name, 16);
addSummaryItem(id, name, amount);
}
}
fclose(fp);
displaySummary();
}
/* Main Program. */
void main() {
RT_initialize();
RT_printRates();
CT_initialize();
LogProcessor();
}
back