-1

I am having some difficulty determining how to solve a part of a problem I am doing for my C++ course. This part requires the use of operator-overloading to correctly increment the days and the month. Maybe I am overlooking some very simple math, but somehow I am a bit confused as to how. Here is the code I have for my overloaded prefix and postfix operators for DayOfYear objects:

//Operators
DayOfYear operator++ () {return day++; }
DayOfYear operator++ (int) {return ++day;}
DayOfYear operator-- () {return day--;}
DayOfYear operator-- (int) {return --day;}

Obviously, this is redundant because day is an int so it only does what I could already do with ++ and -- to begin with. Below is the code for the DayOfYear class:

class DayOfYear {
    std::string month[12] = {"January", "February", "March",
                            "April", "May", "June", "July", "August", 
                            "September", "October", "November", "December"};

    //Each month's number of days, respectively
    int numDaysMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    int day;

    //Convert day # to a string value
    static std::string dayToStr; 

    public:
        //First constructor
        DayOfYear (int day) {this -> day = day;} 

        //Second Constructor
        DayOfYear (std::string mth, int dayOfMonth) {
            //Make sure the dayOfMonth is valid
            if (dayOfMonth > 31 || dayOfMonth < 1) {
                if (mth == "February" && dayOfMonth > 28) {
                    std::cout << "Invalid day. February is assumed to be 28 
                    days for our purposes." << std::endl;
                 } else if ((mth == "April" || mth == "June" || mth == 
                    "September" || mth == "November") && dayOfMonth > 30) {
                    std::cout << "Invalid day. " << mth << " has only 30 
                    days." << std::endl;
                 } else {
                    std::cout << "Invalid day. The day should be >0 and <=31 
                    for most months." << std::endl;
                 }
           } else {
               day = dayOfMonth;
           }

       }

       //Accessors
       std::string getMonth (int mID) {return month[mID];}
       std::string getDay () {return dayToStr;}

       //Mutators
       void setDay (int d) {
           day = d;
       }

       //Operators
       DayOfYear operator++ () {return day++; }
       DayOfYear operator++ (int) {return ++day;}
       DayOfYear operator-- () {return day--;}
       DayOfYear operator-- (int) {return --day;}

       void print () {
           //TO-DO
       }
};

Right now, the code won't compile because the pieces aren't all there. However, I can read code fairly well I think, so I know my operators won't work. Somehow, I need to figure out how to make this code so that my main function (below) can compile and run correctly:

int main () {
    DayOfYear d (2);
    d.print ();
    d = 365;
    d.print ();
    d = 32;
    d.print ();

    d++;
    d.print ();

    d = 365;
    ++d;
    d.print ();
    d = 1;
    --d;
    d.print ();

    d = 32;
    d--;
    d.print ();

    DayOfYear e ("December", 31);
    e.print ();        

    return 0;
}

Specifically, as per the prof's specifications for this lab, I need to

  1. --prefix and postfix-- operators should modify the DayOfYear object(s) so that it represents the previous day. If the day is already the first day of the year, the new value of the object will represent the last day of the year.

  2. ++prefix and postfix++ increment operators. These operators should modify the DayOfYear object so that it represents the next day. If the day is already the end of the year, the new value of the object will represent the first day of the year.

So, I think my solution will require some use of %. Maybe I could overload it? I'm not sure. % can be overloaded according to the textbook.

I've been reading the textbook, and I think I know the basics of operator overloading in C++, but I think I am missing something simple or subtle. I've tried to look for something specific to this, but all I find is general information on operator overloading with structs and classes. I'm not sure what to do at the moment. I think my print () method is gonna be a challenge too, but the solution to this should make that last part of the assignment much easier.

Any guidance or assistance would be appreciated! Thanks.

EDIT: The professor explicitly stated in the problem requirements that I should assume that a year is 365 days.

I am taking the first C++ course offered at my college, so if there is a better way to do this with more advanced concepts, DO NOT POST IT because they are irrelevant and I probably won't know what you are talking about.

