days of week program

Pages: 12
Hi everyone. I am in a computer science class and was given the task of writing a code USING ONE DATA MEMBER in order to implement the days of the week (set the day,print the day, add days, etc). I understand everything except I just cant seem to figure out how to only use one data member. I will add my header here so you can see it, but could someone help me with how to have the user enter in a day and have the enum function be able to take in that string and either print it or add things to it? I wrote out the entire code initially using way more than one data member, so i had to restart completely but now i cant figure it out!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <string>
using namespace std;

class DayOfTheWeek
{
public:
	void setDay(string weekday);
	DayOfTheWeek();
	DayOfTheWeek(string weekday);
	void printDay() const;
	int getDay();
	int getDay(string weekday);
	int plusOneDay();
	int minusOneDay();
	void addDays(int daysadded);
private:
	enum weekday { Monday = 1, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday };
};

DayOfTheWeek::DayOfTheWeek() //
{
	weekday == int day;

}

DayOfTheWeek::DayOfTheWeek(string day) //overloaded function 
{
	string weekday;
}



thats all i have as of right now...
enum is a list of constants.
weekday is a type not a variable.
line 23 is pretty much nonsense.
line 29 is sort of OK but local variables overriding the enum name is bad form, hard to follow which is what. Do not reuse names in confusing ways, or you will drive yourself and everyone else nuts.

so you need
weekday someday = Monday; //ok

but cout << someday
prints 1. is this what you wanted? enums are glorified integers.

lets back up. what exactly are you trying to DO? Convert (some input??) into (some output??) or what?
What i am trying to do is to have a user input some random day of the week and then be able to print the day they entered, print the next day of the week, the previous day of the week, and add days to that day (like if you add 2 to a user input saying monday to have it output wednesday). im just not sure how to accomplish this by only using one data member (thats why i guessed to use enum?
Last edited on
input some random day of the week <- is this a word or a number or ??

to print the day they entered <-- is this a word or a number?

assuming its working in text...
you can do that with a string array and an index, if you want words...

string s[] = {{"Monday"}, {"Tuesday"}, ...};
and a search
for(i = 0; i < 7; i++)
if (input == s[i]) //then i is the day of the week the person put in...

and some fun with modulus..
cout << s[i] << endl; //day user put in..
cout << s[(i+2)%7] << endl; //2 days from i. so they put in 5, that is sat, 6 is sun..
but % 7 so 5 + 2 is 7. 7%7 is 0. 2 days from 5 is monday, then... :)

if the string of names is a constant , you only need i to do the rest.
if you want to be even more snarky you can move the constant days of the week out of the class as a program wide constant, does that let you use i as the only member?
Last edited on
And along those lines there are numerous permutations on how and where to place the conversion from day no. to day name. The class has only one dat member, namely the day number.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <string>

const std::string day_name[]{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};

class Day
{
private:
    int m_day_no;
    
public:
    Day(int day_no): m_day_no(day_no){}
    
    std::string getDayName(){ return day_name[m_day_no - 1]; }
    
    Day daysAhead(int no_days){return Day(( m_day_no + no_days ) % 7);}
    Day tomorrow(){ return Day(daysAhead(1)); }
    Day yesterday(){ return Day(daysAhead(-1)); }
};

int main()
{
    Day today(3);
    std::cout << today.getDayName() << '\n';
    
    Day tomorrow = today.tomorrow();
    std::cout << tomorrow.getDayName() << '\n';
    
    Day yesterday = today.yesterday();
    std::cout << yesterday.getDayName() << '\n';
    
    return 0;
}


Wed
Thu
Tue
Program ended with exit code: 0
Last edited on
There's a very important less in this exercise: the way to present the data to the user (and teh way they present it to you) is often different from the way you store the data in the program.

In this case, you interact with the user using the name of the day. But you want to store the data using the number of the day of the week. I'd use 0-6 for Sunday-Saturday.

Start with two methods to convert internal format to external and vice versa:
1
2
    const char *toName() const;
    bool fromName(string name);

