I'm having an issue with this program it keeps on giving me this error when i compile it
C:\Users\dla\AppData\Local\Temp\ccAB92Md.o extClockType.cpp:(.text+0x74): undefined reference to clockType::printTime() const
C:\Users\dla\AppData\Local\Temp\ccAB92Md.o extClockType.cpp:(.text+0xeb):undefined reference to clockType::clockType(int, int, int)
C:\Users\dla\AppData\Local\Temp\ccAB92Md.o extClockType.cpp:(.text+0x156): undefined reference to clockType::clockType()
I want to know what the issue is?
clockType.h header file
//Header files section
#ifndef H_clockType
#define H_clockType
#include<iostream>
using namespace std;
//specification of the clockType class
class clockType
{
public:
//member functions
void setTime(int, int, int);
void getTime(int&, int&, int&) const;
void printTime() const;
void incrementSeconds();
void incrementMinutes();
void incrementHours();
bool equalTime(const clockType&) const;
//constructors
clockType();
clockType(int, int, int);
private:
//data fields
int hr;
int min;
int sec;
};
#endif
clockType.cpp file
// Header files section
#include "clockType.h"
using namespace std;
//implementation of the clockType class
//setTime function sets the hours, minutes, and seconds to the parameter values
void clockType::setTime(int hours, int minutes, int seconds)
{
if (0 <= hours && hours < 24)
hr = hours;
else
hr = 0;
if (0 <= minutes && minutes < 60)
min = minutes;
else
min = 0;
if (0 <= seconds && seconds < 60)
sec = seconds;
else
sec = 0;
}
//getTime function returns the hours, minutes, and seconds from the parameter values
void clockType::getTime(int& hours, int& minutes,int& seconds) const
{
hours = hr;
minutes = min;
seconds = sec;
}
//printTime function prints the time in 24-hours (00:00:00) format
void clockType::printTime() const
{
if (hr < 10)
cout << "0";
cout << hr << ":";
if (min < 10)
cout << "0";
cout << min << ":";
if (sec < 10)
cout << "0";
cout << sec;
}
//incrementHours function increments the time by 1 hour
void clockType::incrementHours()
{
hr++;
if (hr > 23)
hr = 0;
}
//incrementHours function increments the time by 1 minute
void clockType::incrementMinutes()
{
min++;
if (min > 59)
{
min = 0;
incrementHours();
}
}
//incrementHours function increments the time by 1 second
void clockType::incrementSeconds()
{
sec++;
if (sec > 59)
{
sec = 0;
incrementMinutes();
}
}
//equalTime function returns the equality of two times
bool clockType::equalTime(const clockType & otherClock) const
{
return (hr == otherClock.hr &&
min == otherClock.min &&
sec== otherClock.sec);
}
//default constructor sets the hours, minutes, and seconds to the default values
clockType::clockType()
{
hr = 0;
min = 0;
sec = 0;
}
//paramterized constructor sets the hours, minutes, and seconds to the parameter values
clockType::clockType(int hours, int minutes, int seconds)
{
setTime(hours, minutes, seconds);
}
extClockType.h header file
#include "clockType.h"
#include <iostream>
#include <string>
using namespace std;
//extClockType extends clockType
class extClockType : public clockType
{
public:
// member functions
void setTimeZone(string);
string getTimeZone() const;
void printTime() const;
// constructors
extClockType(int, int, int, string);
extClockType();
private:
// data fields
string tz;
};
#endif
extClockType.cpp file
//Header files section
#include "extClockType.h"
//setTimeZone function sets the time zone to the parameter value
void extClockType::setTimeZone(string timeZone)
{
tz = timeZone;
}
//getTimeZone function returns the time zone
string extClockType::getTimeZone() const
{
return tz;
}
//printTime function prints the time zone
void extClockType::printTime() const
{
// call the base class function
clockType::printTime();
cout << " " << tz << endl;
}
// parameerized constructor sets the clock time and time zone to the parameter values
extClockType::extClockType(int hours, int minutes, int seconds,string timeZone):clockType(hours, minutes, seconds)
{
tz = timeZone;
}
//default constructor sets the clock time and time zone to the default values
extClockType::extClockType() : clockType()
{
tz = "";
}
Related
I am new to programming and an trying to create an array with a series of records in and then have the programme accept input and finally print out the contents of the list.
I am having trouble recording the values of some of the variables in my addRecord() function as the output of the code below is the following:
constructor called
-1:-1 Eat lunch
-1:-1 Watch TV
destructor called
Why am I missing the call to L1.addRecord(5, 30, "Make dinner"); completely and why aren't the times coming through (they are coming through as -1 which is set in the constructor)?
Thank you
#include <iostream>
#include <string>
using namespace std;
class Record {
private:
int hour;
int minute;
string todo;
public:
Record()
{
hour = -1;
minute = -1;
todo = "N/A";
}
void setData(int hour, int minute, const char* td);
void setData(Record& e);
void printRecord();
};
class List
{
private:
Record* recordArr;
int maxRecords;
int actualRecordCount;
public:
List(int maxRecords);
List(List& s) {
actualRecordCount = s.actualRecordCount;
maxRecords = s.maxRecords;
recordArr = new Record[maxRecords];
for (int i = 0; i < actualRecordCount; i++)
{
recordArr[i].setData(s.recordArr[i]);
}
std::cout << "copy constructor called." << std::endl;
}
~List();
bool addRecord(int hour, int minute, const char* todo);
void printList();
};
///////////////////////////
void Record::setData(int hour, int minute, const char* td)
{
hour = hour;
minute = minute;
todo = td;
}
void Record::setData(Record& e)
{
hour = e.hour;
minute = e.minute;
todo = e.todo;
}
void Record::printRecord()
{
std::cout << hour << ":" << minute << " " << todo << std::endl;
}
List::List(int maxRecords)
: maxRecords(maxRecords)
{
actualRecordCount = 0;
recordArr = new Record[maxRecords];
std::cout << "constructor called" << std::endl;
}
List::~List()
{
std::cout << "\ndestructor called";
delete[] recordArr;
}
bool List::addRecord(int hour, int minute, const char* todo)
{
Record newRecord; // create new Record
newRecord.setData(hour, minute, todo); //assign values
if (actualRecordCount >= maxRecords) // array full
{
return false;
}
else
{
recordArr[actualRecordCount] = newRecord; // put new Record into the array of Entry
actualRecordCount++; // increment Entry count
return true;
}
}
void List::printList()
{
for (int i = 0; i < actualRecordCount; i++)
{
recordArr[i].printRecord();
cout << endl;
i++;
}
}
int main() {
List L1(20);
L1.addRecord(2, 30, "Eat lunch");
L1.addRecord(5, 30, "Make dinner");
L1.addRecord(7, 30, "Watch TV");
L1.printList();
}
void Record::setData(int hour, int minute, const char* td)
{
hour = hour;
"hour" is the name of a parameter to this setData() method. hour=hour;, therefore, sets this parameter to itself. This accomplishes absolutely nothing, whatsoever. Same for other two assignments that follow.
Your obvious intent here is to initialize the class that happens to have members with the same name. When different things have the same name in C++ there's a complicated set of rules that choose which "thing" the name represents. These rules are the same on the left and the right side of the = operator, so both of these hours end up referring to the same object: the parameter to this class method.
You can simply rename the parameters to the method:
void Record::setData(int hourArg, int minuteArg, const char* tdArg)
{
hour = hourArg;
and so on. Or, if you wish to keep the parameter names the same, make things more explicit:
this->hour=hour;
The other error is here
void List::printList()
{
for (int i = 0; i < actualRecordCount; i++)
{
recordArr[i].printRecord();
cout << endl;
i++;
}
}
You have i++ twice.
One problem is that your Record::setData function with three arguments doesn't actually set the hour and minute fields of the class object! This is caused by your use of arguments with the same name as the class members, which (IMHO) is bad coding style. So, in the following code, your first two assignments just replace the argument values with themselves:
void Record::setData(int hour, int minute, const char* td)
{
hour = hour; // This and the following line are self-assignments to the arguments
minute = minute; // given and, as such, are effectively doing nothing!
todo = td; // This, however, is OK, because there is no ambiguity.
}
To fix this, either add an explicit this-> reference to the targets:
void Record::setData(int hour, int minute, const char* td)
{
this->hour = hour;
this->minute = minute;
todo = td;
}
Or (much better, in my opinion) give the first two arguments non-ambiguous names:
void Record::setData(int in_hour, int in_minute, const char* td)
{
hour = in_hour;
minute = in_minute;
todo = td;
}
I'm getting the problem with getting the desired results.
I've tried a lot of time frying my brain, but it wasn't working... I think the problem is malfunctions of void functions in Date class and some pointer mistakes and advanceTime functions in Clock class, but I feel ambiguous myself how to further progress in this step.
I tried to describe the problem at my best, so could you please help me?
The expected results are like this:
Setting the clock to 2:03:04 using normal setters
02:03:04
Advancing the clock one hour with a value parameter
02:03:04
Advancing the clock one hour with a pointer parameter
03:03:04
Advancing the clock one hour with a reference parameter
04:03:04
Setting the clock to 8:09:10 with cascading setters returning an instance
08:03:04
Setting the clock to 5:06:07 with cascading setters returning a pointer
05:06:07
Setting the clock to 11:12:13 with cascading setters returning a reference
11:12:13
Setting the clock to 23:59:59
23:59:59
Advancing the clock one second
00:00:00
However, what I get is:
Setting the clock to 2:03:04 using normal setters
02:03:04
Advancing the clock one hour with a value parameter
02:03:04
Advancing the clock one hour with a pointer parameter
03:03:04
Advancing the clock one hour with a reference parameter
04:03:04
Setting the clock to 8:09:10 with cascading setters returning an instance
08:03:04
Setting the clock to 5:06:07 with cascading setters returning a pointer
05:03:04
Setting the clock to 11:12:13 with cascading setters returning a reference
11:03:04
Setting the clock to 23:59:59
23:59:59
Advancing the clock one second
23:59:00
I've tried to do some evaluation of remaining things in hour, minute, and second.
Well, I was getting in lost in the ways of getting the 00:00:00 from 59 marginals, and also, some advancing clock is working, but something is not working.
I was actually getting in confused.
Clock.h
// Clock.h
// This class describes a Clock.
class Clock {
private:
int hour;
int minute;
int second;
public:
// Constructor
Clock();
// Normal Setters
void setHour(int newHour);
void setMinute(int newMinute);
void setSecond(int newSecond);
// Cascading Setters returning an instance
Clock setHourIns(int newHour);
Clock setMinuteIns(int newMinute);
Clock setSecondIns(int newSecond);
// Cascading Setters returning a pointer
Clock * setHourPtr(int newHour);
Clock * setMinutePtr(int newMinute);
Clock * setSecondPtr(int newSecond);
// Cascading Setters returning a reference
Clock & setHourRef(int newHour);
Clock & setMinuteRef(int newMinute);
Clock & setSecondRef(int newSecond);
// Getters
int getHour() const;
int getMinute() const;
int getSecond() const;
// Advance one hour
void advanceOneHour();
void advanceOneMinute();
void advanceOneSecond();
// Printing Methods
void printTwoDigits(int number) const;
void printTime() const;
};
Clock.cpp
// Clock.cpp
// This class describes a Clock.
#include <iostream>
#include <iomanip>
#include "Clock.h"
using namespace std;
// Constructor for Clock
Clock::Clock() {
hour = 0;
minute = 0;
second = 0;
}
// Normal Setters
void Clock::setHour(int newHour) {
hour = newHour;
}
void Clock::setMinute(int newMinute) {
minute = newMinute;
}
void Clock::setSecond(int newSecond) {
second = newSecond;
}
// Cascading Setters which return an instance
Clock Clock::setHourIns(int newHour) {
hour = newHour;
return (*this);
}
Clock Clock::setMinuteIns(int newMinute) {
minute = newMinute;
return (*this);
}
Clock Clock::setSecondIns(int newSecond) {
second = newSecond;
return (*this);
}
// Cascading Setters which return an pointer
Clock * Clock::setHourPtr(int newHour) {
hour = newHour;
return this;
}
Clock * Clock::setMinutePtr(int newMinute) {
minute = newMinute;
return this;
}
Clock * Clock::setSecondPtr(int newSecond) {
second = newSecond;
return this;
}
// Cascading Setters which return a reference
Clock & Clock::setHourRef(int newHour) {
hour = newHour;
return (*this);
}
Clock & Clock::setMinuteRef(int newMinute) {
minute = newMinute;
return (*this);
}
Clock & Clock::setSecondRef(int newSecond) {
second = newSecond;
return (*this);
}
// Getters
int Clock::getHour() const {
return hour;
}
int Clock::getMinute() const {
return minute;
}
int Clock::getSecond() const {
return second;
}
// Advance one hour
void Clock::advanceOneHour() {
if((hour + 1) >= 24) {
hour = 0;
}
hour = (hour + 1) % 24;
}
void Clock::advanceOneMinute() {
if((minute + 1) >= 60) {
minute = 0;
hour++;
}
minute = (minute + 1) % 60;
}
void Clock::advanceOneSecond() {
if((second + 1) >= 60) {
second = 0;
minute++;
}
second = (second + 1) % 60;
}
// Printing methods
void Clock::printTwoDigits(int number) const {
cout << setw(2) << setfill('0') << number;
}
void Clock::printTime() const {
printTwoDigits(hour); cout << ":";
printTwoDigits(minute); cout << ":";
printTwoDigits(second); cout << endl;
}
ClockMain.cpp
// ClockMain.cpp
#include <iostream>
#include "Clock.h"
using namespace std;
// Advance the clock by one hour with a value parameter
void advanceOneHourVal(Clock myClock) {
myClock.advanceOneHour();
}
// Advance the clock by one hour with a pointer parameter
void advanceOneHourPtr(Clock * myClock) {
myClock->advanceOneHour();
}
// Advance the clock by one hour with a reference parameter
void advanceOneHourRef(Clock & myClock) {
myClock.advanceOneHour();
}
int main() {
Clock c1;
cout << "Setting the clock to 2:03:04 using normal setters" << endl;
c1.setHour(2); c1.setMinute(3); c1.setSecond(4); c1.printTime();
cout << "Advancing the clock one hour with a value parameter" << endl;
advanceOneHourVal(c1);
c1.printTime();
cout << "Advancing the clock one hour with a pointer parameter" << endl;
advanceOneHourPtr(&c1);
c1.printTime();
cout << "Advancing the clock one hour with a reference parameter" << endl;
advanceOneHourRef(c1);
c1.printTime();
cout << "Setting the clock to 8:09:10 with cascading setters returning an instance" << endl;
c1.setHourIns(8).setMinuteIns(9).setSecondIns(10);
c1.printTime();
cout << "Setting the clock to 5:06:07 with cascading setters returning a pointer" << endl;
c1.setHourIns(5).setMinuteIns(6).setSecondIns(7);
c1.printTime();
cout << "Setting the clock to 11:12:13 with cascading setters returning a reference" << endl;
c1.setHourIns(11).setMinuteIns(12).setSecondIns(13);
c1.printTime();
cout << "Setting the clock to 23:59:59" << endl;
c1.setHourRef(23).setMinuteRef(59).setSecondRef(59);
c1.printTime();
c1.advanceOneSecond();
cout << "Advancing the clock one second" << endl;
c1.printTime();
}
Similarly, I'm also getting the similar errors, in Date class.
The error indicates that there's wrong returning of void functions, in advancing.
Date.cpp
// Date.cpp
// This class describes a Date.
#include <iostream>
#include <iomanip>
#include "Date.h"
using namespace std;
// Constructor for Clock
Date::Date() {
year = 0;
month = 0;
day = 0;
}
// Normal Setters
void Date::setYear(int newYear) {
year = newYear;
}
void Date::setMonth(int newMonth) {
month = newMonth;
}
void Date::setDay(int newDay) {
day = newDay;
}
// Cascading Setters which return an instance
Date Date::setYearIns(int newYear) {
year = newYear;
return (*this);
}
Date Date::setMonthIns(int newMonth) {
month = newMonth;
return (*this);
}
Date Date::setDayIns(int newDay) {
day = newDay;
return (*this);
}
// Cascading Setters which return an pointer
Date * Date::setYearPtr(int newYear) {
year = newYear;
return this;
}
Date * Date::setMonthPtr(int newMonth) {
month = newMonth;
return this;
}
Date * Date::setDayPtr(int newDay) {
day = newDay;
return this;
}
// Cascading Setters which return a reference
Date & Date::setYearRef(int newYear) {
year = newYear;
return (*this);
}
Date & Date::setMonthRef(int newMonth) {
month = newMonth;
return (*this);
}
Date & Date::setDayRef(int newDay) {
day = newDay;
return (*this);
}
// Getters
int Date::getYear() const {
return year;
}
int Date::getMonth() const {
return month;
}
int Date::getDay() const {
return day;
}
// Advance one date
void Date::advanceOneYear() {
year = year + 1;
}
void Date::advanceOneMonth() {
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 9 || month == 11) {
month = (month + 1) % 31;
} else if (month == 2) {
month = (month + 1) % 28;
} else {
month = (month + 1) % 30;
}
}
void Date::advanceOneDay() {
day = (day + 1) % 365;
}
// Printing methods
void Date::printTwoDigits(int number) const {
cout << setw(2) << setfill('0') << number;
}
void Date::printDate() const {
printTwoDigits(year); cout << ":";
printTwoDigits(month); cout << ":";
printTwoDigits(day); cout << endl;
}
Date.h
// Date.h
// This class describes a Clock.
class Date {
private:
int day;
int month;
int year;
public:
// Constructor
Date();
// Normal Setters
void setYear(int newYear);
void setMonth(int newMonth);
void setDay(int newDate);
// Cascading Setters returning an instance
Date setYearIns(int newYear);
Date setMonthIns(int newMonth);
Date setDayIns(int newDate);
// Cascading Setters returning a pointer
Date * setYearPtr(int newYear);
Date * setMonthPtr(int newMonth);
Date * setDayPtr(int newDate);
// Cascading Setters returning a reference
Date & setYearRef(int newYear);
Date & setMonthRef(int newMonth);
Date & setDayRef(int newDate);
// Getters
int getYear() const;
int getMonth() const;
int getDay() const;
// Advance one hour
void advanceOneYear();
void advanceOneMonth();
void advanceOneDay();
// Printing Methods
void printTwoDigits(int number) const;
void printDate() const;
};
DateMain.cpp
// DateMain.cpp
#include <iostream>
#include "Date.h"
using namespace std;
int main() {
Date d1;
cout << "Setting the date to 2018/02/17 using cascading setters" << endl;
d1.setYear(2018).setMonth(2).setDay(17);
d1.printDate();
cout << "Advancing the date one month" << endl;
advanceOneMonth(d1);
d1.printDate();
cout << "Happy St. Patrick's Day!!" << endl << endl;
cout << "Setting the date to 12/31/2018 (US Style) using cascading setters" << endl;
d1.setMonth(12).setDay(31).setYear(2018);
d1.printDate();
cout << "Advancing the date one day" << endl;
advanceOneDay(d1);
d1.printDate();
cout << "Happy New Year!!" << endl;
}
The problem is that you only look at the seconds variable. You need to check to see if there is overflow. Something like this:
if((seconds +1) >= 60) {
//advance one minute...
}
You will need to do similar things in the rest of your clock (minutes, hours, etc) too.
Lets examine this function.
void Clock::advanceOneMinute() {
minute = (minute + 1) % 60;
if((minute + 1) >= 60) {
hour++;
}
}
In pseudocode:
1. Add 1 to minute, divide by 60 and store the remain into minute.
2. If minute is greater or equal than 59, then add 1 to hour
Before calling: minute=58, hour=5.
After calling: minute=59, hour=6.
Fix: swap change and comparison
void Clock::advanceOneMinute() {
if((minute + 1) >= 60) {
hour++;
}
minute = (minute + 1) % 60;
}
Please note that Clock::advanceOneMinute() has the same problem.
In this code I have an object that contains two variables hours and minutes. Im trying to consecutively add a value of 15 minutes and a value of 20 minutes to an object called t1. But I get the error : left of '.plus' must have class/struct/union.
Thanks in advance.
#include <iostream>
#include <iomanip>
using namespace std;
class Time {
public:
Time(int u, int m);
Time(int g);
void plus(Time t);
void plus(int x);
void print();
private:
int min;
int hour;
};
void Time::plus(Time t) {
min += t.min;
if (min > 59) {
hour++;
min = min - 60;
}
}
void Time::plus(int x) {
min += x;
if (min > 59) {
hour++;
min = min - 60;
}
}
void Time::print() {
cout << setw(2) << hour << " hour and " << min << " minutes";
}
Time::Time(int u, int m) : hour(u), min(m) {
}
Time::Time(int m) : hour(0), min(m) {
}
int main() {
Time t1(1, 10);
const Time kw(15);
t1.plus(kw).plus(20);
cout << "t1 = "; t1.print(); cout << endl;
cin.get();
return 0;
}
Right now, your plus returns void, or nothing! So you can't do t1.plus(kw).plus(20);. If you want to, you need to have your .plus() return a Time:
class Time {
public:
Time &plus(Time t);
Time &plus(int x);
...
};
I've gone ahead and made it return a Time by reference so that when you chain the function like you are, the next plus will still modify the original object the first plus was called on! We can do this if you implement the plus functions like:
Time &Time::plus(Time t) {
min += t.min;
if (min > 59) {
hour++;
min = min - 60;
}
return *this; //return ourselves so that the next func will be called on us too!
}
Time &Time::plus(int x) {
min += x;
if (min > 59) {
hour++;
min = min - 60;
}
return *this; //return ourselves so that the next func will be called on us too!
}
I am trying to write a class with 3 attribute and some constructors and following methods: set (h, m, s), Double getHousrs () operator +
correctTime(). To change e.g 1:76:84 to 2:13:13
Current code
#include <iostream>
using namespace std;
class duration {
public:
duration(int h, int m, int s)
:hour (h), minutes (m), seconds (s);
{}
void printDate()
{
cout << hour<< ":" << minutes << ":" << seconds << endl;
}
double getHours() {
return hours;
}
double getSeconds() {
return seconds;
}
private:
int hour;
int minutes;
int seconds;
duration operator+(duration &obj)
{ }
};
int main()
{
duration obj;
return 0;
}
The solution to your problem would be to add the values together which can be most efficiently done like this I also fixed all the other errors you had in your class:
#include <iostream>
using namespace std;
class duration {
public:
duration(int h, int m, int s)
:hour (h), minute (m), second (s)
{}
void printDate()
{
cout << hour<< ":" << minute << ":" << second << endl;
}
double getHours() {
return hour;
}
double getSeconds() {
return second;
}
duration operator + (const duration& other)
{
duration temp(0, 0, 0);
temp.second = (other.second+second)%60;
temp.minute = ((other.second + second)/60 + other.minute + minute)%60;
temp.hour = ((other.minute+minute)/60 + other.hour + hour)%60;
return temp;
}
private:
int hour;
int minute;
int second;
};
int main()
{
duration obj(3, 5, 10);
duration obj2(4, 55, 40);
duration temp = obj + obj2;
temp.printDate();
return 0;
}
I have two classes (appointment, schedule), and a driver (main).
main.cpp:
#include <iostream>
#include "schedule.h"
#include "appointment.h"
using namespace std;
int main()
{
schedule mySch2("hello");
appointment myAppt(100002,"appointment",10,1,2013);
myAppt.printS(cout,2);
mySch2.addtoSchedule(myAppt);
system("PAUSE");
return EXIT_SUCCESS;
}
schedule.h
#ifndef SCHEDULE_H
#define SCHEDULE_H
#include<iostream>
#include "appointment.h"
using namespace::std;
const int SCH_ENTRIES = 10;
class schedule
{
public:
schedule(void);
schedule(const char *p);
bool addtoSchedule(const appointment &);
private:
char title[40];
int count;
appointment appointmentArray[SCH_ENTRIES];
};
#endif
schedule.cpp
#include "schedule.h"
#include "appointment.h"
#include <iostream>
using namespace::std;
schedule::schedule(void)
{
}
schedule::schedule(const char *p)
{
strcpy(title, p);
count = 0;
cout << title << endl;
cout << count << endl;
cout << "----" << endl;
}
bool schedule::addtoSchedule(const appointment & myAppt)
{
cout << appointmentArray[0].getDay();
return false;
}
appointment.h (I did not write this, this was provided) - not super important for this question
#ifndef APPOINTMENT_H
#define APPOINTMENT_H
#include <fstream>
#include <cstring>
using std::ostream;
// The Designer decides upon the following data and actions (i.e. Functions)
// and places the class in the file appointment.h
class appointment
{
public:
appointment(void); // default constructor
appointment(long, const char [],int d, int m, int y); // 5 argument constructor
appointment(const appointment &); // copy constructor
void keyBoardInput(void); // Assume no blanks in the desc
long getSource(void) const; // return source
void setSource(long); // change source
void setMonth(int);
void setDay(int);
void setYear(int);
int getMonth(void) const;
int getDay(void) const;
int getYear(void) const;
const char *getDescription(void) const; // return the address of the description
void changeDescription(const char *) ; // change an existing description
void copyTo(appointment &) const; // copy invoking instance to parameter
void incrementDate (void); // advance the date by ONE day
// You can assume 30 days in each month
void printS(ostream &, int dateFormat) const; // print all fields
// dateFormat == 1 month/day/year
// dateFormat == 2 day/month/year
~appointment(); // destructor - indicate the address
// of the variable that is leaving
private:
void setDescription(const char *); // used to allocated memory
// data
long source; // id of the person scheduling the appointment
char * desc; // description of the appointment - Dynamic Data
int day; // day, month, and year when the appointment
int month; // will happen
int year;
};
#endif
appointment.cpp (I did not write this, this was provided) - not super important for this question
#include "appointment.h"
#include <iostream>
using std::cin;
using std::cout;
appointment::appointment()
{
day = 0;
cout << "default appt\n";
}
appointment::appointment(long lSource, const char cDescription[], int d, int m, int y)
{
source = lSource;
day = d;
month = m;
year = y;
setDescription(cDescription);
}
appointment::appointment(const appointment & aToCopy)
{
source = aToCopy.getSource();
day = aToCopy.getDay();
month = aToCopy.getMonth();
year = aToCopy.getYear();
setDescription(aToCopy.getDescription());
}
void appointment::setDescription(const char * cSource)
{
if (desc != NULL) free (desc);
if (cSource == NULL)
return;
desc = (char *)malloc (strlen (cSource) + 1);
strcpy(desc, cSource);
}
long appointment::getSource(void) const
{
return source;
}
void appointment::setSource(long lSource)
{
source = lSource;
}
void appointment::setMonth(int iMonth)
{
month = iMonth;
}
void appointment::setDay(int iDay)
{
day = iDay;
}
void appointment::setYear(int iYear)
{
year = iYear;
}
int appointment::getMonth(void) const
{
return month;
}
int appointment::getDay(void) const
{
return day;
}
int appointment::getYear(void) const
{
return year;
}
//return the address of the description
const char * appointment::getDescription(void) const
{
return desc;
}
//change an existing description
void appointment::changeDescription(const char * cDescription)
{
setDescription(cDescription);
}
void appointment::copyTo(appointment &p) const
{
p.source = source;
p.day = day;
p.month = month;
p.year = year;
p.setDescription(desc);
}
void appointment::incrementDate(void)
{
int days;
switch (month)
{
case 1: // Jan: 31 Days
case 3: // Mar: 31 Days
case 5: // May: 31 Days
case 7: // Jul: 31 Days
case 10: // Oct: 31 Days
case 12: // Dec: 31 Days
days = 31;
break;
case 4: // Apr: 30
case 6: // Jun: 30
case 8: // Aug: 30
case 9: // Sep: 30
case 11: // Nov: 30
days = 30;
break;
case 2: // Feb: 28/29 Days (Depends on year modulus 4 a modulus 100).
days = !(year % 4) || !(year % 100) ? 29 : 28;
break;
}
day++;
if (day > days)
{
month++;
day = 1;
if (month > 12)
{
month = 1;
year++;
}
}
}
void appointment::printS(ostream &out, int dateFormat) const
{
if (dateFormat == 1)
{
out << month << "/" << day << "/" << year << "\n";
}
else if (dateFormat == 2)
{
out << day << "/" << month << "/" << year << "\n";
}
else
out << "Unsupported dateFormat parameter specified (should be 1 or 2).";
}
appointment::~appointment()
{
if (desc != NULL)
{
free (desc);
desc = NULL;
}
}
void appointment::keyBoardInput()
{
char temp[1024];
cout << "Please type the description: ";
cin.getline (temp, sizeof(temp) - 1, '\n');
cout << std::endl;
setDescription(temp);
}
My error occurs when the main driver calls mySch2.addtoSchedule(myAppt);
If I uncomment out the line inside of schedule appointmentArray[0].getDay() then everything runs and works fine with no segmentation error. As soon as that line gets uncommented, it throws the error during runtime (after a crash and I go into the debugger and step through the program).
You never initialize desc to nullptr for class appointment before invoking setDescription. This happens in both constructors. Learn to use an initializer list:
appointment::appointment()
: source(), desc(), day(), month(), year()
{
cout << "default appt\n";
}
appointment::appointment(long lSource, const char cDescription[], int d, int m, int y)
: source(lSource), desc(), day(d), month(m), year(y)
{
setDescription(cDescription);
}
appointment::appointment(const appointment & aToCopy)
: source(aToCopy.getSource())
, desc()
, day(aToCopy.getDay())
, month(aToCopy.getMonth())
, year(aToCopy.getYear())
{
setDescription(aToCopy.getDescription());
}
Why did it fault?
Without initialization the value in desc is indeterminate and therefore undefined behavior to dereference, and certainly so to pass to free.
void appointment::setDescription(const char * cSource)
{
if (desc != NULL) free (desc); // desc contains non-null garbage.
if (cSource == NULL)
return;
desc = (char *)malloc (strlen (cSource) + 1);
strcpy(desc, cSource);
}
That said, I would strongly encourage using a std::string instead. It would make the copy-consructor for this class completely disappear, and the default constructor trivial.
Comments about using malloc() in a C++ program reserved, as that opinion is all-but beat to death already on this forum (and I agree with te prevailing opinion).