Monday, July 24, 2017

Bugfix Notice

It has happened again. Twice now, and in a very short period of time at that, I committed some errors in the code for Programming Challenge 12.13. Unlike the last time, I decided to edit the original code, and resubmit it, which is unfortunate. 

The nature of the error resulted from a poor design decision I originally made while in the planning stages. It was looking like a great idea to have a nested structure from which two other structures would be called. What I did not know, or hadn't realized, is the fact that you can have a nested structure, but this brings along many troubles if you're doing it wrong.

Here is part of the original code:


As you will notice there is a structure called Item, which holds two nested structure members. One calls the Date structure, the other calls the Inventory structure. In the code that follows, the Item structure was passed down to all the other functions, and this is what introduced the error. The way the original code was, I had this statement in the write function:

writeRec.write(reinterpret_cast<char *>(&itemRec), sizeof(itemRec));

This must have also written part of the Date information to the file. The same must have happened with the edit function, which contains a very similar line of code to the above. When I started writing code for the Programming Challenge 12.14, it became clear that the records haven't been read in correctly. All data was displayed in the wrong field, item description in the dateAdded field for instance. The 'easy fix' would have been to add the Date structure to the current Programming Challenges' code. With it in place, all data contained in the file was displayed correctly. 

Since it is important only in the original program, but only an artifact in the current program, some changes to the old code was the better way to handle things. A new filed was also added to the Programming Challenge 12.13 code: The 'numRecords' field, which is now contained in the Inventory structure. The idea is to have some sort of 'limit' in place, which is something that I think is beneficial to the current Programming Challenge code.
 
Unlike last time it also had a positive effect. I do know now that structures, if used in the way I did, can cause unexpected trouble. Also I learned that, if there is a Programming Challenge 1 and a Programming Challenge 2 that builds on the first code, I should try functionality in both, before submitting one Challenge, only to find that things would not work in the program that follows it.  

To my readers, if you happen to have run the original code or using the example file: PR_Item.dat, please download it again, and give it another try. Also here is the original Programming Challenge 12.13 code for review purposes. I can only promise and hope that such mistakes will not happen again. I would also like to say how sorry I am for introducing such problems. 

Now it is back to the IDE to write and finish Programming Challenge 12.14, which should go live very soon. My fellow learners I wish that they be wiser and know when and how to use structures the right way, especially when dealing with input and output to files.

Sunday, July 23, 2017

Programming Challenge 12.13 - Inventory Program

Example Files: EvalDate.h
                         UtilityCls.h
                         PR_Item.dat


/* Inventory Program - This program uses a structure to store the following
    inventory data in a file:
  
        * Item Description
        * Quantity on Hand
        * Wholesale Cost
        * Retail Cost
        * Date Added to Inventory

    The program has a menu that allows the user to perform the following tasks:

        * Add new records to the file
        * Display any record in the file
        * Change any record in the file
  
    Input Validation: The program does not accept quantities, or wholesale or
    retail costs, less than 0. The program does not accept dates determined to
    be unreasonable. */

#include "UtilityCls.h"
#include "EvalDate.h"

const int     DESCR_SIZE = 25;
const int     DATE_SIZE = 12;
const string ADMIN_NAME = "Administrator Rhodan";

struct Inventory
{
    int    numRecord;                        /* Holds the record number                */
    char   itemDescr[DESCR_SIZE];        /* Holds the item name                    */
    int    atHand;                            /* Quantity of items available        */
    double wholesaleCost;                /* Holds the wholesale cost            */  
    double retailCost;                    /* Holds the retail cost                */
    char   dateAdded[DATE_SIZE];        /* Holds the date an item was added */

    /* Inventory Constructor */
    Inventory()
    {
        numRecord = 0;
        itemDescr[DESCR_SIZE] = ' ';
        atHand = 0;
        wholesaleCost = 0.0;
        retailCost = 0.0;
        dateAdded[DATE_SIZE] = ' ';
    }

    /* Inventory Destructor */
    ~Inventory()
    {
    }
};      

struct Date
{
    int addDay;        /* Holds day   [1-31] */
    int addMonth;    /* Holds month [1-12] */
    int addYear;    /* Holds year             */

    Date()
    {
        addDay = 0;
        addMonth = 0;
        addYear = 0;
    }

    ~Date()
    {
    }
};

enum class MenuItems
{
    ADD_RECORD = 'A', DISPLAY_RECORD = 'D', EDIT_RECORD = 'E', QUIT = 'Q'
};

enum class Choice
{
    YES = 'Y', NO = 'N'
};

