I am relatively new to C++ and classes. When I pass a char* through to the class constructor and copy it into the m_make and m_model char*'s, they are still empty. They are not pointing to random bits of memory when I print them out, no data is outputted, just blank space.
Constructor:
RentalCar::RentalCar(int year, char * make, char * model, float price, bool available)
{
m_year = year;
myStringCopy(m_make, make);
myStringCopy(m_model, model);
m_price = price;
m_available = available;
}
EDIT:
void readFile(RentalAgencyADT * list, ifstream & file)
{
char letter;
char word[7];
int i = 0; //position in word
int j = 0; //position in RentalCar data
int k = 0; //position of line in RentalAgencyADT
int l = 0; //position of RentalAgencyADT
while((letter = file.get()) != EOF)
{
if(letter == ' ' || letter == '\n')
{
int year;
char make[7], model[7];
float price;
bool available;
i = 0;
if(k != 0)
{
switch(j)
{
case 0:
year = atoi(word);
j++;
break;
case 1:
myStringCopy(make,word);
j++;
break;
case 2:
myStringCopy(model,word);
j++;
break;
case 3:
price = atof(word);
j++;
break;
case 4:
available = (bool) atoi(word);
list[l].inventory[k - 1] = RentalCar(year,make,model,price,available);
j = 0;
k++;
break;
}
clearWord(word);
i = 0;
if(k == 7)
{
}
}
else if(k == 0)
{
switch(j)
{
case 0:
myStringCopy(list[l].name, word);
j++;
break;
case 1:
//intCopy((list[l].zipcode),word);
//cout << list[l].zipcode << endl;
for(int i = 0; i < 5; i++)
{
list[l].zipcode[i] = word[i] - '0';
cout << list[l].zipcode[i];
}
j = 0;
k++;
break;
}
clearWord(word);
}
if(j == 4)
{
clearWord(make);
clearWord(model);
}
}
else
{
word[i] = letter;
i++;
}
}
}
Here is the RentalCar.cpp file:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "RentalCar.h"
using namespace std;
char* myStringCopy(char * destination, char * source);
RentalCar::RentalCar(int year, char * make, char * model, float price, bool available)
{
m_year = year;
myStringCopy(m_make, make);
myStringCopy(m_model, model);
m_price = price;
m_available = available;
}
char* myStringCopy(char * destination, char * source)
{
int i = 0;
while(source[i] != '\0')
{
destination[i] = source[i];
i++;
}
destination[i] = '\0';
return destination;
}
int RentalCar:: getYear()
{
return m_year;
}
void RentalCar:: setYear(int year)
{
m_year = year;
}
char* RentalCar:: getMake()
{
return m_make;
}
void RentalCar:: setMake(char * make)
{
myStringCopy(m_make, make);
}
char* RentalCar:: getModel()
{
return m_model;
}
void RentalCar:: setMode(char * model)
{
myStringCopy(m_model, model);
}
float RentalCar:: getPrice()
{
return m_price;
}
void RentalCar:: setPrice(int price)
{
m_price = price;
}
bool RentalCar:: getAvailable()
{
return m_available;
}
void RentalCar::setAvailable(bool available)
{
m_available = available;
}
void RentalCar::print()
{
cout << m_year << " " << m_make << " " << m_model << ", $" << m_price << ", Available: " << boolalpha << m_available << endl;
}
float RentalCar::estimateCost(int days)
{
return m_price * days;
}
I was using the strcpy() function earlier just to test but it didnt work either.
Headerfile:
#ifndef RENTALCAR_H_
#define RENTALCAR_H_
class RentalCar
{
public:
RentalCar(const int year, char * make, char * model, const float price, bool available);
int getYear();
void setYear(int year);
char* getMake();
void setMake(char make[]);
char* getModel();
void setMode(char model[]);
float getPrice();
void setPrice(int price);
bool getAvailable();
void setAvailable(bool available);
void print();
float estimateCost(int days);
protected:
private:
int m_year;
char * m_make;
char * m_model;
float m_price;
bool m_available;
};
#endif
You are strcpy()-ing into un-initialized char * pointers, which is undefined behaviour.
At the least you should be using strdup(), e.g. m_make = strdup(make);, with a corresponding free() in the destructor.
Related
I'm having an issue with my project. It keeps saying there is an issue with a constructor, but I can't find the issue. I'm sorry for the length of the code, and I'm sure it is something silly I am missing.
Pardon my headers...
DateTime.h
using namespace std;
//Constant array containing the days in the given month
const int DAYS_OF_MONTH[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
//Custom Date/Time format with a year that 1/1 is a sunday (Ex. 2017) to make things simpler
class DateTime {
int month, day, hour, minute;
public:
//Creates a basic blank DateTime
DateTime() {
month = 1;
day = 1;
hour = 0;
minute = 0;
}
//Creates a DateTime with a specific Date and Time
DateTime(int m, int d, int h, int min) {
month = m;
day = d;
hour = h;
minute = min;
}
//Adds the days to the date and updates the month if the day goes over
void addDays(int d) {
try {
for(int i = 0; i < d; i++) {
day++;
if(day > DAYS_OF_MONTH[month-1]) {
month++;
day = 1;
}
}
}
catch(string ex) {
}
}
//Adds a week onto the Date
void addWeeks(int w) {
for(int i = 0; i < w; i++) {
addDays(7);
}
}
//Accessors
int getMonth() {
return month;
}
int getDay() {
return day;
}
int getHour() {
return hour;
}
int getMinute() {
return minute;
}
//Mutators
void setMonth(int newM) {
month = newM;
}
void setDay(int newD) {
day = newD;
}
void setHour(int newH) {
hour = newH;
}
void setMinute(int newM) {
minute = newM;
}
};`
Day.h
#include<string>
#include "DateTime.h"
class Day {
DateTime startTime;
DateTime endTime;
int weekOfYear;
int dayOfWeek;
public:
//Creates a blank day
Day() {
startTime = DateTime(1, 1, 0, 0);
endTime = DateTime(1, 1, 0, 0);
weekOfYear = 0;
dayOfWeek = 0;
}
//Creates a blank day with a specific date
Day(int wOfY, int dOfW) {
startTime = DateTime(1, 1, 0, 0);
endTime = DateTime(1, 1, 0, 0);
weekOfYear = wOfY;
dayOfWeek = dOfW;
//Add weeks of the year and days of the week to the date
startTime.addDays(dOfW-1);
startTime.addWeeks(wOfY-1);
endTime.addDays(dOfW-1);
endTime.addWeeks(wOfY-1);
}
//Create a filled day with specific date and start/end times
Day(int wOfY, int dOfW, int startHr, int startMin, int endHr, int endMin) {
startTime = DateTime(1, 1, startHr, startMin);
endTime = DateTime(1, 1, endHr, endMin);
weekOfYear = wOfY;
dayOfWeek = dOfW;
}
//Accessors
DateTime getStartTime() {
return startTime;
}
DateTime getEndTime() {
return endTime;
}
int getWeekOfYear() {
return weekOfYear;
}
int getDayOfWeek() {
return dayOfWeek;
}
//Mutators
void setStartTime(DateTime newTime) {
startTime = newTime;
}
void setEndTime(DateTime newTime) {
endTime = newTime;
}
void setWeekOfYear(int newWOfY) {
weekOfYear = newWOfY;
}
void setDayOfWeek(int newDOfW) {
dayOfWeek = newDOfW;
}
//Calculates the amount of time between startTime and endTime
float getDailyHours() {
if((float)endTime.getHour() - (float)startTime.getHour() >=1) {
return ((60- (float)startTime.getMinute())/60) + ((float)endTime.getHour() - (float)startTime.getHour() - 1) + ((float)endTime.getMinute() / 60);
}
else {
return ((float)endTime.getMinute() - (float)startTime.getMinute()) / 60;
}
}
//Returns the data of the day in the format to save to the file
string toString() {
return string(",") + to_string(dayOfWeek) + string(",") + to_string(startTime.getHour()) + string(",") + to_string(startTime.getMinute()) + string(",") + to_string(endTime.getHour()) + string(",") + to_string(endTime.getMinute());
}
};
Week.h
#include "Day.h"
#include <vector>
using namespace std;
class Week {
vector<Day> dayList;
float totalWeeklyHours;
int weekOfYear;
public:
//Creates a basic week
Week(int wOfY) {
//dayList.resize(7);
weekOfYear = wOfY;
for(int i = 0; i < 7; i++) {
dayList.push_back(Day(weekOfYear, i));
}
}
//Creates a week given a dayList
Week(int wOfY, vector<Day> dL) {
//dayList.resize(7);
weekOfYear = wOfY;
for(int i = 0; i < 7; i++) {
dayList.push_back(dL.at(i));
}
}
//Accessors
int getWeekOfYear() {
return weekOfYear;
}
vector<Day> getDayList() {
return dayList;
}
//Adds a day to dayList from EmployeeManager.readFile()
void addDay(int wOfY, int dOfW, int startHr, int startMin, int endHr, int endMin) {
Day temp = Day(wOfY, dOfW, startHr, startMin, endHr, endMin);
dayList.at(dOfW) = temp;
weekOfYear = temp.getWeekOfYear();
}
//Adds a day from Employee.addWeek()
void addDay(Day newDay, int dOfW) {
dayList.at(dOfW) = newDay;
weekOfYear = newDay.getWeekOfYear();
}
//Calculates the total amount of hours scheduled in the week
float getTotalWeeklyHours() {
totalWeeklyHours = 0;
for(int i = 0; i < dayList.size(); i++) {
totalWeeklyHours += dayList.at(i).getDailyHours();
}
return totalWeeklyHours;
}
//Returns the data of the week in the format to save in the file
string toString() {
return (string)"," + to_string(weekOfYear) + dayList.at(0).toString() + dayList.at(1).toString() + dayList.at(2).toString() + dayList.at(3).toString() + dayList.at(4).toString() + dayList.at(5).toString() + dayList.at(6).toString();
}
};
Person.h
#include <string>
using namespace std;
class Person {
public:
string firstName;
string lastName;
int employeeID;
int employeePIN;
float hourlyRateOfPay;
public:
Person() {
firstName = "John";
lastName = "Doe";
employeeID = 0;
employeePIN = 0;
hourlyRateOfPay = 0;
}
//Accessors
string getFirstName() {
return firstName;
}
string getLastName() {
return lastName;
}
int getEmployeeID() {
return employeeID;
}
int getEmployeePIN() {
return employeePIN;
}
float getHourlyRateOfPay() {
return hourlyRateOfPay;
}
//Mutators
void setFirstname(string newName) {
firstName = newName;
}
void setLastName(string newName) {
lastName = newName;
}
void setEmployeeID(int newID) {
employeeID = newID;
}
void setEmployeePIN(int newPIN) {
employeePIN = newPIN;
}
void setHourlyRateOfPay(float newPay) {
hourlyRateOfPay = newPay;
}
//Abstract methods
string viewSchedule(int wOfY);
float viewPay(int wOfY);
};
Employee.h
#include "Person.h"
#include "Week.h"
using namespace std;
class Employee : public Person {
vector<Week> weekList;
public:
Employee(int empID, int empPIN, string fName, string lName, float hROP) {
employeeID = empID;
employeePIN = empPIN;
firstName = fName;
lastName = lName;
hourlyRateOfPay = hROP;
/*
setEmployeeID(empID);
setEmployeePIN(empPIN);
setFirstName(fname);
setLastName(lname);
setHourlyRateOfPay(hROP);
*/
for(int i = 0; i < 52; i++) {
weekList.push_back(Week(i));
}
}
Week getWeek(int wOfY) {
return weekList.at(wOfY);
}
//Adds a week to the weekList from EmployeeManager.readFile()
void addWeek(int wOfY, vector<Day> dL) {
for(int i = 0; i < 7; i++) {
weekList.at(wOfY).addDay(dL.at(i), i);
}
}
//Adds a week from client
void addWeek(int wOfY, Week newWeek) {
weekList.at(wOfY) = newWeek;
}
//Returns a specified wek to be viewed by the user
string viewSchedule(int wOfY) {
return weekList.at(wOfY).toString();
}
//Returns the amount of pay for a specified week to be viewed by the user
float viewPay(int wOfY) {
return hourlyRateOfPay * (weekList.at(wOfY).getTotalWeeklyHours());
}
//Returns the data of the employee in the format to save to the readFile
string toString() {
return firstName + "," + lastName + "," + to_string(employeeID) + "," + to_string(employeePIN) + "," + to_string(hourlyRateOfPay);
}
};
EmployeeManager.h
#include "Employee.h"
#include <fstream>
#include <sstream>
using namespace std;
class EmployeeManager {
vector<Employee> employeeList;
public:
EmployeeManager() {
//readFile();
}
void readFile() {
//Variables
int empID, empPIN, wOfY, dOfW, startHr, startMin, endHr, endMin;
float hROP;
string fname, lname;
ifstream input;
input.open("EmployeeList.csv");
while(!input.eof()) {
input >> fname >> lname >> empID >> empPIN >> hROP;
//Create temp Employee
Employee tempEmployee = Employee(empID, empPIN, fname, lname, hROP);
for(int i = 0; i < 52; i++) {
Week tempWeek = Week(i);
input >> wOfY;
for(int j = 0; j < 7; j++) {
input >> dOfW >> startHr >> startMin >> endHr >> endMin;
tempWeek.addDay(wOfY, dOfW, startHr, startMin, endHr, endMin);
}
tempEmployee.addWeek(wOfY, tempWeek.getDayList());
}
addEmployee(tempEmployee);
}
input.close();
}
void saveFile() {
ofstream output("EmployeeList.csv");
for(int i = 0; i < employeeList.size(); i++) {
output << employeeList.at(i).toString();
for(int j = 0; j < 52; j++) {
output << employeeList.at(i).viewSchedule(j);
}
output << "\n";
}
output.close();
}
//Adds a new employee to the employeeList from readFile
void addEmployee(Employee newEmp) {
//employeeList.resize(employeeList.size()*2);
try{
employeeList.push_back(newEmp);
}
catch(out_of_range ex) {
cout << "EmployeeList out_of_range" << endl;
int newSize = employeeList.size() * 2;
employeeList.resize(newSize);
addEmployee(newEmp);
}
}
//Adds a new employee to the employeeList from client
void addEmployee(int empID, int empPIN, string fname, string lname, float hROP) {
Employee newEmp = Employee(empID, empPIN, fname, lname, hROP);
//employeeList.resize(employeeList.size()*2);
try {
employeeList.push_back(newEmp);
}
catch(out_of_range ex) {
cout << "EmployeeList out_of_range" << endl;
int newSize = employeeList.size() * 2;
employeeList.resize(newSize);
addEmployee(newEmp);
}
}
bool validateLogin(int empID, int empPIN) {
for(int i = 0; i < employeeList.size(); i++) {
if(employeeList.at(i).getEmployeeID() == empID) {
if(employeeList.at(i).getEmployeePIN() == empPIN) {
return true;
}
}
}
return false;
}
bool isIDAvailable(int empID) {
for(int i = 0; i < employeeList.size(); i++) {
if(employeeList.at(i).getEmployeeID() == empID) {
return false;
}
}
return true;
}
};
main.cpp
#include <iostream>
#include "EmployeeManager.h"
int main() {
Day d1 = Day(9,6);
cout << d1.toString() << endl;
Week w1 = Week(1);
cout <<"\n\n" << w1.toString() << endl;
Employee e1 = Employee(12345, 9876, "Test", "Employee", 15.60);
cout << "\n\n" << e1.toString();
for(int i = 0; i < 52; i++) {
cout << e1.viewSchedule(i);
}
cout << endl;
EmployeeManager em1 = EmployeeManager();
em1.saveFile();
}
Then I had a .csv file named EmployeeList.csv
This is the Error Message I was given
clang++-7 -pthread -std=c++17 -o main main.cpp
In file included from main.cpp:2:
In file included from ./EmployeeManager.h:1:
In file included from ./Employee.h:2:
In file included from ./Week.h:2:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/vector:62:
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/stl_construct.h:75:38: error:
no matching constructor for initialization of 'Employee'
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/stl_uninitialized.h:527:8: note:
in instantiation of function template specialization
'std::_Construct<Employee>' requested here
std::_Construct(std::__addressof(*__cur));
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/stl_uninitialized.h:583:2: note:
in instantiation of function template specialization
'std::__uninitialized_default_n_1<false>::__uninit_default_n<Employee *,
unsigned long>' requested here
__uninit_default_n(__first, __n);
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/stl_uninitialized.h:645:19: note:
in instantiation of function template specialization
'std::__uninitialized_default_n<Employee *, unsigned long>' requested here
{ return std::__uninitialized_default_n(__first, __n); }
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/vector.tcc:596:8: note:
in instantiation of function template specialization
'std::__uninitialized_default_n_a<Employee *, unsigned long, Employee>'
requested here
std::__uninitialized_default_n_a(this->_M_impl._M_finish,
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/stl_vector.h:827:4: note:
in instantiation of member function 'std::vector<Employee,
std::allocator<Employee> >::_M_default_append' requested here
_M_default_append(__new_size - size());
^
./EmployeeManager.h:64:20: note: in instantiation of member function
'std::vector<Employee, std::allocator<Employee> >::resize' requested here
employeeList.resize(newSize);
^
./Employee.h:5:7: note: candidate constructor (the implicit copy constructor)
not viable: requires 1 argument, but 0 were provided
class Employee : public Person {
^
./Employee.h:5:7: note: candidate constructor (the implicit move constructor)
not viable: requires 1 argument, but 0 were provided
./Employee.h:9:5: note: candidate constructor not viable: requires 5 arguments,
but 0 were provided
Employee(int empID, int empPIN, string fName, string lName, float hROP) {
^
1 error generated.
exit status 1
Operations like employeeList.resize(newSize) in std::vector require a default constructor for the containing element, which is missed in the class Employee. This is necessary to create the empty elements in the container.
Just add the default constructor, or store pointers instead if you can't accommodate/afford the default constructor for some reason.
#include<iostream>
#include<conio.h>
#include <chrono>
#include <ctime>
using namespace std;
typedef std::chrono::high_resolution_clock Clock;
/*struct*/ class Car
{
private:
int carYear;
string carMake;
string carModel;
int carSpeed;
float carGallons;
public:
Car(int cY = 0, string cMa = "", string cMo = "", int cS = 0, float cG = 10)
{
carYear = cY;
carMake = cMa;
carModel = cMo;
carSpeed = cS;
carGallons = cG;
}
Car()
{
carMake = "Bugatti";
carYear = 2020;
carModel = "Chiron";
}
int getCarYear() { return carYear; }
string getCarMake() { return carMake; }
string getCarModel() { return carModel; }
int getCarSpeed() { return carSpeed; }
float getCarGallons() { return carGallons; }
void setCarSpeed(int cS) { carSpeed = cS; }
void setCarGallons(float cG) { carGallons = cG; }
void accelerate()
{
startCar();
if(carGallons>0)
{
carSpeed += 5;
carGallons -= .5;
}
else if (carGallons < 0)
{
carGallons = 0;
cout << "Please refill tank!";
}
}
void brake()
{
startCar();
if(carSpeed>0&&carGallons>0)
{
carSpeed -= 5;
carGallons -= .2;
}
else if(carSpeed<0&&carGallons<0)
{
carSpeed = 0;
cout << "Your car isn't moving!";
}
}
void fillUP()
{
if (carSpeed > 0)
{
cout << "The car is still moving!";
}
else if(carSpeed==0)
{
if (carGallons > 22)
{
cout << "Car is full!";
carGallons = 22;
}
else
{
carGallons += .2;
}
}
}
void startCar(bool carOn=true)
{
while (true)
{
std::chrono::system_clock::time_point then;
auto now = std::chrono::system_clock::now();
auto duration = now - then;
then = now;
if (false) return;
{
auto s = std::chrono::duration_cast<std::chrono::duration<double>>(duration);
carGallons -= s.count() * .05f;
}
}
}
};
int main()
{
bool carOn = false;
Car userCar(2020, "Bugatti", "Chiron");
cout << "\nStart your new " << userCar.getCarYear()<<" "<< userCar.getCarMake() <<" "<< userCar.getCarModel()<<"!";
cout << "\nHit O to start your Engine!";
char ch;
cin >> ch;
if (ch== 'o'|| ch=='O') {
bool carOn = true;
cout << "\nCar is now on! Safe driving!\n";
int c = 0;
while (1)
{
c = 0;
switch (c = _getch())
{
case 32:
userCar.fillUP();
break;
case 72:
cout << userCar.getCarSpeed() << " " << userCar.getCarGallons();
userCar.accelerate();
break;
case 80:
userCar.brake();
break;
case 75:cout << "\nleft"; break;
case 77:cout << "\nright"; break;
default:
cout << " ";
}
}
}
else
{
cout << "\nCar is not on!";
}
return 0;
}
I'm running into an issue where after taking input from the user to turn on their car the inputs freeze up and the switch doesn't accept any other inputs. I know it has something to do with how I'm calling my functions inside the switch but I'm at a loss for how to correct it. Also, I'm fairly certain I've incorrectly implemented my clock inside startCar, it's supposed to subtract gas while the car is on.
This is my code:
#include<iostream>
#include<string.h>
using namespace std;
class Zichara
{
private:
char *name;
int price;
void copy(const Zichara &from)
{
name = new char[strlen(from.name) + 1];
strcpy(name, from.name);
price = from.price;
}
public:
Zichara(const char *name, int price) {
this->name = new char[strlen(name) + 1];
strcpy(this->name, name);
this->price = price;
}
Zichara(const Zichara &from)
{
copy(from);
}
~Zichara() {
delete [] name;
}
friend class PlaninarskiDom;
};
class PlaninarskiDom {
private:
char name[15];
int prices[2];
char star;
bool isZichara;
Zichara *zich;
void copy(const PlaninarskiDom &from) {
strcpy(name, from.name);
star = from.star;
isZichara = from.isZichara;
zich = from.zich;
for(int i = 0; i < 2; i++) {
prices[i] = from.prices[i];
}
}
public:
PlaninarskiDom(const char *name = "", int prices = 0, const char star = '\0') {
strcpy(this->name, name);
this->star = star;
isZichara = 0;
zich = 0;
this->prices[0] = 0;
this->prices[1] = 0;
}
PlaninarskiDom(const char *name, int *prices, const char star) {
strcpy(this->name, name);
this->star = star;
isZichara = 0;
zich = 0;
this->prices[0] = prices[0];
this->prices[1] = prices[1];
}
PlaninarskiDom(const PlaninarskiDom &from) {
copy(from);
}
~PlaninarskiDom() {
delete [] zich;
}
PlaninarskiDom& operator = (const PlaninarskiDom &from) {
if(this == &from) return *this;
delete [] zich;
copy(from);
return *this;
}
void setZichara(Zichara &z) {
if(isZichara == 0) {
zich->copy(z);
isZichara = 1;
}
}
void operator --() {
if((int)star >= 65 && (int)star <= 70) {
++star;
if((int)star == 69) {
++star;
}
}
}
bool operator <= (char c) {
return star >= c;
}
void presmetajDnevenPrestoj(int day, int month, int &price) {
if(day < 0 || day > 31 || month < 0 || month > 12) {
throw 99;
}
else if(month >= 4 && month <= 8) {
price = prices[0];
}
else {
price = prices[1];
}
if(isZichara) {
price += zich->price;
}
}
friend ostream& operator << (ostream &, const PlaninarskiDom &);
};
ostream& operator << (ostream &os, const PlaninarskiDom &rhs) {
cout << rhs.name << " klasa:" << rhs.star << endl;
if(rhs.isZichara) {
cout << " so zichara" << endl;
}
return os;
}
int main(){
PlaninarskiDom p; //креирање на нов објект од класата планинарски дом
//во следниот дел се вчитуваат информации за планинарскиот дом
char imePlaninarskiDom[15],mestoZichara[30],klasa;
int ceni[12];
int dnevnakartaZichara;
bool daliZichara;
cin>>imePlaninarskiDom;
for (int i=0;i<2;i++) cin>>ceni[i];
cin>>klasa;
cin>>daliZichara;
//во следниот дел се внесуваат информации и за жичарата ако постои
if (daliZichara) {
cin>>mestoZichara>>dnevnakartaZichara;
PlaninarskiDom pom(imePlaninarskiDom,ceni,klasa);
Zichara r(mestoZichara,dnevnakartaZichara);
pom.setZichara(r);
p=pom;
}
else{
PlaninarskiDom *pok=new PlaninarskiDom(imePlaninarskiDom,ceni,klasa);
p=*pok;
}
//се намалува класата на планинарскиот дом за 2
--p;
--p;
int cena;
int den,mesec;
cin>>den>>mesec;
try{
p.presmetajDnevenPrestoj(den,mesec,cena); //тука се користи функцијата presmetajDnevenPrestoj
cout<<"Informacii za PlaninarskiDomot:"<<endl;
cout<<p;
if (p<='D')
cout<<"Planinarskiot dom za koj se vneseni informaciite ima klasa poniska ili ista so D\n";
cout<<"Cenata za "<<den<<"."<<mesec<<" e "<<cena; //се печати цената за дадениот ден и месец
}
catch (int){
cout<<"Mesecot ili denot e greshno vnesen!";
}
}
I ran a debugger on this code and it highlighted this:
name = new char[strlen(from.name) + 1];
This is the line of code as the line where the Seg Fault comes from.
This is an exercise for a class I have and I have to do it using dynamic memory allocation.
I've done this exact same thing many times before and there was no such error, so I have no idea why it is appearing, and I couldn't find an answer to this question on Google so far, so I apologize if somewhere out there it does exist.
Thanks everyone for the suggestions, this has been fixed!
You call this method:
void setZichara(Zichara &z) {
if(isZichara == 0) {
zich->copy(z);
isZichara = 1;
}
}
but you never allocate zich so you invoke UB calling a method on nullptr
Note: your PlaninarskiDom::copy() is incorrect as well, as you just assign pointer from another object aka shallow copy, which will lead to multiple destruction, though most probably you did not hit this issue yet. You should do deep copy instead or use std::shared_ptr is you plan to share ownership. Anyway if you are not limited by conditions using smart pointers are preferable when dealing with dynamically allocated objects. Or using special containers like std::vector or std::string which do proper memory management for you.
Why my program is getting these errors?
undefined reference to `PizzaOrder::toppings_offered'
undefined reference to `PizzaOrder::arraySize'
undefined reference to `PizzaOrder::base_price'
undefined reference to `PizzaOrder::MedPizBase'
undefined reference to `PizzaOrder::base_price'
undefined reference to `PizzaOrder::LargePizBase'
...
This is my program:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
class PizzaOrder
{
private:
int size;
int num_toppings;
string toppings[100];
public:
static const string toppings_offered[];
static const double topping_base_cost;
static const double base_price;
static const string defaultSize;
static const double MedPizBase;
static const double LargePizBase;
static const int arraySize;
PizzaOrder();
PizzaOrder(int size);
// MUTATORS & ACCESSORS & METHODS
int GetSize() { return size; }
int GetNumToppings() { return num_toppings; }
string GetToppings();
void GetPrice();
bool SetSize(int size);
void AddTopping(string topping);
void AddTopping(int n); //int represents position in array toppings_offered[]
string StringizeSize(int size);
void DisplayPizza();
};
const string toppings_offered[] = {"1. Onions", "2. Bell Peppers",
"3. Olives", "4. Pepperoni", "5. Sausage",
"6. Mushrooms", "7. Jalapenos"};
const string defaultSize = "Small ";
const double topping_base_cost = 1;
const double base_price = 7;
const double MedPizBase = 0.15;
const double LargePizBase = 0.25;
const int arraySize = sizeof(toppings_offered)/sizeof(toppings_offered[0]);
PizzaOrder::PizzaOrder()
{
SetSize(0);
}
PizzaOrder::PizzaOrder(int size)
{
if (!SetSize(size))
SetSize(0);
}
string PizzaOrder::StringizeSize(int size)
{
string pizzaSize;
if (size == 0)
pizzaSize = "Small";
if (size == 1)
pizzaSize = "Medium";
if (size == 2)
pizzaSize = "Large";
return pizzaSize;
}
bool PizzaOrder::SetSize(int size)
{
if (size != 0 && size != 1
&& size != 2)
return false;
this->size = size;
return true;
}
void PizzaOrder::AddTopping(string topping) // totally wrong
{
for (int i = 0; i < arraySize; i++)
{
if (topping == toppings_offered[i])
{
toppings[num_toppings] = topping;
num_toppings++;
}
}
}
void PizzaOrder::AddTopping(int n) //increments n by 1 for each valid topping chosen
{
if (n > 0 && n < 7)
n++;
n = num_toppings;
}
string PizzaOrder::GetToppings()
{
string result;
for(int i = 0; i < GetNumToppings(); i++)
{
result += toppings[i];
}
return result;
}
void PizzaOrder::DisplayPizza()
{
cout << "Your pizza order: " << PizzaOrder::StringizeSize(GetSize()) << ", "
<< PizzaOrder::GetNumToppings() << ", "
<< PizzaOrder::GetToppings();
}
void PizzaOrder::GetPrice()
{
double TotalPizPrice;
double MedPizzaPrice = base_price+(base_price*MedPizBase);
double LargePizzaPrice = base_price+(base_price*LargePizBase);
double topPrice = (GetNumToppings()*topping_base_cost);
if (GetSize() == 0)
TotalPizPrice = topPrice+base_price;
if (GetSize() == 1)
TotalPizPrice = topPrice+MedPizzaPrice;
if (GetSize() == 2)
TotalPizPrice = topPrice+LargePizzaPrice;
cout << "Your pizza's total price is: $" << TotalPizPrice;
}
int main()
{
PizzaOrder pizza;
string choice;
char selection;
int topChoice;
do
{
cout << "Size of pizza (Small, Medium, Large) or Quit?\n" << endl;
getline(cin, choice);
selection = choice[0];
if (selection == 'S' || selection == 's')
pizza.SetSize(0);
if (selection == 'M' || selection == 'm')
pizza.SetSize(1);
if (selection == 'L' || selection == 'l')
pizza.SetSize(2);
do
{
cout << "Current pizza: "
<< pizza.StringizeSize(pizza.GetSize())
<< pizza.GetToppings() << "\n"
<< "Select an item by number (0 when done):\n" << endl;
for (int i = 0; i < 8; i++)
{
cout << toppings_offered[i] << "\n";
}
cout <<"\nSelection: ";
cin >> topChoice;
pizza.AddTopping(topChoice);
}
while (topChoice != 0);
}
while(selection != 'q' && selection != 'Q');
pizza.DisplayPizza();
pizza.GetPrice();
return 0;
}
The definition of static member variables is wrong, they should be:
const string PizzaOrder::defaultSize = "Small ";
~~~~~~~~~~~~
...
Otherwize they'll be just global variables.
I'm sorry, I know this is the umpteenth seg fault post on Stack Overflow, but I've tried for a few days to fix this code and I'm stumped, so I decided to turn to you guys. I hope you can help!
Anyway, I'm getting a strange segfault in this code:
account.h (Note, I'm not allowed modify the account.h file in anyway, as per the assignment. :)
class account
{
public:
typedef char* string;
static const size_t MAX_NAME_SIZE = 15;
// CONSTRUCTOR
//account();
account (char* i_name, size_t i_acnum, size_t i_hsize);
account (const account& ac);
// DESTRUCTOR
~account ( );
// MODIFICATION MEMBER FUNCTIONS
void set_name(char* new_name);
void set_account_number(size_t new_acnum);
void set_balance(double new_balance);
void add_history(char* new_history);
// CONSTANT MEMBER FUNCTIONS
char* get_name () const;
size_t get_account_number ( ) const;
double get_balance( ) const;
size_t get_max_history_size( ) const;
size_t get_current_history_size ( ) const;
string* get_history() const;
friend std::ostream& operator <<(std::ostream& outs, const account& target);
private:
char name[MAX_NAME_SIZE+1]; //name of the account holder
size_t ac_number; //account number
double balance; //current account balance
string* history; //Array to store history of transactions
size_t history_size; //Maximum size of transaction history
size_t history_count; //Current size of transaction history
};
account.cxx:
#include <string.h>
#include <cassert>
#include <cstdlib>
#include <iostream>
#include "account.h"
using namespace std;
account::account(char* i_name, size_t i_acnum, size_t i_hsize)
{
assert(strlen(i_name) <= MAX_NAME_SIZE);
strcpy(name, i_name);
ac_number = i_acnum;
history_size = i_hsize;
balance = 0;
history_count = 0;
history = new string[history_size];
}
account::account(const account& ac)
{
strcpy(name, ac.name);
ac_number = ac.ac_number;
balance = ac.balance;
history = new string[ac.history_size];
for(size_t i = 0; i < ac.history_count; i++)
{
history[i] = new char[strlen(ac.history[i]) + 1];
strcpy(history[i], ac.history[i]);
}
history_count = ac.history_count;
history_size = ac.history_size;
}
account::~account()
{
delete[] history;
}
void account::set_name(char* new_name)
{
assert(strlen(new_name) <= MAX_NAME_SIZE);
strcpy(name, new_name);
}
void account::set_account_number(size_t new_acnum) {ac_number = new_acnum;}
void account::set_balance(double new_balance) {balance = new_balance;}
void account::add_history(char* new_history)
{
assert(history_count < history_size);
history[history_count] = new char[strlen(new_history) + 1];
strcpy(history[history_count], new_history);
history_count++;
}
char* account::get_name() const
{
char* blah = new char[MAX_NAME_SIZE + 1];
strcpy(blah, name);
return blah;
}
size_t account::get_account_number ( ) const {return ac_number;}
double account::get_balance( ) const{return balance;}
size_t account::get_max_history_size( ) const {return history_size;}
size_t account::get_current_history_size ( ) const {return history_count;}
account::string* account::get_history() const
{
string* blah = new string[history_size];
for(size_t i = 0; i < history_count; i++)
{
blah[i] = new char[strlen(history[i]) + 1];
strcpy(blah[i], history[i]);
}
return blah;
}
std::ostream& operator<< (std::ostream& outs, const account& target)
{
outs << "Name: " << target.name << "\n"
<< "Account Number: " << target.ac_number << "\n"
<< "Balance: " << "$" << target.balance << "\n"
<< "History: ";
for(size_t i = 0; i < target.history_count; i++)
{
outs << target.history[i] << "\n";
}
outs << "Current History Size: " << target.history_count << "\n";
outs << "Max History Size: " << target.history_size << "\n";
return outs;
}
bankledger.h
class bank_ledger
{
public:
static const int MAX_ACC_SIZE = 15;
bank_ledger(int mo, int mc);
bank_ledger(const bank_ledger& copyledger);
~bank_ledger();
void create_account(char* i_name, size_t i_acnum, size_t i_hsize);
void close_account(double accnum);
double balance_of(double accnum);
void deposit(double accnum, double money);
void withdraw(double accnum, double money);
void transfer(double accnum1, double accnum2, double money);
void print_account_history(double accnum);
void print_account_details(double accnum);
void print_current_details();
void print_closed_details();
account* lookup(double accnum);
private:
account** open;
account** closed;
int max_open;
int max_closed;
int num_open;
int num_closed;
};
bankledger.cxx:
#include <cstdlib>
#include <iostream>
#include <cassert>
#include "account.h"
#include "bank_ledger.h"
using namespace std;
bank_ledger::bank_ledger(int mo = 30, int mc = 30)
{
max_open = mo;
max_closed = mc;
open = new account*[max_open];
closed = new account*[max_closed];
num_open = 0;
num_closed = 0;
}
bank_ledger::bank_ledger(const bank_ledger& copyledger)
{
int i;
max_open = copyledger.max_open;
max_closed = copyledger.max_closed;
num_open = copyledger.num_open;
num_closed = copyledger.num_closed;
open = new account*[num_open];
closed = new account*[num_closed];
for(i = 0; i < max_open; i++)
{
if (i < num_open)
open[i] = copyledger.open[i];
}
for(i = 0; i < max_closed; i++)
{
if (i < num_closed)
closed[i] = copyledger.closed[i];
}
}
bank_ledger::~bank_ledger()
{
for(int i = 0; i < num_open; i++)
{
delete open[i];
}
for(int i = 0; i < num_closed; i++)
{
delete closed[i];
}
delete[] open;
delete[] closed;
}
account* bank_ledger::lookup(double accnum)
{
for(int i = 0; i < num_open; i++)
{
if(open[i]->get_account_number() == accnum)
{
return *open + i;
}
if(closed[i]->get_account_number() == accnum)
{
return *closed + i;
}
}
}
void bank_ledger::create_account(char* i_name, size_t i_acnum, size_t i_hsize)
{
assert(num_open < max_open);
open[num_open] = new account(i_name, i_acnum, i_hsize);
open[num_open]->add_history("Account Created");
num_open++;
}
void bank_ledger::close_account(double accnum)
{
int i;
double temp = -1;
cout << *(open[0]) << endl << "Good Idea" << endl;
account* acc = lookup(accnum);
for(i = 0; i < num_open; i++)
{
if(open[i]->get_account_number() == acc->get_account_number())
{
temp = i;
closed[num_closed] = open[i];
for(i = temp; i < num_open - 1; i++)
{
open[i] = open[i+1];
}
closed[num_closed]->add_history("Account Closed");
num_open--;
num_closed++;
return;
}
}
}
double bank_ledger::balance_of(double accnum)
{
return lookup(accnum)->get_balance();
}
void bank_ledger::deposit(double accnum, double money)
{
account* acc = lookup(accnum);
acc->set_balance(acc->get_balance() + money);
acc->add_history("Deposited $");
}
void bank_ledger::withdraw(double accnum, double money)
{
account* acc = lookup(accnum);
acc->set_balance(acc->get_balance() - money);
acc->add_history("Withdrew $");
}
void bank_ledger::transfer(double accnum1, double accnum2, double money)
{
withdraw(accnum2, money);
deposit(accnum1, money);
}
void bank_ledger::print_account_history(double accnum)
{
account* acc = lookup(accnum);
account::string *hist = acc->get_history();
cout << "History of " << acc->get_name() << "'s account: " << endl;
for (int i = 0; i < acc->get_current_history_size(); i++) cout << hist[i] << endl;
}
void bank_ledger::print_account_details(double accnum)
{
account* acc = lookup(accnum);
cout << *acc;
cout << "\n";
}
void bank_ledger::print_current_details()
{
for(int i = 0; i < num_open; i++)
{
cout << *open[i] << "\n";
}
}
void bank_ledger::print_closed_details()
{
for(int i = 0; i < num_closed; i++)
{
cout << *closed[i] << "\n";
}
cout << "\n";
}
sample_test_input2.cxx
#include <cstdlib>
#include <iostream>
#include "account.h"
#include "bank_ledger.h"
using namespace std;
int main()
{
bank_ledger bl(30, 30);
bl.create_account("name1", 1, 30);
bl.create_account("name2", 2, 30);
bl.create_account("name3", 3, 30);
bl.create_account("name4", 4, 30);
bl.print_current_details();
bl.close_account(2);
return 0;
}
Valgrind and GDB both say that *(open[i]) is uninitialized. Here's the exact output from Valgrind:
==7082== Use of uninitialised value of size 8
==7082== at 0x1000018C6: account::get_account_number() const (account.cxx:74)
==7082== by 0x10000246B: bank_ledger::lookup(double) (bank_ledger.cxx:85)
==7082== by 0x1000027D0: bank_ledger::close_account(double) (bank_ledger.cxx:105)
==7082== by 0x100003117: main (sample_test_input2.cxx:17)
==7082==
==7082== Invalid read of size 8
==7082== at 0x1000018C6: account::get_account_number() const (account.cxx:74)
==7082== by 0x10000246B: bank_ledger::lookup(double) (bank_ledger.cxx:85)
==7082== by 0x1000027D0: bank_ledger::close_account(double) (bank_ledger.cxx:105)
==7082== by 0x100003117: main (sample_test_input2.cxx:17)
==7082== Address 0x10 is not stack'd, malloc'd or (recently) free'd
It goes from main to bankledgrer::close_account, to bankledger::lookup and then it crashes at if(open[i]->get_account_number() == accnum)
If I stick cout << *(open[i]) right before that line, it prints it out fine.
I'm afraid I'm at a loss. Any help would be appreciated. If you want me to include the header files, or clarify anything please let me know.
PS. Also, I know this code is very C, but that's the way my professor wants it, even though it's a C++ class. Go figure. :\
In this method:
account* bank_ledger::lookup(double accnum)
{
for(int i = 0; i < num_open; i++)
{
if(open[i]->get_account_number() == accnum)
{
return *open + i;
}
if(closed[i]->get_account_number() == accnum)
{
return *closed + i;
}
}
}
You are assuming there are at least the same amount of closed accounts than the amount of open accounts. You should iterate through the open and closed arrays in different loops, since you're trying to access closed[i], being i = 1,2,3..., and closed does not contain any valid pointers(just a bunch of NULL pointers). This should work(unless i'm missing something else):
account* bank_ledger::lookup(double accnum) {
for(int i = 0; i < num_open; i++) {
if(open[i]->get_account_number() == accnum)
return open[i];
}
for(int i = 0; i < num_closed; i++) {
if(closed[i]->get_account_number() == accnum)
return closed[i];
}
return 0;
}