Parallel arrays problem.

How do I make it so the elements in one array match up with the elements in different arrays? For example, I created a program that that displays the ID, name, pay rate, and weekly salary for an employee. There are a total of 20 who will be hired, but only 3 are working so far: Tom, Sarah, and Jim. Each employee has been assigned an ID ranging from 101 to 120. Tom, Sarah, and Jim have been assigned 101, 102, and 103 respectively. Their hourly pay rates are $14, $12, $15 respectively. The program calculates their salary from week to week. The first week is shown below.

1) My question is, how do I make it so Tom always gets ID 101, Sarah 102, and Jim 103? The only way I can accomplish this is if I enter in the names in order. If I don't, then they will get the wrong ID # and pay rate. But I want to be able to enter the names in any order with the correct ID # and pay rate.

2) Also, say that one of them quits in the second week. How do I make it so that their spot in the array gets filled, so there are no empty spaces. How do I compact the arrays to avoid wastage of space?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
#include <string>
#include <cmath>
#include <iomanip>
using namespace std;

int main()
{
	string name[20] = { "Tom", "Sarah", "Jim" }; // 20 total employees. 
	int ids[20] = { 101, 102, 103 }; // employee ids. 
	int hours_worked[20]; // hours worked for the employees. 
	double pay_rate[20] = { 14.00, 12.00, 15.00 }; // pay rate for the employees. 
	double weekly_salary[20]; // weekly salary for the employees. 
	int i; // loop counter

	cout << "This program will calculate the first week. " << endl << endl;

	for (i = 0; i <= 2; i++)
	{
		cout << "Please enter employee's name: ";
		cin >> name[i];
		cout << endl; // adds blank line
		cout << "Please enter hours worked: ";
		cin >> hours_worked[i];
		cout << endl;
	}

	for (i = 0; i <= 2; i++)
	{
		cout << fixed << showpoint << setprecision(2);
		weekly_salary[i] = hours_worked[i] * pay_rate[i];
	}

	cout << endl;
	cout << "ID" << "\t\t" << "Name" << "\t\t" << "Pay Rate" << "\t\t" << "Hours Worked" << "\t\t" << "Weekly Salary" << endl; 
	cout << "__" << "\t\t" << "____" << "\t\t" << "________" << "\t\t" << "____________" << "\t\t" << "_____________" << endl << endl;

	for (i = 0; i <= 2; i++)
	{
		cout << ids[i] << "\t\t" << name[i] << "\t\t" << "$" << pay_rate[i] << "\t\t\t" << hours_worked[i] << "\t\t\t" << "$" << weekly_salary[i] << endl << endl;
	}
	
	cout << endl;
	return 0; 
}


The display shows the ID, name, pay rate, hours worked, and the weekly salary. But if I put in Jim first, it will show him with ID 101 and pay rate $14. It will show that for whoever I put first. I want to be able to assign those elements to specific names. Even if I enter in Tom last, it should read 103 for his ID and $15 for his pay rate.

Edit: I think I found a way around the first question. I will give the name and tell the user to enter in the hours for that name. This will force everything to be in order, because the user will have to enter in the hours for Tom first and so on, because I will tell the user to do so. So I will remove the cout << "Please enter employee's name: "; line. And I will change the cout << "Please enter hours worked: "; line to cout << "Please enter hours worked by <name> "; like cout << "Please enter hours worked Tom: "; for example.
Last edited on
If you have change the order of one array, then you have to change the order in all arrays the same way. That is possible, but obviously quite delicate.

You could read about structs. With a struct you could convert five arrays into one and keep all data about one employee "together".


You do have a logical issue that is separate from how you store data. You do take name and hours as input. You overwrite existing names. There are at least two approaches to that:

1. Show existing name and read hours for it. The order of employees remains as initialized. You did not like that option.

2. Read name, seek it from the list to get index, and then update hours of that employee. You still allow the possibility that input contains unknown names, same name multiple times, and some names not at all. How you handle them is up to you.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <string>
#include <cmath>
#include <iomanip>
using namespace std; 

string name[20] = { "Carla", "Steve", "Bob" }; // 20 total employees. this is the 1st week.
int ids[20] = { 101, 102, 103 }; // employee ids. 
int hours_worked[20]; // hours worked for the employees.
double pay_rate[20] = { 14.00, 12.00, 15.00 }; // pay rate for the employees. 
double weekly_salary[20]; // weekly salary for the employees.
int i; // loop counter

int main()
{
	cout << "This program will calculate the first week. " << endl << endl;
	cout << "Please enter the hours for Carla, Steve, and Bob in the order mentioned. " << endl << endl;
	cout << "Enter in the hours for Carla first, then hit enter. Then do the same for Steve, and then Bob. " << endl << endl;

	for (i = 0; i <= 2; i++)
	{
		cout << "Please enter hours worked: ";
		cin >> hours_worked[i];
		cout << endl;
	}

	for (i = 0; i <= 2; i++)
	{
		cout << fixed << showpoint << setprecision(2);
		weekly_salary[i] = (hours_worked[i] * pay_rate[i]);
	}

	cout << endl;
	cout << "ID" << "\t\t" << "Name" << "\t\t" << "Pay Rate" << "\t\t" << "Hours Worked" << "\t\t" << "Weekly Salary" << endl; // need to add ID and pay rate later on
	cout << "__" << "\t\t" << "____" << "\t\t" << "________" << "\t\t" << "____________" << "\t\t" << "_____________" << endl << endl;

	for (i = 0; i <= 2; i++)
	{
		cout << ids[i] << "\t\t" << name[i] << "\t\t" << "$" << pay_rate[i] << "\t\t\t" << hours_worked[i] << "\t\t\t" << "$" << weekly_salary[i] << endl << endl;
	}

	cout << endl;
	return 0; 
}