void     menu(Inventory &);
string getFileName();
void   getItemInfo(Inventory &);
void   getDate(Inventory &);
string dateToString(int, int, int);
void     processRecord(Inventory &, const string);
int    writeRecord(Inventory &, const string);
int    readRecord(Inventory &, const string);
int    editRecord(Inventory &, const string);
void   displayRecord(const Inventory &, const int);

int main()
{
    Inventory itemInfo;

    cout << "\nCOSMIC WAREHOUSE COMPANY - TERRA HQ.\n\n"
          << "Welcome " << ADMIN_NAME << "!\n";

    menu(itemInfo);
  
   pauseSystem();
   return 0;
}

/* **********************************************************
    Definition: menu

    This function accepts a structure variable passed to it by
    reference as its argument. It provides a menu structure
    that allows the user to select from the following items:

        * Add a record
        * Display a record
        * Edit a record
        * Quit
    ********************************************************** */

void menu(Inventory &itemRec)
{
    const char addRec     = static_cast<char>(MenuItems::ADD_RECORD);
    const char dispRec = static_cast<char>(MenuItems::DISPLAY_RECORD);
    const char editRec = static_cast<char>(MenuItems::EDIT_RECORD);
    const char quit     = static_cast<char>(MenuItems::QUIT);
  
    string fileName = "";
    char     choice     = ' ';

    fileName = getFileName();

    do
    {
        cout << "\nCOSMIC WAREHOUSE COMPANY - ADMINISTRATIVE MENU\n\n"
              << "[A] - ADD RECORD\n"
              << "[D] - DISPLAY RECORD\n"
              << "[E] - EDIT RECORD\n"
              << "[Q] - QUIT\n\n";
        cout << "Please make your choice, " << ADMIN_NAME << ": ";
        cin >> choice;
        cout << "\n";

        choice = toupper(choice);

        switch (choice)
        {
            case addRec :
            {
                clearScreen();
                processRecord(itemRec, fileName);
            }
            break;

            case dispRec :
            {
                clearScreen();
                readRecord(itemRec, fileName);  
            }
            break;

            case editRec :
            {
                clearScreen();
                editRecord(itemRec, fileName);
            }
            break;

            case quit :
            {
                cout << "I will now shut this program down, " << ADMIN_NAME << ".\n"
                      << "The Cosmic Warehouse Company Item Record System "
                      << "wishes you a successful day!";
            }
        }
    } while (choice != quit);  
}

/* **********************************************************
    The user is asked for a filename, which is returned from
    this function.
    ********************************************************** */

string getFileName()
{
    string fileName = "";

    cout << "\nPlease enter the name of the file you wish me to store\n"
          << "or retrieve item information from, " << ADMIN_NAME << ": ";
    cin >> fileName;

    return fileName;
}

/* **********************************************************
   Definition: getItemInfo

    This function accepts a structure variable passed to this
    function as its argument. It stores information about an
    item in the member variables of the Inventory structure.
   ********************************************************** */

void getItemInfo(Inventory &itemRec)
{
    Date addDate;

    cout << "Please provide information about the item you wish me\n"
          << "to process " << ADMIN_NAME <<"\n\n";

    /* Get item information */
    cout << "Item Description: ";
    cin.ignore();
    cin.getline(itemRec.itemDescr, DESCR_SIZE);

    cout << "Quantity Available: ";
    cin >> itemRec.atHand;

    while (itemRec.atHand <= 0)
    {
        cout << "Quantity Available: ";
        cin >> itemRec.atHand;
    }

    cout << "Wholesale Cost: $ ";
    cin >> itemRec.wholesaleCost;

    while (itemRec.wholesaleCost <= 0.0)
    {
        cout << "Wholesale Cost: $ ";
        cin >> itemRec.wholesaleCost;
    }

    cout << "Retail Cost: $ ";
    cin >> itemRec.retailCost;

    while (itemRec.retailCost <= 0.0)
    {
        cout << "Retail Cost: $ ";
        cin >> itemRec.retailCost;
    }

    getDate(itemRec);
}

/* **********************************************************
   Definition: getDate

    This function accepts a structure variable passed to it by
    reference as its argument. It asks and evaluates the date
    entered. This information is stored in a member variable
    of the Inventory structure.
   ********************************************************** */

