MCC - CIS162AB - C++ Level I
P09 Array and File Processing - 20 points
(turn in source code, input file, and sample output)
   cpp.gif

The purpose of this C++ programming project is to allow the student to perform array, file, string, and Cstring processing. The logic for string and Cstring has already been completed, so the assignment can be started before we actually cover string and Cstring in detial. This program has the following five menu options:
  A: List Payroll Information by Employee ID         
  B: List Payroll Information by Employee Name       
  C: Search Payroll Information by Employee ID   
  D: Search Payroll Information by Employee Name 

  X: Exit the Payroll Information Module

Options B, and D have already been developed and tested. Your assignment  
is to copy-and-paste the source code below, and implement options A and C.  

In addition, the arrays are currently loaded with data typed in by the user (cin),  
so the loadArray function must be modified to load the arrays by reading the data  
from a file (P09.txt).

Input File:
  Add a text file to project P09 named P09.txt.  This file will 
  serve as the input file.

  Enter or copy-and-paste the following data into the text file:

  1018 Smit            Bruce            9.50  50  10  25  30
  1005 Bob             Billy            5.00  30  35  40  50
  1002 Long_Last_Name1 Long_First_Name  8.00  50  50  10  40
  1004 Flores          Jose             9.00  35  40  50  60
  1010 Smitts          Scott            7.00  10  30  50  30
  1001 Smith           Joe              6.00  35  40  50  60
  1007 Lee             JJ               8.00  35  40  50  60
  1006 Sanchez         Maria            7.00  10  50  50  60
  1009 Eldridge        Melissa          6.50  20  20  30  40
  1003 Jones           Larry           10.00  25  45  30  35

  Make sure to press enter after the last record, so that EOF test will work
  correctly.
  
General Processing:
  The records stored in the payroll file P09.txt are loaded into 
  arrays.  All of the menu options are implemented by manipulating the arrays.
  The last name is loaded into a char array, and 
  the first name is loaded into a string array.

Option A - List Payroll Information by Employee ID:  
Option B - List Payroll Information by Last Name:

  For option A the arrays must be sorted by ID and for opiton B they are sorted by
  Name.  After the sort, the data loaded in the arrays is displayed on the screen.

  All of the fields stored in the file are listed, including employee id,
  last name, first initial only, payrate, and the hours worked each of the 4 weeks.

  The output has column headings, is neatly spaced, and at the bottom the total 
  number of records stored in the file is also displayed.
 
Option C - Search Payroll Information by Employee ID:
  Prompt the user to enter an employee id. Create a local int variable to 
  store the search criteria. Only search for exact matches. 
  
  You must include the early exit logic. To facilitate an early exit from the search 
  loop, the array must be sorted by id before beginning the search.  An early exit is 
  when the loop is terminated because it has been determined that the search criteria is
  not in the list. This occurs when the table element is greater than the search criteria.
  
  Headings must be displayed above the detail information of the matching record.
  List the record of the matching employee id.  
  Display an error message if a match was not found.

Option D - Search Payroll Information by Employee Name:
  Prompts the user to enter a name to search for.  A local char array is 
  declared to store the search criteria.  Records that match the name entered, as  
  well as those that partially match the criteria, are displayed.  This is call a 
  wildcard search.  The strnicmp function is used because it ignores case for
  the comparison.

  Headings are displayed above the detail information of the matching record.
  An error message is displayed if a match was not found.

  Before searching, the arrays are sorted ascending so that an early exit to the 
  search can be implemented.  An early exit is when the loop is terminated because
  it has been determined that the search criteria is not in the list.  This is when
  the table element is greater than the search criteria.

Requirements:
  Create a new project (P09).
  Copy-and-paste the source code provided below.
  Code the loadArray, searchById with early exit, and sortById functions.  
  Turn in:
     source code (P09.cpp), P09.txt
     sample output from the two list options (A & B) 
     sample output of the two search options (C & D)
       For the name search option include copies of partial name matches.
       For the employee id search include copies of matches found.
       For both searches include copies of the not found messages.

Report Layout with Scale:

         1         2         3         4         5         6         7         8
12345678901234567890123456789012345678901234567890123456789012345678901234567890

Employee  Last name        F.     Rate   Wk1   Wk2   Wk3   Wk4

  1001    Smith            J.     6.00    35    40    50    60
  1002    Long_Last_Name1  L.     8.00    50    50    10    40
  1003    Jones            L.    10.00    25    45    30    35
  1004    Flores           J.     9.00    35    40    50    60
  1005    Bob              B.     5.00    30    35    40    50
  1006    Sanchez          M.     7.00    10    50    50    60
  1007    Lee              J.     8.00    35    40    50    60
  1018    Smit             B.     9.50    50    10    25    30
  1009    Eldridge         M.     6.50    20    20    30    40
  1010    Smitts           S.     7.00    10    30    50    30

