Saturday, January 13, 2018

A Chapter Closed

It does not happen very often, but it does occasionally; the lack of words to describe how happy this person is, that yet another chapter is history. 

The experience was a mix between utmost interest in the contents of the main chapter, the Challenges were a different story. Not knowing why, but there was a feeling of disconnectedness with many of the early Challenges. There was also lots of repetition. One instance is the Number Class, which is a variation of the Programming Challenge 10.19 - Check Writer program. Another is the Date Class, which had to be modified in this chapter. With Challenge 14.4 and 5 and 6, interest grew, as it allowed me to implement some personal touch to these programs. If you don't know, the names are taken from Alexander McCall Smith's "Mma. Ramotswe" books. Please read them, if you find time! This is something I like doing, as my recurring readers and visitors should already have noticed.

All these were not very challenging, as most of the work was done in previous chapters, which does not mean that all the published solutions are mere copies. No, in most cases it was an opportunity to improve what has been done before. It reflects a growth in knowledge and gives a sense of accomplishement when the new code is indeed better than the old one. 

There was little problem to solve any problem, up to the (Un)challenge 14.9 Feet Inches Modification. This was so unchallenging, that it was done in less than 15 minutes! While in previous chapters this kind of problem would be giving a welcoming breather, it seems that it was not necessary at this chapter, and if it were, than it could have been something more interesting, or a little more challenging at least. 

At a later point, Challenge 11 in particular, this one was really difficult to solve. The task was to write a FeetInches class modification, containing a copy constructor, which allows for the multiplication of two FeetInches objects. The problem was not so much how to write code, but what should the output be? Based on this decision, the formula had to change. As the feet and inches are foreign, I had little knowledge about the expected output. It has taken quite some time to find an online calculator website that offered the functionality of multiplying feet and inches, outputting a result in a way to confirm that my code delivers correct results. This is most important, correct results.  

Truly interesting was the work on the Parking Ticket Simulator and Car Instrument Simulator programs. Both of which I was looking forward to, and indeed, they were rather easy to solve. 14.14 which is the Parking Ticket Simulator was rather difficult in some aspects. Here the problem was more of the nature of how to make the classes interact and do their magic behind the scenes. Most troublesome was to find a way to resolve the dreaded 'circular dependency' issue between the PoliceOfficer and ParkingMeter class. The other was the question how to write the code so, that the classes are not tightly linked to each other. (Or is the correct term coupled?) That was the nature of the problems to face when solving this problem. 

On the whole, this chapter was not too difficult. There was even one solution that felt most complete. That for the Date Class Modification which was Challenge 14.8. It is difficult to express the meaning of 'most complete', the closest is that it feels like one whole, in which every part has its place and everything interacts without any one part - or function, having too much weight or content. It is not perfect, but it is the only good solution for any of the previous two chapters.

Code never feels perfect, in almost no case is this person able to say, it is good enough. Yet, this way of thinking is wrong. While researching the FeetInches problem, I found an article on Nature.com which is all about code sharing. It describes the feeling related to my own code solutions. The important thing to take away is this: "If code is good enough to to do the job, it is good enough to release ..." Of course there are differences, I would release my code anyway in the hopes that it helps someone out there in the world overcome a problem. 

This is a challenge in itself - to overcome the way of thinking that everything has to be perfect, else it has little worth. The other, and I noticed this, is: "Why is this code still so long? It could be much shorter, if only I knew how ...", it is a way of thought that has resurfaced. Maybe it is something that was planted into the mind in the early stages of learning. Without the knowledge about loops, etc., code for a solution was rather long. In particular the Travel Expense program comes to mind. With the introduction of arrays and loops, it may have felt as if code has become shorter, while in fact it had not. Over time the expectation has grown that, with each new tool or part of what C++ has to offer, solutions would become shorter, less code has to be written to accomplish a task.

With time, and more experience, it still will remain an illusion, for now the important thing is what comes next. Chapter 15, the closing chapter about classes, will certainly be most interesting. My hope is, that, once this next chapter will become history, that things become much easier and it is all downhill from that point onward.

This marks the end of this chapter summary, and after a good days rest tomorrow a new chapter will begin. And with this, I wish my readers and visitors that they are able to solve - or overcome all of their challenges whatever they may be. Soon there will be more code, until then, stay well!

Programming Challenge 14.15 - Car Instrument Simulator

Example Files: CarInstrumentSimulator.7z

FuelGauge.h


#ifndef FUEL_GAUGE_H_
#define FUEL_GAUGE_H_

class FuelGauge
{
    private:
        const  int MAX_CAPACITY = 15;        // The max fuel capacity
        static int fuelCapacity;            // Holds the fuel capacity

    public:
        FuelGauge()
        { }

        int getFuelCapacity() const
        { return fuelCapacity; }

        // Overloaded operator functions
        int operator ++(int);                // Postfix ++
        int operator --(int);                // Postfix --
};

#endif

FuelGauge.cpp


