Adding Objects from a Class to another Class - c++

INPUT STDIN -> <street> <city> <house_number> <number of objects of house> <object1> <price1> .......<object-n> <price-n> (until EOF)
I need to use the "add" method in the "House" Class.
objective: adding the specific n objects of each House in "House" class
This is what i did since now:
#include <iostream>
#include <utility>
#include<vector>
#include<string>
using namespace std;
class Object {
public:
string valuable;
float price;
public:
Object() : Object("",0) {}
Object(string v, float p) : valuable(std::move(v)), price(p) {}
string getValuable() {
return valuable;
}
float getPrice() {
return price;
}
};
class House{
public:
string street;
string city;
uint32_t number;
vector<Object>valuables;
public:
House(): House("","",0){}
House(string s,string c,uint32_t n): street(std::move(s)),city(std::move(c)),number(n){}
string getStreet() {
return street;
}
string getCity() {
return city;
}
uint32_t getNumber() {
return number;
}
uint32_t getValuablesSize() {
return valuables.size();
}
Object getValuable(uint32_t x){
return valuables[x];
}
void add(Object a){
valuables.emplace_back(a);
}
};
float getTotalPrice(House a) {
float sum = 0;
for (int i = 0; i < a.getValuablesSize(); i++) {
sum +=a.valuables[i].getPrice();
}
return sum;
}
int main() {
vector<Object>obj;
vector<House>house;
char object[30],street[30],city[30];
float price;
uint32_t house_number;
int n;
while(cin>>street>>city>>house_number>>n) {
house.emplace_back(string(street),string(city),house_number);
Object a;
for(int i=0;i<n;i++){
cin>>object>>price;
obj.emplace_back(object,price);
a.valuable=object;
a.price=price;
for(int k=0;k<house.size();k++)
house[k].add(a);
}
}
for(int i=0;i<obj.size();i++){
cout<<obj[i].getValuable()<<" "<<obj[i].getPrice()<<endl;
} // trying to print the object vector
for(int i=0;i<house.size();i++){ //trying to verify if i have the correct input
cout<<house[i].getStreet()<<" "<<house[i].getCity()<<" "<<house[i].getNumber()<<" ";
for(int j=0;j<house[i].getValuablesSize();j++) {
cout << house[i].valuables[j].valuable<< " "<<house[i].valuables[j].price<<" ";
}
cout<<endl;
}
return 0;
}
That's what i think:
-when i read <house_number> ,read the objects and prices and then the add method should be used in order to have the vector<Object>valuables usable.
It's necesarly to check if the input is stored corectly in the class "House", in order to continue summing the objects in every house

With the statements
for(int k=0;k<house.size();k++)
house[k].add(a);
you add the current "valuable" object to every house that has been created thus far.
I suggest you instead create the house object separately, then add the valuable objects to the current house, and after that add the house to your collection of houses.
Perhaps something like:
std::string street;
std::string city;
unsigned house_number;
unsigned n;
while(std::cin >> street >> city >> house_number >> n) {
House current_house(street, city, house_number);
std::string object;
float price;
for(int i = 0; i < n && std::cin >> object >> price; ++i) {
Object a(object, price)
current_house.add(a);
}
house.push_back(current_house);
}

Related

How do you pass struct parameters in a method