void getDate(Inventory &itemRec)
{
    Date addDate;

    cout << "\nDate added:\n";
    cout << "Day: ";
    cin >> addDate.addDay;

    cout << "Month: ";
    cin >> addDate.addMonth;

    cout << "Year: ";
    cin >> addDate.addYear;

    while (validateDate(addDate.addDay, addDate.addMonth, addDate.addYear) == false)
    {
        cout << "\nI am sorry but this date is invalid, "
              << ADMIN_NAME << ". Please repeat your input ...\n";
        cin.clear();

        cout << "\nDate added:\n";
        cout << "Day: ";
        cin >> addDate.addDay;

        cout << "Month: ";
        cin >> addDate.addMonth;

        cout << "Year: ";
        cin >> addDate.addYear;
    }

    string vDate = dateToString(addDate.addDay, addDate.addMonth,
                                         addDate.addYear);

    strcpy_s(itemRec.dateAdded, DATE_SIZE, vDate.c_str());
}

/* **********************************************************
   Definition: dateToString

    This function accepts three integer values as arguments.
    A stringstream object is used to store the date in a
    specific format, which is returned from the function.
   ********************************************************** */

string dateToString(const int dd, const int mm, const int yy)
{
    stringstream dateStream;

    if (dd < 10 && mm < 10)
    {
        dateStream << "0" << dd << "/0" << mm << "/" << yy;
    }
    else if (dd >= 10 && mm < 10)
    {
        dateStream << dd << "/0" << mm << "/" << yy;
    }
    else
    {
        dateStream << dd << "/" << mm << "/" << yy;
    }

    return dateStream.str();
}

/* **********************************************************
   Definition: processRecord

    This function accepts a structure variable passed to it by
    reference, and a filename as its arguments. It calls two
    functions:

        * getItemInfo()
        * writeRecord()

    As long as the user decides that he or she wishes to add
    a record, these functions are called. If the user, when
    asked, answers with 'n', the function will exit and the
    program returns to the menu function.
   ********************************************************** */

void processRecord(Inventory &itemRec, const string fileName)
{
    const char positive = static_cast<char>(Choice::YES);
    const char negative = static_cast<char>(Choice::NO);

    char choice = ' ';

    do
    {
        getItemInfo(itemRec);
        writeRecord(itemRec, fileName);

        cout << "\nDo you wish to add another item record " << ADMIN_NAME << "?\n"
              << "[Y]es | [N]o: ";
        cin.ignore();
        cin.get(choice);
        cout << "\n";

        choice = toupper(choice);

        while (toupper(choice) != positive && toupper(choice) != negative)
        {
            cout << "\nDo you wish to add another item record " << ADMIN_NAME << "\n";
            cout << "[Y]es | [N]o: ";
            cin.ignore();
            cin.get(choice);
            cout << "\n";

        }
    } while (choice != negative);
}

/* **********************************************************
   Definition: writeRecord

    This function accepts a structure variable passed to it
    by reference and a filename as its arguments. It tries to
    open a file in binary write mode. Upon success, data is
    written in append mode to the file. If an error occurs, a
    message is displayed and the function exits to the menu.
   ********************************************************** */

int writeRecord(Inventory &itemRec, const string fileName)
{
    fstream writeRec(fileName.c_str(), ios::out | ios::binary | ios::app);

    if (!writeRec.fail())
    {
        ++itemRec.numRecord;
       writeRec.write(reinterpret_cast<char *>(&itemRec), sizeof(itemRec));

        cout << "\nI have successfully written the item information to\n"
              << fileName << " " << ADMIN_NAME << ".\n";
    }
    else
    {
        cout << "I could not write the item information to " << fileName
              << ", " << ADMIN_NAME << ".\n"
              << "I will now return to the main menu ...\n";
    }
    writeRec.close();

    return 0;
}

/* **********************************************************
   Definition: readRecord

    This function accepts a structure variable passed to it by
    reference and a filename as its arguments. It tries to
    open a file to read data back in. Upon success, the user
    is first asked to enter a record number. The position of
    this record is retrieved, and the record displayed. In
    case of an error, a message is displayed, and the function
    will exit to the menu.
   ********************************************************** */

int readRecord(Inventory &itemRec, const string fileName)
{
    long recNum = 0;

    fstream readRec(fileName.c_str(), ios::in | ios::binary);

    /* Upon success, the item record conforming to the input made
       by the user is retrieved, and the item information is
        displayed. */
    if (!readRec.fail())
    {
        cout << "\nPlease enter the number of the record I should display, "
              << ADMIN_NAME << ": ";
        cin >> recNum;

        readRec.seekg((recNum -1) * sizeof(itemRec), ios::beg);
        readRec.read(reinterpret_cast<char *>(&itemRec), sizeof(itemRec));

        displayRecord(itemRec, recNum);
    }
    else
    {
        cout << "\nI could not retrieve item information from" << fileName
              << ", " << ADMIN_NAME << "...\n"
              << "I will now return to the main menu ...\n";
        return -1;
    }
    readRec.close();

    return 0;
}