#include "FuelGauge.h"

// Definition of fuelCapacity
int FuelGauge::fuelCapacity = 0;

/* **********************************************************
            Overloaded ++ operator
    ********************************************************** */

int FuelGauge::operator ++(int)
{
    if (fuelCapacity < MAX_CAPACITY)
    {
        fuelCapacity++;
    }
    else
    {
        fuelCapacity = MAX_CAPACITY;
    }

    return fuelCapacity;
}

/* **********************************************************
            Overloaded -- operator
   ********************************************************** */

int FuelGauge::operator --(int)
{
    if (fuelCapacity > 0)
    {
        fuelCapacity--;
    }
    else
    {
        fuelCapacity = 0;
    }
   
    return fuelCapacity;
}

Odometer.h


#ifndef ODOMETER_H_
#define ODOMETER_H_

#include "FuelGauge.h"

class Odometer
{
    private:
        const int MAX_MILEAGE = 999999;    // The maximum mileage an odometer can display

        static int mileage;                    // Holding the mileage of a car
        static int milesDriven;                // Counter variable

        // Class object
        FuelGauge gaugeCapacity;

    public:
        Odometer()
        { }

        Odometer(int);

        int getMilesDriven() const
        { return milesDriven; }

        int getCurrentMileage() const
        { return mileage; }

        // Overloaded operator function
        int operator ++(int);                // Postfix ++
};

#endif

Odometer.cpp


#include "Odometer.h"

// Definition of static variables mileage and milesDriven
int Odometer::mileage = 0;
int Odometer::milesDriven = -1;

/* **********************************************************
            Odometer::Odometer() - Constructor : int
   ********************************************************** */

Odometer::Odometer(int miles)
{
    if (mileage >= 0 && mileage <= MAX_MILEAGE)
    {
        mileage = miles;
    }
    else
    {
        miles = 0;
    }
}

/* **********************************************************
            Overloaded Postfix ++
    The postfix operator increments the mileage, and decreases
    the FuelGauge object's current amount of fuel by 1 gallon
    for every 24 miles traveled. If mileage reaches 999999,
    the mileage counter is reset to 0.
   ********************************************************** */

int Odometer::operator ++(int)
{
    if (mileage < MAX_MILEAGE)
    {
        mileage++;

        if (++milesDriven == 24)
        {
            milesDriven = 0;
            gaugeCapacity--;
        }
    }
    else if (mileage >= MAX_MILEAGE)
    {
        mileage = 0;
    }

    return mileage;
}

CarInstrumentSimulator.cpp


#include "FuelGauge.h"
#include "Odometer.h"

#include <iomanip>
using std::left;
using std::right;
using std::setw;

#include <iostream>
using std::cin;
using std::cout;

void timer();
void refillTank(FuelGauge &);
void instrumentSimulator(Odometer &, const FuelGauge &);

int main()
{
    FuelGauge gauge;
    Odometer meter(999998);

    cout << "CAR INSTRUMENT SIMULATOR\n\n";

    refillTank(gauge);
    instrumentSimulator(meter, gauge);

    cin.get();
    cin.ignore();
    return 0;
}

/* **********************************************************
            timer()
    A very simple timer function.
   ********************************************************** */

void timer()
{
    static int seconds = 5;
    static int timeLeft = 0;
    static int counter = 193559599;

    while (timeLeft > 0)
    {
        timeLeft--;
    }

    timeLeft = counter - seconds;
}

/* **********************************************************
            refillTank() : obj &
    This function accepts a FuelGauge object passed to it by
    reference as argument. It simulates a refueling process.
   ********************************************************** */

void refillTank(FuelGauge &gauge)
{
    cout << "Fuel meter E |";

    for (int i = gauge.getFuelCapacity(); i < 15; i++)
    {
        gauge++;
        timer();

        cout << (i + 1) << "*|";
    }

    cout << " F\n\n";
}

/* **********************************************************
            instrumentSimulator() : obj &, const obj &
    This function simulates the main instrument panel of a
    car. It outputs the current mileage driven and current
    gauge capacity.
   ********************************************************** */

void instrumentSimulator(Odometer &meter, const FuelGauge &gauge)
{
    while (gauge.getFuelCapacity() >= 1)
    {
            meter++;

            if (gauge.getFuelCapacity() >= 3)
            {
                cout << "Miles Driven: " << setw(25) << left << meter.getCurrentMileage();
                cout << "Gas Gauge: " << right << gauge.getFuelCapacity() << "\n";
            }
            else if (gauge.getFuelCapacity() > 0 && gauge.getFuelCapacity() <= 3)
            {
                cout << "Miles Driven: " << setw(25) << left << meter.getCurrentMileage();
                cout << "Gas Gauge: "    << right << gauge.getFuelCapacity() << " FUEL LOW!\n";
            }
            else if (gauge.getFuelCapacity() == 0)
            {
                cout << "\nOUT OF FUEL!\n";
            }

            timer();
    }
}

