I have a struct list, a class castomer. I want to store my castomer to the list. For that I am creating a castomer each time and I strore them to a list table. There are no errors except that the program crashes each time I try to store a castomer into my table.
I have this list and class:
class castomer{
private:
string name;
string lastname;
int number;
double time;
public:
void setAll(string,string,int,double);
int numberR(){return number;}
double timeR(){return time;}
void displayAll();
};
struct node {
castomer person;
struct node *next;
};
This function for adding castomer:
void add(clock_t *start,struct node *table[])
{
*start = clock();
double time=(double)*start;
int i=0;
while(table[i]!=NULL)
{
i++;
}
if(i > 24)
cout << "We are not able to add another castomer becase we are full please wait for ont to go "<<endl;
else{
castomer c1;
cout<<i;
cout<< "Give me the castomers name and lastname :";
string temp1,temp2;
cin>>temp1;
cin>>temp2;
c1.setAll(temp1,temp2,i,time);
table[i]->person=c1;//my program crases here anyone knows why?
}
}
ps: In my main the table[] looks like this struct node * table[25];
struct node* table[25]
This is declaring table to be an array of 25 pointers. You have to allocate memory for each of these pointers which from looking at your code is missing.
After your while-loop, table[i] will be NULL.
table[i]->person = c1; // Your program crashes here because of that.
Using your code as it is, you should do
table[i] = new node;
table[i]->person = c1;
But the code looks very strange, like you want to implement a linked list (the node structure) but are sticking to using arrays for some reason.
If you're aiming for a linked list, you need to rethink a lot of your code.
If you're not, you can lose the node type completely.
Since you are using (or trying to use) C++ I will make mention of a few things you can do to improve your code and make your own life easier.
In C++ you can define constructors for initializing objects.
Your function setAll is a bad practice. You don't really want to change all data of a person after you have created. You just want to initialize the data at creation time. Well use constructors.
You don't need pointers
For what you want to do you don't need complicate the code using pointers you could pass the arguments by reference.
You are using C++, use STL
Specifically vector I guarantee it, will help you.
Use cout << for displaying yuor object
you could add a friend ostream& operator<< function to your class in order to be able to write code like:
Customer a;
cout << a << endl;
A complete example:
#include <iostream>
#include <vector>
#include <ctime>
#include <string>
using namespace std;
class Customer
{
public:
Customer(){} // default constructor.
Customer(string pname, string plastname): name(pname), lastname(plastname)
{
id = ++idgen; // Set an id number.
time = (double)clock(); // initialize time.
}
int getId() {return id;} // former numberR().
double getTime() {return time;} // former timeR().
friend ostream& operator<<(ostream &out, Customer obj)
{out << obj.name << " " << obj.lastname << ". " << "Id: " << obj.id << " Time: " << obj.time;}
private:
static int idgen; // static values are a good way for keep some sort of id.
int id; // former member: number.
double time; // Why don't use clock_t directly?
string name, lastname;
};
int Customer::idgen = 0; // Initialize static variable.
int main()
{
int const MAX_NUMBER_PERSONS = 2;
std::vector<Customer> customer_list;
string name, lastname;
while (customer_list.size() < MAX_NUMBER_PERSONS)
{
cout << "Give me the castomers name and lastname <name> <lastname>:";
cin >> name >> lastname;
customer_list.push_back(Customer(name, lastname));
}
for (auto &x: customer_list) // If you're learnign C++ its a good moment for search
{ // for c++11 doc.
cout << x << endl;
}
return 0;
}
Related
I'm working on a small program for school that is an intro to using objects. I'm new to class and still trying to wrap my head around it. I'm not really asking how to fix my code, I'm just looking to get a better understanding of things.
In the code below, in my implementation file student.cpp, there is a function called isLessThanByID. It is supposed to compare the current object to the object being passed in. I'm having a hard time understanding what the "current" object is and how the function knows what the current object is. There are two objects s1 and s2. My instructor says assume s1 is the current object and s2 is the passed in object. I asked my instructor how the function knows about s1 if it's not being passed in and she said it's because s1 is an object of class and the function is a class member. This made sense for a minute and then I thought on it more and realized I'm still confused. If s1 doesn't need to be passed in, then why does s2 need to be passed in?
I'm getting an error on that function that says
"error: extra qualification ‘Student::’ on member ‘isLessThanByID’ [-fpermissive] bool Student::isLessThanByID(const Student &s2) const;".
I'm not sure what it means by "extra qualification".
I really appreciate any help in wrapping my head around this! Thank you!
Here's my code:
app.cpp
const double minGpaForHonor = 3.75;
int main()
{
Student s1("G10", 3.9);
Student s2("G20", 3.5);
s1.print();
s2.print();
//write code to test Student::isLessThanByID
s1.isLessThanByID(s2);
if (true)
cout << "s2 is less than s1" << endl;
else
cout << "s1 is less than s2" << endl;
//write code to test Student::qualifyForHonor
s1.qualifyForHonor(minGpaForHonor);
if (true)
cout << "s1 qualifies for honors" << endl;
s2.qualifyForHonor(minGpaForHonor);
if (true)
cout << "s2 qualifies for honors" << endl;
return 0;
}
student.cpp - implementation file
//implement the required 3 functions here
Student::Student(const char initId[], double gpa)
{
//initialize ID
for (int i = 0; i < strlen(initId); i++)
{
id[i] = initId[i];
}
gpa = gpa;
//initialize gpa
}
bool Student::isLessThanByID(const Student &s2) const
{
//compare current student object to passed in object}
if (strcmp(s1.id, s2.id) < 0)
return true;
else
return false;
}
bool Student::qualifyForHonor(double minGpaForHonor) const
{
//return true if gpa is higher than "minGpaForHonor"
if(gpa >= minGpaForHonor)
return true;
}
void Student::print() const
{
cout << id << '\t' << gpa << endl;
}
student.h- header file
#define STUDENT_H
#include <iostream>
#include <cstring>
using namespace std;
class Student
{
public:
Student(const char initId[], double gpa);
bool Student::isLessThanByID(const Student &s2) const;
bool qualifyForHonor(double minGpaForHonor) const;
void print()const;
private:
const static int MAX_CHAR = 100;
char id[MAX_CHAR];
double gpa;
};
#endif
How the function knows about s1 if it's not being passed in?
Each member function has an implicit (hidden) first parameter that passes a pointer to the "current" object (available inside that function as this). Imagine that
bool Student::isLessThanByID(const Student &s2) const
{
return strcmp( /* s1. */ id, s2.id) < 0;
}
is actually something like
bool Student::isLessThanByID(const Student* this, const Student &s2) // not real code
{
return strcmp(this->id, s2.id);
}
Similarly, imagine that the call
s1.isLessThanByID(s2);
is actually
Student::isLessThanByID(&s1, s2); // not real code
Note that there is no s1 inside isLessThanByID available. That object exist outside of the function definition, so, you cannot use it inside. Instead of s1.id just write this->id, or, shortly, just id (which will be interpreted as this->id implicitly in your case).
I have been trying to do debug this for a long time using visual studio debugger but I can't figure out why my function emp.setHoursWorked(hWorked); in recordHoursWorkedForEmployee only seems to be update numOfHoursWorked while in recordHoursWorkedForEmployee, as soon the program exits the function the numOfHoursWorked of all Employees in the vector go back to 0. Below is the code in question. Any help would be appreciated.
#ifndef PAYROLLSYSTEM
#define PAYROLLSYSTEM
#include "Employee.h"
#include "Paycheck.h"
#include <string>
#include <vector>
using namespace std;
class PayRollSystem
{
public:
//custom constructor gets company name
PayRollSystem(string);
void createEmployee(string, string,string, double);
void removeEmployee(string);
void recordHoursWorkedForEmployee(string);
void issuePaychecks();
private:
string companyName;
vector<Employee> companyEmployees;
};
#endif
void PayRollSystem::createEmployee(string empId, string fName, string lName, double hWage)
{
Employee temEmp = Employee(empId, fName, lName, hWage);
companyEmployees.push_back(temEmp);
}
void PayRollSystem::recordHoursWorkedForEmployee(string empId)
{
for (Employee emp : companyEmployees)
{
if (emp.getEmployeeId() == empId)
{
int hWorked = 0;
cout << "What are the hours the worked for " + emp.getEmployeeId() + " during current pay period?" << endl;
cin >> hWorked;
//TODO: For some reason this line is not updating the hours worked. Must fix!
emp.setHoursWorked(hWorked);
cout << "Hours for " + emp.getEmployeeId() + " have been changed to " << emp.getHoursWorked() << endl;
}
}
}
I excluded the header file here in order to not paste too many things not relevant to the problem i'm facing, only implementations of member functions relevant to the problem provided
//Overloaded constructor to be used with PayRollSystem
Employee::Employee(string empId, string fName, string lName, double hWage)
{
employeeId = empId;
firstName = fName;
lastName = lName;
hourlyWage = hWage;
numOfHoursWorked = 0;
}
void Employee::setHoursWorked(int hWorked)
{
if (hWorked >= 0)
numOfHoursWorked = hWorked;
else
{
cout << "Invalid number of hours worked." << endl;
exit(EXIT_FAILURE);
}
}
string Employee::getEmployeeId() const
{
return employeeId;
}
This line makes a copy of each employee:
for (Employee emp : companyEmployees)
The variable emp is a copy of the object in the container. So if you update this you are only updating the copy. Each iteration you get a new value copied into emp but any changes are not reflected in the original object.
You probably meant:
for (Employee& emp : companyEmployees)
^^^
Here emp is a reference to the object inside the vector. If you modify this you are modifying the original value inside the vector.
I am trying to create a program that uses class, arrays, and functions to show information about two students(Name, id#, classes registered). The part I am struggling with is passing arrays to a function. How do I do that?
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;
class Student // Student class declaration.
{
private:
string name;
int id;
string classes;
int arraySize;
public:
void setName(string n)
{
name = n;
}
void setId(int i)
{
id = i;
}
void setClasses(string c, int num)
{
classes = c;
arraySize = num;
}
string getName()
{
return name;
}
int getId()
{
return id;
}
void getClasses()
{
for (int counter=0; counter <arraySize; counter++) {
cout << classes[counter] << endl;
}
}
};
int main()
{
//Student 1
string s1Name = "John Doe";
int s1Id = 51090210;
int const NUMCLASSES1 = 3;
string s1Classes[NUMCLASSES1] = {"C++","Intro to Theatre","Stagecraft"};
//Student 2
string s2Name = "Rick Harambe Sanchez";
int s2Id = 666123420;
int const NUMCLASSES2 = 2;
string s2Classes[NUMCLASSES2] = {"Intro to Rocket Science","Intermediate Acting"};
//
Student info;
info.setName(s1Name);
info.setId(s1Id);
//info.setClasses(s1Classes, NUMCLASSES1);
cout << "Here is Student #1's information:\n";
cout << "Name: " << info.getName() << endl;
cout << "ID: " << info.getId() << endl;
//cout << "Classes: " << info.getClasses() << endl;
info.setName(s2Name);
info.setId(s2Id);
// info.setClasses(s2Classes, NUMCLASSES1);
cout << "\n\nHere is student #2's information:\n";
cout << "Name: " << info.getName() << endl;
cout << "ID: " << info.getId() << endl;
//cout << "Classes: " << info.getClasses() << endl;
return 0;
}
The usual way to pass around variable-length lists in C++ is to use an std::vector. A vector is a single object that you can easily pass to a function, copying (or referencing) its contents. If you are familiar with Java, it's basically an ArrayList. Here is an example:
#include <vector>
#include <string>
using namespace std;
class foo {
private:
vector<string> myStrings;
public:
void setMyStrings(vector<string> vec) {
myStrings = vec;
}
}
//...
foo myObj;
vector<string> list = {"foo","bar","baz"};
myObj.setMyStrings(list);
If don't want to use the standard library though, you can pass an array C-style. This involves passing a pointer to the first element of the array, and the length of the array. Example:
void processStrings(string* arr, int len) {
for (int i = 0; i < len; i++) {
string str = arr[i];
//...
}
}
string array[] = {"foo","bar","baz"};
processStrings(array, 3); // you could also replace 3 with sizeof(array)
Passing raw arrays like this, especially if you wanted to then copy the array into an object, can be painful. Raw arrays in C & C++ are just pointers to the first element of the list. Unlike in languages like Java and JavaScript, they don't keep track of their length, and you can't just assign one array to another. An std::vector encapsulates the concept of a "list of things" and is generally more intuitive to use for that purpose.
Life lesson: use std::vector.
EDIT: See #nathanesau's answer for an example of using constructors to initialize objects more cleanly. (But don't copy-paste, write it up yourself! You'll learn a lot faster that way.)
You can pass array of any_data_type to function like this
void foo(data_type arr[]);
foo(arr); // If you just want to use the value of array
foo(&arr); // If you want to alter the value of array.
Use std::vector. Also, don't add functions you don't need. Here's an example of using std::vector
#include <string>
#include <iostream>
#include <vector>
using std::string;
using std::vector;
class Student // Student class declaration.
{
private:
vector<string> classes;
string name;
int id;
public:
Student (const vector<string> &classesUse, string nameUse, int idUse) :
classes (classesUse),
name (nameUse),
id (idUse)
{
}
void print ()
{
std::cout << "Name: " << name << std::endl;
std::cout << "Id: " << id << std::endl;
std::cout << "Classes: ";
for (int i = 0; i < classes.size (); i++)
{
if (i < classes.size () - 1)
{
std::cout << classes[i] << ", ";
}
else
{
std::cout << classes[i] << std::endl;
}
}
std::cout << std::endl;
}
};
int main()
{
Student John ({"C++","Intro to Theatre","Stagecraft"},
"John",
51090210);
John.print ();
Student Rick ({"Intro to Rocket Science","Intermediate Acting"},
"Rick",
666123420);
Rick.print ();
return 0;
}
Name: John
Id: 51090210
Classes: C++, Intro to Theatre, Stagecraft
Name: Rick
Id: 666123420
Classes: Intro to Rocket Science, Intermediate Acting
In the private variables of class Student, you are storing a string:
String classes;
where as you should be storing an array of strings like:
String classes[MAX_NUM_CLASSES];
then in the set classes function, pass in an array of strings as the first argument, so it should be :
void setClasses(string[] c, int num)
{
classes = c; //not sure if simply setting them equal will work, rather copy entire array using a for loop
arraySize = num;
}
This should point you in the right direction
Also, use std::vector instead of string[], it will be easier.
I am trying to simply create a vector of objects, add an object to it, and then display some variables in that object in the vector by accessing the function "getter's". Code compiles but it shows nothing for functions that return string and a garbage number for the ones that return double. I am sure it is something simple....can you help (assignment due in a couple of hours :S)?
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Employee
{
string fName, lName;
double weeklyIncome, grossSales, bonus;
public:
Employee(){};
Employee(string fn, string ln, double sales)
{
fName = fn;
lName = ln;
grossSales = sales;
bonus = sales * 0.09;
weeklyIncome = 200;
}
double getNetIncome() {return bonus + weeklyIncome;}
string getfName() {return fName;}
double getgrossSales() {return grossSales;}
~Employee(){};
};
int main()
{
vector<Employee> salespeople(15);
Employee e1("John", "Smith", 5000);
salespeople.push_back(e1);
cout << salespeople[0].getNetIncome();
cout << salespeople[0].getgrossSales();
cout << salespeople[0].getfName();
system("pause");
return 0;
}
vector<Employee> salespeople(15); // This creates a vector of 15 elements
Employee e1("John", "Smith", 5000);
salespeople.push_back(e1); // Now you have added the 16-th element
cout << salespeople[0].getNetIncome(); // The first element is still the default
// constructed element.
cout << salespeople[0].getgrossSales();
cout << salespeople[0].getfName();
You can fix the problem by using
vector<Employee> salespeople; // Create an empty vector and then
// add items to it.
or by changing
salespeople.push_back(e1);
to
salespeople[0] = e1;
Suggestion for improvement
Change the default constructor to initialize the double variables to sane values.
Employee() : weeklyIncome(0.0), grossSales(0.0) bonus(0.0) {};
I'm trying to add some songs to a vector inside a class. One of the values I'm storing is an int representing the song. It's essentially a counter. The first song I add should have the value 1, the second value two and so forth. But It's getting other strange values like big random numbers (positives and negatives). I can't wrap my head around what I'm doing wrong. This is the code:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Jukebox{
public:
void addSong(string artist, string title, string filename) {
song s {++songCounter, artist, title, filename};
Songs.push_back(s);
}
void printSong (int song) {
cout << Songs[song].no << ". ";
cout << Songs[song].artist << " - ";
cout << Songs[song].title << " : ";
cout << Songs[song].filename << endl;
}
private:
struct song {
int no;
string artist;
string title;
string filename;
};
vector<song> Songs;
int songCounter;
};
int main() {
Jukebox jbox;
jbox.addSong("U2", "Magnificent", "U2-Magnificent.mp3");
jbox.addSong("Sting", "Englishman in New York", "Sting-Englishman_in_New_York.mp3");
jbox.addSong("U2", "One", "U2-One.mp3");
jbox.printSong(0);
jbox.printSong(1);
jbox.printSong(2);
return 0;
}
Update
Ok, I'm probably stupid and should read more about classes before trying to implement this. But I think I did read and I still don't get it. This is what my class looks like now (which won't work):
class Jukebox(): songCounter(0)
{
public:
void addSong(string artist, string title, string filename) {
songCounter++;
song s {songCounter, artist, title, filename};
Songs.push_back(s);
}
void printSong (int song) {
cout << Songs[song].no << ". ";
cout << Songs[song].artist << " - ";
cout << Songs[song].title << " : ";
cout << Songs[song].filename << endl;
}
private:
int songCounter;
struct song {
int no;
string artist;
string title;
string filename;
};
vector<song> Songs;
};
Final word
Ok. From the example I've seen of c++ contructor classes I had some kind of wrong impression of how they worked. Now I think I'm getting it a little bit more. But the syntax still seems strange to me. But I try to read more so I really understand it. Here is what I did and to seems to work:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Jukebox {
public:
void addSong(string artist, string title, string filename) {
songCounter++;
song s {songCounter, artist, title, filename};
Songs.push_back(s);
}
void printSong (int song) {
cout << Songs[song].no << ". ";
cout << Songs[song].artist << " - ";
cout << Songs[song].title << " : ";
cout << Songs[song].filename << endl;
}
Jukebox(): songCounter(0) {} // Constructor
private:
int songCounter;
struct song {
int no;
string artist;
string title;
string filename;
};
vector<song> Songs;
};
int main() {
Jukebox jbox;
jbox.addSong("U2", "Magnificent", "U2-Magnificent.mp3");
jbox.addSong("Sting", "Englishman in New York", "Sting-Englishman_in_New_York.mp3");
jbox.addSong("U2", "One", "U2-One.mp3");
jbox.printSong(0);
jbox.printSong(1);
jbox.printSong(2);
return 0;
}
You did not initialize songCounter in your constructor.
Jukebox(): songCounter(0),//....other members
If you do not initialize it, then it may have any random value and that leaves your program in an Undefined State.
Always be careful while using unitialized variables, it often leads to Undefined Behavior and your program is a good example of it.
Also, I am not sure of your design but probably it should be a static member if you want to use it as a counter, which maintains state for all objects of your Song class.
Or
You will have to explicitly set it to a proper value at time of creating a Song object.
Okay its a counter for JukeBox and not Song class so its still okay to be a member.
You didn't initialize the variable songCounter.
Add the following to the class definition of Jukebox:
Jukebox(): songCounter(0) {}
you need a constructor for Jukebox and in that you need to initialise the counter to 0.
I think you should initialize songCounter to be 0. In the public part of the class:
public Jukebox() : songCounter(0) {}
Where do you initialise songCounter? In C++, primitives aren't zero initialised by default. You need to add
: songCounter(0)
to your constructor.