1

I am learning C++ and currently trying to make an enum type called weekday representing the days of the week, along with some basic functions to move back and forth among the days. The enum type is defined as so:

enum weekday {
    Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
};

I want to make a function called changeDay that will find the day that is delta days away from a given startDay. (e.g. changeDay(Monday, 4) == Friday). I have the function defined as so:

void incrementDay(weekday& startDay, int delta){
    startDay = weekday((startDay + delta) % 7);
}

This function works great as long as I'm going forwards in time (i.e. delta > 0). However, I also want to be able to support going back in time (i.e. delta < 0). This leads to the following problem: if I want to go, for example, 4 days prior to Tuesday, I would expect to get Friday. However, the way my function works, the value -3 would be returned, which is not defined as a valid value in my weekday enum.

I would try manipulating the value from my changeDay function to always return a positive value by just adding in the cardinality of the enum (7 + -3 = 4 = Friday), but it appears that "there's not really a good way to do this". (Yes, I know that I could just hard-code the number of days in the week in the function, but I'm not interested in that kind of solution).

Is there any way to essentially allow my function to loop backwards through my enum?

Community
  • 1
  • 1
Shrey Gupta
  • 5,509
  • 8
  • 45
  • 71
  • 3
    Nothing is better than [this answer](http://stackoverflow.com/a/2102615/3959454) (that is, adding `WEEKDAY_COUNT` as the last enum value) – Anton Savin Jun 15 '15 at 14:23
  • 1
    Why `% 4`? That doesn't seem to make sense (the `4`) – Yakk - Adam Nevraumont Jun 15 '15 at 14:30
  • Sorry that was a typo...thanks Yakk – Shrey Gupta Jun 15 '15 at 14:31
  • 1
    See also: http://stackoverflow.com/questions/17211928/simplest-method-for-iterating-through-contiguous-enum-values-in-c – Paul R Jun 15 '15 at 14:31
  • 1
    I wrote a header-only library that would allow you to implement this in a "natural" fashion, but you have to use a macro to declare the enum. To avoid me posting spam, please say if you're looking for a no-library solution. – antron Jun 15 '15 at 14:42
  • Thanks all! I'm thinking I might just switch the implementation to an array, since that seems to make more sense for the purpose of looping. Also, @antron, I would still be interested in seeing the library. – Shrey Gupta Jun 15 '15 at 14:46
  • It's this – the macro generates both an enum and an array (and also a string array): https://github.com/aantron/better-enums You can use the `::_size` member to implement modular arithmetic. By the way, were you also unsatisfied with the `% 7` when going forwards? – antron Jun 15 '15 at 14:51
  • Awesome thank you! And yeah I wasn't terribly happy that I had to hardcode the `% 7` in there; I would have preferred something like `% NUM_VALUES`; that's probably behavior that would be better suited to C++ arrays or this enum library. – Shrey Gupta Jun 15 '15 at 14:58
  • Ok, then yes, either an array or some "fat enum"/"macro enum" approach is probably your best bet. There are also other macro solutions on SO (search for enum to string) that would allow you to get the count. One of the reasons I was asking is I am wondering why you don't use modular arithmetic for going backwards as well? It's a little tricky, but it's the right way if you ever want to go back more than a week (edit – perhaps I misunderstood you and you *are* using it, just adding 7 at the end if the number is negative?) – antron Jun 15 '15 at 15:00

1 Answers1

0

Try the following

#include <iostream>

enum weekday 
{
    Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
};

const char * weekday_name[] = 
{
    "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"
};

void incrementDay( weekday &startDay, int delta )
{
    if ( delta )
    {        
        delta %= Sunday + 1;
        if ( delta < 0 ) delta = Sunday + delta + 1;

        startDay = static_cast<weekday>( ( startDay + delta ) % ( Sunday + 1 ) );
    }       
}

int main()
{
    for ( int i = 0; i < 14; i++ ) 
    {
        weekday day = Monday;
        incrementDay( day, i );
        std::cout << day << ": " << weekday_name[day] << std::endl;
    }

    std::cout << std::endl;

    for ( int i = 0; i < 14; i++ ) 
    {
        weekday day = Monday;
        incrementDay( day, -i );
        std::cout << day << ": " << weekday_name[day] << std::endl;
    }
}    

The program output is

0: Monday
1: Tuesday
2: Wednesday
3: Thursday
4: Friday
5: Saturday
6: Sunday
0: Monday
1: Tuesday
2: Wednesday
3: Thursday
4: Friday
5: Saturday
6: Sunday

0: Monday
6: Sunday
5: Saturday
4: Friday
3: Thursday
2: Wednesday
1: Tuesday
0: Monday
6: Sunday
5: Saturday
4: Friday
3: Thursday
2: Wednesday
1: Tuesday
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335