In my program, I am asking the user to input a date (in just integers such as 12 31 2019 367) and the number of days they add to it. In one of my functions, this is precisely what I am doing.
The user inputs 12 31 2019 367, and the program is meant to print 1 1 2021, but instead prints 1 1 2020 (a year behind)...
What I did (sorry for a lot of code, I tried to keep it simple and clean):
int days_in_month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
void add_days_to_date(int *mm, int *dd, int *yy, int days_left_to_add)
{
int days_left_in_month;
while(days_left_in_month > 0)
{
days_left_in_month = days_in_month[*mm] - *dd;
// days_left_in_month = days_in_month[*mm] - *dd;
if (days_in_month[2] && is_leap_year(*yy) == true)
{
days_left_in_month++;
}
} // end while
printf("after while\n");
if(days_left_to_add > days_left_in_month)
{
days_left_to_add -= days_left_in_month;
*dd = 1;
if(*mm == 12)
{
*mm = 1;
(*yy)++;
}
else
{
(*mm)++;
}
}
else
{
*dd += days_left_to_add;
days_left_to_add = 0;
}
}
int main()
{
int mm, dd, yy, days_left_to_add;
printf("Please enter a date between the years 1800 and 10000 in the format mm dd yy and provide the number of days to add to this date:\n");
scanf("%d %d %d %d", &mm, &dd, &yy, &days_left_to_add);
// printf("\nREAD\n");
//These are pointers, so they have to be at certain location i.e. int* mm = &mm
add_days_to_date(&mm, &dd, &yy, days_left_to_add);
printf("%d %d %d\n", mm, dd, yy);
}
What I got after inputs:
Inputs: 12 31 2019 367
Output: 1 1 2020 (meant to be 1 1 2021)
Your loop in the function needs to be while (days_left_to_add > 0), and should cover the whole of the function (and then needs some minor adjustments). As it is, you add just one month, which given that your input is 2019-12-31 lands you on 2020-01-01.
Your code should validate the input date.
This code works, at least for a number of test cases similar to your example.
/* SO 74925-5084 */
#include <stdio.h>
#include <stdbool.h>
static const int days_in_month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static bool is_leap_year(int year)
{
if (year % 4 != 0)
return false;
if (year % 100 != 0)
return true;
if (year % 400 != 0)
return false;
return true;
}
static void add_days_to_date(int *mm, int *dd, int *yy, int days)
{
while (days > 0)
{
int days_left_in_month = days_in_month[*mm] - *dd + 1;
if (*mm == 2 && is_leap_year(*yy))
days_left_in_month++;
//printf("DAYS = %2d, DLIM = %2d, leap(%4d) = %s\n",
// days, days_left_in_month, *yy, is_leap_year(*yy) ? "true" : "false");
if (days >= days_left_in_month)
{
days -= days_left_in_month;
*dd = 1;
if (*mm == 12)
{
*mm = 1;
(*yy)++;
}
else
{
(*mm)++;
}
}
else
{
*dd += days;
days = 0;
}
// This is informative while debugging
printf("%.4d-%.2d-%.2d + %d\n", *yy, *mm, *dd, days);
}
}
int main(void)
{
int mm, dd, yy, days_left_to_add;
printf("Please enter a date between the years 1800 and 10000 in the format mm dd yyyy\n"
"and provide the positive number of days to add to this date:\n");
if (scanf("%d %d %d %d", &mm, &dd, &yy, &days_left_to_add) != 4)
{
fprintf(stderr, "Failed to read 4 numbers\n");
return 1;
}
printf("Input: %.4d-%.2d-%.2d + %d\n", yy, mm, dd, days_left_to_add);
/* Data validation */
if (days_left_to_add <= 0)
{
fprintf(stderr, "The number of days to add must be a positive number (unlike %d)\n",
days_left_to_add);
return 1;
}
if (yy < 1800 || yy > 10000)
{
fprintf(stderr, "Year %d is outside the range 1800..10000\n", yy);
return 1;
}
if (mm < 1 || mm > 12)
{
fprintf(stderr, "Month %d is outside the range 1..12\n", mm);
return 1;
}
int dim = days_in_month[mm];
if (mm == 2 && is_leap_year(yy))
dim++;
if (dd < 1 || dd > dim)
{
fprintf(stderr, "Day %d is outside the range 1..%d\n", dd, dim);
return 1;
}
add_days_to_date(&mm, &dd, &yy, days_left_to_add);
printf("%d %d %d\n", mm, dd, yy);
return 0;
}
Sample runs (program ad41 created from ad41.c):
$ ad41
Please enter a date between the years 1800 and 10000 in the format mm dd yyyy
and provide the positive number of days to add to this date:
12 31 2019 367
Input: 2019-12-31 + 367
2020-01-01 + 366
2020-02-01 + 335
2020-03-01 + 306
2020-04-01 + 275
2020-05-01 + 245
2020-06-01 + 214
2020-07-01 + 184
2020-08-01 + 153
2020-09-01 + 122
2020-10-01 + 92
2020-11-01 + 61
2020-12-01 + 31
2021-01-01 + 0
1 1 2021
$ ad41
Please enter a date between the years 1800 and 10000 in the format mm dd yyyy
and provide the positive number of days to add to this date:
12 31 2018 60
Input: 2018-12-31 + 60
2019-01-01 + 59
2019-02-01 + 28
2019-03-01 + 0
3 1 2019
$ ad41
Please enter a date between the years 1800 and 10000 in the format mm dd yyyy
and provide the positive number of days to add to this date:
12 31 2019 60
Input: 2019-12-31 + 60
2020-01-01 + 59
2020-02-01 + 28
2020-02-29 + 0
2 29 2020
$
Related
I need to write a program in C that it prints a month chosen by the user from the year 2022.
If the user enter January (has 31 days) and the user enter to print 20 days, then should be printed from 1st January untill 20 January.
Same for every month.
I have this pice of code but I'm not happy with it and I googled everything.
void print_month(char *mo, int number_day_userInput){
int i,j; // as counters
int week = 7; // as 7 days in a week
int day=1;
int day_of_the_week=1;
printf("M\tT\tW\tT\tF\tS\tS");
//January
if(strcmp(mo, "January")== 0){
for(i=0;i<=5;i++){ // this 5 is as 5 weeks in January
printf("\n");
for(j=1;j<=week;j++){
if(day_of_the_week>=6){ // 1st day start printing
printf("%i",day);
day++;
if(day > number_day_userInput){
break;
}
}
day_of_the_week++;
printf("\t");
}
}
printf("\n\nJanuary has 31 days");
}
I can't figure it out, how to determine for each month where to start printing the first day. For example, January 1st starts on a Saturday, the 6th day. February starts on 2nd day. Also, I don't know how to determine how many weeks are in a month. Could you please share some ideas ? Not necessarily in C, but an advice will be welcomed. Thank you
Here I started with Sunday as day 0 (Gregorian calendar). It should print out correctly based on the month given. Core concept here is just using the modulus operator % to find remainders, and basic for-loop stuff :)
#include <stdio.h>
#include <string.h>
static int daysOfMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static int start = 6;
void print_month(char *mo, int number_day_userInput)
{
int j = 0;
if(strcmp(mo, "February") == 0) { j = 1; }
else if(strcmp(mo, "March") == 0) { j = 2; }
else if(strcmp(mo, "April") == 0) { j = 3; } // and so on...
for(int i = 0; i < j; ++i)
{
start += daysOfMonth[i];
}
int startDay = start % 7;
printf("S\tM\tT\tW\tT\tF\tS\n");
for(int tab = 0; tab < startDay; ++tab)
{
printf("\t");
}
for(int day = 1; day <= number_day_userInput; ++day)
{
printf("%d\t", day);
if(++startDay % 7 == 0)
{
printf("\n");
}
}
printf("\n");
}
int main()
{
print_month("March", 20);
}
SAMPLE OUTPUT of print_month("January", 31):
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
The 2nd answer in How do I convert "2012-03-02" into unix epoch time in C? does provides the solution. But it uses tm_yday instead of tm_mday and tm_mon of tm structure.
My Input is human readable date and time and the desired output is UNIX epoch time.
int main(int argc, char *argv[])
{
char timeString[80] = {"05 07 2021 00 33 51"}; //epoch is 1620347631000
struct tm my_tm = {0};
if(sscanf(timeString, "%d %d %d %d %d %d", &my_tm.tm_mon, &my_tm.tm_mday, &my_tm.tm_year, &my_tm.tm_hour, &my_tm.tm_min, &my_tm.tm_sec)!=6)
{
/* ... error parsing ... */
printf(" sscanf failed");
}
// In the below formula, I can't use my_tm.tm_yday as I don't have the value for it.
//I want to use my_tm.tm_mday and tm_mon.
printf("%d",my_tm.tm_sec + my_tm.tm_min*60 + my_tm.tm_hour*3600 + my_tm.tm_yday*86400 +
(my_tm.tm_year-70)*31536000 + ((my_tm.tm_year-69)/4)*86400 -
((my_tm.tm_year-1)/100)*86400 + ((my_tm.tm_year+299)/400)*86400 );
return EXIT_SUCCESS;
}
So, in other words, I'm looking for a replacement for my_tm.tm_yday*86400 in terms of my_tm.tm_mday and my_tm.tm_mon
A year in the range "date of adoption of Gregorian calendar" to INT_MAX and a month in the range 1 to 12 can be converted to a zero-based "year day" in the range 0 to 365 by the following helper function:
int yday(int year, int month)
{
static const short int upto[12] =
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
int yd;
yd = upto[month - 1];
if (month > 2 && isleap(year))
yd++;
return yd;
}
That uses the following helper function isyear that takes a year in the range "date of adoption of Gregorian calendar" to INT_MAX and returns 0 if the year is not a leap year, 1 if the year is a leap year:
int isleap(int year)
{
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
}
I am a newbie to coding and I am trying to code for the "Friday the Thirteenth" problem posted in USACO, which requires us to compute the frequency that the 13th of each month lands on Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, and Saturday over a given period of N years. The time period to test will be from January 1, 1900 to December 31, 1900+N-1 for a given number of years, N. N is positive and will not exceed 400.
It was given that Jan 1, 1900 was on a Monday. We are not supposed to use any in-built functions.
I tried to solve this problem with a different approach (which I think isn't the best approach). My code (in C) is given below:
#include<stdio.h>
int daysInMonth (int month, int year)
{
/*
30 should be returned if the months are Apr, June, Sept and Nov.
31 should be returned in all other cases.
29 should be returned if the month is Feb and the year is a leap year
*/
if (month == 1) //Feb
{
if (year % 4 == 0 || (year % 100 != 0 && year % 400 == 0)) //leap year
return 29;
else
return 28;
}
switch (month)
{
case 3:
case 5:
case 8:
case 10: return 30;
default: return 31;
}
}
void main ()
{
int month, year, n, i, noOfDays, start = 0, result[] = { 0, 0, 0, 0, 0, 0, 0 }, day = 0, daycheck = 1;
scanf ("%d", &n);
for (year = 1900; year <= 1900 + n - 1; ++year)
{
for (month = 0; month < 12; ++month)
{
if (month == 0 && year == 1900) // to identify the first 13th and the day it falls on
{
while (daycheck != 13)
{
++daycheck;
day = (day + 1) % 7;
}
++result[day];
}
else
{
if (month == 0) //If January, add the noOfDays of the prev. month i.e. December
noOfDays = 31;
else
noOfDays = daysInMonth (month - 1, year);
day += (noOfDays - 28); // Adding a multiple of 7 (here, 28) does not change the day
day %= 7;
++result[day];
}
}
}
for (i = 0; i < 7; ++i)
printf("%d ", result[(i + 5) % 7]); //Sat, Sun, Mon, Tue, Wed, Thu, Fri
}
For an input of 20, the expected output is 36 33 34 33 35 35 34.
However, my output turns out to be 35 35 33 35 32 35 35.
Even though my answer is within the range of the expected output, there's something wrong with my logic that makes it erroneous.
I would appreciate if someone could point out the error. I would also be happy if you could suggest a better way to approach this problem. I am a student of Computer Science and am yet to learn about algorithms in detail.
Your leap year condition is wrong.
Change the Leap year condition as follows.
int daysInMonth (int month, int year)
{
if (month == 1) //Feb
{
if (( year%400 == 0)|| (( year%4 == 0 ) &&( year%100 != 0)))
return 29;
else
return 28;
}
I am trying to print out a calendar for a specific year and month but keep getting the same calendar for every month. I tried to also add a statement to see if the year is a leap year to add to the number of days but it made no difference. I am new to c.Please help with any suggestions. Thanks in advance.
void print_month_calendar(int year, int month)
{
int day;
int daycode = ddaycode(year);
int days_in_month[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
char *months[]=
{
" ",
"\n\n\nJanuary",
"\n\n\nFebruary",
"\n\n\nMarch",
"\n\n\nApril",
"\n\n\nMay",
"\n\n\nJune",
"\n\n\nJuly",
"\n\n\nAugust",
"\n\n\nSeptember",
"\n\n\nOctober",
"\n\n\nNovember",
"\n\n\nDecember"
};
printf("%s", months[month]);
printf("\n\nSun Mon Tue Wed Thu Fri Sat\n");
if(( year%4==0 && year%100 !=0) || year%400==0)
days_in_month[2] = 29;
for (day = 1; day <= 1 + daycode * 5; day++)
{
printf(" ");
}
//Print all the dates for the month
for (day = 1; day <= days_in_month[month]; day++)
{
printf("%2d", day);
if ((day + daycode) % 7 > 0)
printf(" ");
else
printf("\n ");
}
}
int ddaycode(int year)
{
int daycode;
int d1, d2, d3;
d1 = (year - 1.)/ 4.0;
d2 = (year - 1.)/ 100.;
d3 = (year - 1.)/ 400.;
daycode = (year + d1 - d2 + d3) %7;
return daycode;
}
You have to know the first weekday in the month. You can use localtime to go to specific date, use mktime to get struct tm data which contains weekday. In addition, you can use strftime to get the month name. Example:
void print_month_calendar(int year, int month)
{
time_t rawtime;
struct tm * timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
timeinfo->tm_year = year - 1900;
timeinfo->tm_mon = month - 1;
timeinfo->tm_mday = 1;
mktime(timeinfo);
//sunday is 1 ... saturday is 7
int weekday = 1 + timeinfo->tm_wday;
int days_in_month[] = { 0, 31,28,31,30,31,30,31,31,30,31,30,31 };
if ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0))
days_in_month[2]++;
char monthname[30];
strftime(monthname, sizeof(monthname), "%B", timeinfo);
printf(" %s %d\n", monthname, year);
printf(" Su Mo Tu We Th Fr Sa\n");
int day = 1;
for (int i = 1; i <= 40; i++)
{
if (i < weekday)
{
printf(" ");
}
else
{
printf("%3d ", day);
if (day == days_in_month[month])
break;
day++;
if ((i % 7) == 0)
printf("\n");
}
}
printf("\n");
}
int main()
{
print_month_calendar(2016, 10);
return 0;
}
ideone example
October 2016
Su Mo Tu We Th Fr Sa
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
I'm stuck on a program that takes the user's desired year and prints out a 12 month calendar for the same year. This is all I have so far and I'm pretty sure I have the right way to figure out whether the year is a leap year (in the code) and how to find out when the 1st of Jan is (underneath first with just variables then filled in). Also I am trying to print this in normal Calendar format with the month on top then the days of the week underneath followed by the day numbers. Any help would be appreciated.
Find first day:
h = (1 + [(13(m + 1))/5] + K + [K/4] + [J/4] - 2J) mod 7
h = (1 + [(13(13 + 1))/5] + (year % 100) + [(year % 100)/4] + [(year/100)/4] - 2(year/100) % 7
H is the starting day, M is the month, K is yr % 100, J is yr / 100.
/* Calendar.c */
#include <stdio.h>
int main(void){
int year, month, date;
int startingDay; /* initfrom user input*/
printf("Enter the year of your desired calendar: ");
scanf("%d\n", &year);
if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0))
int months[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
else
int months[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
for (month = 0; month < 12; month++) {
const int daysInMonth = ; /* set # of days */
int dayOfWeek;
printf(…); //month name
printf(…); //days of week
for (dayOfWeek = 0; dayOfWeek<startingDay; dayOfWeek++)
printf(/*blanks*/);
for (int date = 1; date <= daysInMonth; date++) {
printf("…", date);
if (++dayOfWeek>6) {
printf("\n");
dayOfWeek = 0;
}
} // for date
if (dayOfWeek !=0)
printf("\n");
startingDay = dayOfWeek;
} // for month
}
Output:
February 2009
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6 7
8 9 10 11 12 13 14
The following compiles, but there are still opportunities for improvement:
/* calender.c */
#include <stdio.h>
#include <stdlib.h>
#define JULIAN 1
#define GREGORIAN 2
/*
* return the day of the week for particualr date
* flag JULIAN or GREGORIAN
* (the divisions are integer divisions that truncate the result)
* Sun = 0, Mon = 1, etc.
*/
int get_week_day(int day, int month, int year, int mode) {
int a, m, y;
a = (14 - month) / 12;
y = year - a;
m = month + 12*a - 2;
if (mode == JULIAN) {
return (5 + day + y + y/4 + (31*m)/12) % 7;
}
return (day + y + y/4 - y/100 + y/400 + (31*m)/12) % 7; // GREGORIAN
}
int main(void) {
int year, month, date;
int startingDay; /* of the week: init from user input*/
char *names[] = {"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"};
printf("Enter the year of your desired calendar: ");
scanf("%d", &year);
// could check whether input is valid here
startingDay = get_week_day(1, 1, year,GREGORIAN);
int months[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0))
months[1] = 29;
for (month = 0; month < 12; ++month) {
const int daysInMonth = months[month]; /* set # of days */
int dayOfWeek, date;
printf("\n ------------%s-------------\n", names[month]); // month name
printf(" Sun Mon Tue Wed Thu Fri Sat\n"); // days of week
for (dayOfWeek = 0; dayOfWeek < startingDay; ++dayOfWeek)
printf(" ");
for (date = 1; date <= daysInMonth; ++date) {
printf("%5d", date);
if (++dayOfWeek > 6) {
printf("\n");
dayOfWeek = 0;
}
} // for date
if (dayOfWeek != 0)
printf("\n");
startingDay = dayOfWeek;
} // for month
return EXIT_SUCCESS;
}