This is my new program. I don't have to worry about the order anymore. I will look into what you said, though. Thanks. I need to sleep.
Last edited on
IDs are usually unique while first names are not, so consider asking the user for the identification code (instead of name), and then entering whatever Employee data for that. So you see where this is going -- a lookup table, id -> Employee.
Example implementation, though it goes a lil overboard w/ regex ;D . Can test-run it at https://repl.it/repls/ElasticPreciousLamp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#include <iostream>
#include <iomanip>
#include <sstream>
#include <map>
#include <regex>
using namespace std;

struct Employee
{
    Employee() :
        pay_rate(0.0f),
        hours_worked(0.0f)
    {
    }
    
    Employee(string id, string name, float pay_rate) :
        id(id),
        name(name),
        pay_rate(pay_rate),
        hours_worked(0.0f)
    {
    }
    
    Employee(string id, string name, float pay_rate, float hours_worked) :
        id(id),
        name(name),
        pay_rate(pay_rate),
        hours_worked(hours_worked)
    {
    }
    
    string id;
    string name;
    float pay_rate;
    float hours_worked;
};
typedef Employee Employee;

class Company
{
public:
    Company()
    {
        // Initial seeding
        workers_ = 
        {
            {"101", {"101", "Carla", 14.00f, 40.0f}},
            {"102", {"102", "Steve", 12.00f, 35.5f}},
            {"103", {"103", "Bob", 15.00f, 12.5f}},
            {"S13925813", {"S13925813", "Rachel", 16.50f, 40.0f}},
        };
    }
    const map<string, Employee>& Workers() const
    {
        return workers_;
    }
    
    // Adds an employee to the company
    void Add(string id, string name, float pay_rate)
    {
        if (workers_.count(id) != 0)
            cout << "\nError: id \""<<id<<"\" already exists in the company!\n";
        else
        {
            workers_[id] = Employee(id,name,pay_rate);
            cout << "\nSuccessfully added id "<<id<<" to the company.\n";
        }
    }
    
    void Show()
    {
        cout << setw(15) << "ID" << 
                setw(15) << "Name" << 
                setw(15) << "Rate" << 
                setw(15) << "Hours" <<
                setw(15) << "Total" << endl;
    
        for (auto& wpair : workers_)
        {
            auto& e = wpair.second;
            cout << setw(15) << e.id << 
                  setw(15) << e.name << 
                  setw(12) << MoneyString(e.pay_rate) << "/hr" <<
                  setw(12) << e.hours_worked << "hrs" <<
                  setw(15) << MoneyString(e.hours_worked * e.pay_rate) << endl;
                    
        }
    }
    
private:
    string MoneyString(float amount)
    {
        ostringstream oss;
        oss << "$" << fixed << setprecision(2) << amount;
        return oss.str();
    }

    map<string, Employee> workers_;
};

void ShowMainMenu()
{
    cout << "Welcome to Employee Management." << endl <<
            "[1] View employees" << endl <<
            "[2] Add employees" << endl <<
            "[3] Change hours worked" << endl <<
            "[q] Quit" << endl << endl;
}

void ShowAddPrompt()
{
    cout << "Adding an employee to the Company." << endl << 
            "[q] Go Back" << endl <<
            "Please add an employee using the following comma-separated format:"<< endl <<
            "  id,Employee Name,Pay Rate" << endl << endl <<
            "Example: " << endl <<
            "12345,John Doe,12.50" << endl << endl;
}

int main () 
{
    regex employee_r(R"(([A-Za-z\d]+),([A-Za-z\s]+),([0-9]*\.?[0-9]+))");
    Company company;

    ShowMainMenu();
    string main_input;
    while (true)
    {
        cout << "Choice? ";
        cin >> main_input;
        if (main_input == "1")
        {
            company.Show();
        }
        else if (main_input == "2")
        {
            ShowAddPrompt();
            string add_input;
            
            for (;;)
            {
                cout << "\n? ";
                getline(cin, add_input);
                if (add_input == "") // Weird empty string bug?
                    continue;
                
                if (add_input == "q")
                    break;
                
                smatch employee_matches;
                if (regex_search(add_input, employee_matches, employee_r))
                {
                    string id = employee_matches[1];
                    string name = employee_matches[2];
                    float pay_rate = stof(employee_matches[3]);
                    company.Add(id,name,pay_rate);
                }
                else
                {
                    cout << "\nInvalid input \""<<add_input<<"\".  Follow the add employee format\n";
                }
            }
            ShowMainMenu();
        }
        else if (main_input == "3")
        {
            cout << "Choice 3 not implemented yet!\n";
        }
        else if (main_input == "q")
        {
            break;
        }
        else
        {
            cout << "\nInvalid option.\n";
        }
    }
    return 0;
}
Last edited on
Topic archived. No new replies allowed.