Example Output:


Animation created with ScreenToGif


Thursday, January 11, 2018

Programming Challenge 14.14 - Parking Ticket Simulator

Example Files: ParkingTicketSimulator.7z


ParkedCar.h


#ifndef PARKED_CAR_H_
#define PARKED_CAR_H_

#include <iostream>
using std::ostream;

#include <string>
using std::string;

class ParkedCar
{
    private:
        string make;                        // Car make
        string model;                        // Car model
        string color;                        // Car color
        string plateNumber;                // Car plate number
        int    minutesParked;            // Number of minutes a car is parked

    public:
        ParkedCar()
        { }

        ParkedCar(string, string, string, string, int);

        int getMinutesParked() const
        { return minutesParked; }

        // Friend
        friend ostream &operator << (ostream &, const ParkedCar &);
};

#endif

ParkedCar.cpp


#include "ParkedCar.h"

/* **********************************************************
            ParkedCar::ParkedCar() : Constructor
    Constructor accepting four string objects and an int as
    arguments.
   ********************************************************** */

ParkedCar::ParkedCar(string cMake, string cModel, string cColor, string cLicNum, int minutes)
{
    make = cMake;
    model = cModel;
    color = cColor;
    plateNumber = cLicNum;
    minutesParked = minutes;
}

/* **********************************************************
            Overloaded << operator
   ********************************************************** */

ostream &operator << (ostream &oStrm, const ParkedCar &obj)
{
    return oStrm << "Make:        "           << obj.make             << "\n"
                         << "Model:        "          << obj.model            << "\n"
                         << "Color:        "           << obj.color              << "\n"
                         << "License Number: " << obj.plateNumber << "\n";
}

ParkingMeter.h


#ifndef PARKING_METER_H_
#define PARKING_METER_H_

class ParkingMeter
{
    private:
        int timePurchased;        // The amount of time purchased

    public:
        ParkingMeter()
        { }
       
        ParkingMeter(int minutes)
        { timePurchased = minutes; }

        int getTimePurchased() const
        { return timePurchased; }
};

#endif

PoliceOfficer.h


#ifndef POLICE_OFFICER_H_
#define POLICE_OFFICER_H_

class ParkingTicket;

#include "ParkedCar.h"
#include "ParkingMeter.h"

#include <iostream>
using std::istream;
using std::ostream;

#include <string>
using std::string;

class PoliceOfficer
{
    private:
        string name;                    // Holding the name of an officer
        string badgeNumber;            // Holding the officer's badge number
       
    public:
        PoliceOfficer()
        { }

        PoliceOfficer(string, string);
       
        void setPoliceOfficer(string, string);
        bool isViolator(const ParkingMeter &, const ParkedCar &);
        void issueTicket(const ParkingMeter &, const ParkedCar &);

        // Friends
        friend istream &operator >> (istream &, PoliceOfficer &);
        friend ostream &operator << (ostream &, const PoliceOfficer &);
};

#endif

PoliceOfficer.cpp


#include "PoliceOfficer.h"
#include "ParkingTicket.h"

#include <iostream>
using std::cout;

/* **********************************************************
            PoliceOfficer::PoliceOfficer() - Constructor
    Accepts two string objects as its argument.
   ********************************************************** */

PoliceOfficer::PoliceOfficer(string n, string ID)
{
    setPoliceOfficer(n, ID);
}

/* **********************************************************
            PoliceOfficer::setPoliceOfficer() : string, string
    This function determines whether the string objects passed
    to it are empty. If one or both are empty, a default name
    or badge number is assigned to the appropriate class
    member variables. Else, the values passed to this function
    will be assigned to them.
   ********************************************************** */

void PoliceOfficer::setPoliceOfficer(string n, string ID)
{
    if (!n.empty())
    {
        name = n;
    }
    else
    {
        name = "Haruto Nakayama";
    }

    if (!ID.empty())
    {
        badgeNumber = ID;
    }
    else
    {
        badgeNumber = "NTPD-9284984-RD";
    }
}

/* **********************************************************
            ParkingTicket::isViolator(bool) : const obj &,
                                                         const obj &
    This function accepts two class objects passed to it by
    reference. It compares the time a car is parked to the
    amount of time purchased at the parking meter to determine
    whether the car is legally parked. The result of this
    evaluation is returned from the function.
    ********************************************************** */

bool PoliceOfficer::isViolator(const ParkingMeter &meter, const ParkedCar &car)
{
    bool status = false;

    if (car.getMinutesParked() > meter.getTimePurchased())
    {
        status = true;
    }

    return status;
}

/* **********************************************************
            ParkingTicket::issueTicket() const obj &,
                                                  const obj &
    This function creates a ParkingTicket object and passes to
    its constructor a ParkedCar, an PoliceOfficer, and a
    ParkingMeter object. It then calls the printTicket()
    function of the ParkingTicket class to output the ticket-
    information.
   ********************************************************** */

