0
\$\begingroup\$

I'm working on a project that creates a calendar based on user input of a month and a year. With that information, the code should count the number of days in that month and output a calendar. I would love to have extra eyes on my code. I'm still a beginner and limiting myself to just the libraries mentioned in the code!

I want to know if there is a simpler way to write this code or any suggestions on what I should change to make the code simpler. I was thinking of incorporating switch statements, but don't really know how to. Any feedback is appreciated! Right now my code looks oversimplified.. right?

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

int month, day, year, start;

#define MONTHS_PER_YEAR 12 // Cannot change.

const unsigned short DAYS_PER_MONTH[MONTHS_PER_YEAR] =
    {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // Cannot change.

const char MONTH_NAMES[MONTHS_PER_YEAR][10] =
    {"January",   "February", "March",    "April",
     "May",       "June",     "July",     "August",
     "September", "October",  "November", "December"}; // Cannot change.

bool leapYear()
{
    if (((year % 4 == 0) && year % 100 != 0) || year % 400 == 0)
    {
        return false;
    }
    else
    {
        return true;
    }
}
//I actually do not think I am supposed to use static.

int day_of()
{
    
    static int t[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
    year = year - month < 3;
    return ( year + year /4 - year /100 + year /400 + t[month-1] + day) % 7;
}

void printMonth()
{
    start = day_of();
    int count, days_in_month = DAYS_PER_MONTH[month - 1];
    if (leapYear() && month == 2)
    {
        days_in_month = DAYS_PER_MONTH[month - 1] + 1;
    }
    if (start == 6)
    {
        start = -1;
        cout << " ";
    } 
    for (count = 0; count <= start; count++)
    {
        cout << (count > 0? "   ": "    ");

    }
    for (day = 1; day <= days_in_month; day++)
    {
        if (++count > 6)
        {
            count = 0;
            if (day > 9)
            {
                cout << day << '\n';
            }
            else
            {
                cout << day << '\n' << " ";
            }
        }
        else
        {
            if (day >= 9)
            {
                cout << day;
            }
            else
            {
                cout << day << " ";
            }
            cout << " ";
        }
    }
    cout << endl;
}

// Controls operation of the program.
int main()
{
    cout << "Enter the month: ";
    cin >> month;
    cout << "Enter the year: ";
    cin >> year;
    cout << MONTH_NAMES[month - 1] << " " << year << std::endl;
    cout << "Su" << "  "<< "M" << "  "<< "T"<< "  " << "W" << " " << "Th" << "  " << "F" << " " << "Sa\n";
    printMonth();
    cout << endl;
    return 0;
}
\$\endgroup\$
2
  • \$\begingroup\$ Mandatory watching for anyone implementing their own date/time code: youtube.com/watch?v=-5wpm-gesOY \$\endgroup\$
    – G. Sliepen
    Commented Feb 2, 2022 at 19:48
  • 1
    \$\begingroup\$ Please do not vandalize your posts by removing (parts of) the code. \$\endgroup\$
    – Mast
    Commented Feb 27, 2022 at 8:15

2 Answers 2

2
\$\begingroup\$

That leapYear looks strange to me, to know if the year is leap year you need something like this:

bool leapYear()
{
    return !(((year % 4 == 0) && year % 100 != 0) || year % 400 == 0) ;
}

Some function name are a bit weird. Also what happens if somebody type month > 12?

#include <cmath>

is not necesary, since no math functions are used.

\$\endgroup\$
0
2
\$\begingroup\$

Don’t write using namespace std;.

int month, day, year, start; What's this doing here at the top of the file? Global variables, not even static, multiple on one statement, not initialized?

#define MONTHS_PER_YEAR 12 // Cannot change.

⧺ES.31 Don't use macros for constants or "functions"

I suggest you start by bookmarking the Standard Guidelines that I've linked to twice above, and browse through them to start getting familiar with them.


 if (something)
    {
        return false;
    }
    else
    {
        return true;
    }

In C++ (as in C), the something (the "condition") is not a special kind of syntax, but is just an expression like you use in arithmetic and anywhere else. You can have boolean variables and manipulate boolean values just like you do with numbers.

So, the grotesque formulation above is just what is meant by: return !something;

Right now my code looks oversimplified.. right?

On the contrary, it looks convoluted and overly wordy.

Thinking about when I wrote such a thing in 8-bit BASIC, I'd say you did a pretty good job of starting to organize it. You made several helper functions and defined constant data outside your main code. But once you got into that main logic, you micro-managed the whole process. printMonth is more if than actual logic.

You should have a simple call to print out a number in two characters, that always works whether it needs a leading space or not. That should not be inlined as more decisions to make inside printMonth itself! BTW, there are capabilities in the standard library for doing this.

Your printMonth should be simple and mostly list other functions to call. Continue to do "top-down decomposition" on the body of this function.

\$\endgroup\$
4
  • \$\begingroup\$ @TobySpeight That's not correct. A non-const variable not declared static at global namespace scope will have external linkage. Another translation unit can declare it with extern and see it. That's why you use static to keep things local to the translation unit (or more generally, use an anonymous namespace). \$\endgroup\$
    – JDługosz
    Commented Feb 11, 2022 at 15:43
  • 2
    \$\begingroup\$ Oops, yes - you're right. I misunderstood the standard here. (I can't remember the last time I needed a file-scope variable, external or otherwise!) \$\endgroup\$ Commented Feb 11, 2022 at 16:39
  • \$\begingroup\$ @TobySpeight it affects the names of functions and types and templates, too. All the helper functions and templates (even if no global variables) in the file get put in an anonymous namespace which keeps them local to that file. \$\endgroup\$
    – JDługosz
    Commented Feb 11, 2022 at 17:30
  • 1
    \$\begingroup\$ Yes - for some reason, I thought that objects defaulted to internal or no linkage and only functions and types to external. I don't know where I got that from, but I've been educated today. Thank you! \$\endgroup\$ Commented Feb 12, 2022 at 10:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.