Explicit goals for assignment: Write a class named DayOfYear that takes an integer representing a day of the year and translates it to a string consisting of the month followed by day of the month. Examples: Day 2 => January 2, Day 32 => February 1, Day 365 => December 31. Assume 365 days in a year. The constructor for the class should take as parameter an integer representing the day of the year. The class should have a member function print() that prints the day in the month-day format like the examples above. Add a second constructor that takes two parameters: a string representing month and an integer (1-31) for the day of the month. The constructor should then initialize the integer member of the class to represent the day specified by the month and day of month parameters. Add the following overloaded operators: ++prefix and postfix increment operators. These operators should modify the DayOfYear object so that it represents the next day. If the day is already the end of the year, the new value of the object will represent the first day of the year. --prefix and postfix decrement operators. These operators should modify the DayOfYear object so that it represents the previous day. If the day is already the first day of the year, the new value of the object will represent the last day of the year.

My goal is to figure out these operators and the print () method mainly. I think I handled the other stuff okay, but this is giving me a snag.

jameyb
  • 37
  • 7
  • 3
    What is the question? – Robert Andrzejuk Dec 01 '18 at 19:37
  • Why are you storing the date as (day, month, year) triple to begin with? Just store the days since Unix Epoch or sth. like that. – Baum mit Augen Dec 01 '18 at 19:37
  • That would also make it a lot easier to get rid of that awkward restriction of "no Feb. 29". – Baum mit Augen Dec 01 '18 at 19:41
  • 1
    @BaummitAugen That clearly defeats the object of the assignment, which is about composing multiple pieces of data into a single class and implementing sensible operations around them. – Lightness Races in Orbit Dec 01 '18 at 19:41
  • 1
    .. and of learning how to deal with awkward restrictions – Lightness Races in Orbit Dec 01 '18 at 19:42
  • that you (maybe) wouldn't take this approach for dates in production is irrelevant – Lightness Races in Orbit Dec 01 '18 at 19:45
  • @LightnessRacesinOrbit First of all, I phrased my earlier comment as question on purpose. If the answer is "because I'm not allowed to", fine. Regarding moving the goalposts, I do believe that separating the logic of building a human-readable representation of a date from the rest of the functionality makes sense, in that it's easier and clearer. – Baum mit Augen Dec 01 '18 at 19:49
  • Yes, actually, specifically in the problem he stated to assume that a year has 365 days. I also have no idea what you mean by "Unix Epoch or sth". I'm taking a class that is introductory C++. The awkward requirements are an unfortunate product of the fact that better solutions haven't been presented by this course. I will edit the question and make it explicitly state the requirements you wish were not so awkward based on your far greater experience. – jameyb Dec 01 '18 at 19:50
  • What exactly is the reason for making ***every*** instance of the `DayOfYear` class store the names of the 12 months of the year, and the number of days in each month, in addition to the day number as well. You need to urgently open your C++ book to the chapter that explains how static class members work, and review the chapter's material, and understand precisely what that means. – Sam Varshavchik Dec 01 '18 at 19:52
  • This is a totally normal introductory assignment. Let's not send the OP off deviating from expectations so that they go into class with a UNIX timestamp and a serialisation routine and get zero marks. – Lightness Races in Orbit Dec 01 '18 at 19:53
  • @JameyBryce Just for the record, I meant that storing the days that have passed since some fixed date (like the Unix epoch, for example, but the choice doesn't really matter) would simplify things. If your assignment says you can't do that, you can't of course. – Baum mit Augen Dec 01 '18 at 19:53
  • Helpful reading: [What are the basic rules and idioms for operator overloading?](https://stackoverflow.com/questions/4421706/what-are-the-basic-rules-and-idioms-for-operator-overloading) – user4581301 Dec 01 '18 at 19:56
  • `month[12]` should be `static` and `const` otherwise every instance will get a private copy of the array. – rustyx Dec 01 '18 at 19:58
  • @rustyx Ah, that makes sense. I recall that I should do that. Thank you, that is a helpful tip. I'll go implement it and try some other suggestions from below and get back to you guys. One thing: it seems some answerers are confused about what my question is or don't like the way I asked it? Improvement suggestions? I read the guidelines for the site. Did I forget something? – jameyb Dec 01 '18 at 20:06
  • @JameyBryce Suggestion: Indent your code properly – Aykhan Hagverdili Dec 01 '18 at 20:21
  • Oh. I see. Unfortunately, it looks like the formatting got messed up when I copy/pasted it. I'll go fix that in a bit. – jameyb Dec 01 '18 at 20:28
  • Take a hard look at `dayToStr`, and also reconsider which pieces of data can be shared globally. – Deduplicator Dec 01 '18 at 21:22

1 Answers1

1

All of your overloadings have problems. One thing they all shouldn't do is returning an int, and int day is an integer.


DayOfYear operator++ () {return day++; }

Here, the return type is DayOfYear, but it is supposed to be DayOfYear&.

DayOfYear&operator++() {
    ++day;
    return *this;
}

DayOfYear operator++ (int) {return ++day;}

Here, the return type is correct. You just have to return an object with the old value:

  DayOfYear operator++(int) {
    auto old_val = *this;
    ++*this;
    return old_val;
  }

Incorporated suggestions by @Deduplicator:

  • note the use of auto. It simplifies the method and improves readability
  • ++*this may be preferred to calling the operator manually since it is shorter and easier to type

Same applies to -- operators


Implementing a print function is indeed simple but you have some choices:

This one prints the date to standard output. The downside is that the only place it prints its output is standard output:

void print () {
    std::cout << getDay () << " / "  << getMonth() << std::endl;
}

You may send an std::ostream object and use it instead of std::cout:

void print (std::ostream& os) {
    os << getDay() << " / "  << getMonth() << std::endl;
}

Converting an int to an std::string is very conveniently possible with std::to_string. It is defined in header <string>, so make sure to include it:

std::string getDay () {
    return std::to_string(day);
}

Edit: As @Deduplicator pointed out, you may replace the print function with overloading <<:

friend std::ostream& operator<<(std::ostream& os, DayOfYear x) {
    os << getDay () << " / "  << getMonth() << std::endl;
    return os;
}
Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
  • This can't be the end of the story; you'd end up with days that get out-of-bound for the month they are in. – Baum mit Augen Dec 01 '18 at 19:55
  • I don't think OP is that far yet ;) – rustyx Dec 01 '18 at 19:59
  • @BaummitAugen Yes, you are right. I was just pointing out why his code won't even compile (which seems to be the main question here) and I think fixing the logic is something OP should be in charge of. Any suggestions on how to improve this answer? – Aykhan Hagverdili Dec 01 '18 at 20:00
  • @Ayxan To be honest, I'm not 100% sure what the scope of this question is; your answer might well be fine. – Baum mit Augen Dec 01 '18 at 20:04
  • @Ayxan I think I can get it to compile. If I have any syntax errors, they can be fixed. I know I need to define the print () method. I'll be trying your suggestion above as well. Thanks for the feedback. EDIT: By compile, I meant once I get the rest of the pieces put in place. – jameyb Dec 01 '18 at 20:08
  • This is the correct answer. I have had a few problems with converting `int` to `std::string`. Causing syntax errors. I'll review some type casting stuff like `static_cast` unless there is something that's in my course which I am not recalling currently. Will mark as correct for the purposes of the initial difficulty. I looked through it and your solution seems very solid the more I think about it. I'll get back to you after I can compile. Type conversion is something I just need to review well I think. You've all been very helpful today! – jameyb Dec 01 '18 at 20:46
  • @JameyBryce added some help for converting an `int` to an `std::string` too :) – Aykhan Hagverdili Dec 01 '18 at 20:52
  • `auto r = *this; ++*this; return r;` reads better, imho. And `print()` should obviously become `friend std::ostream& operator<<(std::ostream& os, DayOfYear x)`. – Deduplicator Dec 01 '18 at 20:58
  • @Deduplicator thanks for the feedback. Since OP overloads pre-increment anyway, not implementing the same logic again seemed like a better idea (OP will probably have to handle the case when days get out of the bound). In what regard would your suggestion improve the design? I am not sure if OP meant to overload `<<` either. As the question states, this is a task with specific goals. – Aykhan Hagverdili Dec 01 '18 at 21:03
  • @Deduplicator Actually, the chapter that had the operator overloading in it also has friend functions in it. That actually looks like a very good idea. I gotta go to my part-time job soon, but I'll try that out asap! Thanks. – jameyb Dec 01 '18 at 21:08
  • Well, use of `auto` removes some duplication. Personally, I prefer to simply use an operator, instead of explicitly naming the special function involved, as then I don't have to know whether member of free was used. Naturally, the friend-operator is for following the iostreams-pattern. – Deduplicator Dec 01 '18 at 21:08
  • @Deduplicator tried to add your suggestions. Any other improvements? – Aykhan Hagverdili Dec 01 '18 at 21:18
  • Following your guidance for my code above, I have something that compiles. However, now I need to do some of that modulus stuff to make sure the days dont go out of bounds. That's just arithmetic/logic stuff so thanks guys! I appreciate it. Best answer. – jameyb Dec 04 '18 at 21:38