/* **********************************************************
   Definition: editRecord

    This function accepts a structure variable passed to it
    by reference and a filename as its arguments. It tries to
    open a file in read and write mode. Upon succes, the user
    is asked to enter the record number he or she wishes to
    change. This position is retrieved, the record is read in
    from the file, and the item record displayed.
  
    The user is then asked if this is the record he or she
    wishes to edit. If the answer is positive, a function that
    allows the user to enter data is called. Once finished,
    the user is asked if the information is correct. If the
    answer is positive, the item record is written to file
    and the function will exit.

    In case the user decides that he or she does not wish to
    either change a particular record, or finds the item info
    is incorrect, the function exits and the program returns
    to the main menu.
   ********************************************************** */

int editRecord(Inventory &itemRec, const string fileName)
{
    const char positive = static_cast<char>(Choice::YES);
    const char negative = static_cast<char>(Choice::NO);

    long recNum = 0;
    char choice = ' ';

    fstream alterRec(fileName.c_str(), ios::in | ios::out | ios::binary);

    if (!alterRec.fail())
    {
        cout << "\nWhich item record do you wish me to change, "
              << ADMIN_NAME << ": ";
        cin >> recNum;

        alterRec.seekg((recNum -1) * sizeof(itemRec), ios::beg);
        alterRec.read(reinterpret_cast<char *>(&itemRec), sizeof(itemRec));

        /* Display the item information */
        displayRecord(itemRec, recNum);

        /* The user is asked to confirm his or her choice before changing
           any information. */
        cout << "Do you wish me to change this record, " << ADMIN_NAME << "?\n"
                << "[Y]es, [N]o: ";
        cin >> choice;
        cout << "\n";

        choice = toupper(choice);

        if (toupper(choice) == positive)
        {
            /* Get new item information */
            getItemInfo(itemRec);

            /* Moves to the position the item record is stored at. */
            alterRec.seekp((recNum - 1) * sizeof(itemRec), ios::beg);

            /* The user is asked to confirm his or her choice before the changed
                record is written to the file. */
            cout << "\nIs this information correct, " << ADMIN_NAME << "?\n"
                  << "[Y]es, [N]o: ";
            cin >> choice;
            cout << "\n";

            choice = toupper(choice);

            while (toupper(choice) != positive && toupper(choice) != negative)
            {
                cout << "\nIs this information correct, " << ADMIN_NAME << "?\n"
                    << "[Y]es, [N]o: ";
                cin >> choice;
                cout << "\n";
            }

            if (toupper(choice) == positive)
            {
                alterRec.write(reinterpret_cast<char *>(&itemRec), sizeof(itemRec));
            }
        }
        else
        {
            cout << "\nAs you wish, " << ADMIN_NAME << ".\n"
                  << "I will now return to the main menu ...\n";
        }
    }
    else
    {
        cout << "\nI could not read from or write item records to " << fileName
              << ", " << ADMIN_NAME << ".\n"
              << "I will now return to main menu ...\n";
        return -1;
    }
    alterRec.close();

    return 0;
}

/* **********************************************************
    Definition: displayRecord

    This function accepts a nested structure variable passed
    to it by reference and a record number as its arguments.
    It displays information stored in the file under that
    record number.
    ********************************************************** */

void displayRecord(const Inventory &itemRec, const int recNum)
{
    cout << "\nHere is the item with record number: " << recNum << " " << ADMIN_NAME << "\n\n";

    cout << setw(19) << left  << "Item Description:\t\t" << itemRec.itemDescr << "\n";
    cout << setw(17) << left  << "Quantity Available:\t\t" << itemRec.atHand << "\n";
    cout << setprecision(2)    << showpoint << fixed;
    cout << setw(16) << left  << "Wholesale Cost: "
          << setw(15) << right << "$ "
          << setw(4) << right  << itemRec.wholesaleCost << "\n";
    cout << setw(16) << left  << "Retail    Cost: "
          << setw(15) << right << "$ "
          << setw(4) << right  << itemRec.retailCost << "\n";
    cout << "Date Added: "    << setw(30) << right << itemRec.dateAdded << "\n\n";
}

Example Output:







Monday, July 17, 2017

Programming Challenge 12.12 - Corporate Sales Data Input

Example File: IshikawaSalesData.dat


/* Corporate Sales Data Input - This program reads the data in the file
    created by the program in Programming Challenge 12.11. The program
    calculates and displays the following figures:

        * Total corporate sales for each quarter
        * Total yearly sales for each division
        * Total yearly corporate sales
        * Average quarterly sales for the division
        * The highest and lowest quarters for the corporation */

#include "Utility.h"