With these, the rest is practically trivial. In fact, toName() is trivial too. Here it is, without the code for fromName():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
#include <string>
using namespace std;

class DayOfTheWeek
{
public:
    const char *toName() const;
    bool fromName(string name);
    DayOfTheWeek();
    DayOfTheWeek(const string weekday);
    int get() const;
    void addDays(int daysadded);
private:
    int dayNum;			// 0=Sunday, 6=Saturday
};

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

const char *
DayOfTheWeek::toName() const
{ return dayNames[dayNum]; }

bool DayOfTheWeek::fromName(string name)
{
    // YOUR CODE GOES HERE
}

DayOfTheWeek::DayOfTheWeek() : dayNum(0) {}

DayOfTheWeek::DayOfTheWeek(const string weekday) : dayNum(0)
{
    fromName(weekday);
}
int DayOfTheWeek::get() const {
    return dayNum;
}

void DayOfTheWeek::addDays(int daysadded) {
    dayNum = (dayNum+daysadded) % 7;
}

int main()
{
    string str;
    DayOfTheWeek dow;
    while (cin >> str) {
	if (dow.fromName(str)) {
	    cout << dow.toName() << '\n';
	} else {
	    cout << str << " is not a valid day name\n";
	}
    }
}


I went all out in my implementation of fromName(). It will work for any prefix that uniquely matches a day's name. So, M, Wed, wednesday and FR all match a name, but T, Thor, TuesdayBlues and S do not.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <string>

class Day
{
    const std::string day_name[7]{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
private:
    int m_day_no;
    
public:
    Day(int day_no): m_day_no(day_no){}
    
    Day(std::string aDayName)
    {
        for (int i = 0; i < 7; i++)
        {
            if(aDayName == day_name[i])
                m_day_no = i + 1;
        }
    }
    
    std::string getDayName(){ return day_name[m_day_no - 1]; }
    
    Day daysAhead(int no_days){return Day(( m_day_no + no_days ) % 7);}
    Day tomorrow(){ return Day(daysAhead(1)); }
    Day yesterday(){ return Day(daysAhead(-1)); }
    
    int getDayNo(){return m_day_no;}
};

int main()
{
    Day today(4);
    std::cout << today.getDayName() << '\n';
    
    Day tomorrow = today.tomorrow();
    std::cout << tomorrow.getDayName() << '\n';
    
    Day yesterday = today.yesterday();
    std::cout << yesterday.getDayName() << '\n';
    
    Day some_day("Tue");
    std::cout << some_day.getDayName() << '\n';
    std::cout << some_day.getDayNo() << '\n';
    std::cout << some_day.yesterday().getDayName() << '\n';
    
    return 0;
}


Thu
Fri
Wed
Tue
2
Mon
Program ended with exit code: 0
@againtry Setting

 
Day today(0);

and next calls

1
2
3
std::cout << today.getDayName() << '\n';
Day yesterday = today.yesterday();
std::cout << yesterday.getDayName() << '\n'; 

cause std::bad_alloc exception due to passing an incorrect indices in daysAhead and getDayName functions.
@TomCPP
Could be because I haven’t fully checked it. So be a good boy and fix it. There’s a good chap.
USING ONE DATA MEMBER in order to implement the days of the week


Againtry's solution stores the array of names within the class, so it misses this requirement. You can fix that by simply making it static:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
#include <string>

class Day
{
    static const std::string day_name[7];
private:
    int m_day_no;
    
public:
    Day(int day_no): m_day_no(day_no){}
    
    Day(std::string aDayName)
    {
        for (int i = 0; i < 7; i++)
        {
            if(aDayName == day_name[i])
                m_day_no = i + 1;
        }
    }
    
    std::string getDayName(){ return day_name[m_day_no - 1]; }
    
    Day daysAhead(int no_days){return Day(( m_day_no + no_days ) % 7);}
    Day tomorrow(){ return Day(daysAhead(1)); }
    Day yesterday(){ return Day(daysAhead(-1)); }
    
