Anda di halaman 1dari 5

Array Of Pointers To Strings

I have an array of pointers to strings (char *name[maxnum]). I add elements to the array and output each
element right after to check their content and it is okay.
char[counter] = value;
cout << char[counter] << endl;

However, at a later point in the code I output all the elements, and they are all equal to element the last
element (maxnum). :-(

for (int i=0;i<=maxnum;i++) {


cout << char[i] << endl;
}

I do a similar process with an array of doubles (double [maxnum]) and the process above works fine.

Note that I do not want to use strings.


Can you help figure out what is wrong when I use the array of pointers to store strings?

// Homework1.cpp : Exercise 2.56: Program to compute weekly payroll


// for a company
// Written by: Michelle M. Irizarry-Ortiz
//

#include <iostream>

#include <iomanip>

using namespace std;

// Function declaration
void eatline();

// Global variables
char mainMenuSelection = ' ';
char employeeName[40];
char employeeType;

int main()
{

// Constant declarations
const int maxEmployees = 100;
const double hrThreshold = 40.0, wklyCommSalary = 250.,
overTimeRatio=1.5, wklySalesPerc=5.7;

// Variable declarations
int numberItems, val_employee_counter=0;
double wklyPay = -1.,
fixedWklySalary,
hourlyWage, hoursWorked,
grossWklySales,
ratePerItem,
validwklyPay[maxEmployees];
char *validEmployeeName[maxEmployees];
// While user does not want to quit program
while (mainMenuSelection != 'Q' && mainMenuSelection !='q') {

// Display main menu


cout << "\n";
cout << "**************************************\n";
cout << "***** WELCOME TO PAYROLL PROGRAM *****\n";
cout << "* *\n";
cout << "* E - Enter employee information *\n";
cout << "* P - Print report *\n";
cout << "* C - Clear database *\n";
cout << "* Q - Quit program *\n";
cout << "* (To quit a module, enter '!' *\n";
cout << "* at any time) *\n";
cout << "* *\n";
cout << "**************************************\n\n";
cout << " Enter letter from above menu: ";

// Get menu selection from user


if (cin.peek() == '!') {eatline(); break;}
cin >> mainMenuSelection;
eatline(); // To empty input stream in case
// more than one character is entered

// If user wants to enter employee info


if (mainMenuSelection == 'E' || mainMenuSelection == 'e') {

while (wklyPay < 0) {

// Display employee info form


cout << "\n";
cout << "**************************************\n";
cout << "***** EMPLOYEE INFO FORM *****\n";
cout << "**************************************\n";
cout << " Enter employee name: " << endl;
//Get employee name
if (cin.peek() == '!') {eatline(); break;}
cin.get(employeeName,40,'\n'); // To be able to enter whitespace
eatline();
cout << "\n Employee types:\n";
cout << " 1 - Manager\n";
cout << " 2 - Hourly worker\n";
cout << " 3 - Commission worker \n";
cout << " 4 - Piece worker\n";
cout << " Enter employee type (1-4): ";
// Get employee type
if (cin.peek() == '!') {eatline(); break;}
cin >> employeeType; //Note: Need to flush input stream so ok if more than one character is
entered
eatline(); // To empty input stream in case
// more than one character is entered
cout << "\n";

// Enter additional employee information


// depending on type
// Change output precision for dealing with currency
cout << fixed << setprecision(2);

switch (employeeType) {

case '1': // manager


cout << " Enter fixed weekly salary: ";
if (cin.peek() == '!') {eatline(); break;}
cin >> fixedWklySalary;
wklyPay = fixedWklySalary;
break;

case '2': // hourly worker


cout << " Enter hourly wage: ";
if (cin.peek() == '!') {eatline(); break;}
cin >> hourlyWage;
cout << " Enter hours worked: ";
if (cin.peek() == '!') {eatline(); break;}
cin >> hoursWorked;
if (hoursWorked <= hrThreshold) {
wklyPay = hourlyWage * hoursWorked;
}
else {
wklyPay = hourlyWage * (hrThreshold
+ 1.5 * (hoursWorked-hrThreshold));
}

break;

case '3': // commision worker


cout << " Enter gross weekly sales: ";
if (cin.peek() == '!') {eatline(); break;}
cin >> grossWklySales;
wklyPay = wklyCommSalary + grossWklySales * wklySalesPerc / 100;
break;

case '4': // piece worker


cout << " Enter items produced: ";
if (cin.peek() == '!') {eatline(); break;}
cin >> numberItems;
cout << " Enter rate per item: ";
if (cin.peek() == '!') {eatline(); break;}
cin >> ratePerItem;
wklyPay = numberItems * ratePerItem;
break;

default: // default
cout << "Incorrect employee type entered.\n";
cout << "Try again!\n";
break; // Need to go back to enter employee info if something is wrong
} // end switch

// Store valid data into arrays for summary report


if (wklyPay >= 0.) {
cout << "\nPay for employee " << employeeName << ": $" << wklyPay << endl;
validwklyPay[val_employee_counter] = wklyPay;
validEmployeeName[val_employee_counter] = new char[40];
validEmployeeName[val_employee_counter] = employeeName;
cout << "here" << val_employee_counter << validEmployeeName[val_employee_counter] <<
endl;
for (int i=0;i<=(val_employee_counter);i++) {
cout << "here2!!! " << validwklyPay[i] << " " << &validEmployeeName[i] << endl;
}
val_employee_counter++;
} // end if

} // end while

wklyPay = -1.; // Restore weekly pay to -1


cout << validEmployeeName[0] << endl;

} // end if

else if (mainMenuSelection == 'P' || mainMenuSelection == 'p') {

if (val_employee_counter >= 1) { //Issue: If second employeename is too long, first will be sub by it
cout << endl << endl;
cout << setw(40) << left << " Employee Name" << setw(15) << right << " Pay " << endl;
cout << setw(40) << left << " *************" << setw(15) << right << "*******" << endl;
for (int i=0; i<=(val_employee_counter-1); i++) {
cout << i+1 << ". " << setw(40) << left << validEmployeeName[i] << "$" << setw(14) << right <<
validwklyPay[i] << endl;
}
cout << endl << endl;
} // end if

else {
cout << "\nNo employee information has been entered!\n";
} // end else

} // end else if

else if (mainMenuSelection == 'C' || mainMenuSelection == 'c') {


val_employee_counter = 0;
} // end else if

} // end while

return 0;
}

// Function to eat remainder of line


void eatline()
{
while(cin.get() != '\n') continue;

}
The statements/blocks in question are:

char *validEmployeeName[maxEmployees];

validEmployeeName[val_employee_counter] = employeeName;

for (int i=0; i<=(val_employee_counter-1); i++) {


cout << i+1 << ". " << setw(40) << left << validEmployeeName[i] << "$" << setw(14) << right <<
validwklyPay[i] << endl;
}

ou are using arrays of char. You want to use strcpy() to copy the names:

Your program does this:


CPP / C++ / C Code:
validEmployeeName[val_employee_counter] = employeeName;

This makes the pointer point to the employeName array, whose content changes for each entry, and
finally it contains the last employee name that was entered. In other words, all of your
validEmployeeName[] pointers end up pointing to the employeeName array, therefore the output will
show them to be the same.

To get the name into the pointer array element that you just obtained from new, use strcpy.

CPP / C++ / C Code:


// at the top of the file: use this header for strcpy()
#include <cstring>

//
// Instead of your statement use this:
strcpy(validEmployeeName[val_employee_counter], employeeName);

//

(Also setting validEmployeeName[...] equal to something other than the value given by new means that
the memory can never be freed. This is a Bad Thing. It is the programmer's responsibility to make sure
that for every memory block obtained by new it is returned to the operating system by a delete before
exiting. This is important!)

Hi! Thanks! This worked. Now it makes sense!


My only question is: how do I use delete to free up the memory for every pointer in the array?

Within the 'C' option, I tried a single: delete [] validEmployeeName;

but it did not work. :-(

Do I need a loop?

Ok! Got it:


for (int ctr=0; ctr<=(val_employee_counter - 1); ctr++){
delete [] validEmployeeName[ctr];
}

Finally getting the hang of it

Anda mungkin juga menyukai