const int NAME_LENGTH = 15;
const int NUM_BRANCHES = 4;
const int NUM_QUARTERS = 4;

struct CorporateSales
{
    char divisionName[NAME_LENGTH];                    /* Holds the division names */
    array<double, NUM_QUARTERS> qrtlySales;        /* Holds the quarterly sales results */
};

struct SalesResults
{
    array<double, NUM_QUARTERS> totalSalesQtr;    /* Total corporate sales for each quarter          */
    array<double, NUM_QUARTERS> totalSalesDiv;    /* Total yearly sales for each division          */       
    array<double, NUM_QUARTERS> avgQtrlySales;    /* Average quarterly sales for the division      */
    double totalYrlyCorp;                                /* Total yearly corporate sales                      */
    double highestQtr;                                    /* Highest quarterly sales for the corporation */
    double lowestQtr;                                        /* Lowest quarterly sales for the corporation  */
    int     highest;                                        /* Holds the quarter with highest sales result */   
    int     lowest;                                            /* Holds the quarter with lowest sales result  */
};

struct DivisionSales
{
    CorporateSales sales[NUM_BRANCHES];        /* Nested CorporateSales array structure member */
    SalesResults   summary;                        /* Nested SalesResult structure member               */
};

void initStruct(DivisionSales &);
int  readSalesData(DivisionSales &);
void totalSalesQtr(DivisionSales &);
void totalDivSales(DivisionSales &);
void avgDivSalesQtr(DivisionSales &);
void totalCorpSales(DivisionSales &);
void hiLoCorpSales(DivisionSales &);
void displaySalesReport(const DivisionSales &);

int main()
{
    DivisionSales division;
    int fOpen = 0;

    initStruct(division);

    cout << "\n\tISHIKAWA FRUIT COMPANY\n\n";

    if (fOpen = readSalesData(division) != -1)
    {
        totalSalesQtr(division);
        totalDivSales(division);
        totalCorpSales(division);
        avgDivSalesQtr(division);
        hiLoCorpSales(division);
        displaySalesReport(division);
    }

    cout << "\n\n\tNow exiting the program ...\n"
          << "\n\tISHIKAWA FRUIT COMPANY - Your number one fruit supplier!";

   pauseSystem();
   return 0;
}

/* **********************************************************
   Definition: initStructure

    This function uses a reference variable to a struct as
    its argument. All structure members are initialized to a
    default value.
   ********************************************************** */

void initStruct(DivisionSales &sales)
{
    sales.summary.totalYrlyCorp = 0.0;
    sales.summary.highestQtr = 0.0;
    sales.summary.lowestQtr = 0.0;
    sales.summary.highest = 0;
    sales.summary.lowest = 0;

    for (int index = 0; index < NUM_BRANCHES; index++)
    {
        sales.summary.totalSalesQtr[index] = 0.0;
        sales.summary.totalSalesDiv[index] = 0.0;
        sales.summary.avgQtrlySales[index] = 0.0;
    }
}

/* **********************************************************
   Definition: readSalesData

    This function uses a reference variable to a struct as
    parameter. The user is asked to enter the name of the file
    from which the sales data should be read in. Upon succes,
    the sales data is read in, and the structure members are
    populated. In case of failure a message is displayed, and
    the program exits.
   ********************************************************** */

int readSalesData(DivisionSales &division)
{
    string fileName = "";
    cout << "\tEnter filename containing sales data:   ";
    cin >> fileName;

    fstream readData(fileName.c_str(), ios::in | ios::binary);

    if (!readData.fail())
    {
        cout << "\tReading in sales data from\t\t" << fileName << "\n";

        readData.read(reinterpret_cast<char *>(&division),
                          sizeof(CorporateSales) * NUM_BRANCHES);

        cout << "\tData successfully read in from\t\t" << fileName << "\n"
              << "\tNow closing\t\t\t\t" << fileName << "\n\n\n\n";
    }
    else
    {
        cout << "\n\tFile Read Error. Could not open or process " << fileName << "\n"
              << "\tThis program will now exit ...";
        return -1;
    }
    readData.close();

    return 0;
}

/* **********************************************************
   Definition: totalSalesQtr

    This function uses a reference variable to a struct as
    paramter. It calculates the sales total achieved by the
    whole company in each of the four quarters. This data is
    stored in the appropriate struct member variable.
   ********************************************************** */

void totalSalesQtr(DivisionSales &corp)
{
    for (int index = 0; index < NUM_BRANCHES; index++)
    {       
        for (int qtrs = 0; qtrs < NUM_QUARTERS; qtrs++)
        {
            corp.summary.totalSalesQtr[qtrs] += corp.sales[index].qrtlySales[qtrs];
        }       
    }
}