Records Read: 10

Note: Only the initial for the first name is displayed.
All options should use the same output routine.

Sample Output Option A - List Payroll Information by Employee ID:
(This option is currently not available, but should generate the following.)

P09    Juan Marquez    TR 1:00pm

Employee  Last name        F.     Rate   Wk1   Wk2   Wk3   Wk4

  1001    Smith            J.     6.00    35    40    50    60
  1002    Long_Last_Name1  L.     8.00    50    50    10    40
  1003    Jones            L.    10.00    25    45    30    35
  1004    Flores           J.     9.00    35    40    50    60
  1005    Bob              B.     5.00    30    35    40    50
  1006    Sanchez          M.     7.00    10    50    50    60
  1007    Lee              J.     8.00    35    40    50    60
  1009    Eldridge         M.     6.50    20    20    30    40
  1010    Smitts           S.     7.00    10    30    50    30
  1018    Smit             B.     9.50    50    10    25    30

Records Listed: 10


Sample Output Option B - List Payroll Information by Last Name:

Employee  Last name        F.     Rate   Wk1   Wk2   Wk3   Wk4

  1005    Bob              B.     5.00    30    35    40    50
  1009    Eldridge         M.     6.50    20    20    30    40
  1004    Flores           J.     9.00    35    40    50    60
  1003    Jones            L.    10.00    25    45    30    35
  1007    Lee              J.     8.00    35    40    50    60
  1002    Long_Last_Name1  L.     8.00    50    50    10    40
  1006    Sanchez          M.     7.00    10    50    50    60
  1018    Smit             B.     9.50    50    10    25    30
  1001    Smith            J.     6.00    35    40    50    60
  1010    Smitts           S.     7.00    10    30    50    30

Records Listed: 10


Sample Output Option C - Search Payroll Information by Employee ID:
(This option is currently not available, but should generate the following.)

Enter the Employee Id to search for: 1008

Early exit...Employee Id not on file.


Enter the Employee Id to search for: 1020

Employee Id not on file.


Enter the Employee Id to search for: 1004

P09    Juan Marquez    TR 1:00pm

Employee  Last name        F.     Rate   Wk1   Wk2   Wk3   Wk4

  1004    Flores           J.     9.00    35    40    50    60

Sample Output Option D Search Payroll Information by Last Name:

Enter the Employee Name to search for: Marquez

Early exit...Employee Name not on file.


Enter the Employee Name to search for: L

Employee  Last name        F.     Rate   Wk1   Wk2   Wk3   Wk4

  1007    Lee              J.     8.00    35    40    50    60
  1002    Long_Last_Name1  L.     8.00    50    50    10    40


Enter the Employee Name to search for: Smit

Employee  Last name        F.     Rate   Wk1   Wk2   Wk3   Wk4

  1018    Smit             B.     9.50    50    10    25    30
  1001    Smith            J.     6.00    35    40    50    60
  1010    Smitts           S.     7.00    10    30    50    30


Source Code:

//P09 Array Processing   Juan Marquez  
/*
   This program uses simple arrays, multidimensional arrays, cstrings, strings, and files.  
   It allows a payroll clerk to choose an option from a menu.  The choices are:
   
     A: List the Payroll Information by Employee ID
     B: List the Payroll Information by Employee Name 
     C: Search Payroll Information by Employee ID
     D: Search Payroll Information by Employee Name

     X: Exit the Payroll Information Module
     

   The following items for each employee are saved in the file p10.txt:
     Employee ID  (1000 - 9999)
     Last Name    (15 characters)
     First Name   (15 characters)
     Rate         (5.00 - 10.00)
     Hours W1,W2,W3,W4    (0-60)

*/
#include <fstream>  // file processing
#include <iostream> // cin and cout
#include <cctype>   // toupper
#include <iomanip>  // setw
#include <cstring>  // cstring functions strlen, strcmp, strcpy stored in string.h
#include <string>   // string class

using namespace std;


//Disable warning messages C4267 C4996.
//To see the warnings, comment out the following line.
#pragma warning( disable : 4267 4996 )

//Warning C4267: coversion from size_t to int, possible lost of data
//size_t is a data type defined in  and is an unsigned integer.
//The function strlen returns a value of the type size_t, but in 
//searchByName we assign the returned value to an int. 
//We could also declare the variable as size_t instead of int.
//   size_t stringLength;

//Warning C4996: strnicmp strcpy, stricmp was declared deprecated, means
//the compiler encountered a function that was marked with deprecated. 
//The deprecated function may no longer be supported in a future release.


//Global Constants
//When using to declare arrays, must be defined with const modifier
const int  ARRAY_SIZE = 20,  HOURS_SIZE = 4, NAME_SIZE = 16; 