    int getDayNo(){return m_day_no;}
};

const std::string Day::day_name[7] {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};

int main()
{
    Day today(4);
    std::cout << "Day is " << sizeof(Day) << " bytes\n";
    std::cout << today.getDayName() << '\n';
    
    Day tomorrow = today.tomorrow();
    std::cout << tomorrow.getDayName() << '\n';
    
    Day yesterday = today.yesterday();
    std::cout << yesterday.getDayName() << '\n';
    
    Day some_day("Tue");
    std::cout << some_day.getDayName() << '\n';
    std::cout << some_day.getDayNo() << '\n';
    std::cout << some_day.yesterday().getDayName() << '\n';
    
    return 0;
}

Day is 4 bytes
Thu
Fri
Wed
Tue
2
Mon

The array of day names isn’t a data member wherever it goes, whatever permutation or placement is adopted.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <string>
#include <iomanip>

class Day
{
    const std::string day_name[7]{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
private:
    int m_day_no;
    
public:
    Day(int day_no) { m_day_no = (day_no % 7 + 7) % 7; }
    ~Day(){}
    
    Day(std::string aDayName)
    {
        for (int i = 0; i < 7; i++)
        {
            if(aDayName == day_name[i])
                m_day_no = i;
        }
    }
    
    std::string getDayName(){ return day_name[m_day_no]; }
    int getDayNo(){ return m_day_no; }
    
    Day daysAhead(int no_days){ return Day( m_day_no + no_days ); }
    Day tomorrow(){ return Day( daysAhead(1)); }
    Day yesterday(){ return Day( daysAhead(-1)); }
    Day lastWeek(){return Day( daysAhead(-7)); }
    Day nextWeek(){return Day( daysAhead(7)); }
};

int main()
{
    Day today(4);
    std::cout << today.getDayName() << '\n';
    
    Day tomorrow = today.tomorrow();
    std::cout << tomorrow.getDayName() << '\n';
    
    Day yesterday = today.yesterday();
    std::cout << yesterday.getDayName() << '\n';
    
    Day some_day("Tue");
    std::cout << some_day.getDayName() << '\n';
    std::cout << some_day.getDayNo() << '\n';
    std::cout << some_day.yesterday().getDayName() << '\n';
    
    for(int i = -10; i < 10; i++)
    {
        Day x(i);
        std::cout
        << std::setw(4) << i
        << std::setw(4) << x.getDayName() << " ->"
        
        << std::setw(4) << x.lastWeek().getDayName() << ' ' << x.lastWeek().getDayNo()
        << std::setw(4) << x.daysAhead(-2).getDayName()
        << std::setw(4) << x.yesterday().getDayName()
        << std::setw(4) << x.getDayName()
        << std::setw(4) << x.tomorrow().getDayName()
        << std::setw(4) << x.daysAhead(2).getDayName()
        << std::setw(4) << x.nextWeek().getDayName()
        
        << '\n';
    }
    
    return 0;
}
Example with enum class and overloading operators.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <iostream>
#include <map>

using namespace std;

enum class DAY { MON , TUE , WED , THU , FRI , SAT , SUN };

const map<DAY,string> mDAY { {DAY::MON,"Monday"},{DAY::TUE,"Tuesday"},
                             {DAY::WED,"Wednesday"},{DAY::THU,"Thursday"},
                             {DAY::FRI,"Friday"},{DAY::SAT,"Saturday"},
                             {DAY::SUN,"Sunday"} };

DAY operator++( DAY day )
{
    return static_cast<DAY>((static_cast<int>(day)+1)%mDAY.size());
}

DAY operator--( DAY day )
{
    auto iday {static_cast<int>(day)-1};
    return static_cast<DAY>( iday<0?mDAY.size()-1:iday );
}

ostream& operator<<( ostream& out , const DAY& day )
{
    out << mDAY.at(day);
    return out;
}

class Day
{

private:
    DAY day;

public:
    Day( DAY day_ ): day {day_} {}

    Day tomorrow() const { return ++day; }
    Day yesterday() const { return --day; }

