Struct passed by reference results in garbage values - c++

Going through Project Euler and working through what I thought was a simple problem. For some reason when passing a struct Date by reference it results in garbage values when I try to reference or assign them. Any ideas?
#include <iostream>
using namespace std;
bool isLeapYear(int year)
{
// century
if ((year % 100 == 0) && (year % 400 == 0))
return true;
// not a century
else if ((year % 100 != 0) && (year % 4 == 0))
return true;
return false;
}
enum Months {JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC};
struct Date
{
int year;
Months month;
int day;
};
int calculateNumberOfDays(const Date& begin, const Date& end)
{
int numberOfDays = 0;
//PROBLEM: This loop never runs... Upon running it through the debugger
// the value of year is garbage i.e. -859382918
// This results in the loop not being entered and the value
// (numberOfDays) being returned as 0
for (int year = begin.year; year < end.year; year++)
{
if (isLeapYear(year))
numberOfDays += 366;
else
numberOfDays += 365;
}
//TODO: Finish for final year
return numberOfDays;
}
int main()
{
int numberOfDays = 0;
int year = 1900;
Months month = JAN;
int day = 1;
Date begin = { 1990, JAN, 1 };
Date end = { 1901, DEC, 31 };
cout << calculateNumberOfDays(begin, end) << endl;
return 0;
}

You begin date is after your end date, so the loop doesn't run. Swapping the two dates causes the loop to run correctly.
Your debugger is likely getting confused because you have two variables called year. That sent you down the wrong path.

Related

Can you put color only on certain words/paragraphs/lines?

i have a calendar in c++ and i wanted to put certain colors on certain days for each different month, but i dont know how, so i tried to at least put a certain color for every month, but i cant manage to do it. I used this code at the end of the main code, but i tried putting it anywhere tbh:
system("color A");
std::cout<<"hi"<<std::endl;
This is the entire code:
#include <stdio.h>
#include <string>
#include <windows.h>
#include <conio.h>
#include <iostream>
using namespace std;
int dayNumber(int day, int month, int year)
{
static int t[] = { 0,3,2,5,0,3,5,1,4,6,2,4 };
year -= month < 3;
return (year + year / 4 - year / 100 + year / 400 + t[month - 1] + day) % 7;
}
string getMonthName(int monthNumber)
// returns the names of the months in the order i wrote them to be
{
string months[] = { "January", "February", "March", "April",
"May", "June", "July", "August",
"September", "October", "November", "December" };
return (months[monthNumber]);
}
int numberOfDays(int monthNumber, int year)
// returns the number of days each month has, and instead of having numbers from 28 to 31 i
put 30 for each month there is
{
// January
if (monthNumber == 0)
return (30);
// February
if (monthNumber == 1)
return (30);
// March
if (monthNumber == 2)
return (30);
// April
if (monthNumber == 3)
return (30);
// May
if (monthNumber == 4)
return (30);
// June
if (monthNumber == 5)
return (30);
// July
if (monthNumber == 6)
return (30);
// August
if (monthNumber == 7)
return (30);
// September
if (monthNumber == 8)
return (30);
// October
if (monthNumber == 9)
return (30);
// November
if (monthNumber == 10)
return (30);
// December
if (monthNumber == 11)
return (30);
}
void printCalendar(int year)
// making a calendar for the months and days to be in order and nice looking
{
printf(" Calendar - %d\n\n", year);
int days;
int current = dayNumber (1, 1, year);
// i is for iterating months
// j is for iterating days of the months
for (int i = 0; i < 12; i++)
{
days = numberOfDays(i, year);
//The name of the current month
printf("\n -------------%s------------- \n",
getMonthName(i).c_str());
//The columns for each day in the week so they dont get mixed together
printf(" Sun Mon Tue Wed Thu Fri Sat\n");
/* blank spaces for the spaces in the calendar that dont regard the days in the exact
month, for example if 30 was on monday,
we would see the next 6 days as blank, as they are not part of this month, but are part of
the other month */
int k;
for (k = 0; k < current; k++)
printf(" ");
for (int j = 1; j <= days; j++)
{
printf("%5d", j);
if (++k > 6)
{
k = 0;
printf("\n");
}
}
if (k)
printf("\n");
current = k;
}
return;
}
// here we put what year we want, but it doesnt matter as the months have all 30 days,
//therefor whatever year we put we still have the same amounts of days
void Color(int color)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
}
int main()
{
system("color A");
std::cout<<"hi"<<std::endl;
int year = 2020;
printCalendar(year);
return 0;
}
Do not use system command, it will change the color of your whole console and will not be specific for a certain text on console.
Instead, use the SetTextConsoleAttribute function, as you did in your Color function. You may simply call the Color function wherever you want the color of console to change.
For example,
int main()
{
Color(7); // Use this color as default
for (int i = 0; i < 10; i++)
{
if (i == 4)
Color(10); // Change color to 10 if i = 4, otherwise use the default color.
cout << i << " ";
Color(7); // Change color to default.
}
}
I have modified your code to change the color for the complete month of Feburary and also for some specific days of November. Use the same pattern in any way you wish to color your Calendar. I have also added comments with all the changes I have made for better understanding. Ask any confusion if you still have any.
#include <stdio.h>
#include <string>
#include <windows.h>
#include <conio.h>
#include <iostream>
using namespace std;
void Color(int); // Make prototype of function.
int dayNumber(int day, int month, int year)
{
static int t[] = { 0,3,2,5,0,3,5,1,4,6,2,4 };
year -= month < 3;
return (year + year / 4 - year / 100 + year / 400 + t[month - 1] + day) % 7;
}
string getMonthName(int monthNumber)
// returns the names of the months in the order i wrote them to be
{
string months[] = { "January", "February", "March", "April",
"May", "June", "July", "August",
"September", "October", "November", "December" };
return (months[monthNumber]);
}
int numberOfDays(int monthNumber, int year)
// returns the number of days each month has, and instead of having numbers from 28 to 31 i
{
// January
if (monthNumber == 0)
return (30);
// February
if (monthNumber == 1)
return (30);
// March
if (monthNumber == 2)
return (30);
// April
if (monthNumber == 3)
return (30);
// May
if (monthNumber == 4)
return (30);
// June
if (monthNumber == 5)
return (30);
// July
if (monthNumber == 6)
return (30);
// August
if (monthNumber == 7)
return (30);
// September
if (monthNumber == 8)
return (30);
// October
if (monthNumber == 9)
return (30);
// November
if (monthNumber == 10)
return (30);
// December
if (monthNumber == 11)
return (30);
}
void printCalendar(int year)
// making a calendar for the months and days to be in order and nice looking
{
printf(" Calendar - %d\n\n", year);
int days;
int current = dayNumber(1, 1, year);
// i is for iterating months
// j is for iterating days of the months
for (int i = 0; i < 12; i++)
{
if (i == 1) // If month is Feb
Color(10);
days = numberOfDays(i, year);
//The name of the current month
printf("\n -------------%s------------- \n",
getMonthName(i).c_str());
//The columns for each day in the week so they dont get mixed together
printf(" Sun Mon Tue Wed Thu Fri Sat\n");
/* blank spaces for the spaces in the calendar that dont regard the days in the exact
month, for example if 30 was on monday,
we would see the next 6 days as blank, as they are not part of this month, but are part of
the other month */
int k;
for (k = 0; k < current; k++)
printf(" ");
for (int j = 1; j <= days; j++)
{
if (i == 10) // If the month is November
{
switch (j)
{
case 5:
case 6:
case 15:
Color(12); // For the days of 5, 6, 7 => Change color to Red.
break;
default:
Color(7); // Otherwise, use the default color.
}
}
printf("%5d", j);
if (++k > 6)
{
k = 0;
printf("\n");
}
}
if (k)
printf("\n");
current = k;
Color(7); // Change color to default color
}
return;
}
// here we put what year we want, but it doesnt matter as the months have all 30 days,
//therefor whatever year we put we still have the same amounts of days
void Color(int color)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
}
int main()
{
Color(7); // Default Color. Use color value = 7
std::cout << "hi" << std::endl;
int year = 2020;
printCalendar(year);
return 0;
}

Q&A: How do I figure out what the last day of the month is?

I was trying to write a roll-your-own timezone converter and I needed a way of determining what the last possible day of the month was. Upon some research, I discovered the formulas for finding a leap year.
It's a small contribution, but maybe I'll save someone else the 20 minutes it took me to figure out and apply it.
This code accepts a signed short month, indexed at 0 (0 is January) and an int year that is indexed as 0 as well (2012 is 2012).
It returns a 1 indexed day (the 27th is the 27th, but in SYSTEMTIME structures, etc., you usually need 0 indexed - just a head's up).
short _get_max_day(short month, int year) {
if(month == 0 || month == 2 || month == 4 || month == 6 || month == 7 || month == 9 || month == 11)
return 31;
else if(month == 3 || month == 5 || month == 8 || month == 10)
return 30;
else {
if(year % 4 == 0) {
if(year % 100 == 0) {
if(year % 400 == 0)
return 29;
return 28;
}
return 29;
}
return 28;
}
}
What about
#include <time.h>
#include <iostream>
int LastDay (int iMonth, int iYear)
{
struct tm when;
time_t lastday;
// Set up current month
when.tm_hour = 0;
when.tm_min = 0;
when.tm_sec = 0;
when.tm_mday = 1;
// Next month 0=Jan
if (iMonth == 12)
{
when.tm_mon = 0;
when.tm_year = iYear - 1900 + 1;
}
else
{
when.tm_mon = iMonth;
when.tm_year = iYear - 1900;
}
// Get the first day of the next month
lastday = mktime (&when);
// Subtract 1 day
lastday -= 86400;
// Convert back to date and time
when = *localtime (&lastday);
return when.tm_mday;
}
int _tmain(int argc, _TCHAR* argv[])
{
for (int m = 1; m <= 12; m++)
std::cout << "Last day of " << m << " is " << LastDay (m, 2002) << std::endl;
return 0;
}
It prints out (for year 2002)...
Last day of 1 is 31
Last day of 2 is 28
Last day of 3 is 31
Last day of 4 is 30
Last day of 5 is 31
Last day of 6 is 30
Last day of 7 is 31
Last day of 8 is 31
Last day of 9 is 30
Last day of 10 is 31
Last day of 11 is 30
Last day of 12 is 31
I use a simple function that returns the whole date in the from of a (Standard) COleDateTime. It may not be as fast other options, but it is very effective, works for leap years and pretty fool proof.
This is the Code that I am using:
COleDateTime get_last_day_of_month(UINT month, UINT year)
{
if(month == 2)
{ // if month is feb, take last day of March and then go back one day
COleDateTime date(year, 3, 1, 0, 0, 0); // 1 March for Year
date -= 1; // go back one day (the standard class will take leap years into account)
return date;
}
else if(month == 4 || month == 6 || month == 9 || month == 11) return COleDateTime(year, month, 30, 0, 0, 0);
else return COleDateTime(year, month, 31, 0, 0, 0);
}
import datetime
from datetime import date
from dateutil.relativedelta import relativedelta
year = int((date.today()).strftime("%Y"))
month = list(range(1, 13, 1))
YearMonthDay = [(datetime.datetime(year, x, 1) + relativedelta(day=31)).strftime("%Y%m%d") for x in month]
print(YearMonthDay)
['20220131', '20220228', '20220331', '20220430', '20220531', '20220630', '20220731', '20220831', '20220930', '20221031', '20221130', '20221231']
In C++20:
#include <chrono>
std::chrono::day
get_max_day(std::chrono::month m, std::chrono::year y)
{
return (y/m/std::chrono::last).day();
}
If you really need it with a type-unsafe API:
int
get_max_day(int m, int y)
{
return unsigned{(std::chrono::last/m/y).day()};
}
Word Year, Month, Day;
TDateTime datum_tdatetime = Date();
// first day of actual month
datum_tdatetime.DecodeDate(&year, &month, &day);
day = 1;
datum_tdatetime = EncodeDate(year, month, day);
// last day of previous month
datum_tdatetime -= 1;
// first day of previous month
datum_tdatetime.DecodeDate(&year, &month, &day);
day = 1;
datum_tdatetime = EncodeDate(year, month, day);

C++ get which day by input date

How do I able to get which day by input date?
Input Date example: 15-08-2012
How do I know if its monday, tuesday or which day using C++.
I am trying to omit out weekends from the date available of a month, so If i input e.g the month of August 2012, i want to check which day is saturday and which day is sunday, so i can omit it out from the available date for my program.
Code that I tried for getting the amount of days in a month:
if (month == 4 || month == 6 || month == 9 || month == 11)
{
maxDay = 30;
}
else if (month == 2)
//{
// bool isLeapYear = (year% 4 == 0 && year % 100 != 0) || (year % 400 == 0);
// if (isLeapYear)
// {
// maxDay = 29;
// }
//else
{
maxDay = 28;
}
The next thing i want to know is in that month, which day are weekend so i can omit that from result.
#include <ctime>
std::tm time_in = { 0, 0, 0, // second, minute, hour
4, 9, 1984 - 1900 }; // 1-based day, 0-based month, year since 1900
std::time_t time_temp = std::mktime( & time_in );
// the return value from localtime is a static global - do not call
// this function from more than one thread!
std::tm const *time_out = std::localtime( & time_temp );
std::cout << "I was born on (Sunday = 0) D.O.W. " << time_out->tm_wday << '\n';
Date to Day of the week algorithm?
I'd use mktime(). Given day, month and year, fill out a tm, then
call mktime on it:
tm timeStruct = {};
timeStruct.tm_year = year - 1900;
timeStruct.tm_mon = month - 1;
timeStruct.tm_mday = day;
timeStruct.tm_hour = 12; // To avoid any doubts about summer time, etc.
mktime( &timeStruct );
return timeStruct.tm_wday; // 0...6 for Sunday...Saturday
Here is a simpler and probably better implementation as it does not need any extra library imports.
The result returned is an int from 0 to 6 (Sunday, Mon, Tue... Saturday).
#include <iostream>
int dayofweek(int d, int m, int y){
static int t[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
y -= m < 3;
return ( y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
}
/* Driver function to test above function */
int main(){
int day = dayofweek(23, 10, 2013);
// Above statement finds the week day for 10/23/2013
//dayofweek(<day in month>,<month>,<year>)
std::cout << day;
return 0;
}
You should use mktime and ctime and extract the tm_wday field of the tm structure. It is guaranteed that mktime doesn't require that field, so you can populate a skeleton tm structure, process it and decompose it back into a complete structure:
#include <ctime>
std::tm t = {};
t.tm_mday = 15;
t.tm_mon = 8;
t.tm_year = 2012;
std::tm * p = std::localtime(std::mktime(&t));
// result is p->tm_wday
#include <stdio.h>
#include <time.h>
int main ()
{
char *str = "15-08-2012";
struct tm tm;
if (strptime (str, "%d-%m-%Y", &tm) == NULL) {
/* Bad format !! */
}
char buffer [80];
strftime (buffer, 80, "Day is %a", &tm);
puts (buffer);
return 0;
}

Can't seem to get the correct output from my code block

I was just wondering if anyone noticed i was doing something wrong with my code block. Ths program is supposed to be a test program that compares 2 dates. The function that im working on is supposed to return a 1 if the invoking date is greater, a -1 f the invoking date is less than, and a 0 if the invoking date is equal to the date in the parameter. My test Program :
#include <cstdlib>
#include <iostream>
#include <string>
#include "date.h"
using namespace std;
//date is initialized in a month/day/year format.
int main(int argc, char* argv[])
{
string* d;
date d1(4,1,4);
date d4(4,4,4);
int greaterTest = d4.compareTo(d1);
int lessTest = d1.compareTo(d4);
cout << greaterTest << endl; //i believe these two lines are printing out a
cout << lessTest << endl; //location in memory
cout<<&d <<endl;
system("pause");
return EXIT_SUCCESS;
}
The huge compareTo() function :
int date::compareTo (date another_date)
{
if (this->year == another_date.year && this->month == month && this->day < another_date.day) //if both year and month are the same, test to see if day is less
{
return -1;
}
else if (this->year == another_date.year && this->month == month && this->day > another_date.day) //if both year and month are the same, test to see if day is greater
{
return 1;
}
else if (this->year == another_date.year && this->month > month) //if the years are the same, test to see if the invoking month is greater
{
return 1;
}
else if (this->year == another_date.year && this->month < month) //if the years are the same, test to see if the invoking month is less
{
return -1;
}
else if (this->year > another_date.year) //test to see if the invoking year is greater
{
return 1;
}
else if (this->year < another_date.year) //test to see if the invoking year is less
{
return -1;
}
else if(this-> year == another_date.year && this-> month == another_date.month //test if the dates are exactly the same
&& this-> day == another_date.day)
{
return 0;
}
//else{ return 15;} //if none are true, return 15
}
the only problem im getting is when i try to change the day (the second parameter for date).
I'm not sure if this is the problem, since I can't test it... But, your compareTo function has this line:
this->month == month
Shouldn't it be:
this->month == another_date.month
?
In the first if statement and a few below it as well you have:
this->month == month
This is comparing month to itself, I think you meant:
this->month == another_date.month
Also you don't need to use the 'this' pointer all the time,
month == another_date.month
should suffice.
That might benefit from some early exit:
int date::compareTo (date another_date)
{
if (year > another_date.year) {
//the invoking year is greater
return 1;
}
if (year < another_date.year) {
//the invoking year is less
return -1;
}
// if we reached here, the years are the same. Don't need to compare them for the other cases
if (month > another_date.month) {
return 1;
}
if (month < another_date.month) {
return -1;
}
// if we reached here, the year and month are the same
if (day > another_date.day) {
return 1;
}
if (day < another_date.day) {
return -1;
}
// if we reached here, the year and month and day are the same
return 0;
}
Along the way, the cut+paste error just... disappeared, because that test became redundant.
Unless you're really set on doing an element-by-element comparison, I'd put each set of inputs into a struct tm, then use mktime to convert those to a time_t, and the compare the two time_ts directly. In a typical case, those will be a 32- or 64-bit integer of the number of seconds since midnight Jan 1, 1970, so after the conversion, comparison becomes trivial.
I didn't find your bug in your original code because it was too hard for me to read. I suppose that's why you didn't find it either.
This alternative might be easier to read, and easier to prove correct:
// untested
int date::compareTo (date another_date)
{
if (year < another_date.year) return -1;
if (year > another_date.year) return 1;
if (month < another_date.month) return -1;
if (month > another_date.month) return 1;
if (day < another_date.day) return -1;
if (day > another_date.day) return 1;
return 0;
}

easy way to add 1 month to a time_t in C/C++

I have some code that uses the Oracle function add_months to increment a Date by X number of months.
I now need to re-implement the same logic in a C / C++ function. For reasons I don't want/need to go into I can't simply issue a query to oracle to get the new date.
Does anyone know of a simple and reliable way of adding X number of months to a time_t?
Some examples of the types of calculations are shown below.
30/01/2009 + 1 month = 28/02/2009
31/01/2009 + 1 month = 28/02/2009
27/02/2009 + 1 month = 27/03/2009
28/02/2009 + 1 month = 31/03/2009
31/01/2009 + 50 months = 31/03/2013
You can use Boost.GregorianDate for this.
More specifically, determine the month by adding the correct date_duration, and then use end_of_month_day() from the date algorithms
Convert time_t to struct tm, add X to month, add months > 12 to years, convert back. tm.tm_mon is an int, adding 32000+ months shouldn't be a problem.
[edit] You might find that matching Oracle is tricky once you get to the harder cases, like adding 12 months to 29/02/2008. Both 01/03/2009 and 28/02/2008 are reasonable.
Really new answer to a really old question!
Using this free and open source library, and a C++14 compiler (such as clang) I can now write this:
#include "date.h"
constexpr
date::year_month_day
add(date::year_month_day ymd, date::months m) noexcept
{
using namespace date;
auto was_last = ymd == ymd.year()/ymd.month()/last;
ymd = ymd + m;
if (!ymd.ok() || was_last)
ymd = ymd.year()/ymd.month()/last;
return ymd;
}
int
main()
{
using namespace date;
static_assert(add(30_d/01/2009, months{ 1}) == 28_d/02/2009, "");
static_assert(add(31_d/01/2009, months{ 1}) == 28_d/02/2009, "");
static_assert(add(27_d/02/2009, months{ 1}) == 27_d/03/2009, "");
static_assert(add(28_d/02/2009, months{ 1}) == 31_d/03/2009, "");
static_assert(add(31_d/01/2009, months{50}) == 31_d/03/2013, "");
}
And it compiles.
Note the remarkable similarity between the actual code, and the OP's pseudo-code:
30/01/2009 + 1 month = 28/02/2009
31/01/2009 + 1 month = 28/02/2009
27/02/2009 + 1 month = 27/03/2009
28/02/2009 + 1 month = 31/03/2009
31/01/2009 + 50 months = 31/03/2013
Also note that compile-time information in leads to compile-time information out.
Method AddMonths_OracleStyle does what you need.
Perhaps you would want to replace IsLeapYear and GetDaysInMonth to some librarian methods.
#include <ctime>
#include <assert.h>
bool IsLeapYear(int year)
{
if (year % 4 != 0) return false;
if (year % 400 == 0) return true;
if (year % 100 == 0) return false;
return true;
}
int daysInMonths[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int GetDaysInMonth(int year, int month)
{
assert(month >= 0);
assert(month < 12);
int days = daysInMonths[month];
if (month == 1 && IsLeapYear(year)) // February of a leap year
days += 1;
return days;
}
tm AddMonths_OracleStyle(const tm &d, int months)
{
bool isLastDayInMonth = d.tm_mday == GetDaysInMonth(d.tm_year, d.tm_mon);
int year = d.tm_year + months / 12;
int month = d.tm_mon + months % 12;
if (month > 11)
{
year += 1;
month -= 12;
}
int day;
if (isLastDayInMonth)
day = GetDaysInMonth(year, month); // Last day of month maps to last day of result month
else
day = std::min(d.tm_mday, GetDaysInMonth(year, month));
tm result = tm();
result.tm_year = year;
result.tm_mon = month;
result.tm_mday = day;
result.tm_hour = d.tm_hour;
result.tm_min = d.tm_min;
result.tm_sec = d.tm_sec;
return result;
}
time_t AddMonths_OracleStyle(const time_t &date, int months)
{
tm d = tm();
localtime_s(&d, &date);
tm result = AddMonths_OracleStyle(d, months);
return mktime(&result);
}