/* **********************************************************
   Definition: totalDivSales

    This function uses a reference variable to a struct as
    paramter. It calculates the sales total achieved by each
    of the four companies' divisions, for each of the four
    quarters. This result is stored in the appropriate struct
    member variable.
   ********************************************************** */

void totalDivSales(DivisionSales &division)
{
    for (int index = 0; index < NUM_BRANCHES; index++)
    {
        division.summary.totalSalesDiv[index] = 0;
   
        for (int qtrs = 0; qtrs < NUM_QUARTERS; qtrs++)
        {
            division.summary.totalSalesDiv[index] += division.sales[index].qrtlySales[qtrs];
        }
    }
}

/* **********************************************************
   Definition: avgDivSalesQtr

    This function uses a reference variable to a struct as
    paramter. It calculates the average sales results achieved
    by each division in each of the four quarters. This data
    is stored in the appropriate struct member variable.
   ********************************************************** */

void avgDivSalesQtr(DivisionSales &division)
{
    for (int index = 0; index < NUM_BRANCHES; index++)
    {
        division.summary.avgQtrlySales[index] = 0;

        for (int qtrs = 0; qtrs < NUM_QUARTERS; qtrs++)
        {
            division.summary.avgQtrlySales[index] +=
            division.sales[index].qrtlySales[qtrs] / NUM_BRANCHES;
        }
    }
}

/* **********************************************************
   Definition: totalCorpSales

    This function uses a reference variable to a struct as
    paramter. It calculates the sales total achieved by the
    company. This data is stored in the appropriate struct
    member variable.
   ********************************************************** */

void totalCorpSales(DivisionSales &corp)
{
    for (int qtrs = 0; qtrs < NUM_QUARTERS; qtrs++)
    {
        corp.summary.totalYrlyCorp += corp.summary.totalSalesQtr[qtrs];

    }
}

/* **********************************************************
   Definition: totalSalesQtr

    This function uses a reference variable to a struct as
    paramter. It determines the quarters with the highest
    and lowest sales results. Both the highest and lowest
    results as well as the quarter in which it was achieved
    is stored in the appropriate struct member variables.
   ********************************************************** */

void hiLoCorpSales(DivisionSales &corp)
{
    corp.summary.highestQtr = corp.summary.totalSalesQtr[0];
    corp.summary.lowestQtr = corp.summary.totalSalesQtr[0];
   
    for (int index = 0; index < NUM_BRANCHES; index++)
    {
        corp.summary.highestQtr < corp.summary.totalSalesQtr[index] ?
            corp.summary.highestQtr = corp.summary.totalSalesQtr[index],
            corp.summary.highest = (index + 1):
        corp.summary.highestQtr;
    }
   
    for (int index = 0; index < NUM_BRANCHES; index++)
    {
        corp.summary.lowestQtr > corp.summary.totalSalesQtr[index]?
            corp.summary.lowestQtr = corp.summary.totalSalesQtr[index],
            corp.summary.lowest = (index + 1) :
            corp.summary.lowestQtr;
    }
}

/* **********************************************************
   Definition: totalSalesQtr

    This function uses a reference variable to a struct as
    paramter. It displays a detailed summary of the sales
    results.
   ********************************************************** */

void displaySalesReport(const DivisionSales &corp)
{
    cout << "\n\tISHIKAWA FRUIT COMPANY SALES DATA REPORT\n";

    cout << setprecision(2) << fixed << showpoint << "\n";
    cout << "\t" << setw(31) << right << "\tQuarterly Sales Corp." 
          << setw(30) << right << "Yearly Sales Div."  
          << setw(42) << right << "Quarterly Average Sales Div.\n";
    cout << "\t" << setw(109) << setfill('-') << right;
    cout << "\n" << setfill(' ');
    for (int qtrs = 0; qtrs < NUM_QUARTERS; qtrs++)
    {
        cout << "\tQuarter " << (qtrs + 1)
              << setw(7) << right << "$ " << corp.summary.totalSalesQtr[qtrs]
              << setw(25) << right << "$ " << corp.summary.totalSalesDiv[qtrs]
              << setw(21) << right << "$ " << corp.summary.avgQtrlySales[qtrs] << "\n";
    }
   
    cout << "\t" << setw(109) << setfill('-') << right;
    cout << "\n" << setfill(' ');
    cout << "\tSales Total: " << setw(3) << right << "$ " << corp.summary.totalYrlyCorp;

    cout << "\n\n\tHighest Sales Result achieved in Quarter " << (corp.summary.highest + 1)
          << setw(52) << right << "\tSales Result $ "             << (corp.summary.highestQtr);
   
    cout << "\n\tLowest  Sales Result achieved in Quarter " << (corp.summary.lowest)
          << setw(52) << right << "\tSales Result $ "          << (corp.summary.lowestQtr);
}