void PoliceOfficer::issueTicket(const ParkingMeter &meter, const ParkedCar &car)
{
    ParkingTicket tempTicket(car, *this, meter);

    tempTicket.printTicket();
}

/* **********************************************************
            Overloaded >> operator
   ********************************************************** */

istream &operator >> (istream &iStrm, PoliceOfficer &obj)
{
    cout << "Officer name: ";
    getline(iStrm, obj.name);
    cout << "Officer ID:   ";
    getline(iStrm, obj.badgeNumber);

    obj.setPoliceOfficer(obj.name, obj.badgeNumber);

    return iStrm;
}

/* **********************************************************
            Overloaded << operator
   ********************************************************** */

ostream &operator << (ostream &oStrm, const PoliceOfficer &obj)
{
    return oStrm << "Officer Name: " << obj.name << "\n"
                         << "Officer ID:   " << obj.badgeNumber << "\n";
}

ParkingTicket.h


#ifndef PARKING_TICKET_H_
#define PARKING_TICKET_H_

#include "PoliceOfficer.h"

class ParkingTicket
{
    private:   
        const double BASE_FINE   = 25.0;        // Base fine for the first hour or part of an hour
        const double HOURLY_FINE = 10.0;        // Additional fine for every additional hour or part of an hour

        double fine;                                // The amount of fine to be paid
        double hourlyFine;                     // The amount of additional fine to be paid

        // class objects
        PoliceOfficer issuer;
        ParkedCar violator;
        ParkingMeter parkingMeter;

    public:
        ParkingTicket()
        { }

        ParkingTicket(const ParkedCar &, const PoliceOfficer &, const ParkingMeter &);

        void calcFine();
        void printTicket();

        double getFine() const
        { return fine; }

        double getHourlyFine() const
        { return hourlyFine; }
};

#endif

ParkingTicket.cpp


#include "ParkingTicket.h"

#include <iomanip>
using std::cout;
using std::setprecision;

#include <iostream>
using std::fixed;

/* **********************************************************
            ParkingTicket::ParkingTicket()
    Constructor accepting three class objects passed to it by
    reference.
   ********************************************************** */

ParkingTicket::ParkingTicket(const ParkedCar &car, const PoliceOfficer &officer, const ParkingMeter &meter)
{
    violator = car;
    parkingMeter = meter;
    issuer = officer;

    calcFine();
    printTicket();
}

/* **********************************************************
            ParkingTicket::calcFine()
    This function calculates the amount of fine. If the amount
    of time is lower than two hours, the base fine is assigned
    to the fine class member variable. Else, the fine and
    additional fine is calculated and assigned to the class
    member variables fine and addFine.
   ********************************************************** */

void ParkingTicket::calcFine()
{
    int overTime = (1 + (violator.getMinutesParked() - parkingMeter.getTimePurchased()) / 60);

    if (overTime < 2)
    {
        fine = BASE_FINE;
    }
    else
    {
        fine = BASE_FINE + (HOURLY_FINE * overTime);
        hourlyFine = fine - BASE_FINE;
    }
}

/* **********************************************************
            ParkingTicket::printTicket()
    This function outputs a traffic-ticket with all relevant
    information.
   ********************************************************** */

void ParkingTicket::printTicket()
{
    cout << "NEO TOKYO CHIYODA WARD - PARKING VIOLATION NOTICE\n\n";
    cout << "Allowed parking time exceeded\n\n";
    cout << "Minutes Parked:    " << violator.getMinutesParked() << "\n";
    cout << "Minutes Purchased: " << parkingMeter.getTimePurchased() << "\n\n";
   
    cout << "REPORTING PATROL OFFICER\n";
    cout << "------------------------\n\n";
    cout << issuer << "\n";

    cout << "VIOLATOR\n";
    cout << "--------\n";
    cout << violator << "\n";

    cout << fixed << setprecision(2);

    cout << "FINE\n";
    cout << "----\n";

    if (getFine() == BASE_FINE)
    {
        cout << "Base Fine:   NTY " << BASE_FINE << "\n";
    }
    else
    {
        cout << "Base Fine:   NTY " << BASE_FINE << " +\n";
        cout << "Hourly Fine: NTY " << getHourlyFine() << "\n";
    }
    cout << "------------------------\n";
    cout << "Total Fine:  NTY " << getFine() << "\n\n\n";
}

ParkingTicketSimulator.cpp


#include "PoliceOfficer.h"
#include "ParkedCar.h"
#include "ParkingMeter.h"

#include <iostream>
using std::cin;
using std::cout;

#include <vector>
using std::vector;