    Day& operator++(){ day = ++day; return *this; }
    Day& operator--(){ day = --day; return *this; }

    friend ostream& operator<<( ostream& out , const Day& day )
    {
        out << day.day << endl;
        return out;
    }
};

int main()
{
    Day day {DAY::MON};
    cout << day << day.tomorrow();
    --day;
    cout << day << day.yesterday();

    return 0;
}
Last edited on
1
2
3
day = ++day;
// ...
day = --day;
Please don't do this in code. While it might no longer be undefined behavior as C++17 (I think), it is still unnecessarily convoluted and would be much clearer if you simply did ++day; return *this;
Last edited on
1
2
3
4
const map<DAY,string> mDAY { {DAY::MON,"Monday"},{DAY::TUE,"Tuesday"},
                             {DAY::WED,"Wednesday"},{DAY::THU,"Thursday"},
                             {DAY::FRI,"Friday"},{DAY::SAT,"Saturday"},
                             {DAY::SUN,"Sunday"} };

That works, but I want to point out that it's 10 times larger and probably at least 5 times slower than an array.

The array of day names isn’t a data member wherever it goes, whatever permutation or placement is adopted.
Huh? If you put it in the class then of course it's a data member. Maybe you're referring to the items within the map. Those are on the heap, but the map itself has a non-zero size. Also, if the map is a data member, then each Day object has it's own map with its own strings, so it's far more memory than required.
1
2
3
4
5
6
7
8
9
10
#include <map>
#include <string>
#include <iostream>

const std::string day_name[7]{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

int main()
{
    std::cout << sizeof(day_name) << '\n';
}
56


While it might no longer be undefined behavior as C++17 (I think)

IMHO it is completely valid (since C++11 that is required to use enum classes)
day = ++day;
because it has the same effect as the following expression
day = operator++(day);
where operator++ is a pure function.
My point isn't about enums or pure functions, that's beside the point. All I'm saying is that even if it's defined behavior, it still unnecessarily adds complexity and may be confusing to the reader, with no benefit over just doing a simple increment (g++ will even still warn about possible undefined behavior, although I think the warning in this case is outdated).
Last edited on
I see your point. Here is a modified version.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <iostream>
#include <array>

using namespace std;

enum class DAY { MON , TUE , WED , THU , FRI , SAT , SUN };

const array<string,7> aDAY { "Monday","Tuesday","Wednesday","Thursday",
                             "Friday","Saturday","Sunday" }; 

DAY& operator++( DAY& enumday )
{
    enumday = static_cast<DAY>((static_cast<int>(enumday)+1)%aDAY.size());
    return enumday;
}

DAY& operator--( DAY& enumday )
{
    auto iday {static_cast<int>(enumday)-1};
    enumday = static_cast<DAY>( iday<0?aDAY.size()-1:iday );
    return enumday;
}

ostream& operator<<( ostream& out , const DAY& enumday )
{
    out << aDAY[static_cast<int>(enumday)];
    return out;
}

class Day
{

private:
    DAY enumday;

public:
    Day( DAY enumday_ ): enumday {enumday_} {}

    Day tomorrow() const { return ++Day{enumday}; }
    Day yesterday() const { return --Day{enumday}; }

    Day& operator++(){ ++enumday; return *this; }
    Day& operator--(){ --enumday; return *this; }

    friend ostream& operator<<( ostream& out , const Day& day )
    {
        out << day.enumday << endl;
        return out;
    }
};

int main()
{
    Day day {DAY::MON};
    cout << day << day.tomorrow();
    --day;
    cout << day << day.yesterday();

    return 0;
}
Huh? If you put it in the class then of course it's a data member.

Wrong! It's not a data member, even remotely, grandpa. MYOFB
Wrong! It's not a data member, even remotely, grandpa. MYOFB
1
2
3
4
5
6
class Day
{
    const std::string day_name[7]{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
private:
    int m_day_no;
}

day_no and day_name are both data members. They both add to the sizeof the class. There's no magic fairy dust that makes day_name a non-member. If you think otherwise then please explain.
Pages: 12