Example Output:




Sunday, July 16, 2017

Deletion and Updates

It has been quiet around here for almost 2 weeks, hasn't it? Then all of a sudden a new blog post is being uploaded and another deleted? What is going on? For one thing I didn't change any of my policies, for instance never change code once it has been submitted. Only in the case where there are bugs, or the code is in other ways being found to be faulty. So far it wasn't necessary to remove any code, and there is always a first, and this is the first case this has happened. 

The previous code for Programming Challenge 12.11 contained an error of sorts, or design-flaw rather. I sought help in a Coding community and received plenty of it. I got more help than I could ever have hoped for actually. In the beginning there was I and there was my code, I posted some snippets, of which I thought worked very well. In the following discussion I learned that I should not use a char array for division names but instead string class objects. This then led to lots of headaches on my part as I tried figuring out how to get a string in a struct into a binary file. 

I tried hard, asked many questions, and eventually managed to make things work. But instead of the fruits of all my labor in the past couple of days all you are getting to see is what seems like code containing minor changes? No fair! Of course it wouldn't be fair if I wouldn't share it with you. Here it is then, free for you to download and enjoy in all its sad glory. 

Example Files: CppSData.cpp
                         Xtra.dat

Of course you might think, why has this person not uploaded this code, and instead decided to upload another code as the solution to the Programming Challenge? To be honest with you? Doubts. While indeed the above code works, and I tested it numerous times, I still doubt that I should go with it until I learn way more about things. Until then I stick with what I know and can predict, which is reflected in the code I uploaded as solution. This will stay online as long as this blog will be live. (So, hopefully for eternity and a day ;-))

With this, I think, I will call it a day, and work hard to (finally) solve the next Programming Challenge. As always I would like to thank my visitors old and new, from all over the world, thank you for dropping by! I hope you found what you came looking for. Also many thanks for all the +s! My fellow learners I wish that you have a pleasant summer, and temperatures in a range allowing you to solve your own programming challenges without your brain melting. I hate the thought that I be learning alongside one of these:

Picture Copyright: PopCap Games


Programming Challenge 12.11 - Corporate Sales Data Output

Example File: IshikawaSalesData.dat


/* Corporate Sales Data Output - This program uses a structure to store
    the following data on a company division:

        * Division Name: East, West, North, South
        * Quarter: 1, 2, 3, 4
        * Quarterly Sales

    The user is asked for the four quarters' sales figures for the East,
    West, North and South divisions. The data for each quarter for each
    division is written to a file.

    Input Validation: No negative numbers for sales figures are accepted. */

#include "Utility.h"

const int NAME_SIZE = 15;
const int NUM_BRANCHES = 4;
const int NUM_QUARTERS = 4;

struct CorporateSales
{
    char divisionName[NAME_SIZE];                            /* Holds the division names */
    array<double, NUM_BRANCHES> quarterlySales;        /* Array to hold the quarterly sales figures*/
};

struct DivisionSales
{
    CorporateSales sales[NUM_BRANCHES];

    /* Initializer list */
    DivisionSales() : sales{ { "North Branch", { 0.0 } }, { "South Branch", { 0.0 } },
                                     { "East Branch",     { 0.0 } }, { "West Branch",  { 0.0} } } {}
};

void getSalesData(DivisionSales &);
int  writeData(DivisionSales &);

int main()
{
    DivisionSales division;

    getSalesData(division);
    writeData(division);

   pauseSystem();
   return 0;
}

/* **********************************************************
   Definition: getSalesData

    This function uses a reference parameter to a structure as
    its argument. The user is asked to enter quarterly sales
    figures for the four branches of a company. This data is
    stored in the appropriate structure member variables.
   ********************************************************** */

void getSalesData(DivisionSales &division)
{
    cout << "\n\tISHIKAWA FRUIT COMPANY - SALES DATA SYSTEM\n\n";
         
    for (int index = 0; index < NUM_BRANCHES; index++)
    {
        cout << "\n\tEnter Sales Data for " << division.sales[index].divisionName << ":\n";
        for (int qtrs = 0; qtrs < NUM_QUARTERS; qtrs++)
        {
            cout << "\tQuarter " << (qtrs + 1) << ":\t$ ";
            cin >> division.sales[index].quarterlySales[qtrs];

            while (division.sales[index].quarterlySales[qtrs] <= 0.0)
            {
                cout << "\tQuarter " << (qtrs + 1) << ":\t$ ";
                cin >> division.sales[index].quarterlySales[qtrs];
            }
        }
    }   
}