int main()
{
    int numTicketsIssued = 0;

    vector<ParkedCar> car { ParkedCar("Porsche", "Cayenne", "Cyan", "NT-923865", 480),
                                   ParkedCar("Toyota", "Vellfire 2.5 X MPV", "Black", "NT-239575", 25),
                                   ParkedCar("Mazda", "2 G115 Revolution Top", "Machine Gray", "NT-392755", 61),
                                   ParkedCar("Alfa", "Giulietta Exclusive", "Nero Etna", "NT-23975", 55) };

    vector<ParkingMeter> meter { ParkingMeter(120),
                                          ParkingMeter(30),
                                          ParkingMeter(60),
                                          ParkingMeter(60) };

    PoliceOfficer officer;

    cout << "NEO TOKYO CHIYODA WARD - PARKING TICKET SIMULATOR\n\n";
    cout << "Assign Patrol Officer\n\n";
    cin >> officer;
    cout << "\n";

    for (size_t idx = 0; idx < meter.size(); idx++)
    {
        if (officer.isViolator(meter[idx], car[idx]) == true)
        {
            officer.issueTicket(meter[idx], car[idx]);
            numTicketsIssued++;
        }
    }

    if (numTicketsIssued == 0)
    {
        cout << "Chiyoda Ward's streets are safe!\n"
              << "There have been no parking violation reports.";
    }
   
    cin.get();
    cin.ignore();
    return 0;
}

Example Output:








Friday, January 5, 2018

Programming Challenge 14.13 - Carpet Calculator

Example Files: CarpetCalculator.7z

Note: Since the only addition to the FeetInches.h and FeetInches.cpp files written for Programming Challenge 14.11 is a conversion function that converts a FeetInches object to a double, there is no listing published for both of these files here.

RoomDimension.h


#ifndef ROOM_DIMENSION_H_
#define ROOM_DIMENSION_H_

#include "FeetInches.h"

class RoomDimension
{
    private:
        FeetInches width;
        FeetInches length;
   
    public:
        RoomDimension() {}

        RoomDimension(FeetInches w, FeetInches l) : width(w), length(l)
        {
        }

        FeetInches calcArea()
        {
            return width.multiply(length);
        }
};

#endif

RoomCarpet.h


#ifndef ROOM_CARPET_H_
#define ROOM_CARPET_H_

#include "RoomDimension.h"

class RoomCarpet
{
    private:
        RoomDimension dimension;

        double sqFtPrice;                // The cost per square footage of carpeting
        double totalCost;                // The total cost of a carpet

    public:
        RoomCarpet(RoomDimension dim, double price = 0.0) : dimension(dim), sqFtPrice(price)
        {
            calcTotalCost();
        }

        void calcTotalCost()
        {   
            totalCost = (dimension.calcArea()) * sqFtPrice;
        }
       
        double getTotalCost() const
        { return totalCost; }
};

#endif

CarpetCalculatorDm.cpp


#include "RoomCarpet.h"

#include <iomanip>
using std::setprecision;

#include <iostream>
using std::fixed;
using std::cin;
using std::cout;

int main()
{
    double price = 0.0;
    char choice = ' ';

    FeetInches width, length;

    cout << "WESTFIELD CARPET COMPANY - CARPET CALCULATOR\n\n";

    do
    {
        cout << "Please enter the width of your room:\n";
        cin >> width;
        cout << "\nPlease enter the length of your room:\n";
        cin >> length;

        RoomDimension dim(width, length);

        cout << "\nPlease enter the price per square yard: $ ";
        cin >> price;

        RoomCarpet purchase(dim, price);

        cout << setprecision(2) << fixed;
        cout << "\nThe total price of your "
              << width << " by " << length << " carpet is $ "
              << purchase.getTotalCost() << "\n\n";

        cout << "Do you wish to calculate the price for another room? ";
        cin >> choice;

        while (toupper(choice) != 'Y' && toupper(choice) != 'N')
        {
            cout << "Do you wish to calculate the price for another room? ";
            cin >> choice;
        }

        if (toupper(choice) == 'N')
        {
            cout << "\nThe Westfield Carpet Company thanks you for your patronage.";
        }
        cout << "\n";

    } while (toupper(choice) != 'N');

    cin.get();
    cin.ignore();
    return  0;
}

Example Output:



Thursday, January 4, 2018

Programming Challenge 14.12 - LandTract Class

Example Files: LandTractClass.7z

FeetInches.h


#ifndef FEET_INCHES_H_
#define FEET_INCHES_H_

#include <iostream>
using std::istream;
using std::ostream;

class FeetInches
{
    private:
        int feet;                        // To hold a number of feet
        int inches;                        // To hold a number of inches

        void simplify();                // Defined in FeetInches.cpp

    public:
        FeetInches(int f = 0, int i = 0)
        {
            feet = f;
            inches = i;
            simplify();
        }

        // Copy Constructor
        FeetInches(const FeetInches &obj)
        {
            feet = obj.feet;
            inches = obj.inches;
        }

        // Mutator functions
        void setFeet(int f)
        {
            feet = f;
        }

        void setInches(int i)
        {
            inches = i;
             simplify();
        }

        // Accessor functions
        int getFeet() const
        { return feet; }

        int getInches() const
        { return inches; }

