initializing a const struct of months

I am finishing a date class with validity checking for a C++ class. Class has covered structs, classes, and templates, but not any STL subjects.
I would like to create and load a struct for the months, containing int fields for month number and number of days in the month, and a string for the month's name.
I would like a couple of easy options to load the struct so I can use it in the rest of the class.

What I have so far:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private:
	int day, year;

	int month;  //will be replaced by struct
	string stMonthName;   //S.A.A.

/*	struct month {
		int nNumb;
		string stName;
		int nDaysIn;
	} Month[12];

	for(int i = 0; i < 12; ++i)
		Month.nNumb = i-1;

*/ //Obviously the commented out portion is my work-in-progress


Thanks for any suggestions. I'm not looking for 'how-to-do-it', I'm looking for 'how-to-do-it-well'.

ERandall
Well, you are doing well. But you should put your for loop in a Constructor, and don't need 12 months, because you will only pick a single month in the end.
I forgot to mention we had to check for a valid day value? Against each month, including February during a leap year.
I'm assuming I will need 13 months, not twelve.

ERandall
Last edited on
Yes, but still user only needs a single month. Or are you just going to store them all in the struct uselessly?

What I mean is, when you call GetMyTime() or whatever function it will be, if you are in may, user don't need to know about all other month's names. So why storing all the months? You can only store the "May" month, requiring less data.

Anyways all stays in how user can access data.
You can make it like, private variables and public functions called SetDay, SetMonth, SetYear/Get Day, GetMonth, GetYear and clamping data.
Okay, I have to take an int month, output the corresponding string. I need to verify the inputted day, month and year are each valid values (day in context of month and leap year) using exceptions (try/throw/catch is this week's chapter).
I feel brain-dead, SGH, that I am missing how to generate the comparison data without storing it.

ERandall
This is what I am trying to "clean up":
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
bool cValidDateType::fnValidateDay(int day) {

	bool valid = true;

	if (day < 0)
		valid = false;

	if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12)
		if (day > 31)
			valid = false;

	if (month == 4 || month == 6 || month == 9 || month == 11)
		if (day > 30)
			valid = false;

	if (month == 2)
		if (day > 28)
			valid = false;

		//Feb 29th test 
				if (day == 29)
					if (year % 4 == 0)
						if (year % 100 != 0 || year % 400 == 0)
							valid = true;

	return valid;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bool cValidDateType::fnValidateDay(int day) {
    if(day < 0 || day > 31)
        return 0;
    switch(month)
    {
         case 4:
         case 6:
         case 9:
         case 11:
             return (day <= 30);
         case 2:
             return ((day <= 28) || (year%4 == 0 && (year%100 != 0 || year%400 == 0)));
         default:
             return 1;
    }
}


This code does THE SAME yours does.
What I mean is, you will NOT store all data in the struct, but in the functions. This will make you using less ram.

Also:

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
std::string GetMonthName(int Month) {
    switch(Month)
    {
        case 1:
            return std::string("January");
        case 2:
            return std::string("February");
        case 3:
            return std::string("March");
        case 4:
            return std::string("April");
        case 5:
            return std::string("May");
        case 6:
            return std::string("June");
        case 7:
            return std::string("July");
        case 8:
            return std::string("August");
        case 9:
            return std::string("September");
        case 10:
            return std::string("October");
        case 11:
            return std::string("November");
        case 12:
            return std::string("December");
        default:
            return std::string("");
    }
};


EDIT: Shortened a bit more.
Last edited on
I knew I would be using a switch. Thanks for confirming that. In case 2, though, I will need to include an (day == 29 && [/i](year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)))

right? To check for Feb 30th or 31st?

And just enum the month strings. This is more efficient, yes?

ERandall

PS: Like I said, want it to work, but work right. Thx.
PPS:"When you have a shiny, new hammer, everything looks like a nail."
edit: kill the "else if," leave the added condition.
Last edited on
1. I'm already checking for february.
2. There is no else if?
3. You cannot enum strings.
This is my string generator (alternative to the hard-coded switch method):
1
2
3
4
5
string cValidDateType::fnGetMonthName(int month) {
	int index = month - 1;
	string Month[12] = {"JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"};
	return Month[index];
}


This is easier for me to read, but how much more wasteful is it in processor and/or memory overhead?

ERandall

Edit: Intellisense spotted a typo in the string array declaration.
Last edited on
By the way, this kind of feedback is why I love asking about things on cplusplus.
ER
Oh, i tought all other things. Just a little optimization:

1
2
3
4
5
6
string cValidDateType::fnGetMonthName(int month) {
    if(month < 1 || month > 12)
        return string("");
    static string Month[] = {"JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"};
    return Month[month-1];
}
Thanks, SGH. I'm going to call this one 'solved'.
ER
Topic archived. No new replies allowed.