Professional Documents
Culture Documents
C
* Author: Baddie
* Date: 04/10
* Description: Handles phonenumbers
gets a phone number as input
prints out a phone number
compares with other phone numbers
based on area, xchange
*/
/* builds a PhoneNumber object from
* input string which is of the form (aaa) lllnnnn
*/
#include "PhoneNumber.h"
#include<iostream>
#include <string.h>
using namespace std;
//set up area,exchange and number parts of a phone number
void PhoneNumber :: input(istream& s)
{
//Eg input: (412) 5804489
string phnum;
getline(s,phnum);
if(s) {
//if the line is not empty then extract substrings
area = phnum.substr(1,3);
exchange = phnum.substr(6,3);
number = phnum.substr(10,4);
}
}
//__________________________________________________________________
// prints output in the i/p form
void PhoneNumber :: output(ostream& s) const
{
cout<<"("<<area<<")"<<" "<<exchange<<""<<number;
}
//__________________________________________________________________
// overloaded i/p operator
istream& operator >> (istream& s, PhoneNumber& v)
{
v.input(s);
return s;
}
//__________________________________________________________________
// overloaded o/p operator
ostream& operator << (ostream& s, const PhoneNumber& v)
{
v.output(s);
return s;
}
//___________________________________________________________________
// overloaded relational operators
bool PhoneNumber :: operator < (const PhoneNumber& v) const
{
if (this>area < v.area)
return true;
else if (this>area == v.area) {
// area codes are equal
//check exchange less/equal/greater
if(this>exchange < v.exchange)
return true;
else if (this>exchange == v.exchange) {
//exchange code too is equal check the number
if (this>number < v.number)
return true;
else
return false; //number greater
}
return false; //if xchange is greater
}
return false; //if area is greater
}
//_________________________________________________________________________
//comparing phone numbers implementation of relational operators
bool PhoneNumber :: operator > (const PhoneNumber& v) const
{
if (this>area > v.area)
return true;
else if (this>area == v.area) {
// area codes are equal
//check exchange less/equal/greater
if(this>exchange > v.exchange)
return true;
else if (this>exchange == v.exchange) {
if (this>number > v.number)
return true;
else
return false; //number lesser
}
return false; //if xchange is lesser
}
return false; //if area is lesser
}
//_________________________________________________________________________
//two phone numbers are unequal if their area codes are unequal
bool PhoneNumber :: operator != (const PhoneNumber& v) const
{
return (this>area != v.area);
}
//_________________________________________________________________________
//two phone numbers are equal if their area codes are equal
bool PhoneNumber :: operator == (const PhoneNumber& v) const
{
return (this > area == v.area && this > exchange == v.exchange &&
this > number == v. number);
}
//__________________________________________________________________________
//phone numbers belong to same exchange if they have same area code and exchange code
bool PhoneNumber :: sameExchange(const PhoneNumber& v) const
{
return (this>area == v.area && this>exchange == v.exchange);
}
//_________________________________________________________________________
//phone numbers with same area code
bool PhoneNumber :: sameArea(const PhoneNumber& v) const
{
return (this>area == v.area);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* FILE : Call.C
* AUTHOR : Baddie
* DATE : 04/10
* DESCRIPTION : Details of a call are handles here
*/
#include "Call.h"
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <sstream>
using namespace std;
/* Reads a call information
* caller, callee, date, time , duration
*/
void Call :: input(istream& s)
{
//Eg input: (412) 5804489 (231) 4567888 2010/03/04 20:04:10 10
string callLine, caller, callee, durationString ;
getline(s,callLine);
if(s) {
caller = callLine.substr(0,14);
istringstream callerString(caller);
callerString >> callingNumber;
callee = callLine.substr(15,14);
istringstream calleeString(callee);
calleeString >> calledNumber;
date = callLine.substr(30,10);
time = callLine.substr(41,8);
durationString = callLine.substr(50, (callLine.length()50));
//string to int conversion
duration = atoi(durationString.c_str());
}
}
//__________________________________________________________________________
//returns caller phone number
const PhoneNumber& Call :: getCaller() const
{
return callingNumber;
}
//__________________________________________________________________________
//return duration
int Call :: getDuration() const
{
return duration;
}
//__________________________________________________________________________
// o/p in form of i/p
void Call :: output(ostream& s) const
{
cout<< "\n\t"<<callingNumber<<" "<<calledNumber<<" "<<
date<<" "<<time<<" "<<duration<< "\n";
}
//___________________________________________________________________________
/* A call is local when the calling and called number
* have same area code and same exchange number
* Eg:call from (412) 5804489 to (412) 5802344
*/
bool Call :: isLocal() const
{
if( callingNumber.sameExchange(calledNumber) )
return true;
}
//____________________________________________________________________________
/* A call is area call when calling and called number
* have same area code but not exchange code
* Eg: (412) 5804489 to (412) 4442341
*/
bool Call :: isArea() const
{
if( callingNumber.sameArea(calledNumber) )
return true;
}
//____________________________________________________________________________
/* A call is nonarea when calling and called number
* dont match in area code
* Eg: (412) 5804489 and (514) 3929322
*/
bool Call :: isNonArea() const
{
if(callingNumber.sameArea(calledNumber) == false)
return true;
}
//_____________________________________________________________________________
istream & operator >>(istream &s, Call & v)
{
v.input(s);
}
//_____________________________________________________________________________
ostream & operator <<(ostream &s, const Call & v)
{
v.output(s);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* File : CallList.C
* Author:Baddie
* Date : 04/11
* Description: define input order list of calls
calls can be inserted and printed
*/
#include "CallList.h"
//construct an empty list
CallList :: CallList()
{
//creating a sentinel element
// both head and tail will point to this sentinel
head = new Elem;
Call c; //creates a call with junk doesnt matter it will be ignored
head > info = c;
head > next = NULL;
tail = head;
}
//__________________________________________________________________________
// copy constructor
CallList :: CallList(const CallList& v)
{
head = new Elem;
head > info = v. head > info;
head > next = v. head > next;
tail = head;
}
//____________________________________________________________________________
// assignment
CallList& CallList :: operator= (const CallList& v)
{
if(this != &v) {
//selfassignment checked
//delete the memory held
Elem *curr, *p;
p = head;
curr = NULL;
while( p != NULL) {
curr = p;
p = p>next;
delete curr;
}
head = new Elem;
head > info = v. head > info;
head > next = v. head > next;
tail = head;
}
}
//___________________________________________________________________________
//destructor
CallList :: ~CallList()
{
//delete the memory held
Elem *curr, *p;
p = head;
curr = NULL;
while( p != NULL) {
curr = p;
p = p>next;
delete curr;
}
}
//__________________________________________________________________________
//insert calls to tail of the list
// to maintain input order
void CallList :: insert(const Call& call)
{
Elem *newElem;
// create a new node with call info in it
newElem = new Elem;
newElem > info = call;
newElem > next = NULL;
//tail never point to null. even if the 1st elt is to be inserted in
//the list tail will be pointing to the sentinel that time
//so need to check if the list not empty condition
tail > next = newElem; //the elt is added to the tail of the list
tail = newElem; // move the tail pointer to the last elem
}
//_________________________________________________________________________
// output calls one by one in input order from head to tail
void CallList :: output(ostream& s)const
{
//head element is sentinel and contains junk
// so p iterates from head's next
Elem *p = head > next;
while(p){
s << (p>info); //output calls
p = p>next; // move to next call node in the callList
}
}
//____________________________________________________________________________
// overloading output operator <<
ostream& operator << (ostream& s, const CallList& v)
{
v. output(s);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* File : Account.h
* Author : Baddie
* Date : 04/11
* Description : Defines a phone account of a person
identified by his phone number
has list of local, area, nonarea calls got
a/c holder's address and previous balance
*/
#include "Account.h"
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std;
//noarg constructor
Account :: Account()
{
//phoneNumber is not given any value
// so far not encountered a necessity to use this Account()
// AccountDB even uses the 1 arg consturctor only
address = " ";
prevBalance = 0;
localMinutes = 0;
localCalls = CallList();
areaMinutes = 0;
areaCalls = CallList();
nonAreaMinutes = 0;
nonAreaCalls = CallList();
}
//__________________________________________________________________________
// 1 arg constructor that sets the phone number
Account :: Account(const PhoneNumber& number)
{
phoneNumber = number;
address = " ";
prevBalance = 0;
localMinutes = 0;
localCalls = CallList();
areaMinutes = 0;
areaCalls = CallList();
nonAreaMinutes = 0;
nonAreaCalls = CallList();
}
//___________________________________________________________________________
// gets phonenumber,address and previous balance
// this has to be splitted properly
// from | to | will be address thats to be written still
void Account :: input(istream& s)
{
string accountLine, phoneString, addr;
int start, last;
string balanceString;
float balance;
getline(s,accountLine);
if(s) {
phoneString = accountLine.substr(0,14) ; //the appropriate sub
//be extracted from the stream to form
//the phonenumber
istringstream phoneNumberString(phoneString);
phoneNumberString >> phoneNumber;
//the fullstring is tokenized to get the address and balance
//balanceString is converted into a float using atof()
start = accountLine.find_first_of("|");
last = accountLine.find_last_of("|");
address = accountLine.substr(start+1, (laststart)1);
balanceString = accountLine.substr
(last+2, accountLine.length());
balance = atof(balanceString.c_str());
prevBalance = (float) balance;
}
}
//____________________________________________________________________________
/* adds a call to the account's one of the 3 lists
* depending on the phone number in the call argument
* compare the account holder's phnum and the one in call arg
* to decide whether its local/area/nonarea call
*/
void Account :: addCall(const Call& call)
{
std :: cout.setf(ios::fixed, ios::floatfield);
std :: cout.setf(ios::showpoint);
if(call.isLocal()) {
//the caller and the a/c holder are in same exchange
// hence this is a local call
// add to localCalls list
// increment the local minutes
(this>localCalls).insert(call);
localMinutes += call.getDuration();
}
else if(call.isArea()) {
//the excchange code is different for caller
// and the a/c holder where as the area codes
// are same. this is inarea call and add
//this call to areaCalls list
//increment the area minutes
(this>areaCalls).insert(call);
areaMinutes += call.getDuration();
}
else{
//not in same area. so its outofarea call
//add this call to the nonAreaCalls list
(this>nonAreaCalls).insert(call);
nonAreaMinutes += call.getDuration();
}
}
//____________________________________________________________________________
/* prints the bill for the a/c holder
* charge for each type of call is calculated
* by getting the duration of the call by call :: getDuration
* and multiplying it with per min charge for the type of call
* charges permin:
* Local: 1 cent/min
* area: 5 cents/min
* out of area: 25 cents/min
*/
void Account :: printBill(ostream& s) const
{
//charges per minute for each kind of call
float localpm = 0.01; //1 cent = $ 0.01
float areapm = 0.05; //5 cents
float nonareapm = 0.25; //25 cents
//variables to store charge for each type of call
float balance, localCharge, areaCharge, nonareaCharge;
float totalCharge;
//methods to set the floating point notation
// without these 0 will not be displayed in floating point form
std :: cout.setf(ios::fixed, ios::floatfield);
std :: cout.setf(ios::showpoint);
cout << "\n" << this>phoneNumber; //a/c holder's phnum
cout << "\t" << address; //a/c holder's address
balance = ((float) this>prevBalance/100.00);
cout << "\n previous balance: " << setprecision(2) << balance;
cout << "\n local minutes: " << localMinutes;
localCharge = (localMinutes * localpm);
cout << "\n\t charge: " << setprecision(2) << localCharge;
cout << "\n area minutes: " << areaMinutes;
areaCharge = (areaMinutes * areapm);
cout << "\n\t charge: " << setprecision(2) << areaCharge;
cout << "\n nonAreaMinutes: " << nonAreaMinutes;
nonareaCharge = (nonAreaMinutes * nonareapm);
cout << "\n\t charge: " << setprecision(2) << nonareaCharge;
totalCharge = balance + localCharge + areaCharge + nonareaCharge;
cout << "\n total charge: " << setprecision(2) << totalCharge;
// print list of calls
cout << "\n\n local calls" ;
s << localCalls; //invokes << in CallList
cout << "\n\n area calls" ;
s << areaCalls;
cout << "\n\n non area calls";
s << nonAreaCalls;
}
//____________________________________________________________________________
/* checking whether this account is greater/lesser to the one passed
* on basis of phoneNumber
*/
bool Account :: operator > (const Account& v) const
{
return (this>phoneNumber > v.phoneNumber);
}
//____________________________________________________________________________
bool Account :: operator < (const Account& v) const
{
return (this>phoneNumber < v.phoneNumber);
}
//____________________________________________________________________________
bool Account :: operator != (const Account& v) const
{
return (this>phoneNumber != v.phoneNumber);
}
//____________________________________________________________________________
bool Account :: operator == (const Account& v) const
{
return (this > phoneNumber == v. phoneNumber) ;
}
//___________________________________________________________________________
istream& operator >> (istream&s, Account& v)
{
if(s) {
v.input(s);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* File : AccountDB.C
* Name : Baddie
* Date : 04/13
* Description: A DB of Accounts searched in original insertion order (list)
or by phone numbers (BST impl)
*/
#include "AccountDB.h"
#include <iostream>
#include<stdlib.h>
using namespace std;
// an empty DB where the list pointers and the tree ptr is set to null
AccountDB :: AccountDB()
{
head = tail = root = NULL;
}
//__________________________________________________________________________
//destructor
AccountDB :: ~AccountDB()
{
Node* p = head;
Node* prev = NULL;
while(p != NULL) {
prev = p;
p = p> next;
delete prev;
}
}
//__________________________________________________________________________
//Inserts an account to the database
void AccountDB :: insert(const Account& acct)
{
//the insertion order is maintained
//meaning elts are added to tail of the list
Node *prev = NULL, *p = root, *curr = NULL ;
bool lastleft = false;
if( head == NULL ){
//the DB is empty
head = new Node;
head > info = acct;
head > next = NULL;
head > left = head > right = NULL;
tail = head;
root = head;
}
else {
curr = tail;
Node *account = new Node;
account > info = acct;
account > next = NULL;
account > left = NULL;
account > right = NULL;
tail > next = account;// account is appended to tail of list
tail = account; //account node is made the tail
while(p != NULL) {
prev = p;
if(acct < p > info) {
//go through the left subtree
//find the leaf node
//make the leaf node's left to point to this account
p = p > left;
lastleft = true;
}
else {
p = p > right;
lastleft = false;
}
}
if(prev == NULL)
root = account;
else {
if(lastleft)
prev > left = account;
else
prev > right = account;
}
}
}
//__________________________________________________________________________
//prints bill of all accounts in the DB
void AccountDB :: printBills(ostream& s) const
{
Node *p = head;
while( p != NULL) {
cout<< "\n\n \n";
// p > info is the account on which Account ::printBill()
// is invoked
(p > info).printBill(s);
p = p > next;
}
}
//__________________________________________________________________________
void AccountDB :: addCall(const Call& call)
{
Node *p = head;
// the 1st field in a call obj is where the call originated
//get the caller using getCaller() which returns a phoneNumber
//use this to access the BST
//find the account to which this phoneNumber belongs to
// find the account p>info
//invoke addCall(const Call& call) on it
PhoneNumber phNumToBeBilled = call.getCaller();
Account dummy = Account(phNumToBeBilled);
while( p != NULL ) {
if(p>info == dummy) {
//the account to which the call is
//to be added is found
// now add the call to that account
(p>info).addCall(call);
break;
}
else if(dummy < p>info) {
p = p > left;
}
else if(dummy > p>info) {
p = p > right;
}
}
//if the call doesnt belong to an a/c thats in the DB,
//after searching through all a/c's the ctrl comes out of
//while and does nothing thus ignoring that call
}
//__________________________________________________________________________
/* File : main.C
* Author: Baddie
* Date: 04/14
* Description: sets up account DB
reads accounts and calls from files
invokes function to print the bill
*/
#include "PhoneNumber.h"
#include "Call.h"
#include "CallList.h"
#include "Account.h"
#include "AccountDB.h"
#include <fstream>
#include <stdlib.h>
#include <iostream>
#include <string.h>
#include <sstream>
using namespace std;
using std :: ifstream;
int main(int argc, const char* argv[])
{
cout<< "\n\n THERE SHOULD BE TWO FILES PASSED AS ARGUMENTS \n A FILE CONTAINI
G ACCOUNTS FOLLOWED BY THE ONE CONTAINING CALLS \n\n";
ifstream accdata;
ifstream calldata;
if(argc == 1 || argc == 2) {
cerr<< "\n There are not two arguments! Program Aborting...\n";
exit(1); //program aborts
}
accdata.open(argv[1]);
calldata.open(argv[2]);
if(!accdata || !calldata) {
cerr<< "\n Problem opening files! check file name.Program Aborting...\n";
exit(1);
}
AccountDB *database = new AccountDB(); //empty account DB is set
Account newAccount = Account(); //calls the default constructor
string accline;
stringstream iss;
while( getline(accdata, accline) ) {
iss << accline;
iss >> newAccount;
database > insert(newAccount);
iss.clear();
}
accdata.close(); //closes acc file as all account details are stored in DB
//now calls are read from callfile and added to the corresponding account
Call newCall;
string calline;
while( getline(calldata, calline) ) {
iss << calline;
iss >> newCall;
database > addCall(newCall);
iss.clear();
}
calldata.close(); //all calls in the file are added to corresponding a/c
//now the bills are printed
database > printBills(cout);
return 0;
}