views:

476

answers:

7

Hello, I am writing a "Date" class for an assignment and I am having trouble doing one the of the functions.

This is the header file for the class.

class Date
{
public:
Date();                                  // Constructor without parameters
Date(int m, int d, int y); // Constructor with parameters.

// accessors
int GetMonth();               // returns the size of the diamond
int GetDay();
int GetYear();

// mutators
bool Set(int m, int d, int y);
bool SetFormat(char f);

// standard input and output routines
void Input();             
void Show();              
void Increment(int numDays = 1);                 
int Compare(const Date& d);     

private:
int month,                    // month variables
    day,                 // day variable
    year;               // year variable
char format;
};

The member function I am trying to make is the int Compare(const Date& d) function. I need this function to compare two Date objects (the calling object and the parameter), and should return: -1 if the calling object comes first chronologically, 0 if the objects are the same date, and 1 if the parameter object comes first chronologically.

I have tried doing a simple if statement with the == operator but I get errors.

  if (d1 == d2)
     cout << "The dates are the same";
     return (0);

After the objects are created, the function should be called like this d1.Compare(d2)

Thank you in advance!

+3  A: 

into the class's public area

bool operator==(const Date& rhs) const {
    return
       year == rhs.year
       && month == rhs.month
       && day == rhs.day
    ;
}
Notinlist
Notice that the method is const. Your Compare() method (and others) should be const too. If your Compare() would be const I could call it from the operator==() :-)
Notinlist
+3  A: 

Compare object by contents, i.e. in your case the dates are equal of the day, month and year are equal (and perhaps format - depending on your semantics).

Also, C++ already includes a great facility for object comparison: operator == which allows writing clearer code than calling a Compare method.

By the way, take care with this:

  if (d1 == d2)
     cout << "The dates are the same";
     return (0);

If the condition is true, the cout line will be executed. The return will be executed even if the condition is false.

Eli Bendersky
+1, nice catch on the return the statement.
Void
+3  A: 
int Date :: Compare (const Date& d) {

   if (year<d.year) {
      return -1;
   }
   else if (year>d.year) {
      return 1;
   }
   else if (month<d.month) {
      return -1;
   }
   else if (month>d.month) {
      return 1;
   }
   // same for day

   return 0;
}

Usually, you'lll also want to provide overloaded comparison operators, for example (also within the class definition):

bool operator == (const Date& d) const {
   return !Compare(d);
}

bool operator < (const Date& d) const {
  return Compare(d)<0;   
}

... // consider using boost::operators

PS: There are smarter implementations of Compare() - just check the other answers. This one is pretty straightforward and readable, but conforms exactly to your specification.

Alexander Gessler
Thank you, that's exactly what I was trying to do.
jualin
+1  A: 

You can't do d1 === d2, because I believe it compares the memory addresses (haven't done C++ in a while).

What you need to do is write a function that will compare each member of your Date class and return negative number, 0, or positive number. Negative means lesser, 0 means the same, and positive means greater.

For example, in Java:

public int compareTo(Date date) {
  int returnValue = 0;

   returnValue = this.getYear() - date.getYear();

   if(returnValue == 0) {
      returnValue = this.getMonth() - date.getMonth();

      if(returnValue == 0) {
         returnValue = this.getDay() - date.getDay();
      }
   }
}
Vivin Paliath
d1 == d2 doesn't compile unless the operation is implemented someplace. In this case it's not implemented.
John Dibling
Void
Thank you for the "this" pointer, I did not think about that.
jualin
@Void Ah, good point. Like I said, I haven't done C++ in a while. I was in Java-land where everything is a reference/pointer :)
Vivin Paliath
This implementation of compareTo isn't a good general strategy, because of overflow. Obviously dates aren't going to overflow, so you can get away with it, but consider if `this.getYear()` is INT_MAX and `date.getYear()` is -1. Then LHS > RHS, but LHS - RHS < 0.
Steve Jessop
Thank you for pointing that out.
jualin
Hopefully there is a validation function that ensures that the year attribute isn't at INT_MAX.But yes, this probably isn't a generally good strategy.
Vivin Paliath
Yes, it's fine for dates as long as your dates don't go absurdly far into the future.
Steve Jessop
+1  A: 

In order to use operator== for user-defined types, you must implement it. In addition, your Compare function should be marked as a const member function:

class Date
{
...
int Compare(const Date& d) const;     

bool operator==(const Date& rhs) const
{
    return 0 == Compare(rhs);
}
John Dibling
+2  A: 

The semantics of C++'s || make this a little cluttered:

static inline int cmp(int a, int b)
{
  return a < b ? -1 : a == b ? 0 : 1;
}

int Date::Compare(const Date& d)
{
  int result;
  (result = cmp(year, d.year))     ||
    (result = cmp(month, d.month)) ||
      (result = cmp(day, d.day));

  return result;
}
Greg Bacon
Thank you, that also helped.
jualin
@jualin You're welcome!
Greg Bacon
But if you really must start the name with an underscore, make sure it's not in the global namespace - that's not allowed.
Mike Seymour
@Mike Good point; thanks! Revised.
Greg Bacon
+2  A: 

Here's how I might implement your Compare function, although the format takes a moment to get used to:

int Date::Compare(const Date& d) const {
  return
    (year < d.year)   ? -1 :
    (year > d.year)   ?  1 :
    (month < d.month) ? -1 :
    (month > d.month) ?  1 :
    (day < d.day)     ? -1 :
    (day > d.day)     ?  1 :
                         0;
}

Or perhaps:

template<typename T>
int Compare(T a, T b) {
    if (a < b) return -1;
    if (b < a) return 1;
    return 0;
}

int Date::Compare(const Date& d) const {
    int a = Compare(year, d.year);
    if (a == 0) a = Compare(month, d.month);
    if (a == 0) a = Compare(day, d.day);
    return a;
}

I wouldn't use operator== in Compare, although the answers telling you how to implement operator== are fine if you want that as well. The reason is that operator== is clearly going to have to look at the same fields compare does, and if it returns false then Compare will do very similar work again. Efficiency probably isn't an issue, but it duplicates the logic.

And for what it's worth, idiomatic C++ is to implement operator< and possibly also a consistent operator== and operator>, rather than an all-in-one Compare function. The operators are what the standard algorithms use for searching and sorting, and everything else follows. Java chose to do things differently.

Steve Jessop
+1. Awesome answer.
ChadNC
Thank you, that's a great explanation.
jualin