//Declare arrays as global so we don't have to pass the arrays to each function.
//Normally we wouldn't declare variables that change values a global.
    int    employeeId[ARRAY_SIZE];
    string firstName[ARRAY_SIZE];
    char   lastName[ARRAY_SIZE][NAME_SIZE];
    double rate[ARRAY_SIZE];
    int    hours[ARRAY_SIZE][HOURS_SIZE];

    int    numberOfEmps;    //count of how many employees were loaded into arrays

//Function Prototypes
//menu options
void listById( );

void listByName( );

void searchById( );

void searchByName( );

//helper functions
void loadArray( );

void sortById( );

void sortByName( );

void swapValues(int i, int minIndex);


//list employee functions
void listEmployees( );

void listEmployeesHeadings( );

void listEmployeesDetails(int i);

void listEmployeesTotals( );

void displayContinuePrompt( );


//Program starts here   
int main()
{
//Declare and initialize local main variables
    char   choice;            //menu option

//Load the arrays with data
    loadArray( );

//check to see what the user wants to do
    do  // while (choice != 'X')
    {
        cout << "P09   Juan Marquez    \n\n";

        cout << "Enter the letter of the desired menu option. \n"
             << "Press the Enter key after entering the letter. \n \n"

             << "  A: List Payroll Information by Employee ID \n"
             << "  B: List Payroll Information by Employee Name \n"
             << "  C: Search Payroll Information by Employee Id \n"
             << "  D: Search Payroll Information by Name \n\n"

             << "  X: Exit the Payroll Information Module \n \n"

             << "Choice: ";

        cin >> choice;
        choice =toupper(choice);

        switch (choice)
        {
            case 'A':
                listById( );
                break;
            case 'B':
                listByName( );
                break;
            case 'C':
                searchById( );
                break;
            case 'D':
                searchByName( );
                break;
            case 'X':
                cout << "\n\nNow exiting Payroll Information...please wait.\n\n";
                break;
            default:
                cout << "\a\n\n Invalid Option Entered - Please try again. \n\n";

        } // end of switch

    } while (choice != 'X');

return 0; 
} // end of main


//Function Definitions
void loadArray( )
{  
//This function must be modified by the student to read the 
//data from a file instead of having the user type it in.
//Keep in mind that we are using parallel arrays, and that
//all eight items in the data file need to be loaded into 
//the arrays.  The read statement will be very much like
//the current cin statement below.  

    char answer;
    cout << "P09   Juan Marquez    \n\n";
    cout << "Before processing the arrays, the data must be loaded.\n\n";

    cout << "Would like to add an employee? (Y/N) ";
    cin >> answer;

//Intialize index to load the 1st record into the 1st row of the array 
    int i = 0;

    while (toupper(answer) != 'N')
    {
//get the data
        cout << "\nEnter the Employee Id, lastname, firstname, rate, w1, w2, w3, w4\n";

        cin >> employeeId[i] >> lastName[i] >> firstName[i] >> rate[i]
            >> hours[i][0] >> hours[i][1] >> hours[i][2] >> hours[i][3];

        i++;
        if (i < ARRAY_SIZE)
        {
            cout << "\n\nWould like to add another employee? (Y/N) ";
            cin >> answer;
        }
        else
        {
            break;        // get out of loop
        }
    }

//Save the number of records loaded
    numberOfEmps = i;
    return;
}


//Opt A: List by ID
void listById( )
{
    sortById( );
    listEmployees( ); 
    displayContinuePrompt( );
    return;
}


//Opt B: List by Name
void listByName( )
{
    sortByName( );
    listEmployees( );
    displayContinuePrompt( );
    return;
}


//Opt C: Search by ID 
void searchById( )
{  
//This funciton is currently implemented as a stub.
//The missing logic must be developed and implemented by the student.
//See example P09ex for details on searching with integers.
//Employee Id is an int, so the strcmp function will not be used.  

    cout << "\nThis option is currently not available...\n\n";

//To facilitate the early exit logic, data must be sorted by id 
    sortById( );

//    int searchId;
//    bool recordFound = false;    

//    cout << "\n\nEnter the Employee Id to search for: ";
//    cin  >> searchId;

//continue adding the search logic

    displayContinuePrompt( );
    return;
}