        // Friends
        friend ostream &operator << (ostream &, const FeetInches &);
        friend istream &operator >> (istream &, FeetInches &);
};

#endif

FeetInches.cpp


#include "FeetInches.h"

#include <cstdlib>

#include <iostream>
using std::cout;

/* **********************************************************
            FeetInches::simplify()
    This function checks for values in the inches member
    greater than twelve or less than zero. If such a value is
    found, the numbers in feet and inches are adjusted to
    conform to a standard feet & inches expression. For
    example:

    3 feet 14 inches would be adjusted to 4 feet 2 inches and
    5 feet -2 inches would be adjusted to 4 feet 10 inches.

    The standard library function abs() is used to get the
    absolute value of the inches member. The abs() function
    requires to #include <cstdlib>.
   ********************************************************** */

void FeetInches::simplify()
{
    if (inches >= 12)
    {
        feet += (inches / 12);
        inches = inches % 12;
    }
    else if (inches < 0)
    {
        feet -= ((abs(inches) / 12) + 1);
        inches = 12 - (abs(inches) % 12);
    }
}

/* **********************************************************
            Overloaded << operator
    Gives cout the ability to directly display FeetInches
    objects.
   ********************************************************** */

ostream &operator << (ostream &strm, const FeetInches &obj)
{
    strm << obj.feet << " feet, " << obj.inches << " inches.";

    return strm;
}

/* **********************************************************
            Overloaded >> operator
    Gives cin the ability to directly store user input into
    FeetInches objects.
   ********************************************************** */

istream &operator >> (istream &strm, FeetInches &obj)
{
    // Prompt the user for the feet
    cout << "Feet: ";
    strm >> obj.feet;

    // Prompt the user for the inches
    cout << "Inches: ";
    strm >> obj.inches;

    // Normalize the values
    obj.simplify();

    return strm;
}

LandTract.h


#ifndef LAND_TRACT_H_
#define LAND_TRACT_H_

#include "FeetInches.h"

class LandTract
{
    private:
        int area;

        FeetInches width;
        FeetInches length;

    public:
        LandTract(FeetInches w, FeetInches l) : width(w), length(l)
        {
            area = 0;
            calcArea();
        }

        void calcArea();

        int getArea() const
        { return area; }

        // Overloaded operator
        bool operator == (const LandTract &);                    // Overloaded ==
};

#endif

LandTract.cpp


#include "LandTract.h"

/* **********************************************************
            LandTract::calcArea()
    Calculates the area of two tracts of land.
   ********************************************************** */

void LandTract::calcArea()
{
    int w = width.getFeet() * 12 + width.getInches();
    int len = length.getFeet() * 12 + length.getInches();
   
    area = (w * len);
}

/* **********************************************************
            Overloaded == operator
    Returns true if the current object is set to a value equal
    to that of right.
   ********************************************************** */

bool LandTract::operator == (const LandTract &right)
{
    bool status;

    if (area == right.area)
    {
        status = true;
    }
    else
    {
        status = false;
    }

    return status;
}

LandTractDm.cpp


#include "LandTract.h"

#include <iomanip>
using std::setprecision;

#include <iostream>
using std::fixed;
using std::cin;
using std::cout;

int main()
{
    const double TO_SQR_FT = 144.0;

    FeetInches w, l;

    cout << "Land Tract Area Calculator\n\n";
    cout << "This program lets you enter the dimensions for two tracts of land.\n"
          << "It will calculate the area for each, and output the result in square feet.\n"
          << "In addition it will tell you, whether the tracts are of same size.\n\n";

    cout << "Enter the width of tract #1:\n\n";
    cin >> w;
    cout << "\nEnter the length of tract #1:\n\n";
    cin >> l;

    LandTract lot(w, l);

    cout << "\nThe area of your lot is: ";
    cout << setprecision(2) << fixed;
    cout << (lot.getArea() / TO_SQR_FT) << " sq. ft.\n\n";

    cout << "Enter the width of tract #2:\n\n";
    cin >> w;
    cout << "\nEnter the length of tract #2:\n\n";
    cin >> l;

    LandTract garden(w, l);

    cout << "\nThe area of your garden is: ";
    cout << (garden.getArea() / TO_SQR_FT) << " sq. ft.\n\n";

    if (lot == garden)
    {
        cout << "Both tracts of land are of equal size.";
    }
    else
    {
        cout << "The tracts of land are of different size.";
    }

    cin.get();
    cin.ignore();
    return 0;
}

Example Output:





Tuesday, January 2, 2018

Happy New Year - An Outlook



Dear visitors, fellow students, and those who happen to visit this person's humble blog for the first time: I wish all of you a Happy New Year! May it be a successful one!

On this occasion let me tell you a little about the goals for this year. On top of the list is finishing Starting Out with C++ 9/E. With 4 Programming Challenges to be solved and 7 chapters to go, the goal is to get done with it until summer.

