Here, better yet, I will give you a screenshot! :D
User Media - TinyPic - Free Image Hosting, Photo Sharing & Video Hosting
Printable View
Here, better yet, I will give you a screenshot! :D
User Media - TinyPic - Free Image Hosting, Photo Sharing & Video Hosting
Oh, well, the reason I thought data[] could be used is because I am calling it through using the Employee class like I do in the sorting function.
If only I could use the buttons, heh-heh.
Anyway, read post #15.
See, this is why I am confused:
Using data[] here worked, but in the searching it doesn't...? Any idea?Code:// Sort fuction used to sort through the employee struct and sort by last name else, customer ID
void Employees::sortNameeID() {
int smallestOrLargest;
int index;
for ( int i = 0; i < size-1; i++ ) {
int smallestOrLargest = i;
for ( int index = i + 1; index < size; index++ ) {
int cmpName = strcmp(data[index].eLName, data[smallestOrLargest].eLName);
if (cmpName<0) { smallestOrLargest = index;
} else if (cmpName==0) { // names match
if (data[index].eID<data[smallestOrLargest].eID) {
smallestOrLargest = index;
}
}
}
if (smallestOrLargest != i) { //swap them
Employee temp = data[i];
data[i] = data[smallestOrLargest];
data[smallestOrLargest] = temp;
}
}
}
This is annoying...
Alright, so I changed the function a bit to match the others...here is the declaration inside the public under the employees class:
void inSearch();
Here is the error:
http://i43.tinypic.com/11goo6e.jpg
Because data[] is a member of class Employees.
I know this sounds like a drag, but (this is kind of what I meant before) you are not saving yourself any time or trouble by writing so much code involving (clearly) numbers of concepts (such as classes) which you have between zero and no experience with. In the end, it will only take you longer to debug, and the concepts will still have some fuzzy edges in your mind.
You should write a couple short, simple programs that focus not on the goals of your assignment but on specific C++ concepts that you are using within it it. This will give you a place to quickly and simple test "a premise" with regard to how to use the syntax. So here's an example:
Of course, this works and contains no errors, but if I had used:Code:#include <iostream>
using namespace std;
class test {
public:
int data;
test (int x) {
data = x;
}
};
int main () {
test eg(666);
cout << eg.data <<endl;
return 0;
}
instead, there would be a problem. If I couldn't find a solution myself, I could easily post that code and ask "why is data undefined?" and you would have your answer in probably a few minutes, from just about anyone. Rather than expecting someone to go thru all those details -- which can happen, but, well, I have to make dinner...etc...and it's taken you most of an hour to get this far.Code:cout << data <<endl;
Notice above, many irrelevant details and such eliminated. I promise, this will make it easier for you too ;)
Alright, I got this to work without errors, now I just need to figure out how to get this thing to compare and search the array the right way...
Call Function:Code:// Search Array
void Employees::searchNameeID() {
int index;
string target;
cout << "Please enter last name to search for: ";
cin >> target; cin.ignore();
for ( int i = 0; i < size-1; i++ ) {
for(int index = i + 1; index < size; index++){
if(data[index].eLName == target){
cout << data[index].eLName << ", " << data[index].eName << "\n"; // Last Name, First Name
cout << data[index].eStreetNum << " " << data[index].eStreetName << "\n"; // Street Number Street Name
cout << data[index].eCity << ", " << data[index].eState << " " << data[index].eZip << "\n"; // City, State Zip
}
}
}
}
So, now that I did this, how exactly would I go about searching for the data[index].eLName and comparing it to the target string?Code:// Search for employee
xEmployee.searchNameeID();
Why can't you just use the STL? As long as you have strings going, a vector of employees could get rid of the array, buy you out of the box sorting and with a simple helper function, searching as well...
Alright, so everyone will be happy to know that I finished it!!!! Everything works now!!!
Thank you everyone for putting up with me being stupid. :P Thanks a ton for making me think through it!!
Just because you helped me!:
Code:/******************************************************
** Name: Joshua Long
** Filename: CPP_FINAL1.cpp
** Project Description: Enter the number of employees you want
to input into the database, enter all of the employees and
then sort the employees by last name. Prompt user to search
for an employee by last name then display employee.
** Output: Employee data that was entered and then organized
by the program to have better formatting.
** Input: Employee data
** Strees Level: Very HIGH ;)
******************************************************/
// Include Files
#include <iostream> // used for cin, cout
#include <iomanip>
#include <string.h>
#include <stdio.h>
using namespace std;
const int MAX_NAME_SIZE = 22; // Max size for names
const int MAX_SIZE = 25; // Max size for all other strings
// Employee Structure (Used for all employees
struct Employee {
// Chars used instead of strings for use of spaces
char eName[MAX_NAME_SIZE], eLName[MAX_NAME_SIZE], eStreetName[MAX_SIZE], eCity[MAX_SIZE], eState[MAX_SIZE];
int eID, eStreetNum, eZip;
void inNameeID();
};
// Max amount of employees allowed in program
const int MAX_EmployeeS = 50;
// The Employees class
class Employees {
public:
// Fuction Prototypes
void inEmployees();
void inNameeID();
void sortNameeID();
void searchNameeID();
void print(const char *prompt);
// Private declarations
private:
Employee data[MAX_EmployeeS];
int size;
};
// Main Processing
int main() {
//xEmployee.print("Original list"); // Used to print original
//xEmployee.print("Alphabetized list"); // Used to print aplha list
// Create new instance of Employees (stores all employee's data)
Employees xEmployee;
// Display which employee is being input
xEmployee.inEmployees();
// Prompt for input of the employee data and display entered results
xEmployee.inNameeID();
xEmployee.print("Initial Employee Data");
// Sort the employee data by last name
xEmployee.sortNameeID();
// Print the employees that have been entered
xEmployee.print("Sorted Employee List");
cout << endl << endl; // Skip a few lines after list displayed
// Search for employee
xEmployee.searchNameeID();
cout << endl;
//Pause program before shutting down
system("PAUSE");
}
// Search Array
void Employees::searchNameeID() {
int index;
string target;
cout << "Please enter last name to search for: ";
cin >> target; cin.ignore();
cout << endl;
for(int index = 1; index < size; index++){
if(data[index].eLName == target){
cout << data[index].eLName << ", " << data[index].eName << "\n"; // Last Name, First Name
cout << data[index].eStreetNum << " " << data[index].eStreetName << "\n"; // Street Number Street Name
cout << data[index].eCity << ", " << data[index].eState << " " << data[index].eZip << "\n"; // City, State Zip
}
}
}
// Prompt for the user input on the employee's data
void Employee::inNameeID() {
cout << "First Name: ";
cin.getline( eName, MAX_NAME_SIZE); // First Name
cout << "Last Name: ";
cin.getline( eLName, MAX_NAME_SIZE); // Last Name
cout << "Street Number: ";
cin >> eStreetNum; cin.ignore(); // Street Number
cout << "Street Name: ";
cin.getline( eStreetName, MAX_SIZE); // Street Name
cout << "City: ";
cin.getline( eCity, MAX_SIZE); // City
cout << "State: ";
cin.getline( eState, MAX_SIZE); // State
cout << "Zip Code: ";
cin >> eZip; cin.ignore(); // Zip Code
cout << "Customer ID: ";
cin >> eID; cin.ignore(); // Customer ID
cout << endl;
}
// Prompt for how many employees should be entered
void Employees::inEmployees() {
cout << "Enter number of Employees (1 . . " << MAX_EmployeeS << ")" << endl << '>';
cin >> size; cin.ignore();
}
// Display which employee is being entered
void Employees::inNameeID() {
for ( int count = 0; count < size; count++ ) {
cout << "Employee " << (count + 1) << endl;
data[count].inNameeID();
}
}
// Print the employees that have been entered
void Employees::print(const char *prompt) {
cout << prompt << endl;
cout << "------------------------------" << endl;
for ( int count = 0; count <size; count++ ) {
cout << data[count].eLName << ", " << data[count].eName << "\n"; // Last Name, First Name
cout << data[count].eStreetNum << " " << data[count].eStreetName << "\n"; // Street Number Street Name
cout << data[count].eCity << ", " << data[count].eState << " " << data[count].eZip << "\n"; // City, State Zip
//cout << setw( 8 ) << left << "Customer ID: " <<data[count].eID << "\n"; // Customer ID
cout << endl;
}
cout << endl;
}
// Sort fuction used to sort through the employee struct and sort by last name else, customer ID
void Employees::sortNameeID() {
int smallestOrLargest;
int index;
for ( int i = 0; i < size-1; i++ ) {
int smallestOrLargest = i;
for ( int index = i + 1; index < size; index++ ) {
int cmpName = strcmp(data[index].eLName, data[smallestOrLargest].eLName);
if (cmpName<0) { smallestOrLargest = index;
} else if (cmpName==0) { // names match
if (data[index].eID<data[smallestOrLargest].eID) {
smallestOrLargest = index;
}
}
}
if (smallestOrLargest != i) { //swap them
Employee temp = data[i];
data[i] = data[smallestOrLargest];
data[smallestOrLargest] = temp;
}
}
}
I am pleased to hear you made it; many do not and when they don't get an immediate answer they give up. After reading your thread earlier I thought it would be fun to sit down and see what kind of solution I could come up with in the shortest amount of time using nothing but the C++ standard. Additional points were for creating an employee mgmt class that could sort and search without me having to implement any of that code. To the rescue came the std::map class. I typed the map to use strings as the key field and an instance of Employee as the value. With that in place I wrote a couple of simplistic printing searching methods and (what took the most time) a reasonable test function to it all to show it all works and to generate data for the test. I have a tarball of it here:
http://jbcobb.net/bin/sortsearchdemo.tar.gz. You can just look at the source or if you need to compile it to see it run, install cmake if you don't already have it (I forgot your platform but it is available for all major platforms (Linux, Windows, Mac, etc). To build it, just run "cmake ." from the same folder as the CMakeLists.txt file and then type make. Note that this was not to do your program requirements but rather to demo how the STL can be used for a lot of things. This project will create a shared object library (or DLL on Winders) and a main executable that just calls the testEmployeeClass() method in the library. stl_sort_search.hpp/.cpp implements the testing function as well as a CEmployeeManager class which does the heavy lifting (such as there is here).
Started with a very simple Employee class with copy constructor (needed for many STL functions).
Code://******************************************************************
//* File:employee.hpp
//*
//* Description:simple employee class
//*
//* Date:2010-05-14
//*
//* Author:jeff cobb
//******************************************************************
//* R E V S I O N S
//*
//******************************************************************
#ifndef EMPLOYEE_HPP
#define EMPLOYEE_HPP
#include <string>
using namespace std;
class Employee
{
private:
string strLastName;
string strFirstName;
string strAddress;
string strCity;
string strState;
string strZip;
public:
Employee(): strLastName(""), strFirstName(""), strAddress(""), strCity(""), strState(""), strZip(""){};
Employee(const Employee &ref)
{
strLastName = ref.strLastName;
strFirstName = ref.strFirstName;
strAddress = ref.strAddress;
strCity = ref.strCity;
strState = ref.strState;
strZip = ref.strZip;
}
Employee(string &strLN, string &strFN, string &strAdr, string &strCt, string &strSt, string strZ)
{
strLastName = strLN;
strFirstName = strFN;
strAddress = strAdr;
strCity = strCt;
strState = strSt;
strZip = strZ;
}
void setLastName(string &str)
{
strLastName = str;
}
string getLastName()
{
return strLastName;
}
void setFirstName(string &str)
{
strFirstName = str;
}
string getFirstName()
{
return strFirstName;
}
void setAddress(string &str)
{
strAddress = str;
}
string getAddress()
{
return strAddress;
}
void setCity(string &str)
{
strCity = str;
}
string getCity()
{
return strCity;
}
void setState(string &str)
{
strState = str;
}
string getState()
{
return strState;
}
void setZip(string &str)
{
strZip = str;
}
string getZip()
{
return strZip;
}
};
#endif
Here is the header for the manager class:
and finally the implementation:Code:/*************************************************
* File: stl_sort_search.hpp
*************************************************/
#ifndef __STL_SORT_SEARCH_HPP
#define __STL_SORT_SEARCH_HPP
#include <map>
#include <iostream>
#include <string>
using namespace std;
#include "employee.hpp"
class CEmployeeManager
{
private:
// this will hold all of the employees.
// because it is a map (tree) it will automatically
// sort them on insertion so that need is taken care
// of. The key for the map is a string of the last
// name. Alter this if you need to search by something else
map<string, Employee> Employees;
public:
// ctor. doesn't have much to do
CEmployeeManager(){};
// add an employee to our data store.
// return true if add is successful, false
// if employee is already here
bool addEmployee(Employee newEmp);
// print out a list of employees sorted by last name
void printSortedList();
// look up an employee. Return false if not
// found, true if found and set into Emp
bool lookupEmployee(string strLastName, Employee &Emp);
// pretty print an employee
void printEmployee(Employee &Emp);
};
int testEmployeeClass(int nNumberOfEmployees);
#endif
Nothing in main so I didn't add it here. Follow the link above if you want the whole project.Code:/*************************************************
* File: stl_sort_search.cpp
*************************************************/
#include "stl_sort_search.hpp"
#include <string.h>
#include <stdio.h>
#define MAX_NAMES 25
// test names...
const char *nameList[] =
{
"Jones",
"Brown",
"White",
"Johnson",
"Stratten",
"Townsend",
"Fielding",
"Anderson",
"Middleton",
"Kirby",
"Lee",
"Burnap",
"Golden",
"Nash",
"Yang",
"Ullman",
"Vogelman",
"Charleston",
"Deitel",
"Stroustrup",
"Kernigan",
"Richie",
"Cook",
"Dempsey"
};
int testEmployeeClass(int nNumberOfEmployees)
{
int nResultCode = 0;
if( nNumberOfEmployees >= MAX_NAMES)
{
cout << "Too many names in test (" << nNumberOfEmployees << ")" << endl;
nResultCode = -1;
return nResultCode;
}
CEmployeeManager EmpMgr;
// generate some employees
int nCount;
for(nCount = 0; nCount < nNumberOfEmployees; nCount++)
{
Employee Emp;
string strLastName = string(nameList[nCount]);
Emp.setLastName(strLastName);
char buf[30];
memset(buf, 0, 30);
sprintf(buf, "FirstName%d", nCount);
string strFN = string(buf);
Emp.setFirstName(strFN);
memset(buf, 0, 30);
sprintf(buf, "%d00 Address Lane", nCount);
string strAddress = string(buf);
Emp.setAddress(strAddress);
memset(buf, 0, 30);
sprintf(buf, "City%d", nCount);
string strCity(buf);
Emp.setCity(strCity);
memset(buf, 0, 30);
sprintf(buf, "State%d", nCount);
string strState(buf);
Emp.setState(strState);
memset(buf, 0, 30);
sprintf(buf, "%d0987", nCount);
string strZip(buf);
Emp.setZip(strZip);
// insert into map
if( EmpMgr.addEmployee(Emp))
{
cout << "Added employee #" << nCount << " successfully" << endl;
}
else
{
cout << "Epic fail adding employee " << nCount << ". Aborting test." << endl;
nResultCode = -1;
return nResultCode;
}
}
// now lets search for an employee
cout << "Search test..." << endl;
string strSearchKey = nameList[2];
Employee resultEmp;
if( EmpMgr.lookupEmployee(strSearchKey, resultEmp))
{
cout << "Searched for " << strSearchKey << " and found:" << endl;
EmpMgr.printEmployee(resultEmp);
}
else
{
cout << "Failed to find " << strSearchKey << ". Aborting." << endl;
nResultCode = -1;
return nResultCode;
}
// print out sorted list
cout << "Sorting and printing test.." << endl;
cout << endl << "List of employees: " << endl;
EmpMgr.printSortedList();
return nResultCode;
}
// pretty print an employee
void CEmployeeManager::printEmployee(Employee &Emp)
{
cout << "******************************" << endl
<< "Last Name: " << Emp.getLastName() << endl
<< "First Naem: " << Emp.getFirstName() << endl
<< "Address: " << Emp.getAddress() << endl
<< "City: " << Emp.getCity() << endl
<< "State: " << Emp.getState() << endl
<< "Zip: " << Emp.getZip() << endl
<< "******************************" << endl;
}
// add an employee to our data store.
// return true if add is successful, false
// if employee is already here
bool CEmployeeManager::addEmployee(Employee newEmp)
{
bool bSuccess = false;
map<string, Employee>::iterator itr = Employees.find(newEmp.getLastName());
if(itr != Employees.end())
{
// last name already exists, set result and return
bSuccess = false;
}
else
{
// this is a new employee
Employees[newEmp.getLastName()] = newEmp;
bSuccess = true;
}
return bSuccess;
}
// print out a list of employees sorted by last name
void CEmployeeManager::printSortedList()
{
// Since the employees are already sorted by last name
// we just walk the map in natural order and print them out
map<string, Employee>::iterator ptr = Employees.begin();
while(ptr != Employees.end())
{
printEmployee((*ptr).second);
ptr++;
}
cout << "End of list." << endl;
}
// look up an employee. Return false if not
// found, true if found and set into Emp
bool CEmployeeManager::lookupEmployee(string strLastName, Employee &Emp)
{
bool bSuccess = false;
map<string, Employee>::iterator ptr = Employees.find(strLastName);
if(ptr != Employees.end())
{
// if ptr is not pointing to the end of the list
// the node it IS pointing at is a winner
Emp = (*ptr).second;
bSuccess = true;
}
return bSuccess;
}
I have a few suggestions about some of what I would change with that:
The copy-constructor can be removed:
Really you should never implement the copy-constructor manually whenever the default generated version will already do the right thing. In this case it will do the right thing because strings already know how to copy-construct themselves. What's more, the auto-generated one is more efficient that what you wrote because you used assignment rather than construction, and that incolved the extra step of destroying the old value first, even if the old value also happened to be an empty string.
Also with this:The default constructor for strings make them empty, thus all you would need is:Quote:
Code:Employee(): strLastName(""), strFirstName(""), strAddress(""), strCity(""), strState(""), strZip(""){};
The getters should be marked const. Lots of getters and setters indicates poor encapsulation anyway, but I wont go into that.Code:Employee() {}
None of the strings should be passed merely by reference. Ideally they would all be passed by const reference.
Prefer ptr->second over (*ptr).second
Remove the memsets. In C++ the ideal thing to use is std::fill, but here there is no need anyway. You could use the following for zero initialisation if you wish:However even better that that, stringstreams are your friend :)Code:char buf[30] = {};
Another recommendation:The second const stops you doing nameList[i] = "Some Other String";Code:static const char * const nameList[] =
Well I appreciate all of the tips though I really didn't need them as I was keeping my primary goal in mind to demonstrate how the OP could solve both this (searching) and his other problem (sorting) by leveraging the STL. The rest is just window-dressing. I am surprised that I did not get the namespace nazis on me for 'polluting the namespace' by using namespace std.
Re: Copy ctor: true enough in this case but in general having a copy ctor is a good thing.
Re: Initialization ctor: again, true enough in this case but being in a habit of initializing your variables is s a good thing.
Re: memset vs std::fill: agreed although either will work just as well.
Re: const and the nameList: At this point I was just trying to get through the test code as quickly as possible.
Re: ptr-> vs (*ptr). : you say tomato, I say tomahto. One is not inherently more correct than the other.
Re: us of string streams: That did occur to me, it really did. The reason I did not use it over the more old-school sprintf() stuff is that I was trying to keep the OP in mind. Basically if he/she didn't know that std::map could be used in this manner, I didn't want to confuse him by adding more std:: stuff, hopefully so he could focus on the solution that I presented here. In other cases, stringstreams are indeed my friend :)
Re: getters and setters: This is the first time I have ever heard that they are bad for encapsulation when indeed that is what they facilitate. Care to back that statement up?
Re: getters and using const: agreed and in production code I do. Again for me this was an exercise to see how quickly I could generate a solution for his/her problem (while eating dinner and watching Fringe with the wife).
Alright, we have a new problem here...this works and everything that it needs to right now, but for some odd reason, the program keeps being unresponsive...could someone show me the way? :P I don't know why it is doing that.
Code:#include <cstdlib>
#include <iostream>
using namespace std;
class BaseAcc {
public:
// Contstructors
BaseAcc(string aNamein, int aNumberin, double aBalancein){
aName = aNamein;
aNumber = aNumberin;
aBalance = aBalancein;
}
BaseAcc(){
aName = "";
aNumber = 0;
aBalance = 0;
}
// Mutator functions
void setAccName(string aNamein) {
aName = aNamein;
}
void setAccNumber(int aNumberin) {
aNumber = aNumberin;
}
void setBalance(double aBalancein) {
aBalance = aBalancein;
}
// Accessor functions
string getName() {
return aName;
}
int getAccNum() {
return aNumber;
}
double getBalance() {
return aBalance;
}
// Member functions
string Account() {
cout << "-----Account-----" << endl;
cout << aName << endl;
cout << "Account Number: " << aNumber << endl;
cout << "Balance: " << "$" << aBalance << endl;
cout << "-----Account-----" << endl;
}
private:
// Member data
string aName;
int aNumber;
double aBalance;
};// End of BaseAcc
class Savings : public BaseAcc {
private:
double APR;
double DepositAmount, WithdrawAmount;
public:
Savings(double DepositAmountin, double WithdrawAmountin, double APRin){
DepositAmount = DepositAmountin;
WithdrawAmount = WithdrawAmountin;
APR = APRin;
}
Savings(){
DepositAmount = 0;
WithdrawAmount = 0;
APR = 0.04;
}
void Deposit() {
cout << "Amount to deposit: ";
}
};
int main(int argc, char *argv[])
{
BaseAcc bob;
bob.setAccName("Bob");
bob.setAccNumber(559598);
bob.setBalance(44000);
cout << bob.Account() << endl;
system("PAUSE");
return EXIT_SUCCESS;
}
Where does yours stop reacting to input? system("PAUSE") does nothing for non-Windows platforms which put this outside of the amount of work I want to put into the solution but knowing which line it stops on could be all the clues we need to solve this.