//Opt D: Search by Name
void searchByName( )
{
//To facilitate the early exit logic, data must be sorted by name 
    sortByName( );

//declare searching variables
    int  stringLength;
    char searchName[NAME_SIZE];
    bool recordFound = false;
    bool headingsDisplayed = false;

//Since we are supporting a wildcard search, there could be more than
//one lastName that matches the search criteria.  However, we only 
//want to display the headings after the first match and not for the
//subsequent matches.  We use headingsDisplayed for this logic.

    cout << "\n\nEnter the Employee Name to search for: ";
    cin  >> searchName;

//We only compare upto the length of the search string
    stringLength = strlen(searchName);     // '\0' not included in length

//strncmp is case sensitive and strnicmp ignores case 
    for (int i = 0; i < numberOfEmps; i++) //walk through the array
    {
        if (strnicmp(lastName[i],searchName, stringLength) == 0) 
        {
            if (! headingsDisplayed)
            {
                listEmployeesHeadings();   //display the headings to cout 
                headingsDisplayed = true;  //only after 1st match
            }                              //display the record found
            recordFound = true;
            listEmployeesDetails(i); 
            //don't get out of the for-loop, because there may be more matches
        }
        else if (strnicmp(lastName[i],searchName, stringLength) > 0)  //early exit 
        {
            cout << endl << "Early exit...";
            break;                         //get out of for-loop
        }
    }

    if (false == recordFound)
    {
        cout << "Employee Name not on file. \n";
    }

    displayContinuePrompt( );
    return;
}


void sortById( )
{ 
//This funciton is currently implemented as a stub.
//The missing logic must be developed and implemented by the student.
//See example P09ex on comparing and saving interger values.
//Employee Id is an int, so strcpy and strcmp will not be used. 
    
//    int    minIndex, minId; 

//Be sure to use the function swapValues, which is already defined below.
//All arrays need to be swapped instead of just employeeId.

    return;
}


void sortByName( )
{
//First for-loop walks through the entire array 
//The current entry is saved as the min value

//Second for-loop looks for values lower than the
//current value.  If one is found, then all values are swapped.
    int    minIndex;
    char   minName[NAME_SIZE];

    for (int i = 0; i < (numberOfEmps - 1); i++)
    {
        minIndex = i;
        strcpy(minName,lastName[i]);

        for (int i2 = i + 1; i2 < numberOfEmps; i2++)
        {
            if (stricmp(lastName[i2],minName) < 0) //if str1 < str2  
            {                                      //a neg number returned 
                minIndex = i2;
                strcpy(minName,lastName[i2]);
            }
        }
        swapValues(i, minIndex);
    }
    return;
}


void swapValues(int i, int minIndex)
{
//temp holding variables
    int    holdInt;
    char   holdName[NAME_SIZE];
    string holdStr;
    double holdDbl;

    holdInt = employeeId[i];
    employeeId[i] = employeeId[minIndex];
    employeeId[minIndex] = holdInt;

    strcpy(holdName,lastName[i]);
    strcpy(lastName[i],lastName[minIndex]);
    strcpy(lastName[minIndex],holdName);

    holdStr = firstName[i];
    firstName[i] = firstName[minIndex];
    firstName[minIndex] = holdStr;

    holdDbl = rate[i];
    rate[i] = rate[minIndex];
    rate[minIndex] = holdDbl;

    holdInt = hours[i][0];
    hours[i][0] = hours[minIndex][0];
    hours[minIndex][0] = holdInt;

    holdInt = hours[i][1];
    hours[i][1] = hours[minIndex][1];
    hours[minIndex][1] = holdInt;

    holdInt = hours[i][2];
    hours[i][2] = hours[minIndex][2];
    hours[minIndex][2] = holdInt;

    holdInt = hours[i][3];
    hours[i][3] = hours[minIndex][3];
    hours[minIndex][3] = holdInt;

    return;
}


void listEmployees( )
{
    listEmployeesHeadings();

    for (int i = 0; i < numberOfEmps; i++)
    {
        listEmployeesDetails(i);
    }

    listEmployeesTotals( );
    return;
}


void listEmployeesHeadings( )
{
    cout.setf(ios::fixed);
    cout.setf(ios::showpoint);
    cout.precision(2);

    cout << "\n\nP09    Juan Marquez     \n\n"
         << "Employee  Last name        F.     "
         << "Rate   Wk1   Wk2   Wk3   Wk4 \n\n";
    return;
}


void listEmployeesDetails(int i)
{
    cout << setw(6) << employeeId[i] << "    ";

    cout.setf(ios::left);
    cout << setw(17) 
         << lastName[i]
         << firstName[i][0] << ".";
    cout.unsetf(ios::left);

    cout << setw(9) << rate[i];

    for (int i2 = 0; i2 < HOURS_SIZE; i2++)  // i2 = 0,1,2,3
    {
        cout << setw(6) << hours[i][i2];
    }
    cout << endl;

    return;
}


void listEmployeesTotals( )
{
    cout << "\nRecords Listed: " << numberOfEmps << endl << endl;
    return;
}


void displayContinuePrompt( )
{
    char prompt;

    cout << "\n\nProcedure completed. Press Enter to continue: ";
    cin.ignore();
    prompt = cin.get( );

    system("cls");   //clear screen - DOS

    return;
}
//End of program

Revised: 11/05/2007 - www.mc.maricopa.edu/~marquez/cis162ab/p09_arrays.html