Need some help formatting calendar

Hi! So I have a program written to build a calendar. It is currently set to output the days of the month in a straight line. How can I change my program to have it output by week?

The output I am looking for is:
What year do you want a calendar for? 2002
What day of the week does January 1 fall on (0 for Sunday, 1 for Monday, etc.)? 2

2002

January
S M T W T F S
---------------------
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

February
S M T W T F S
---------------------
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

.
.
.
.
December
S M T W T F S
---------------------
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

Here is what I have so far:

#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstdlib>
using namespace std;

void info(int & year, int & day);
void printMonth (int year, int month, int day);
void info(int & year, int & day);
void printHeader(int month);
void printDays(int month, int year, int day);
int getNumDays(int month, int year);
bool isLeapYear(int year);



int main()
{
int year;
int day;
info(year, day);
for (int i = 0; i < 12; i++)
{
printMonth(year, i, day);
}
}






void info(int & year, int & day)
{
cout << "Enter year" << endl;
cin >> year;
cout << "Enter day" << endl;
cin >> day;
}






void printMonth(int year, int month, int day)
{
printHeader(month);
printDays(month, year, day);

}






void printHeader(int month)
{
cout << " ";
switch (month)
{
case 0:
cout << "January" << endl;
break;
case 1:
cout << "February" << endl;
break;
case 2:
cout << "March" << endl;
break;
case 3:
cout << "April" << endl;
break;
case 4:
cout << "May" << endl;
break;
case 5:
cout << "June" << endl;
break;
case 6:
cout << "July" << endl;
break;
case 7:
cout << "August" << endl;
break;
case 8:
cout << "September" << endl;
break;
case 9:
cout << "October" << endl;
break;
case 10:
cout << "November" << endl;
break;
case 11:
cout << "December" << endl;
break;
}
cout << "S M T W T F S" << endl;
cout << "-------------" << endl;

}





void printDays(int month, int year, int startDay)
{
for (int i = 0; i < startDay * 2; i++)
{
cout << " ";
}
int NumDays = getNumDays(month, year);
for (int i = 1; i < NumDays + 1; i++)
{
cout << i << " ";
}
cout << endl;
}







int getNumDays(int month, int year)
{
switch (month)
{
case 0:
return 31;
case 1:
if (isLeapYear(year))
return 29;
else
return 28;
case 2:
return 31;
case 3:
return 30;
case 4:
return 31;
case 5:
return 30;
case 6:
return 31;
case 7:
return 31;
case 8:
return 30;
case 9:
return 31;
case 10:
return 30;
case 11:
return 31;

}
}






bool isLeapYear(int year)
{
if (year % 400 == 0) {
return true;
}

if (year % 100 == 0) {
return false;
}

if (year % 4 == 0) {
return true;
}

return false;
}
iomanip has manipulators for left, right etc but no center. So, I first define a function string_pad() that sets the string padding and hence gives greater control on aligning the visible output (you may have to change my number for padding the string depending upon your system configurations).

Also, it is more natural for users to enter the months by name, "January", "April", "August" etc and the struct below is set up in those terms. This however requires some way to convert the months input as strings to numbers. I've used a map<string,int> but you could also use switch-case, enum etc. Full program below:

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <iostream>
#include <map>
#include <iomanip>

using namespace std;
map<string, int> months{{"January", 1}, {"February", 2}, {"March", 3}, {"April", 4}, {"May", 5}, {"June", 6}, {"July", 7},
                        {"August", 8}, {"September", 9}, {"Ocotber", 10}, {"November", 11}, {"December", 12}};
void skip (int i)
{
    while (i > 0)
    {
        cout << " ";
	    i = i - 1;
    }
}
void skipToDay (int d)
{
    return skip(3*d);
}
void string_pad(const string& DaysOfWeek, int padding)
{
    int s = DaysOfWeek.size();
	int pad1 = (padding - s)/2;
	int pad2 = pad1;

	for (int f = 0; f < pad1; f++)
	{
	  cout << " ";
	  ++f;
	}
    cout << DaysOfWeek;
    for (int e = 0; e < pad2; e++)
    {
        cout << " ";
        ++e;
    }
    cout<<"\n";
}


struct DaysOf
{
	string 	m_month;
	int	m_year;

	DaysOf(string month, int year) : m_month(month), m_year(year) {}

	int firstDay ()//Sakamoto algorithm;
	{
		static int t[]  {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
		auto iter = months.find(m_month);
   		m_year -= iter->second < 3;//this statement prevents method from being declared const; 
		return (m_year + m_year/4 - m_year/100 + m_year/400 + t[iter->second-1] + 1) % 7;
	}
	int daysMonth ()const
	{
        auto iter = months.find(m_month);
        int numberOfDays;

        if (iter->second == 4 || iter->second == 6 || iter->second == 9 || iter->second == 11)
        numberOfDays = 30;
        else if (iter->second == 2)
        {
            bool isLeapYear = (m_year % 4 == 0 && m_year % 100 != 0) || (m_year % 400 == 0);

            if (isLeapYear)
            {
                numberOfDays = 29;
            }
			else
            {
                numberOfDays = 28;
            }

        }
        else
        {
            numberOfDays = 31;
        }

        return numberOfDays;
	}

    void Print()
    {
        int num_days = this-> daysMonth();
        int day_week = this-> firstDay();//Print() can't also be const as firstDay() isn't const; 
        string_pad("S  M  T  W  T  F  S", 25);
        int day = 1;
        skipToDay(day_week);
        while (day <= num_days)
        {
            cout<<setw(3) << day << "";
            if (day_week == 6)
            {
                cout<<"\n";
                day_week = 0;
            }
            else
            {
                day_week = day_week + 1;
            }
            day = day + 1;
        }
        cout<<"\n\n";
    }
};

int main()
{
DaysOf test("February", 2000);
test.Print();
}

Last edited on
Topic archived. No new replies allowed.