The next goal is to (finally) dive into the wonderful world of (2D) game programming. For this task, the following books will be used, which I received as christmas presents:

Beginning C++ Game Programming - by John Horton.
SFML Game Development by Example - by Raimondas Pupius
Procedural Content Generation for C++ - by Dale Green
SFML Blueprints - by Maxime Barbier

Hopefully, if all goes as planned, the first game will follow. However humble it will turn out to be, I hope that it will bring a little joy into the lifes of many people, something that entertains children and adults alike.

Besides programming, there are hundreds of hours of music waiting to listen to (this is an easy goal, as I always listen to good music to keep the good spirits up, currently it is mainly Yo-Yo Ma), about 56 books to be read, (the first book being "The Brothers Karamazov"), and getting back into 3D-design, starting and finishing a scene every month, (or in less time than that). This should be enough for this year to keep this person busy. 

And with this, it is back to the IDE, to solve the remaining Programming Challenges of this chapter. I wish my visitors and fellow students that you be able to achieve all goals you have set for yourself this year, and that you will come by from time to time, to see whatever little progress this person has made in an attempt to move past the beginning stages of programming in C++.

Programming Challenge 14.11 - FeetInches Class Copy Constructor and Multiply Function

Example Files: FeetInchesCcMult.7z

FeetInches.h


#ifndef FEET_INCHES_H_
#define FEET_INCHES_H_

#include <iostream>
using std::istream;
using std::ostream;

class FeetInches
{
    private:
        int feet;                        // To hold a number of feet
        int inches;                        // To hold a number of inches

        void simplify();                // Defined in FeetInches.cpp

    public:
        FeetInches(int f = 0, int i = 0)
        {
            feet = f;
            inches = i;
            simplify();
        }

        // Copy Constructor
        FeetInches(const FeetInches &obj)
        {
            feet = obj.feet;
            inches = obj.inches;
        }

        // Mutator functions
        void setFeet(int f)
        {
            feet = f;
        }

        void setInches(int i)
        {
            inches = i;
             simplify();
        }

        FeetInches multiply(const FeetInches &);

        // Accessor functions
        int getFeet() const
        { return feet; }

        int getInches() const
        { return inches; }

        // Overload operator functions
        FeetInches operator + (const FeetInches &);            // Overloaded +
        FeetInches operator - (const FeetInches &);            // Overloaded -
        FeetInches operator ++ ();                                    // Prefix ++
        FeetInches operator ++ (int);                                // Postfix ++
   
        bool operator > (const FeetInches &);                    // Overloaded >
        bool operator < (const FeetInches &);                    // Overloaded <
        bool operator == (const FeetInches &);                    // Overloaded ==
        bool operator >= (const FeetInches &);                    // Greater Equal
        bool operator <= (const FeetInches &);                    // Lesser Equal
        bool operator != (const FeetInches &);                    // Inequal

        // Friends
        friend ostream &operator << (ostream &, const FeetInches &);
        friend istream &operator >> (istream &, FeetInches &);
};

#endif

FeetInches.cpp


#include "FeetInches.h"

#include <cstdlib>

#include <iostream>
using std::cout;

/* **********************************************************
            FeetInches::simplify()
    This function checks for values in the inches member
    greater than twelve or less than zero. If such a value is
    found, the numbers in feet and inches are adjusted to
    conform to a standard feet & inches expression. For
    example:

    3 feet 14 inches would be adjusted to 4 feet 2 inches and
    5 feet -2 inches would be adjusted to 4 feet 10 inches.

    The standard library function abs() is used to get the
    absolute value of the inches member. The abs() function
    requires to #include <cstdlib>.
   ********************************************************** */

void FeetInches::simplify()
{
    if (inches >= 12)
    {
        feet += (inches / 12);
        inches = inches % 12;
    }
    else if (inches < 0)
    {
        feet -= ((abs(inches) / 12) + 1);
        inches = 12 - (abs(inches) % 12);
    }
}

/* **********************************************************
            Overloaded binary + operator
   ********************************************************** */

FeetInches FeetInches::operator + (const FeetInches &right)
{
    FeetInches temp;

    temp.inches = inches + right.inches;
    temp.feet = feet + right.feet;
    temp.simplify();

    return temp;
}

/* **********************************************************
            Overloaded binary - operator
   ********************************************************** */

FeetInches FeetInches::operator - (const FeetInches &right)
{
    FeetInches temp;

    temp.inches = inches - right.inches;
    temp.feet = feet - right.feet;
    temp.simplify();

    return temp;
}

/* **********************************************************
            Overloaded prefix ++ operator
    Causes the inches member to be incremented. Returns the
    incremented object.
   ********************************************************** */

FeetInches FeetInches::operator++()
{
    ++inches;
    simplify();

    return *this;
}

/* **********************************************************
            Overloaded postfix ++ operator
    Causes the inches member to be incremented. Returns the
    value of the object before the increment.
   ********************************************************** */

