I am trying to compile my code and I keep getting the error:
redefinition of 'SimpleDate::SimpleDate(int, int, int)
I think the error is usually because of not adding #ifndef, #define, and #endif but I did add those.
simple_date.h:
#ifndef SIMPLE_DATE_H
#define SIMPLE_DATE_H
#include <string>
class SimpleDate
{
int _year, _month, _day;
public:
// create a new 'SimpleDate' object with the given year, month, and day
// throws an invalid_argument error if the date is invalid
SimpleDate(int year, int month, int day) {};
// returns the current year
int year() const { return 0; };
// returns the current month
int month() const { return 0; };
// returns the current day of the month
int day() const { return 0; };
// return string formatted as year-month-day with day an month 0 prefixed
// i.e. 2000-01-01 is Jan 01, 2000
std::string to_string() const { return ""; };
// comparison operators
bool operator==(const SimpleDate& lhs) const { return true; };
bool operator!=(const SimpleDate& lhs) const { return true; };
bool operator> (const SimpleDate& lhs) const { return true; };
bool operator< (const SimpleDate& lhs) const { return true; };
bool operator>=(const SimpleDate& lhs) const { return true; };
bool operator<=(const SimpleDate& lhs) const { return true; };
// returns 'true' if current year is a leap year
bool is_leap() const { return true; };
// returns the day of the week; 0 = Sunday
// HINT: To calculate the day of the week, you need to have a known day. Use
// 1970-01-01 which was a Thursday. Make sure to reference where you found
// the algorithm or how you came up with it.
int wday() const { return 0; };
// returns the day of the year; Jan 1st = 1
int yday() const { return 0; };
// add one day to current date
SimpleDate& incr_day() { SimpleDate dd {2016, 1, 1}; };
SimpleDate& operator++() { SimpleDate dd {2016, 1, 1}; };
// add n day(s) to current date
SimpleDate& operator+=(int n) { SimpleDate dd {2016, 1, 1}; };
// subtract one day from current date
SimpleDate& decr_day() { SimpleDate dd {2016, 1, 1}; };
SimpleDate& operator--() { SimpleDate dd {2016, 1, 1}; };
// subtract n day(s) from current date
SimpleDate& operator-=(int n) { SimpleDate dd {2016, 1, 1}; };
// add one month to current date
SimpleDate& incr_month() { SimpleDate dd {2016, 1, 1}; };
// subtract one month from current date
SimpleDate& decr_month() { SimpleDate dd {2016, 1, 1}; };
// add one year to current date
SimpleDate& incr_year() { SimpleDate dd {2016, 1, 1}; };
// subtract one year from current date
SimpleDate& decr_year() { SimpleDate dd {2016, 1, 1}; };
// returns 'true' if current date is a Monday
bool is_monday() const { return true; };
// returns 'true' if current date is a Tuesday
bool is_tuesday() const { return true; };
// returns 'true' if current date is a Wednesday
bool is_wednesday() const { return true; };
// returns 'true' if current date is a Thursday
bool is_thursday() const { return true; };
// returns 'true' if current date is a Friday
bool is_friday() const { return true; };
// returns 'true' if current date is a Saturday
bool is_saturday() const { return true; };
// returns 'true' if current date is a Sunday
bool is_sunday() const { return true; };
};
#endif
simple_date.cpp:
#include "simple_date.h"
SimpleDate::SimpleDate(int year, int month, int day)
{
std::cout >> year;
if (year < 1970 || year > 2020)
{
throw invalid_argument("Don't care about years less than 1970 or greater than 2020");
}
else
{
_year = year;
}
if (month < 1 || month > 12)
{
throw invalid_argument("Not a real month");
}
else
{
_month = month;
}
if (day < 1 || day>31)
{
throw invalid_argument("Not a real day");
}
else if ((_month == 2 || _month == 4 || _month == 6 || _month == 9 || _month == 11) && day > 30)
{
throw invalid_argument("Not a real day for this month");
}
else if (_month == 2 && day == 29)
{
if (this.is_leap())
_day = day;
else
hrow invalid_argument("Not a real day for this month and year");
}
else
_day = day;
}
You defined the constructor in the header file, here:
SimpleDate(int year, int month, int day) {};
Those innocent-looking braces turned this declaration into a definition. And then compiler got very upset when it later encountered the real definition of this constructor. Just remove them:
SimpleDate(int year, int month, int day);
Related
Hy! This is my first question on this site. Sorry for my English, if I will make mistakes:(
So, my problem is the following. I have simple class Date.
class Date
{
public:
Date();
Date(unsigned short day, unsigned short month, unsigned short year);
Date(const Date &date);
unsigned short getDay();
unsigned short getMonth();
unsigned short getYear();
void setDay(unsigned short day);
void setMonth(unsigned short month);
void setYear(unsigned short year);
void printOnScreen()const;
friend
std::ostream& operator<< (std::ostream& out, const Date& date) {
out << date.day << "." << date.month << "." << date.year;
return out;
}
friend
bool operator<(const Date& a, const Date& b) {
if (a == b) {
return false;
}
if (a.year < b.year) {
return true;
}
if (a.month < b.month) {
return true;
}
if (a.day < b.day) {
return true;
}
return false;
}
friend
Date& operator-(Date& a) {
return a;
}
friend
Date operator-(const Date& a, const Date& b) {
return Date(
abs(a.day - b.day),
abs(a.month - b.month),
abs(a.year - b.year)
);
}
friend
bool operator==(const Date& date1, const Date& date2) {
return (
date1.day == date2.day &&
date1.month == date2.month &&
date1.year == date2.year
);
}
virtual ~Date();
private:
friend KeyHasher;
unsigned short day;
unsigned short month;
unsigned short year;
};
In my main function I call sort like in this example, and after it get the error.
auto dates = {
Date(1, 5, 2016),
Date(3, 2, 2015),
Date(3, 3, 2000),
Date(2, 1, 1991),
Date(1, 8, 2200),
Date(1, 8, 2200),
Date(1, 8, 2020),
Date(21, 9, 2016)
};
vector<Date> v1(dates);
sort(
v1.begin(),
v1.end(),
less<Date>()
);
What is wrong, I don't understand. Thank you for help.
Your operator < is indeed incorrect, use std::tie:
auto as_tuple(const Date& d) {
return std::tie(d.year, d.month, d.day);
}
bool operator<(const Date& lhs, const Date& rhs) {
return as_tuple(lhs) < as_tuple(rhs);
}
bool operator == (const Date& lhs, const Date& rhs) {
return as_tuple(lhs) == as_tuple(rhs);
}
Try to change your conditions like:
if (a.year < b.year)
return true;
else if (a.year > b.year)
return false;
else // a.year == b.year
{
if (a.month < b.month)
return true;
else if (a.month > b.month)
return false;
else // a.month == b.month
{
if (a.day < b.day)
return true;
else
return false;
}
}
I have a program that asks the user to input to dates then it displays which one is more recent I've done it like this
if (year1>year2 || month1>month2 || day1>day2)
return -1;
if (year1<year2 || month1<month2 || day1<day2)
return +1;
but the output is not quite correct.
Here's a clean way to do it:
#include <tuple> // for std::tie
auto date1 = std::tie(year1, month1, day1);
auto date2 = std::tie(year2, month2, day2);
if (date1 == date2)
return 0;
return (date1 < date2) ? -1 : 1;
The comparisons of std::tie objects are lexicographical, so this returns -1 if date1 is less than date2, 0 if they are the same, and 1 if date1 is greater than date2.
You might be better off defining your own date type (or use boost::datetime).
struct Date
{
unsigned year;
unsigned month;
unsigned day;
};
bool operator<(const Date& lhs, const Date& rhs)
{
return std::tie(lhs.year, lhs.month, lhs.day) <
std::tie(rhs.year, rhs.month, rhs.day);
}
bool operator>(const Date& lhs, const Date& rhs) { .... }
bool operator==(const Date& lhs, const Date& rhs) { .... }
int date_cmp(const Date& lhs, const Date& rhs)
{
// use operators above to return -1, 0, 1 accordingly
}
You need a much more complicated check than that:
if (year1 > year2)
return -1;
else if (year1 < year2)
return +1;
if (month1 > month2)
return -1;
else if (month1 < month2)
return +1;
if (day1 > day2)
return -1;
else if (day1 < day2)
return +1;
return 0;
NOTE: Returning -1 for first is greater than second seems counter-intuititive to me, however I have followed the semantics provided by the OP.
This statement
if (year1>year2 || month1>month2 || day1>day2)
return -1;
tests if any one of the three conditions is true. So, if year1 is higher than year 2, or month1 is higher than month2. Lets stop there. Consider
year1 = 2013, month1 = 12, day1 = 31;
year2 = 2014, month2 = 1, day1 = 1;
We know that, infact, year2 is a higher value, but what happens is
is year1 > year2? no
ok, but is month1 > month2? yes
This makes it look like the first year is a higher value, but it's not, it just a higher month value.
As you get further into C++ you'll find that it's a good idea to try and adopt a convention of making all your comparisons use a single operator (< or >), when you reach a point where you are working with operators you'll understand why.
if (year2 < year1)
return 1;
// we reach this line when year1 <= year2
if (year1 < year2) // elimnate the < case
return -1;
// having eliminated both non-matches,
// we know that by reaching point that both
// dates have the same year. Now repeat for
// the month value.
if (month2 < month1)
return 1;
if (month1 < month2)
return -1;
// year and month must be the same, repeat for day.
if (day2 < day1)
return 1;
if (day1 < day2)
return -1;
return 0; // exact match
//You can try this
int lday,lmonth,lyear;
int nday,nmonth,nyear;
int lhour,lminute;
int nhour,nminute;
sscanf(New_Time,"%d-%d",&nhour,&nminute); //reads the numbers
sscanf(Last_Time,"%d-%d",&lhour,&lminute); //from the string
sscanf(New_Date,"%d-%d-%d",&nday,&nmonth,&nyear);
sscanf(Last_Date,"%d-%d-%d",&lday,&lmonth,&lyear);
//cout << "Last date: " << lday << "-" << lmonth << "-" << lyear <<endl;
//cout << "New date: " << nday << "-" << nmonth << "-" << nyear <<endl;
if(nyear>lyear)
return 0;
if(nyear==lyear) {
if(nmonth > lmonth)
return 0;
if (nmonth == lmonth) {
if(nday > lday)
return 0;
if (nday == lday) {
if( nhour > lhour)
return 0;
if( nhour == lhour) {
if(nminute>lminute) {
//cout << "new time >= last time" << endl <<endl;
return 0;
}
else return 1;
}
else return 1;
}
else return 1;
}
else return 1;
}
else return 1;
struct Day
{
int value;
explicit Day(int value)
{
this->value = value;
}
};
struct Month
{
int value;
explicit Month(int value)
{
this->value = value;
}
};
struct Year
{
int value;
explicit Year(int value)
{
this->value = value;
}
};
class Date {
public:
Date(Day newDay, Month newMonth, Year newYear)
{
_day = newDay.value;
_month = newMonth.value;
_year = newYear.value;
}
int GetYear() const {
return _year;
};
int GetMonth() const {
return _month;
};
int GetDay() const {
return _day;
};
private:
int _year;
int _month;
int _day;
};
bool operator < (const Date& lhs, const Date& rhs)
{
if (lhs.GetYear() == rhs.GetYear()) {
if (lhs.GetMonth() == rhs.GetMonth()) {
if (lhs.GetDay() == rhs.GetDay()) {
return false;
}
return lhs.GetDay() < rhs.GetDay();
}
return lhs.GetMonth() < rhs.GetMonth();
}
return lhs.GetYear() < rhs.GetYear();
};
Currently I'm writing a program that has a section to determine the difference in days between two dates, but by overloading the minus operator.
I'm currently staring at my screen drawing a complete blank. I have some fleeting thoughts in my head but they are exactly that, fleeting.
What's to happen in the main.cpp is that there are going to be two variables, for instance beethovenDeathDate and beethovenBirthDate that will be subtracted to determine how long he lived for. Which is something around 22000 days if I recall correctly.
So without further ado, here is my code:
Date.cpp
const std::string Date::MONTH_STRINGS[] =
{
"", //one based indexing
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
};
const int Date::DAYS_PER_MONTH[] =
{
0, //one based indexing
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
Date::Date(int day, int month, int year) : _year(year), _month(month), _day(day)
{
isValid();
}
Date::Date()
{
time_t t = time(0); // get time now
struct tm * now = localtime( & t );
_year = now -> tm_year + 1900;
_month = now -> tm_mon + 1;
_day = now -> tm_mday;
}
int Date::maxDay(int month, int year)
{
int ret = DAYS_PER_MONTH[month];
if(isLeapYear(year) == true && month == 2)
{
++ret;
}
return ret;
}
void Date::addDay(bool forward)
{
if(forward)
{
if(_day < maxDay(_month, _year))
{
++_day;
}
else
{
_day = MIN_DAY;
++_month;
if(_month > MAX_MONTH)
{
_month = MIN_MONTH;
++_year;
}
}
}
else
{
if(_day <= MIN_DAY)
{
--_month;
if(_month < MIN_MONTH)
{
_month = MAX_MONTH;
--_year;
}
_day = maxDay(_month, _year);
}
else
{
--_day;
}
}
}
std::string Date::toString() const
{
if(isValid() == false)
{
return std::string();
}
std::stringstream ss;
ss << MONTH_STRINGS[_month] << " " << _day << ", " << _year;
return ss.str();
}
bool Date::isValid() const
{
if(_month < MIN_MONTH || _month > MAX_MONTH)
{
std::cerr << "Invalid date " << std::endl;
return false;
}
int daysThisMonth = maxDay(_month, _year);
if(_day < MIN_DAY || _day > daysThisMonth)
{
std::cerr << "Invalid date " << std::endl;
return false;
}
return true;
}
bool Date::isLeapYear(int year)
{
if(!(year % 4))
{
if(!(year % 100))
{
if(!(year % 400))
{
return true;
}
else
{
return false;
}
}
else
{
return true;
}
}
else
{
return false;
}
}
bool Date::isLeapYear() const
{
return isLeapYear(_year);
}
bool Date::isLeapDay() const
{
return isLeapDay(_day, _month, _year);
}
bool Date::isLeapDay(int day, int month, int year)
{
if(day == 29 && month == 2 && isLeapYear(year) == true)
{
return true;
}
else
{
return false;
}
}
void Date::addYears(int years)
{
if(years == 0)
{
return;
}
if(isLeapDay() && !isLeapDay(_day, _month, _year + years))
{
_day = Date::DAYS_PER_MONTH[_month];
}
_year += years;
}
void Date::addMonths(int months)
{
if(months == 0)
{
return;
}
int deltayears = months / MAX_MONTH;
int deltamonths = months % MAX_MONTH;
int newMonth = 0;
if(months > 0)
{
newMonth = (_month + deltamonths) % MAX_MONTH;
if((_month + deltamonths) > MAX_MONTH)
{
++deltayears;
}
}
else
{
if((_month + deltamonths) < MIN_MONTH)
{
--deltayears;
newMonth = _month + deltamonths + MAX_MONTH;
}
else
{
newMonth = _month + deltamonths;
}
}
if(_day > maxDay(newMonth, _year + deltayears))
{
_day = maxDay(newMonth, _year + deltayears);
}
_year += deltayears;
_month = newMonth;
}
void Date::addDays(int days)
{
if(days == 0)
{
return;
}
if(days < 0)
{
for(int i = 0; i > days; --i)
{
addDay(false);
}
return;
}
for(int i = 0; i < days; ++i)
{
addDay(true);
}
}
std::ostream& operator<<(std::ostream& os, const Date& date)
{
os << date.toString();
return os;
}
Date Date::operator+(int days) const
{
Date ret = *this;
ret.addDays(days);
return ret;
}
Date& Date::operator+=(int days)
{
addDays(days);
return *this;
}
//This is where I get stumped (the parameters was just one of my failed experiments
Date& Date::operator-(int day, int month, int year)
{
}
The function can be written either as a member, or as a free function. The member function signature would look like this:
TimeDuration Date::operator-(Date const & rhs) const
The free function would look like this:
TimeDuration operator-(Date const & lhs, Date const & rhs)
TimeDuration here is a completely seperate type representing a length of time. If you want, you could just make it an int signifying the number of days, but it would be better, in my opinion, to have a more expressive type for this purpose. Whatever you decide regarding the return type, it doesn't make any sense for the type to be Date (and certainly not Date&).
A possible (albeit not incredibly efficient) implementation, given that you've already written a function to add a day to a date, would be something like this:
if lhs_date comes before rhs_date
add days to (a copy of) lhs_date until lhs_date == rhs_date
return the negative of number of days added
if rhs_date comes before lhs_date
add days to (a copy of) rhs_date until rhs_date == lhs_date
return the number of days added
else
return 0
Another function you might want (or maybe this is what you actually wanted originally, but your wording doesn't indicate it) is a function which can subtract a length of time from a Date. In that case, the return value would be another Date object (but not Date&), and the possible signatures would look something like this:
Date Date::operator-(TimeDuration rhs) const // member version
Date operator-(Date const & lhs, TimeDuration const & rhs) // non-member version
You should do this:
//This is where I get stumped (the parameters was just one of my failed experiments
TimeDuration& Date::operator-(Date const & d1)
{
// ... processing ...
// this - d1;
}
and call it as:
Date d1 = new Date(20, 01, 2013);
TimeDuration duration = d1 - (new const Date(20, 01, 1922));
// Calculate no. of days or years using duration
The logic is as follows:
Pass two Date objects (first could be implicit) to the overloading function and return TimeDuration
To invoke this operator, you may create a Date object with the data that you have, instead of passing each value separately.
Please check for exact syntax.
After much error shooting, I've got a compiling program that runs, but encounters an issue.
It will hang at a certain point, when it seems to call a function.
Main.ccp
#include <cstdlib>
#include <iostream>
#include "Date.h"
using namespace ::std;
string weekday(Date date);
int main() {
int day, month, year;
cout << "What date (d m y)? ";
cin >> day >> month >> year;
Date event (day, month, year);
cout << ("That was a " + weekday(event));
return 0;
}
string weekday(Date date) {
const string days[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"};
Date trial (1, 1, 1);
int weekday = 6;
if (date.precedes(trial)) {
return "Mysteryday";
} else {
while (trial.precedes(date)) {
trial.advance();
weekday = (weekday + 1) % 7;
}
return days[weekday];
}
}
Date.ccp
#include "Date.h"
Date::Date(int day, int month, int year) {
day_ = day;
month_ = month;
year_ = year;
}
int Date::getDay () {
return day_;
}
void Date::setDay (int day) {
day_ = day;
}
int Date::getMonth () {
return month_;
}
void Date::setMonth (int month) {
month_ = month;
}
int Date::getYear () {
return year_;
}
void Date::setYear (int year) {
year_ = year;
}
bool Date::isLeapYear () {
bool lear = false;
if (this->year_ <= 1752) {
if (this->year_ % 4 == 0) {
lear = true;
}
}
else {
lear = false;
}
if (this->year_ > 1752) {
if (this->year_ % 4 == 0 && this->year_ % 100 != 0) {
lear = true;
}
else if (this->year_ % 4 == 0 && this->year_ % 100 == 0 && this->year_ % 400 == 0) {
lear = true;
}
else {
lear = false;
}
}
return lear;
}
int Date::daysInMonth () {
switch (this->month_) {
case 9 :
case 4 :
case 6 :
case 11 :
return 30;
default :
return 31;
case 2 :
return this->isLeapYear() ? 29 : 28;
}
}
void Date::advance () {
this->day_;
if (this->day_ == 3 && this->month_ == 9 && this->year_ == 1752) {
day_ = 14;
month_ = 9;
year_ = 1752;
}
if (this->day_ > this->daysInMonth()) {
this->day_ = 1;
this->month_++;
}
if (this->month_ > 12) {
this->month_ = 1;
this->year_++;
}
}
bool Date::precedes (Date date) {
return this->year_ < date.year_
|| this->year_ == date.year_ && this->month_ < date.month_
|| this->year_ == date.year_ && this->month_ == date.month_ && this->day_ < date.day_;
}
Date.h
#ifndef DATE_H
#define DATE_H
class Date {
public:
Date (int day, int month, int year);
int getDay();
void setDay(int day);
int getMonth();
void setMonth(int month);
int getYear();
void setYear(int year);
bool isLeapYear();
int daysInMonth();
void advance();
bool precedes(Date date);
private:
int day_;
int month_;
int year_;
};
#endif /* DATE_H */
Under the main.ccp, the program seems to hang at this point:
} else {
while (trial.precedes(date)) {
trial.advance();
weekday = (weekday + 1) % 7;
}
If I enter values before 'trial', (Trial is 1 1 1). If I enter 0 0 0, the correct output is displayed of 'Mystery day'.
However any values after the trial value, the program will hang.
It seems to me there is an error somewhere in the Date.ccp on one of the functions such as isLeapYear, advance, or daysInMonth.
Any ideas?
Seems like the advance function
void Date::advance () {
this->day_;
// lots of checks
}
doesn't advance anything.
That will cause the while-condition to never become true.
A while ago I was given the task of converting a Java program to C++.
I've done this, and I've started encountering some odd errors that don't seem to make any sense to me.
The program consists of three files. A main.ccp, a date.ccp and a date.h.
main.ccp
#include <cstdlib>
#include <iostream>
#include "Date.h"
using namespace ::std;
string weekday(Date date);
int main() {
int day, month, year;
cout << "What date (d m y)? ";
cin >> day >> month >> year;
Date event = Date(day, month, year);
cout << ("That was a " + weekday(event));
return 0;
}
string weekday(Date date) {
const string days[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"};
Date trial = Date(1, 1, 1);
int weekday = 6;
if (Date::precedes(trial)) {
return "Mysteryday";
} else {
while (trial.precedes(date)) {
trial.advance();
weekday = (weekday + 1) % 7;
}
return days[weekday];
}
}
Date.ccp
#include "Date.h"
Date::Date(int day, int month, int year) {
day_ = day;
month_ = month;
year_ = year;
}
int Date::getDay () {
return day_;
}
void Date::setDay (int day) {
day_ = day;
}
int Date::getMonth () {
return month_;
}
void Date::setMonth (int month) {
month_ = month;
}
int Date::getYear () {
return year_;
}
void Date::setYear (int year) {
year_ = year;
}
bool Date::isLeapYear () {
bool lear = false;
if (this->year_ <= 1752) {
if (this->year_ % 4 == 0) {
lear = true;
}
}
else {
lear = false;
}
if (this->year_ > 1752) {
if (this->year_ % 4 == 0 && this->year_ % 100 != 0) {
lear = true;
}
else if (this->year_ % 4 == 0 && this->year_ % 100 == 0 && this->year_ % 400 == 0) {
lear = true;
}
else {
lear = false;
}
}
return lear;
}
int Date::daysInMonth () {
// "30 days hath September ... "
switch (this->month_) {
case 9 :
case 4 :
case 6 :
case 11 :
return 30;
default :
return 31;
case 2 :
return this->isLeapYear() ? 29 : 28;
}
}
void Date::advance () {
this->day_;
if (this->day_ == 3 && this->month_ == 9 && this->year_ == 1752) {
day_ = 14;
month_ = 9;
year_ = 1752;
}
if (this->day_ > this->daysInMonth()) {
this->day_ = 1;
this->month_++;
}
if (this->month_ > 12) {
this->month_ = 1;
this->year_++;
}
}
bool Date::precedes (Date date) {
return this->year_ < date->year_
|| this->year_ == date->year_ && this->month_ < date->month_
|| this->year_ == date->year_ && this->month_ == date->month_ && this->day_ < date->day_;
}
Date.h
#ifndef DATE_H
#define DATE_H
class Date {
public:
Date (int day, int month, int year);
int getDay();
void setDay();
int getMonth();
void setMonth();
int getYear();
void setYear();
bool isLeapYear();
int daysInMonth();
void advance();
bool precedes(Date date);
private:
int day_;
int month_;
int year_;
};
#endif /* DATE_H */
I seem to be getting lots of the same errors when I compile.
Date.cpp:97:95: error: base operand of ‘->’ has non-pointer type ‘Date’
I'm not sure if I've done the declaration right or not.
You forgot to put semicolons after your class's closing }.
The class definition for Date is not terminated with a semicolon. Because you #included this file in main.cpp, the first statement after the header is the one that won't parse due to this syntax error; thus you get the error in the wrong place.