Lab 10: Object Oriented Programming - Solution Case Study 1: Bank Account Re-implement the Accounts class to count for the number of accounts and to assign account ID internally (and uniquely). Account - ID: int Owner: String Balance: Double NumOfAccounts: int + Account () + Account (owner, balance) + getID() + getOwner() + setOwner() + getBalance() + setBalance() + getNumOfAccounts() + withdraw() + deposit() + print() • • Create a class variable for the number of accounts. Create a class function to retrieve the number of accounts. Test the class to verify the operation. #include <iostream> using namespace std; class Account { protected: int number; double balance; string owner; static int numofAccounts; public: Account () { number = numofAccounts; balance = 0.0; owner = ""; numofAccounts++; } Account (double b, string o) { number = numofAccounts; balance = b; owner = o; numofAccounts++; } int getNumber () { return (number);} double getBalance() {return (balance); } void setBalance(double b) {balance = b;} string getOwner() {return(owner); } void setOwner(string o) {owner = o;} void deposit (double value) { if (value > 0) { balance += value; cout << "Amount deposited \n"; } } void withdraw (double value) { if (value <= balance) { balance -= value; cout << "Amount withdrawn \n"; } else cout << "Insufficent balance for withdraw \n"; } void print() { cout << "Account information: \n"; cout << "Account number: " << number << endl; cout << "Balance: " << balance << endl; cout << "Owner Name: " << owner << endl; } static int getNumofAccounts() { return numofAccounts; } }; // initialize static variable int Account::numofAccounts = 0; int main() { Account A1(1200, "Alex"); A1.deposit(400); A1.withdraw(200); A1.print(); return 0; } Case Study 2: Fraction Manipulation Define a class of Fractions Consider ordinary fractions like 3/4 and -1/2. A fraction is the ratio of two integers: a numerator and a denominator. Create a user-defined type for fractions by defining a class Fraction. The class should supply a set of necessary operations on fractions • • • • addition subtraction multiplication division and should hide implementation details of data representation and internal manipulations. Remember that a class encapsulates data structures with access and manipulation procedures. In designing a class, an important task is to decide on the internal data representation which is isolated from the outside view. Member methods will keep the data representation consistent. Outside methods are not allowed to create or modify the internal structures directly. They may do this by calling methods in the class. Here are some (internal) representation considerations to guide your design: • • • • A fraction is essentially a pair of integers called numerator and denominator. The numerator carries the sign of the fraction and can be positive, negative, or zero. The denominator is kept positive and can never be zero. Fractions with the same value may have different representations (for example 1/2, 2/4, 3/6). In our representation let's decide for equal fractions to have the same numerator and the same denominator. That means that all fractions must be reduced to their lowest terms. (A data representation in which all equal quantities are represented uniquely is known as a canonical representation. Keeping fractions canonical is desirable and we should enforce this.) The canonical representation of 0 (zero) as a fraction is 0/1. Your Fraction class can be designed to enforce such conventions, not just to have them as principles that one can choose to follow or ignore. This is one big advantage of object-oriented programming. The canonical representation conventions should be enforced by the Fraction constructor. The constructor should take the two arguments n and d and construct a fraction n/d out of it. The denominator of the resulting Fraction should not be zero or negative. The fraction should be reduced by removing the gcd (greatest common divisor) between the numerator and the denominator. You should define a member method gcd that computes the greatest common divisor of two numbers and make the constructor use it to create canonical Fraction. gcd should be implemented as a class wide method since it is independent of Fraction instances. It should be declared private because it does not contribute to the public interface of the Fraction class. The operations for fractions listed above should implement binary operations. In other words, we are going to define methods such that a Fraction can be added to, subtracted from, multiplied with, or divided by another Fraction. The result should be a Fraction. You should also define a few predicates. Each Fraction that you create should be able to respond to the following questions: • • • • isZero() isInt() equals(anotherFraction) greaterThan(anotherFraction) Solution: #include<iostream> using namespace std; class Fractions{ protected: int n,d; private: int gcd(int x, int y){ if(x%y==0) return y; else return gcd(y, x%y); } public:Fractions(int a, int b){ if(b<=0){ cout<<"Invalid fraction"<<endl; exit(1); } int g=gcd(a,b); n=a/abs(g); d=b/abs(g); } bool isZero(){ if (n==0) return true; else return false; } bool isInt(){ if(n%d == 0) return true; else return false; } bool equals(Fractions fr){ if((fr.n == n) && (fr.d == d)) return true; else return false; } bool greaterThan(Fractions fr){ if((float)fr.n/(float)fr.d < (float)n/(float)d) return true; else return false; } Fractions addition(Fractions fr){ int d1 = fr.d*d; int n1= fr.n*d+n*fr.d; return Fractions(n1,d1); } Fractions subtraction(Fractions fr){ int d1 = fr.d*d; int n1= n*fr.d - fr.n*d; return Fractions(n1,d1); } Fractions multiplication(Fractions fr){ int n1 = n*fr.n; int d1 = d*fr.d; return Fractions(n1,d1); } Fractions division(Fractions fr){ int n1 = n*fr.d; int d1 = d*fr.n; return Fractions(n1,d1); } void printFraction(){ cout<<n<<"/"<<d<<endl; } void setNumerator(int n1){ n = n1; } void setDenomirator(int d1){ d = d1; } int getNumerator(){ return n; } int getDenomirator(){ return d; } }; Case Study 3: Flights Monitoring System • • • • • • • A class, named Airplane, to store information about a plane in space (ID, airline, position, type (military/civil)). The class must have a constructor function, modifiers and accessors, a function to print the plane information, and a function to calculate distance to another airplane. Another class, named Zone, to store information about airplanes in a particular zone. This class includes information about the coordinates of the zone, a group of planes currently located in the zone, and it keeps track of the distances between planes. We want to keep track of the number of zones in the system. You may create a class to store and maintain data about a position in 3D space (x, y, z). Any two planes can not come closer than 2 km to each other. Every zone may not have more than 20 planes at the same time. No two planes can have the same ID Additional features: • Checking if plans close to the borders between zones come closer than 2 km to each other. • Create dynamic array for the airplanes for maintaining the exact number of planes currently flying in the zone. • Deleting planes from the list once a plane lands (z coordinate becomes zero). • Other features that you find interesting. #include <iostream> #include <cmath> using namespace std; #define MAX 20 #define MIN_DISTANCE 2 class Position { private: double x; double y; double z; public: Position() { x = 0; y = 0; z = 0; } Position(double a, double b, double c) { x = a; y = b; z = c; } int getX() { return (x); } void setX(int value) { x = value; } int getY() { return (y); } void setY(int value) { y = value; } int getZ() { return (z); } void setZ(int value) { z = value; } double computeDistance (Position another) { return (sqrt((x - another.getX())*(x - another.getX()) + (y another.getY())*(y - another.getY()) + (z - another.getZ())*(z another.getZ()))); } void printPosition() { cout << "X = " << x << ", Y = " << y << ", Z = " << z << endl; } }; class Airplane { private: int id; string airline; Position planePosition; static int numOfPlanes; public: Airplane() { id = numOfPlanes; airline = ""; planePosition.setX(0); planePosition.setY(0); planePosition.setZ(0); numOfPlanes++; } Airplane(string a, Position p) { id = numOfPlanes; airline = a; planePosition = p; numOfPlanes++; } int getID() { return (id); } static int getnumOfPlanes() { return (numOfPlanes); } string getAirline() {return(airline); } void setAirline(string value) {airline = value; } Position getPosition() { return (planePosition); } void setPosition(Position value) { planePosition = value; } void printPlane() { cout << "Plane ID: " << id << endl; cout << "Plane position: "; planePosition.printPosition(); } }; int Airplane::numOfPlanes = 0; class Zone { private: int id; Position start; Position end; int numOfPlanes; Airplane planes[MAX]; double distances[MAX][MAX]; static int numOfZones; bool planeInZone(Airplane p) { Position planePosition = p.getPosition(); if ((planePosition.getX() > start.getX() && planePosition.getX() < end.getX()) && (planePosition.getY() > start.getY() && planePosition.getY() < end.getY()) && (planePosition.getZ() > start.getZ() && planePosition.getZ() < end.getZ())) return (true); else return (false); } public: Zone(int i) { id = numOfZones; numOfPlanes = 0; numOfZones++; } int getID() { return (id); } static int getNumOfZones () { return (numOfZones); } Position getStart() {return(start); } void setStart (Position value) {start = value; } Position getEnd () {return (end); } void setEnd (Position value) {end = value; } void addPlane(Airplane p) { if (numOfPlanes >= MAX) cout << "Can not add more planes \n"; else if (planeInZone(p)) { planes[numOfPlanes]=p; numOfPlanes++; cout << "Plane with ID " << p.getID() << " added successfully \n"; } } void { checkDistances() for (int i=0; i < numOfPlanes; i++) for (int j=0; j < i; j++) { distances[i][j] = (planes[i].getPosition()).computeDistance(planes[j].getPosition()); if (distances[i][j] < MIN_DISTANCE) cout << "Plane with ID: " << planes[i].getID() << ", and plane with ID: " << planes[j].getID() << " are getting too close \n"; } } void printPlanes() { cout << "Planes in zone ID: " << id << endl; for (int i = 0; i < numOfPlanes ; i++) planes[i].printPlane(); cout << endl; } }; int main() { Zone z1(1), z2(2); // create two zones Position p1(0,0,0), p2(10, 10, 10), p3(20,20,20); z1.setStart(p1); z1.setEnd(p2); z2.setStart(p2); z2.setEnd(p3); // create planes and add them to zones Position p4(1,1,1), p5(3, 3, 3),p6(12,12,12); Airplane A1(1, "Etihad", p4); Airplane A2(2, "Emirates", p5); Airplane A3(3, "Qatar", p6); // add planes to zones z1.addPlane(A1); z1.addPlane(A2); z2.addPlane(A3); // print zones information z1.checkDistances (); z1.printPlanes(); z2.checkDistances(); z2.printPlanes(); return 0; }