I did not find anywhere the answer for my issue, I am pretty new to OOP so please give me mercy.
Okay so I have the following code:
class Group
{
public:
struct Student
{
char name[40],
int grades[5]};
}
Student s[10];
.....
private: double med(???)
{
.....
}
}
So where's ??? I want to have as parameters the grades of an individual student and return the average of them. I don't know how should I declare them, I tried in many ways but I get errors everytime.
Ty a lot
So you have a struct with parameters, like:
struct Student
{
std::string name;
std::array<int, 5> grades;
};
Since this is tagged C++, I chose to use a std::array<int, 5> rather than int[5].
In my opinion, Student should not be necessarily inside of Group, but I guess that's opinion based.
Now you have a Group which contains students:
struct Group
{
Group(std::vector<Student> students) :
_students{ std::move(students) }
{}
double med(/* ... */) const
{ /* ... */ }
std::vector<Student> _students; // C++ -> use std::vector
};
Say you want to pass the grades of a particular student as parameter of the function med, than you would simply do:
double Group::med(const std::array<int, 5>& grades) const
{ /* sum up grades, divide by 5, and return the result */ }
And you would call this function as follows:
Student paul{"Paul", {1,2,3,4,5}};
Group group({paul});
group.med(paul.grades);
As suggested in the comments, you might want to pass the name of a student instead of his/her grades:
double med(const std::string& name)
{
// find student
auto it = std::find_if(_students.begin(), _students.end(), [&name](const Student& student)
{
return student.name == name;
});
// if no student by that name
if (it == _students.end())
return -1.0;
// else
int sum{ 0 };
for (const auto& grade : it->grades)
{
sum += grade;
}
return static_cast<double>(sum)/(it->grades.size());
}
Here is a discussion about good C++ books.
Tyr this code Contains four avg() functions all are same but differ in how the functions are called.
#include<iostream>
#include<string.h>
using namespace std;
class Group
{
public:
struct Student
{
char name[40];
int grades[5];
}student;
double avg()
{
double sum=0;
for(int i=0;i<5;i++)
sum+=student.grades[i];
return (sum/5);
}
};
double avg(int *grade)
{
double sum=0;
for(int i=0;i<5;i++)
sum+=grade[i];
return (sum/5);
}
double avg(Group::Student stduent)
{
double sum=0;
for(int i=0;i<5;i++)
sum+=stduent.grades[i];
return (sum/5);
}
double avg(Group group)
{
double sum=0;
for(int i=0;i<5;i++)
sum+=group.student.grades[i];
return (sum/5);
}
int main()
{
Group group1;
strcpy(group1.student.name,"MyName");
for(int i=0;i<5;i++)
group1.student.grades[i]=5;
cout<<"Name:"<<group1.student.name<<endl;
cout<<"Avg:"<<avg(group1.student.grades)<<" "<<avg(group1.student)<<" "<<avg(group1)<<" "<<group1.avg();
return 0;
}
Output:
Name:MyName
Avg:5 5 5 5
Process returned 0 (0x0) execution time : 0.379 s
Press any key to continue.
You may leave the structure unnamed like
struct
{
char name[40];
int grades[5];
}student;
If you delete the function and function call from the code
double avg(Group::Student stduent)
{
double sum=0;
for(int i=0;i<5;i++)
sum+=stduent.grades[i];
return (sum/5);
}

C++ Block type is valid error

