您的位置:首页 > 其它

基于Win32控制台的万年历的实现(上)

2017-06-29 22:19 302 查看
本程序是基于Win32控制台的,当用户输入要显示日历的年份后,会显示该年的每一天所对应的星期,如图1所示。


 
图1
万年历程序效果

1 流程图

万年历程序的流程图如1-1所示。



 图1-1
万年历程序流程

2 代码实现

2.1 确定要查询年份的1月1日

要实现指定年份中所有12个月份的显示,就必须要确定该年份的起始日期即1月1日是星期几。前提是公元1年1月1日为星期一,之后计算从公元1年1月1日起,到指定要查询年份的1月1日止,这个时间段中的天数,通过该天数得到查询年份的1月1日是星期几。

2.1.1 获取时间段内的天数

(1)判断闰年

要获取时间段内的天数,就要判断这个时间段内哪些年份是闰年。通过一个自定义函数实现闰年的判断,该函数的参数是指定的年份,如果指定的年份是闰年,则函数的返回值是366,否则是365。

int IsLeapYear(int year)

{

if ((year % 4 == 0) && (year % 100 !=
0) || year % 400 == 0)

return 366;

else

return 365;

}

(2)获取要显示的年份

通过scanf_s()函数获取输入的年份。

int year;

printf("请输入要显示的年份:");

scanf_s("%d", &year);

(3)获取总天数

在获取了要显示的年份之后,循环调用IsLeapYear()函数对时间段内的年份包含的天数进行判断和累加,最后得到总天数。

int days_sum;

for (i = 1; i<y; i++)

days_sum += IsLeapyear(i);

2.1.2 判断指定年份的1月1日是星期几

在获取了时间段内的总天数之后,用该天数与7(一个星期包含7天)进行取余运算,即可得到1月1日是星期几。假设星期天的值是0,星期一的值是1,依次类推:

int start_week;

start_week = (days_sum + 1) % 7;

其中,days_sum是在“2.1.1”中获取到的总天数,因为公元1年1月1日为星期一,即起点的值是1,所以需要对days_sum进行加1操作。

2.2 循环显示日历标题、星期列表及1号前的空格

从图1中可以看到,显示每个月份的日期时,需要显示当前月份的名字以及星期的列表;如果当前月份的1号不是星期天,则还需要在其前面显示空格。

通过for循环实现指定年份12个月的遍历。

for (int i = 0; i<12; i = i + 1)

{

            ........

}

2.2.1 显示日历标题

在for循环内部,i的值即为要显示的月份数。因此,通过以下代码显示日历标题,即月份数:

printf("        %d月                 \n", i + 1);

其中,i的值是从0开始,而月份是从1开始,所以需要对i进行加1操作。

2.2.2 显示星期列表

通过printf()函数输出字符串即可实现星期列表的显示。

printf("  日  一  二  三  四  五  六  \n");

printf("=============================\n");

2.2.3 显示1号前面的空格

在“2.1.2”中提到,start_week变量表示每个月的1号是星期几,而日历是从星期天开始显示的,星期天的值是0。所以,每个月的1号是星期几,则在1号前面就显示几个空格。

for (int j = 0; j<start_week; j++)

printf("    ");

2.3 显示日期

首先定义一个整形数组,该数组中包含12个元素,分别对应12个月包含的天数。之后,判断当前月份的天数是否已经全部显示,如果没有全部显示,则继续显示天数。

2.3.1 定义月份天数数组

int days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };

if (IsLeapYear(year) == 366)

days[1] = 29;

其中,year是要显示的年份,如果该年份是闰年,则将2月份的天数设置为29天。

2.3.2 判断当前月份的天数是否已经全部显示

int day_month = 1;

while (day_month <= days[i])

{

printf("%4d", day_month);

      day_month++;

}

其中,i是“2.2”中12个月的循环变量;用当前显示的天数day_month与相应月份的天数days[i]进行比较,如果显示的天数小于等于相应月份的天数,则说明当前月份的天数没有全部显示,则调用printf()函数进行显示。

2.4 判断当前星期是否全部显示

在显示日历时,一个星期为一行。因此,还需要判断当前星期是否全部显示,如果全部显示,则换行后继续显示日期。

start_week变量表示当前日期的星期数。因此,在“2.3.2”中的while()循环中,在显示了当前日期之后,接下来对start_week进行操作,判断当前星期是否全部显示。

start_week = (start_week + 1) % 7;

if (start_week == 0)

   printf("\n");

start_week的值是0,则说明当前日期是星期天,此时就应该换行,开始显示下一个星期。

#include "stdafx.h"
#include <stdio.h>

int IsLeapYear(int year)
{
if ((year % 4 == 0) && (year % 100 != 0) || year % 400 == 0)
return 366;
else
return 365;
}

int main()
{
int year;
int i, j, days_sum = 0, t = 0;
int day_month, start_week;
int days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };

printf("请输入要显示的年份:");
scanf_s("%d", &year);
for (i = 1; i<year; i++)
days_sum += IsLeapYear(i);

start_week = (days_sum + 1) % 7;//表示该年1月1日为星期几

if (IsLeapYear(year) == 366)
days[1] = 29;

printf("\n%d年日历如下:\n\n", year);

for (i = 0; i<12; i = i + 1)
{
printf(" %d月 \n", i + 1);
printf(" 日 一 二 三 四 五 六 \n");
printf("=============================\n");
day_month = 1;
for (j = 0; j<start_week; j++)
printf(" ");
while (day_month <= days[i])
{
printf("%4d", day_month);
day_month++;
start_week = (start_week + 1) % 7;
if (start_week == 0)
printf("\n");
}
printf("\n\n");

}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: