找到正确的“'algorithm'”以确定给定月份的第一天
Finding the right ''algorithm'' to determine the first day of a given month
我试图制作一个程序来显示特定年份的给定月份的日历,但我真的找不到能够找到该月第一天的算法。
我的程序:
#include <stdio.h>
#include <stdlib.h>
int get_first_weekDay(int year, int months1, int monthDays[months1])
{
int day;
int months2 = monthDays[months1];
int beginning = 3;
while(months1 > 0)
{
months2 = months2 + monthDays[months1];
months1 = months1 - 1;
}
for (int i = 1800; i < year; i++)
{
if ((i % 4 == 0 && year % 100 != 0) || year % 400 == 0)
{
beginning = beginning + 366;
}
else
{
beginning = beginning + 365;
}
}
day = (beginning + months2) % 7;
return day;
}
int main(int argc, char* argv[])
{
if(argc != 3)
{
printf("Usage: ./calendar year month \n");
return 1;
}
int year = atoi(argv[1]);
int months1 = atoi(argv[2]) - 1;
int day = 0, dayInMonth, weekDay = 0, startingDay ,month;
char *months[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
int monthDays[] = {31,28,31,30,31,30,31,31,30,31,30,31};
if (argc == 3)
{
if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
{
monthDays[1] = 29;
}
startingDay = get_first_weekDay(year, months1, &monthDays[months1]);
for(month = 0; month < 12; month++)
{
if(months1 == month)
{
dayInMonth = monthDays[month] + 1;
printf(" %s %d \n ---------------------------", months[month], year);
printf("\n Sun Mon Tue Wed Thu Fri Sat\n");
for(weekDay = 0; weekDay < startingDay; weekDay++)
{
printf(" ");
}
for(day = 1; day < dayInMonth; day++)
{
printf("%4d", day);
if(++weekDay > 6)
{
printf("\n");
weekDay = 0;
}
startingDay = weekDay;
}
}
}
printf("\n");
return 1;
}
}
例如,如果我想知道 1800 年的第一个月,它会给出输出:
~/calendar/ $ ./calendar 1800 1
Jan 1800
---------------------------
Sun Mon Tue Wed Thu Fri Sat
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
但不正确,因为 1800 年 1 月的第一天不是星期六。
Calendar 1800
谁能帮我找到这样的算法。非常感谢!
您在月份处理中出现差一错误。您打印的是 1800 年 2 月。
int months2 = monthDays[months1];
应该是
int months2 = 0;
了解代码的作用后,这很容易调试。
代码以 Wed (int beginning = 3;
) 开头。
然后添加从 1800 年开始到指定年份的每一年的天数。
然后将指定月份之前每个月的天数添加到其中。
所以它应该为 1800 年 1 月加零。
至少这是它试图做的。那么为什么它返回 6
?好吧,很容易确认从未进入循环。这是对的。而且很容易看出它在 1 月之前的几个月中增加了非零天数。好吧,这显然是错误的。
年的处理也有问题
(i % 4 == 0 && year % 100 != 0) || year % 400 == 0
应该是
(i % 4 == 0 && i % 100 != 0) || i % 400 == 0
已清理:
#include <stdio.h>
#include <stdlib.h>
static const char *months[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
static const int monthDays[] = {31,28,31,30,31,30,31,31,30,31,30,31};
// Returns 0 or 1
static int is_leap_year(int year) {
return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}
static int get_days_in_month(int year, int month0) {
if (month0 == 1) {
int leap_days = is_leap_year(year);
return 28 + leap_days;
} else {
return monthDays[month0];
}
}
static int get_dow(int year, int month0, int day) {
int dow = 3; // 1800-01-01 is a Wednesday.
// For each year up to provided year (exclusive), starting with 1800.
while (year-- > 1800) {
int leap_days = is_leap_year(year);
dow += 365 + leap_days;
}
// For each month up to provided month (exclusive)
while (month0--)
dow += monthDays[month0];
// For each day up to the provided day (exlcusive)
dow += day - 1;
return dow % 7;
}
int main(int argc, char* argv[]) {
if(argc != 3) {
fprintf(stderr, "Usage: ./calendar year month \n");
return 1;
}
int year = atoi(argv[1]);
int month0 = atoi(argv[2]) - 1; // 0-based month
int day = 1; // 1-based day
int dow = get_dow(year, month0, day);
int num_days = get_days_in_month(year, month0);
printf(" %s %d\n", months[month0], year);
printf(" ---------------------------\n");
printf(" Sun Mon Tue Wed Thu Fri Sat\n");
for (int i=0; i<dow; ++i)
printf(" ");
while (day <= num_days) {
printf("%4d", day++);
dow = ( dow + 1 ) % 7;
if (!dow)
printf("\n");
}
if (dow)
printf("\n");
return 0;
}
for (int i = 1800; i < year; i++)
{
...
if ((i % 4 == 0 && year % 100 != 0) || year % 400 == 0)
}
不清楚上面的公式试图计算什么。貌似是闰年计算,不过year
应该是i
.
函数 get_first_weekDay
需要一个数组作为第三个参数。但是你称它为
startingDay = get_first_weekDay(year, months1, &monthDays[months1]);
修复这些错误似乎没有多大作用。其余的计算相当混乱。我重写了函数get_first_weekDay
。请注意,它需要一个数组输入。
#include <stdio.h>
#include <stdlib.h>
int is_leap_year(int y)
{ return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0); }
int get_first_weekday(int year, int month, int days_in_month[12])
{
int beginning = 3; //1800, Jan, 1 is wedndsay (3)
for (int y = 1800; y < year; y++)
beginning += is_leap_year(y) ? 366 : 365;
for (int m = 0; m < month; m++)
beginning += days_in_month[m];
return beginning % 7;
}
void print_calendar(int year, int month)
{
month--;
const char* months[] = { "Jan","Feb","Mar","Apr","May","Jun",
"Jul","Aug","Sep","Oct","Nov","Dec" };
int days_in_month[] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
if (is_leap_year(year))
days_in_month[1] = 29;
int first_week_day = get_first_weekday(year, month, days_in_month);
printf(" %s %d \n", months[month], year);
printf(" ---------------------------\n");
printf(" Sun Mon Tue Wed Thu Fri Sat\n");
for (int wkday = 0; wkday < first_week_day; wkday++)
printf(" ");
for (int day = 1; day < days_in_month[month] + 1; day++)
{
printf("%4d", day);
if(((day + first_week_day) % 7) == 0)
printf("\n");
}
printf("\n\n");
}
int main(void)
{
for (int m = 1; m < 4; m++) print_calendar(1800, m);
for (int m = 8; m <= 12; m++) print_calendar(2021, m);
return 0;
}
我试图制作一个程序来显示特定年份的给定月份的日历,但我真的找不到能够找到该月第一天的算法。
我的程序:
#include <stdio.h>
#include <stdlib.h>
int get_first_weekDay(int year, int months1, int monthDays[months1])
{
int day;
int months2 = monthDays[months1];
int beginning = 3;
while(months1 > 0)
{
months2 = months2 + monthDays[months1];
months1 = months1 - 1;
}
for (int i = 1800; i < year; i++)
{
if ((i % 4 == 0 && year % 100 != 0) || year % 400 == 0)
{
beginning = beginning + 366;
}
else
{
beginning = beginning + 365;
}
}
day = (beginning + months2) % 7;
return day;
}
int main(int argc, char* argv[])
{
if(argc != 3)
{
printf("Usage: ./calendar year month \n");
return 1;
}
int year = atoi(argv[1]);
int months1 = atoi(argv[2]) - 1;
int day = 0, dayInMonth, weekDay = 0, startingDay ,month;
char *months[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
int monthDays[] = {31,28,31,30,31,30,31,31,30,31,30,31};
if (argc == 3)
{
if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
{
monthDays[1] = 29;
}
startingDay = get_first_weekDay(year, months1, &monthDays[months1]);
for(month = 0; month < 12; month++)
{
if(months1 == month)
{
dayInMonth = monthDays[month] + 1;
printf(" %s %d \n ---------------------------", months[month], year);
printf("\n Sun Mon Tue Wed Thu Fri Sat\n");
for(weekDay = 0; weekDay < startingDay; weekDay++)
{
printf(" ");
}
for(day = 1; day < dayInMonth; day++)
{
printf("%4d", day);
if(++weekDay > 6)
{
printf("\n");
weekDay = 0;
}
startingDay = weekDay;
}
}
}
printf("\n");
return 1;
}
}
例如,如果我想知道 1800 年的第一个月,它会给出输出:
~/calendar/ $ ./calendar 1800 1
Jan 1800
---------------------------
Sun Mon Tue Wed Thu Fri Sat
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
但不正确,因为 1800 年 1 月的第一天不是星期六。 Calendar 1800
谁能帮我找到这样的算法。非常感谢!
您在月份处理中出现差一错误。您打印的是 1800 年 2 月。
int months2 = monthDays[months1];
应该是
int months2 = 0;
了解代码的作用后,这很容易调试。
代码以 Wed (int beginning = 3;
) 开头。
然后添加从 1800 年开始到指定年份的每一年的天数。
然后将指定月份之前每个月的天数添加到其中。
所以它应该为 1800 年 1 月加零。
至少这是它试图做的。那么为什么它返回 6
?好吧,很容易确认从未进入循环。这是对的。而且很容易看出它在 1 月之前的几个月中增加了非零天数。好吧,这显然是错误的。
年的处理也有问题
(i % 4 == 0 && year % 100 != 0) || year % 400 == 0
应该是
(i % 4 == 0 && i % 100 != 0) || i % 400 == 0
已清理:
#include <stdio.h>
#include <stdlib.h>
static const char *months[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
static const int monthDays[] = {31,28,31,30,31,30,31,31,30,31,30,31};
// Returns 0 or 1
static int is_leap_year(int year) {
return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}
static int get_days_in_month(int year, int month0) {
if (month0 == 1) {
int leap_days = is_leap_year(year);
return 28 + leap_days;
} else {
return monthDays[month0];
}
}
static int get_dow(int year, int month0, int day) {
int dow = 3; // 1800-01-01 is a Wednesday.
// For each year up to provided year (exclusive), starting with 1800.
while (year-- > 1800) {
int leap_days = is_leap_year(year);
dow += 365 + leap_days;
}
// For each month up to provided month (exclusive)
while (month0--)
dow += monthDays[month0];
// For each day up to the provided day (exlcusive)
dow += day - 1;
return dow % 7;
}
int main(int argc, char* argv[]) {
if(argc != 3) {
fprintf(stderr, "Usage: ./calendar year month \n");
return 1;
}
int year = atoi(argv[1]);
int month0 = atoi(argv[2]) - 1; // 0-based month
int day = 1; // 1-based day
int dow = get_dow(year, month0, day);
int num_days = get_days_in_month(year, month0);
printf(" %s %d\n", months[month0], year);
printf(" ---------------------------\n");
printf(" Sun Mon Tue Wed Thu Fri Sat\n");
for (int i=0; i<dow; ++i)
printf(" ");
while (day <= num_days) {
printf("%4d", day++);
dow = ( dow + 1 ) % 7;
if (!dow)
printf("\n");
}
if (dow)
printf("\n");
return 0;
}
for (int i = 1800; i < year; i++)
{
...
if ((i % 4 == 0 && year % 100 != 0) || year % 400 == 0)
}
不清楚上面的公式试图计算什么。貌似是闰年计算,不过year
应该是i
.
函数 get_first_weekDay
需要一个数组作为第三个参数。但是你称它为
startingDay = get_first_weekDay(year, months1, &monthDays[months1]);
修复这些错误似乎没有多大作用。其余的计算相当混乱。我重写了函数get_first_weekDay
。请注意,它需要一个数组输入。
#include <stdio.h>
#include <stdlib.h>
int is_leap_year(int y)
{ return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0); }
int get_first_weekday(int year, int month, int days_in_month[12])
{
int beginning = 3; //1800, Jan, 1 is wedndsay (3)
for (int y = 1800; y < year; y++)
beginning += is_leap_year(y) ? 366 : 365;
for (int m = 0; m < month; m++)
beginning += days_in_month[m];
return beginning % 7;
}
void print_calendar(int year, int month)
{
month--;
const char* months[] = { "Jan","Feb","Mar","Apr","May","Jun",
"Jul","Aug","Sep","Oct","Nov","Dec" };
int days_in_month[] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
if (is_leap_year(year))
days_in_month[1] = 29;
int first_week_day = get_first_weekday(year, month, days_in_month);
printf(" %s %d \n", months[month], year);
printf(" ---------------------------\n");
printf(" Sun Mon Tue Wed Thu Fri Sat\n");
for (int wkday = 0; wkday < first_week_day; wkday++)
printf(" ");
for (int day = 1; day < days_in_month[month] + 1; day++)
{
printf("%4d", day);
if(((day + first_week_day) % 7) == 0)
printf("\n");
}
printf("\n\n");
}
int main(void)
{
for (int m = 1; m < 4; m++) print_calendar(1800, m);
for (int m = 8; m <= 12; m++) print_calendar(2021, m);
return 0;
}