/* **********************************************************
   Definition: writeData

    This function uses a reference variable to a structure as
    its argument. The user is asked to enter a filename. Upon
    success, the CorporateSales structure data is written to
    to disk. In case of an error a message is displayed, and
    the program exits.
   ********************************************************** */

int writeData(DivisionSales &division)
{
    string fileName = "";

    cout << "\n\tEnter name of the file to output sales data to: ";
    cin >> fileName;

    fstream salesData(fileName.c_str(), ios::out | ios::binary);

    if (!salesData.fail())
    {
        cout << "\n\tWriting " << fileName << " to disk ...\n";

        salesData.write(reinterpret_cast<const char *>(&division),
                             sizeof(CorporateSales) * NUM_BRANCHES);

        cout << "\n\tData successfully written to " << fileName << "\n"
              << "\tNow closing the program ...\n\n"
              << "\tISHIKAWA FRUIT COMPANY - Your number one fruits supplier!";
    }
    else
    {
        cout << "\n\tFile Write Error! Could not write to " << fileName << "\n"
              << "\tPlease close this program and try again ...";
        return -1;
    }
    salesData.close();

    return 0;
}

Example Output:




Tuesday, July 4, 2017

Programming Challenge 12.10 - File Decryption Filter

Example Files: encrypted.txt
                          decrypted.txt


/* File Decryption Filter - This program decrypts the file produced by the
    program in Programming Challenge 12.9. It reads the contents of the coded
    file, restores the data to its original state, and writes it to another
    file. */

#include "Utility.h"

int    readFile(fstream &, string &);
string decryptText(string);
int    writeFile(fstream &, const string);

int main()
{
    fstream textFile;
    fstream textDecrypt;

    int    fOpen = 0;
    string cryptedText = "";
    string decrypted = "";

    cout << "File Decryption Filter\n\n";

    fOpen = readFile(textFile, cryptedText);

    if (fOpen != -1)
    {
        cout << "\nYour file will be decrypted now ...\n";
        decrypted = decryptText(cryptedText);

        cout << "File decrypted. Writing decrypted text to file ...\n";
        fOpen = writeFile(textDecrypt, decrypted);

        if (fOpen != -1)
        {
            cout << "\nFile successfully created. You can now close this program.\n"
                  << "Have a nice day!";
        }
    }

   pauseSystem();
   return 0;
}

/* **********************************************************
    Definition: readFile

    This function uses a reference parameter to an fstream
    object and a reference to a string object as parameters.
    Upon success, the contents of the file is read-in and
    stored in a string object.
   ********************************************************** */

int readFile(fstream &textFile, string &clearText)
{
    string fileName = "";
    string tmpText = " ";

    cout << "Enter name of file you wish to open: ";
    cin >> fileName;

    textFile.open(fileName, ios::in);

    if (!textFile.fail())
    {
        while (getline(textFile, tmpText))
        {
            clearText += tmpText;
        }
    }
    else
    {
        cout << "\nFile Read Error. Could not read " << fileName;
        return -1;
    }

    return 0;
}

/* **********************************************************
    Definition: decryptText

    This function uses a string object as its parameter. The
    contents in the string object is decrypted, and the string
    returned.
   ********************************************************** */

string decryptText(string decrypted)
{
    int basEnc = 0;
    int locEnc = 0;
    int locFin = 0;
    int locTxt = 0;

    basEnc = 32 / 3;
    locEnc = (5 + (basEnc + 5) * (basEnc + basEnc / 8));
    locFin = ((3 * basEnc) + (locEnc - 6));
    locTxt = ((1 - (basEnc + locEnc) * (basEnc + locEnc)) + locFin);

    for (int i = 0; i < decrypted.size(); i++)
    {
        decrypted[i] -= locTxt + locFin / locEnc;
    }

    return decrypted;
}

/* **********************************************************
    Definition: writeFile

    This uses a reference to an fstream object and a constant
    string object variable as parameters. Upon success, the
    file is opened, and the encrypted text contained in the
    string object is written to it.
   ********************************************************** */

int writeFile(fstream &cryptText, const string decrypted)
{
    string fileName = "";
    string tmpText = "";

    cout << "\nEnter name of file you wish to write to: ";
    cin >> fileName;

    cryptText.open(fileName, ios::out);
  
    if (!cryptText.fail())
    {  
        cryptText << decrypted << "\n";
    }
    else
    {
        cout << "File Write Error. Could not write data to " << fileName;
        return -1;
    }
    cryptText.close();

    return 0;
}

Example Output: