You are on page 1of 20

/* File: PhoneNumber.

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) lll­nnnn
 */ 

  #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) 580­4489
     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) 580­4489 (231) 456­7888 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) 580­4489 to (412) 580­2344 
  */
 
  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) 580­4489 to (412) 444­2341
  */

   bool Call :: isArea() const
   {
if( callingNumber.sameArea(calledNumber) )
                return true;

   }

 //____________________________________________________________________________

 /* A call is non­area when calling and called number
  * dont match in area code
  * Eg: (412) 580­4489 and (514) 392­9322
  */ 

   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) {
//self­assignment 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, non­area 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;

//no­arg 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, (last­start)­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/non­area 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 in­area 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 out­of­area 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;
 }

You might also like