My code:
class item{
int plu;
char * name;
double price;
double inv;
public:
void setPLU(int g) { plu = g; }
void setName(const char * p) { name = copyStr(p); }
void setPrice(double g) { price = g; }
void setInventory(double g) { inv = g; }
int getPlu() { return plu; }
char*getName() { return name; }
double getPrice() { return price; }
double getInventory() { return inv; }
item(){
name = nullptr;
}
~item(){
delete name;
}
};
class puItem : public item{
bool type;
public:
void setType(bool g) { type = g; }
bool getType() { return type; }
};
class nodeU{
puItem fruit;
nodeU * next;
public:
nodeU * getNext(){ return next; }
puItem getFruit(){ return fruit; }
void setNext(nodeU * g){ next = g; }
void setFruit(puItem g) { fruit = g; }
nodeU(){
next = nullptr;
}
};
class linkedListU{
nodeU * head;
int size;
public:
nodeU * getHead(){
return head;
}
void setHead(nodeU * n){
head = n;
}
//Append
void appendNode(nodeU * n){
if (head == nullptr){
head = n;
}
else{
nodeU * iter = head;
while (iter){
iter = iter->getNext();
}
iter->setNext(n);
}
size++;
}
linkedListU()
{
head = nullptr;
size = 0;
}
puItem * pluLookup(int g){
nodeU * iter = head;
while (iter)
{
if ((iter->getFruit()).getPlu() == g)
return &(iter->getFruit());
iter = iter->getNext();
}
return nullptr;
}
};
void checkout(linkedListP, linkedListU);
linkedListU unitList;
linkedListP poundList;
nodeU * inputU=new nodeU;
int main()
{
ifstream infile;
ofstream outfile;
int tempPlu;
string tempName;
bool tempType;
double tempPrice, tempInv;
infile.open("products.txt");
puItem unit;
infile >> tempPlu;
if (!infile.good())
{
infile.clear();
infile.ignore();
}
infile >> tempName;
if (!infile.good())
{
infile.clear();
infile.ignore();
}
infile >> tempType;
if (!infile.good())
{
infile.clear();
infile.ignore();
}
infile >> tempPrice;
if (!infile.good())
{
infile.clear();
infile.ignore();
}
infile >> tempInv;
if (!infile.good())
{
infile.clear();
infile.ignore();
}
if (tempType == 0){
unit.setInventory(tempInv);
unit.setName(tempName.c_str());
unit.setPLU(tempPlu);
unit.setType(tempType);
unit.setPrice(tempPrice);
inputU->setFruit(unit);
unitList.appendNode(inputU);
}
checkout(poundList, unitList);
system("pause");
return 0;
}
void checkout(linkedListU p){
int key = -10;
puItem * searchU=nullptr;
int counter = 0;
double total = 0;
double amount;
cout << "Enter the plu for the item you want or enter 0 to exit: ";
cin >> key;
while (key < 0)
{
cout << "\nInvalid input please re enter: ";
cin >> k
searchU = p.pluLookup(key);
}
while (key)
{
When it gets to the plu lookup it throws the error and I cant seem to find out why.
I know that that is error is for deleting something twice but I couldnt find any instance of that in this code.
There are a lot of issues with your code, where most of them are due to your classes not being safely copyable (they lack a user-defined copy constructor and assignment operator, and destructor). Please see the rule of 3:
What is The Rule of Three?
Your checkout function has the following prototype:
void checkout(linkedListU p){
This means that you are passing linkedListU by value. Since linkedListU failed to follow the rule of 3, when you pass this type by value, you will invoke the compiler-defined copy constructor which only makes shallow copies, thus causing undefined behavior.
Your linked list class has members that are pointers to dynamically allocated memory, and they need to be properly handled by following the Rule of 3 at the link above. Since you failed to do that, passing by value cannot be done safely.
To address this issue, you can pass the linked list by reference, not by value:
void checkout(linkedListU& p){
This will stop the copying to occur, but it really doesn't address the underlying issue of the rule of 3 not being used in any of your classes.
For example, your puItem is being returned by value in the puItem::getFruit function, and also passed by value in the puItem::setFruit function. Calling these functions without any changes also invokes undefined behavior due to these classes not being safely copyable (also due to you using members that point to dynamically allocated memory).
To address this issue, the first thing you can do is change the base class item to use std::string name; instead of char *name;. This makes item now a copyable class without having to write user-defined copy operations or to have a destructor that needs to delete name;. The reason is that once std::string is used, all of your members in item can be copied without user intervention. The compiler default version would suffice.
class item
{
int plu;
std::string name;
double price;
double inv;
public:
void setPLU(int g) { plu = g; }
void setName(const char * p) { name = p; }
void setPrice(double g) { price = g; }
void setInventory(double g) { inv = g; }
int getPlu() { return plu; }
std::string getName() { return name; }
double getPrice() { return price; }
double getInventory() { return inv; }
};
Note that there is no need for a destructor. Now, when puItem is derived from this class, puItem is also now safely copyable, and you can pass and return puItem by value:
class puItem : public item
{
bool type;
public:
void setType(bool g) { type = g; }
bool getType() { return type; }
};
Making these changes totally eliminates usage of these classes from causing heap errors, double deletion errors, or memory leaks. Any further errors concerning memory issues are now focused on your linked list class (which uses dynamically allocated memory). So the least, the problem is narrowed down by a huge amount and is now focused.

Is it possible to set the class functions in the two functions?

I don't know how to call my class functions into printData(Testscore&) and readData(TestScore).
Also, could someone tell me why my Average() isn't being called to the main? I just learned about using static member variables and static member functions and was wondering if I am using them incorrectly.
The readData function:
Does not use copy constructor.
Reads all instance variables like the student's names and all their
grades.
Uses functions to store the variables, name, element of each grade of array pointed to private pquiz, and static member
grades of how many grades to read.
The printData function:
Writes the name and average grade of the quizzes.
Uses copy constructor.
This is my program so far:
#include <iostream>
#include <string>
using namespace std;
class TestScore {
private:
static int grades;
string name;
double *pquiz;
double average;
public:
TestScore();
~TestScore();
void setName(string);
static void setGrades(int);
void setPquiz(double *);
void setAverage(double);
string getName();
static int getGrades();
double getPquiz();
void readData(TestScore &);
void printData(TestScore);
double Average(double *, int);
static void Grade(int);
};
TestScore::TestScore() {
name="";
pquiz=new double[grades];
average=0;
}
void TestScore::setName(string name1) {
if(name1!="1") {
name=name1;
}
}
void TestScore::setPquiz(double *pquiz1) {
if(pquiz>=0) {
pquiz=pquiz1;
}
}
void TestScore::setGrades(int grades1) {
if(grades1>=0) {
grades=grades1;
}
}
void TestScore::setAverage(double average1) {
if(average1>=0) {
average=average1;
}
}
string TestScore::getName() {
return name;
}
int TestScore::getGrades() {
return grades;
}
double TestScore::getPquiz() {
return *pquiz;
}
double Average(double *pquiz, int grade) {
int count;
double total=0;
double average=0;
for(count=0; count<grade; count++) {
total+=pquiz[count];
}
average=total/grade;
return average;
}
void readData(TestScore&) {
}
void printData(TestScore) {
}
TestScore::~TestScore() {
delete [] pquiz;
pquiz=0;
}
int TestScore::grades=0;
void TestScore::Grade(int a) {
grades+=a;
}
int main() {
const int grades = 3;
const int students = 4;
TestScore exam;
string student;
int grade;
double *pquiz;
double average;
for(int i=0; i<students; i++) {
cout<<"Student "<<(i+1)<<": ";
cin>>student;
exam.setName(student);
cout<<endl;
for(int count=0; count<grades; count++) {
cout<<"Quiz "<<(count+1)<<": ";
cin>>pquiz[count];
exam.setPquiz(pquiz);
exam.getPquiz();
while(pquiz[count]<0) {
cout<<"Error, invalid test score, please try again."<<endl;
cout<<"Quiz "<<(count+1)<<": ";
cin>>pquiz[count];
}
}
exam.setAverage(average);
cout<<exam.getName()<<" average is "<<Average(pquiz, grade)<<endl<<endl;
}
readData(exam);
printData(exam);
return 0;
}
Don't use static anywhere, at least not for now. You have too many variables of the same name, scattered all over the place. Try to clean them up.
TestScore::TestScore()
{
name = "";
//pquiz = new double[grades];//#grades is undefined
pquiz = NULL;
average = 0;
}
grades is not defined yet, it could be zero, or it could be -817. You should just remove that line, or you can put something like pquiz = new double[10] that's if you are sure the number of quiz will not exceed 10.
TestScore::~TestScore()
{
if (pquiz) delete[] pquiz;
pquiz = NULL;
}
delete pquiz only if it is not NULL
int main() {
const int grades = 3;
const int students = 4;
TestScore exam;
string student;
int grade;
double *pquiz;
...
This is a different pquiz, it is a pointer which points to nothing, it doesn't really exist, you can't use it like that.

C++ Function causing app to crash and not working properly

A problem has come up in my application where my PrintAll function will not work correctly and only ultimately crash my application. My app is supposed to read strings from a file and insert them into an array. The problem is it is reading incorrectly and will ultimately crash my app. Here is where I think the problem lies:
int main()
{
LoadMovies();
MovieList *movies = LoadMovies();
//movies->MovieList::PrintAll();
// // test methods for the Movie and MovieList classes
//PrintAllMoviesMadeInYear(movies, 1984);
//PrintAllMoviesWithStartLetter(movies, 'B');
//PrintAllTopNMovies(movies, 5);
//delete movies;
return 0;
}
MovieList* LoadMovies()
{
vector<string> movies;
ReadMovieFile(movies);
MovieList ml = MovieList(movies.size());
string name;
int year;
double rating;
int votes;
for (int i = 0; i < movies.size(); i++)
{
istringstream input_string(movies[i]);
getline(input_string, name, '\t');
input_string >> year >> rating >> votes;
Movie movie (name, year, votes, rating);
ml.Add(movie);
}
ml.PrintAll();
}
Complete Example:
/*
* File: MovieStatsProgram.cpp
* Author:
* Date:
* ===============================================================
* This is a console app to test the Movie and MovieList classes.
*
* TODO:
*
* You need to finish the implementation of the loadMovies method
* to create and initialize the MovieList object.
*
* You also need to create three static methods:
*
* PrintAllMoviesMadeInYear - it will print all the movies made in a
* given year once sort in alphabetical order and once sorted by the number
* of votes with the movie with the most number of votes printed first.
*
* PrintAllMoviesWithStartLetter - it will print all the movies started with
* a given letter sorted in alphabetical order
*
* PrintAllTopNMovies - it will display the top N movies based on the number of
* votes
*/
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <iomanip>
#include <fstream>
using namespace std;
class Movie {
public:
Movie();
Movie(string n, int y, int v, double r);
string get_name();
void set_name(string n);
int get_year();
void set_year(int y);
int get_votes();
void set_votes(int v);
double get_rating();
void set_rating(double r);
string PrintMovie();
private:
string name;
int year_made;
int votes;
double rating;
};
Movie::Movie() {
name = "null";
year_made = 0;
votes = 0;
rating = 0.0;
}
Movie::Movie(string n, int y, int v, double r) {
name = n;
year_made = y;
votes = v;
rating = r;
}
string Movie::get_name() {
return name;
}
void Movie::set_name(string n) {
name = n;
}
int Movie::get_year() {
return year_made;
}
void Movie::set_year(int y) {
year_made = y;
}
int Movie::get_votes() {
return votes;
}
void Movie::set_votes(int v) {
votes = v;
}
double Movie::get_rating() {
return rating;
}
void Movie::set_rating(double r) {
rating = r;
}
string Movie::PrintMovie() {
cout << fixed << setprecision(1) << rating << "\t\t" << votes << "\t\t" << "(" <<
year_made << ")" << "\t" << name << endl;
}
class MovieList {
public:
MovieList(int size);
~MovieList();
int Length();
bool IsFull();
void Add(Movie const& m);
string PrintAll();
private:
Movie* movies;
int last_movie_index;
int movies_size;
int movie_count = 0;
};
MovieList::MovieList(int size) {
movies_size = size;
movies = new Movie[movies_size];
last_movie_index = -1;
}
MovieList::~MovieList() {
delete [] movies;
}
int MovieList::Length() {
return last_movie_index;
}
bool MovieList::IsFull() {
return last_movie_index == movies_size;
}
void MovieList::Add(Movie const& m)
{
if (IsFull()) {
cout << "Cannot add movie, list is full" << endl;
return;
}
++last_movie_index;
movies[last_movie_index] = m;
}
string MovieList::PrintAll() {
for (int i = 0; i < last_movie_index; i++) {
movies[last_movie_index].Movie::PrintMovie();
//cout << movies[last_movie_index] << endl;
}
}
void ReadMovieFile(vector<string> &movies);
MovieList* LoadMovies();
enum MovieSortOrder
{
BY_YEAR = 0,
BY_NAME = 1,
BY_VOTES = 2
};
int main()
{
LoadMovies();
MovieList *movies = LoadMovies();
//movies->MovieList::PrintAll();
// // test methods for the Movie and MovieList classes
//PrintAllMoviesMadeInYear(movies, 1984);
//PrintAllMoviesWithStartLetter(movies, 'B');
//PrintAllTopNMovies(movies, 5);
//delete movies;
return 0;
}
MovieList* LoadMovies()
{
vector<string> movies;
ReadMovieFile(movies);
MovieList ml = MovieList(movies.size());
string name;
int year;
double rating;
int votes;
for (int i = 0; i < movies.size(); i++)
{
istringstream input_string(movies[i]);
getline(input_string, name, '\t');
input_string >> year >> rating >> votes;
Movie movie (name, year, votes, rating);
ml.Add(movie);
}
ml.PrintAll();
}
void ReadMovieFile(vector<string> &movies)
{
ifstream instream;
instream.open("imdbtop250.txt");
if (instream.fail())
{
cout << "Error opening imdbtop250.txt" << endl;
exit(1);
}
while (!instream.eof())
{
string movie;
getline(instream, movie);
movies.push_back(movie);
}
instream.close();
}
When I use MovieList::PrintAll in the main function, my function just crashes, and when I put it in the LoadMovies function, it will read and add data incorrectly before crashing. The size of the list is 251 and the application will just read the same data 251 times.
You have a two part problem:
1: As Brad S stated, your function returns nothing. This is a no-no.
MovieList* LoadMovies()
{
MovieList ml = MovieList(movies.size());
// Your function returns a pointer to a MovieList, so...
return &ml;
}
So, problem #2 is that you're going to return a pointer to something you created on the stack in your function. When you try to access it outside of your function, you'll run into undefined behavior.
Option 1:
MovieList* ml = new MovieList( movies.size() );
return ml;
You now need to delete ml when you're done w/ it.
Option 2:
Change your function to return a non-pointer... then you don't have the hassle of managing the memory.
EDIT: Try this
int main()
{
// Don't need this
// LoadMovies();
MovieList *movies = LoadMovies();
// Uncommented this
delete movies;
return 0;
}
MovieList* LoadMovies()
{
vector<string> movies;
ReadMovieFile(movies);
// CHANGE
MovieList* ml = new MovieList(movies.size());
// CHANGE
string name;
int year;
double rating;
int votes;
for (int i = 0; i < movies.size(); i++)
{
istringstream input_string(movies[i]);
getline(input_string, name, '\t');
input_string >> year >> rating >> votes;
Movie movie (name, year, votes, rating);
ml.Add(movie);
}
ml.PrintAll();
// CHANGE
return ml;
}
Your MovieList class has a fundamental problem. This comes to light on this line:
MovieList ml = MovieList(movies.size());
Your MovieList class has a member that is a pointer to dynamically allocated memory. Once you have this, you have to manage copying and assignment by creating a user-defined copy constructor and assignment operator.
The easiest fix for this is to use std::vector<Movie> instead of Movie * as a member variable of MovieList. Then copy-assignment comes for free and you don't need to implement further functions.
However, if you can't use std::vector for some reason, the following functions can be added:
class MovieList {
public:
//...
MovieList(const MovieList& m);
MovieList& operator=(MovieList m);
//...
};
#include <algorithm>
//...
// copy constructor
MovieList::MovieList(const MoveList& m) {
movies_size = m.size;
movie_count = m.movie.count;
last_movie_index = m.last_movie_index;
movies = new Movie[movies_size];
for (int i = 0; i < movies_size; ++i)
movies[i] = m.movies[i];
}
//...
// assignment operator
MovieList& MovieList::operator=(MoveList m) {
std::swap(m.movie_size, movie_size);
std::swap(m.last_movie_index, last_movie_index);
std::swap(m.movies, movies);
std::swap(m.movie_count, moviE_count);
return *this;
}
The easiest way to describe this to you is not to describe what these do. The best thing for you is to use your debugger and put a breakpoint in any of these functions and step through the code. When you hit the line I mentioned above, you will more than likely see that the copy constructor function is called -- then you can see it in action as to what it is doing.
The assignment operator is the function that's called when you assign an existing MovieList to another MovieList. It's implemented via the copy/swap idiom. This relies on a working copy constructor (provided above), and a destructor (which you already provided in your code). It works by creating a temporary MovieList, and swapping out the internals of the current MovieList with the temporary MovieList. There are many threads on SO as to how this works.
As to the reason why you need these functions above is that without the above functions, the line:
MovieList ml = MovieList(movies.size());
will create two MovieList objects, one temporary and one non-temporary, however the movies pointer for both will be pointing to the same memory. When the temporary is destroyed, the destructor is called, thus deleting the memory pointed to by movies. Now you have m1 pointing to memory that has gone up in smoke. Bad news when you try to use m1.
The user-defined copy and assignment functions above properly copy the object so that you get two distinct memory allocations for movies, so that when the destructor is called, the memory deleted will be unique to that object.
Again, all of this would be alleviated if you used std::vector and forego having to write copy ctor/assignment operators.

how do i create an array where each element in the array, of size 10, is pointing to an object, in C++?

for example lets have a class or struct name Employee with two constructors, a default constructor and a constructor with parameters two strings and an int. why doesn't the following code work?
Employee *employees = (employee*) malloc(sizeof(Employee)*10);
let's say we have an array, size 10, of type string for first name, last name, and one of type int for salary. how to initialize the data members of each object class using the constructor with the parameters?
for (int i = 0; i < 10; i++)
{
employees[i] = employee(firstname[i], lastname[i], salary[i]);
}
I've been trying to do this for a few days now but wasn't successful. Also, can anyone tell how to do this using c++'s new and delete operator? and also is there a way this can be done using vectors?
Thank you
header file
class employee{
std::string firstname;
std::string lastname;
int salary;
public:
employee(std::string, std::string , int);
employee();
void setFirst(std::string);
void setLast(std::string);
void setSalary(int);
std::string getFirst();
std::string getLast();
int getSalary();
};
employee::employee(std::string x, std::string y, int z)
{
setFirst(x);
setLast(y);
setSalary(z);
}
void employee::setFirst(std::string x)
{
firstname = x;
}
void employee::setLast(std::string y)
{
lastname = y;
}
void employee::setSalary(int z)
{
salary = z > 0 ? z : 0;
}
std::string employee::getFirst()
{
return firstname;
}
std::string employee::getLast()
{
return lastname;
}
int employee::getSalary()
{
return salary;
}
.cpp file
#define MAX 20
using namespace std;
int main(int argc, char* argv[])
{
int n = 1;
cout << "number of employees: ";
cin >> n;
string firstname[MAX];
string lastname[MAX];
double salary[MAX];
float raise[MAX];
for (int i = 0; i < n; i++)
{
cout << "Employee " << i + 1 <<endl;
cout << "-----------\n";
cout << "First Name: ";
cin >> firstname[i];
cout << "Last Name: ";
cin >> lastname[i];
cout << "Monthly Salary: ";
cin >> salary[i];
salary[i] *= 12;
cout <<"Yearly percentage raise (e.g 10% or 0%): ";
scanf("%f%%", &raise[i]);
salary[i] *= (((raise[i])/100.00) + 1);
puts("\n");
}
employee *employees = (employee*) malloc(sizeof(employee)*10);
for (int i = 0; i < n; i++)
{
employees[i] = employee(firstname[i], lastname[i], salary[i]);
}
cout << "TESING USING GET FUNCTIONS" << endl;
cout << "---------------------------\n\n";
for (int i = 0; i < n; i++)
{
cout << "Employee " <<i +1<< endl;
cout <<"-----------\n";
printf("First Name: %s", employees[i].getFirst().c_str());
printf("\nLast Name: %s",employees[i].getLast().c_str());
printf("\nYearly Salary: %d\n\n", employees[i].getSalary());
}
}
If you have an array of Employee instances and Employee is not POD (http://en.wikipedia.org/wiki/POD) you need to allocate memory from the stack using the operator new:
Employee* employees = new Employee[10];
And for having this working:
for (int i = 0; i < 10; i++)
{
employees[i] = Employee(firstname[i], lastname[i], age[i]);
}
you need to implement the operator= in your Employee class:
Employee& operator=(const Employee& src)
{
_firstname = src._firstname;
_lastname = src._lastname;
_age = src._age;
return *this;
}
If this looks like your Employee class:
class Employee
{
std::string first_name;
std::string last_name;
// other members and functions ...
};
Then using malloc() to create 10 of these is a complete and utter failure. The reason why is that yes, you allocated memory using malloc(), but that's all you did. You didn't construct 10 Employee objects. Those std::string members need to be constructed, not merely have memory allocated. So with that call to malloc() you have 10 fake Employees that were "created", and as soon as you attempt to do anything with one of them, then boom goes your program.
Do research on POD and non-POD types. You cannot treat non-POD types (as the class above is non-POD) as you would a POD type. For a non-POD type, the instance must be "officially" constructed, (the constructor must be invoked).
On the other hand, malloc() knows nothing concerning C++ and what is required to create an object correctly via construction. All malloc (and calloc, and realloc) knows is to allocate bytes and return a pointer to the allocated space.
Use a vector instead, it's resizable, it's easier to manage, and as Grady stated in his comment, it's also generally not good practice to use malloc in C++ code (although it's possible). Maybe do something that looks like this:
#include <vector>
...
int size = 10;
std::vector<Employee *> employees;
for(int i = 0; i < size; i++)
{
//as far as pulling in your data, that depends on where it's coming from
Employee *temp = new Employee(...);
employees.push_back(temp);
}
I'm rusty on my C++ but this should work.
Try this way:
#include <iostream>
class Employee
{
std::string m_firstname;
std::string m_lastname;
int m_age;
public:
Employee()
{
m_firstname=m_lastname="";
m_age=0;
}
void setFirstName(std::string firstname)
{
m_firstname=firstname;
}
void setLastName(std::string lastname)
{
m_lastname=lastname;
}
void setAge(int age)
{
m_age=age;
}
void displayEmp()
{
std::cout<<m_firstname;
std::cout<<m_lastname;
std::cout<<m_age;
}
};
int main()
{
std::string fname;
std::string lname;
int age;
Employee *employee = new Employee[10];
Employee *employeeptr=employee;
for(int i=0;i<10;i++)
{
std::cin>>fname;
std::cin>>lname;
std::cin>>age;
employeeptr->setFirstName(fname);
employeeptr->setLastName(lname);
employeeptr->setAge(age);
employeeptr++;
}
employeeptr=employee;
for(int i=0;i<10;i++)
{
employeeptr->displayEmp();
employeeptr++;
}
delete []employee;
return 0;
}