Putting using namespace std
at the top of every program is a bad habit a bad habit that you'd do well to avoid.
All versions of both standards since then (C99 and C++98) have maintained the same idea. We rely on automatically generated member functions in C++, and few people write explicit return;
statements at the end of a void
function. Reasons against omitting seem to boil down to "it looks weird" "it looks weird". If, like me, you're curious about the rationale for the change to the C standard read this question read this question. Also note that in the early 1990s this was considered "sloppy practice" because it was undefined behavior (although widely supported) at the time.
Putting using namespace std
at the top of every program is a bad habit that you'd do well to avoid.
All versions of both standards since then (C99 and C++98) have maintained the same idea. We rely on automatically generated member functions in C++, and few people write explicit return;
statements at the end of a void
function. Reasons against omitting seem to boil down to "it looks weird". If, like me, you're curious about the rationale for the change to the C standard read this question. Also note that in the early 1990s this was considered "sloppy practice" because it was undefined behavior (although widely supported) at the time.
Putting using namespace std
at the top of every program is a bad habit that you'd do well to avoid.
All versions of both standards since then (C99 and C++98) have maintained the same idea. We rely on automatically generated member functions in C++, and few people write explicit return;
statements at the end of a void
function. Reasons against omitting seem to boil down to "it looks weird". If, like me, you're curious about the rationale for the change to the C standard read this question. Also note that in the early 1990s this was considered "sloppy practice" because it was undefined behavior (although widely supported) at the time.
The current Date
class is a very lazy thing, leaving all of the work to separate functions. I'd make it do much more of the work. For instance, I reimpplementedreimplemented your algorithm but did most of the work in class operators. Here's an excerpt of that code:
Consider the cost of object creation
The code currently contains this function:
int DaysInMonth(int month, int year)
{
vector<int> days = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if(isLeapYear(year)) days[1] = 29;
return days[month-1];
}
This is computationally much more costly than it should be because it requires the creation and destruction of a std::vector
on every invocation. Those numbers don't change, so that first line could instead look like this:
static constexpr int days[12]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
In the case of a leap year, alter the returned value instead of the array itself.
The current Date
class is a very lazy thing, leaving all of the work to separate functions. I'd make it do much more of the work. For instance, I reimpplemented your algorithm but did most of the work in class operators. Here's an excerpt of that code:
The current Date
class is a very lazy thing, leaving all of the work to separate functions. I'd make it do much more of the work. For instance, I reimplemented your algorithm but did most of the work in class operators. Here's an excerpt of that code:
Consider the cost of object creation
The code currently contains this function:
int DaysInMonth(int month, int year)
{
vector<int> days = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if(isLeapYear(year)) days[1] = 29;
return days[month-1];
}
This is computationally much more costly than it should be because it requires the creation and destruction of a std::vector
on every invocation. Those numbers don't change, so that first line could instead look like this:
static constexpr int days[12]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
In the case of a leap year, alter the returned value instead of the array itself.
I see a number of things that may help you improve your code.
Don't abuse using namespace std
Putting using namespace std
at the top of every program is a bad habit that you'd do well to avoid.
Sanitize user input better
The date check could be a little more robust. In particular, verifying that the month is in the range of 1 to 12 is particularly important because that number is later used as an index into a vector. If I enter the nonsensical date 40/40/1940 the errorCheck
routine currently accepts it as valid and the program later crashes. If I enter just 40/40, the program also crashes.
Simplify your code
Right now the code includes this line:
while((startDay==endDay)!=1)
It would be more straightforward to simply write this:
while(startDay != endDay)
This would only require the addition of an operator!=
to the Date
.
Don't complicate the code
The code currently contains this structure declaration:
typedef struct Date{
// stuff
}Date;
First, the typedef
is neither needed nor useful. This isn't C. Second, it would make sense to declare it as a class
rather than as a struct
.
class Date {
// stuff
};
Use const
where practical
The operator==
member function of Date
does not alter the underlying object and therefore should be declared const
.
bool operator==(const Date& rhs) const;
Make your classes do more work!
The current Date
class is a very lazy thing, leaving all of the work to separate functions. I'd make it do much more of the work. For instance, I reimpplemented your algorithm but did most of the work in class operators. Here's an excerpt of that code:
int operator-(Date end, Date start) {
bool swapped{false};
if (end < start) {
std::swap(start, end);
swapped = true;
}
int diff = 0;
for ( ; start != end; ++start) {
++diff;
}
return swapped ? -diff : diff;
}
int main() {
Date start, end;
std::cout << "Enter start date in format DD MM YYYY\n";
std::cin >> start;
std::cout << "Enter ending date in format DD MM YYYY\n";
std::cin >> end;
std::cout << end-start << "\n";
}
Omit return 0
When a C or C++ program reaches the end of main
the compiler will automatically generate code to return 0, so there is no need to put return 0;
explicitly at the end of main
.
Note: when I make this suggestion, it's almost invariably followed by one of two kinds of comments: "I didn't know that." or "That's bad advice!" My rationale is that it's safe and useful to rely on compiler behavior explicitly supported by the standard. For C, since C99; see ISO/IEC 9899:1999 section 5.1.2.2.3:
[...] a return from the initial call to the
main
function is equivalent to calling theexit
function with the value returned by themain
function as its argument; reaching the}
that terminates themain
function returns a value of 0.
For C++, since the first standard in 1998; see ISO/IEC 14882:1998 section 3.6.1:
If control reaches the end of main without encountering a return statement, the effect is that of executing return 0;
All versions of both standards since then (C99 and C++98) have maintained the same idea. We rely on automatically generated member functions in C++, and few people write explicit return;
statements at the end of a void
function. Reasons against omitting seem to boil down to "it looks weird". If, like me, you're curious about the rationale for the change to the C standard read this question. Also note that in the early 1990s this was considered "sloppy practice" because it was undefined behavior (although widely supported) at the time.
So I advocate omitting it; others disagree (often vehemently!) In any case, if you encounter code that omits it, you'll know that it's explicitly supported by the standard and you'll know what it means.