FeetInches FeetInches::operator++(int)
{
    FeetInches temp(feet, inches);

    inches++;
    simplify();

    return temp;
}

/* **********************************************************
            Overloaded > operator
    Returns true if the current object is set to a value
    greater than that of right.
   ********************************************************** */

bool FeetInches::operator > (const FeetInches &right)
{
    bool status;

    if (feet > right.feet)
    {
        status = true;
    }
    else if (feet == right.feet && inches > right.inches)
    {
        status = true;
    }
    else
    {
        status = false;
    }

    return status;
}

/* **********************************************************
            Overloaded < operator
    Returns true if the current object is set to a value less
    than that of right.
   ********************************************************** */

bool FeetInches::operator < (const FeetInches &right)
{
    bool status;

    if (feet < right.feet)
    {
        status = true;
    }
    else if (feet == right.feet && inches < right.inches)
    {
        status = true;
    }
    else
    {
        status = false;
    }

    return status;
}

/* **********************************************************
            Overloaded == operator
    Returns true if the current object is set to a value equal
    to that of right.
   ********************************************************** */

bool FeetInches::operator == (const FeetInches &right)
{
    bool status;

    if (feet == right.feet && inches == right.inches)
    {
        status = true;
    }
    else
    {
        status = false;
    }

    return status;
}

/* **********************************************************
            Overloaded Greater Equal => operator
    Returns true if the current object is set to a value
    greater than or equal to that of right.
   ********************************************************** */

bool FeetInches::operator >= (const FeetInches &right)
{
    bool status;

    if (feet >= right.feet)
    {
        return true;
    }
    else if (feet == right.feet && inches >= right.inches)
    {
        status = true;
    }
    else
    {
        status = false;
    }

    return status;
}

/* **********************************************************
            Overloaded Less Equal <= operator
    Returns true if the current object is set to a value less
    than or equal to that of right.
   ********************************************************** */

bool FeetInches::operator <= (const FeetInches &right)
{
    bool status;

    if (feet <= right.feet)
    {
        status = true;
    }
    else if (feet == right.feet && inches <= right.inches)
    {
        status = true;
    }
    else
    {
        status = false;
    }

    return status;
}

/* **********************************************************
            Overloaded Inequal != operator
    Returns true if the current object is set to a value not
    equal to that of right.
    ********************************************************** */

bool FeetInches::operator != (const FeetInches &right)
{
    bool status;

    if (feet != right.feet)
    {
        status = true;
    }
    else if (feet == right.feet && inches != right.inches)
    {
        status = true;
    }
    else
    {
        status = false;
    }

    return status;
}

/* **********************************************************
            FeetInches::FeetInches multiply() : const obj &
    This function multiplies two FeetInches objects. The feet
    and inches attributes are multiplied by the calling feet
    and inches object's feet and inches attributes, and a
    FeetInches object holding the result is returned.
    ********************************************************** */

FeetInches FeetInches::multiply(const FeetInches &right)
{
    FeetInches temp;

    temp.inches = ((feet * 12 + inches) * (right.feet * 12 + right.inches));
    temp.inches /= 12;
    temp.simplify();

    return temp;
}

/* **********************************************************
            Overloaded << operator
    Gives cout the ability to directly display FeetInches
    objects.
   ********************************************************** */

ostream &operator << (ostream &strm, const FeetInches &obj)
{
    strm << obj.feet << " feet, " << obj.inches << " inches.";

    return strm;
}

/* **********************************************************
            Overloaded >> operator
    Gives cin the ability to directly store user input into
    FeetInches objects.
   ********************************************************** */

istream &operator >> (istream &strm, FeetInches &obj)
{
    // Prompt the user for the feet
    cout << "Feet: ";
    strm >> obj.feet;

    // Prompt the user for the inches
    cout << "Inches: ";
    strm >> obj.inches;

    // Normalize the values
    obj.simplify();

    return strm;
}

FeetInchesDm.cpp


#include "FeetInches.h"

#include <iostream>
using std::cin;
using std::cout;

int main()
{
    FeetInches first(15, 4);
    FeetInches second = first;   
    FeetInches third, fourth;

    cout << "FEET INCHES - COPY CONSTRUCTOR & MULTIPLICATION DEMO\n\n"
          << "This program asks you to input two distances, measured in feet and inches.\n"
          << "It will multiply both values, and output the result in feet and inches.\n";
    cout << "Here is an example:\n\n";

    cout << first << " multiplied by " << second << " equals:\n";
    cout << first.multiply(second) << " \n\n";

    cout << "Enter a distance in feet and inches:\n";
    cin >> third;
   
    cout << "\nEnter another distance in feet and inches.\n";
    cin >> fourth;
   
    cout << "\n" << third << " multiplied by " << fourth << " equals:\n";
    cout << (third.multiply(fourth));

    cout << "\n\nThank you for using this demo. Have a nice day!";

    cin.get();
    cin.ignore();
    return 0;
}

Example Output: