pta6-6万年历显示函数

我的心还是热的!

前言

今天有人问了我一个万年历的题,那道题本身不难,因为你只需要写一个函数就可以,但我突发奇想——为什么不把它的全部函数写出来呢?说干就干

(ps如果觉得题目的样例不够的话,可以用手机看日历来对照)。

题目如下

设计一个万年历,当用户输入年份和月份时,显示这个月的日历表。程序重点是这个月的第一天是星期几和这个月有几天,有了这两个值,只需通过排列,就可以显示这个日历。程序要求用户输入的年份是从1900年开始,已知1900年1月1日是星期一。
日历中每个具体的日期占5个字符宽度,右对齐,上下的分隔线分别是由35个’*’ 连字符构成,表示星期的字符是三个字符,加两个空格分隔。

函数接口定义:

void ShowDate(int y, int m);

其中,参数y是给定年,参数m是给定月,函数功能是根据给定的年月,显示该月日历。

裁判测试程序样例:

输入样例:

在这里给出一组输入。例如:

​
1949  10

​

输出样例:

***********************************
  Sun  Mon  Tue  Wen Thur  Fri  Sta
                                  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
***********************************

代码长度限制:16 KB

时间限制:400 ms

内存限制:64 MB

答案如下

void ShowDate(int y, int m)
{
    printf("***********************************\n");
    printf("  Sun  Mon  Tue  Wen Thur  Fri  Sta\n");
    int count=GetFirstDayInTable(y,m),i;
    	for(i=0;i

全部代码实现

ok,那么正文开始

第一个函数

int IsLeapYear(int y);   /*判断是否闰年,细节不表*/

这个记住定义就好——能被4整除且不被100整除或被400整除

如下:

int IsLeapYear(int y)   /*判断是否闰年,细节不表*/
{
    if (!(y % 4) && y % 100 || !(y % 400))
        return 1;
    return 0;
}

这里有俩小细节

1.我只用了if,没有else,这是因为return代表了程序结束,这段代码里有没有else结果不变

所以,不能拘泥于某个形式,要灵活多变

2.我用了个“!”,这个是逻辑非,!(表达式),若表达式为真,则整体为假,反之为真。

第二个函数

int GetDaysofMonth(int y, int m); /*确定某个月的天数,细节不表*/

这里可以借用数组存储数据

int month[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };//全局变量
int GetDaysofMonth(int y, int m)/*确定某个月的天数,细节不表*/
{
    if (IsLeapYear(y) && m == 2)
        return 29;
    return month[m];
}

重点

1.我的数组是个全局变量,这是因为我发现后面的函数还会用到它,所以干脆建个全局

2.if语句的合理应用将代码缩小到了7行,将闰年的月作为特例拿出来,同时可以发现这个if也没有else哦

第三个函数

int GetTotalDays(int y, int m); /*计算从1900年1月开始到给定年月间的天数,不包含给定月的天数,细节不表*/

代码如下

int GetTotalDays(int y, int m) /*计算从1900年1月开始到给定年月间的天数,不包含给定月的天数,细节不表*/
{
    int sum = 0,i;
    for ( i = 1900; i < y; i++)
    {
        sum = sum + 365 + IsLeapYear(i);
    }
    for (i = 1; i < m; i++)
        sum += month[i];
    if (IsLeapYear(y) && m > 2)
        sum++;
    return sum;
}

重点

1.俩个循环的使用,一个调控年份,一个调控月份

2.注意在年份的循环中我还引入了一个函数,来判断是否为闰年,而且进行相加,这也是为什么前面的返回值要设置为1或0,因为闰年就是多一天!!!

3.对于闰年2月还是和之前一样当作特殊情况拿出来

第四个函数

int GetFirstDayInTable(int y, int m); /*计算给定年月的第一天在日历表中的位置,返回值为0对应Sun位置,返回值为6对应Sta位置,细节不表*/

代码如下

int GetFirstDayInTable(int y, int m)/*计算给定年月的第一天在日历表中的位置,返回值为0对应Sun位置,返回值为6对应Sta位置,细节不表*/
{
    int sum= GetTotalDays(y, m);
    sum %=7;
    if (sum == 6)
        return 0;
    return sum+1;
}

这个就比较好理解了,余数为6说明是周日返回零,其他就是“sum+1 ”,(因为最开始是周一)。

第五个函数

void ShowDate(int y, int m); /*显示日历*/

这个就是题目要求写的,,代码如下

void ShowDate(int y, int m)
{
    printf("***********************************\n");
    printf("  Sun  Mon  Tue  Wen Thur  Fri  Sta\n");
    int count = GetFirstDayInTable(y, m);
    int i;
    for (i = 0; i < count; i++)
        printf("     ");
    for (i = 1; i <= GetDaysofMonth(y, m); i++)
    {
        printf("%5d", i);
        count++;
        if (count % 7 == 0)
            printf("\n");
    }
    if (count % 7 != 0)
        printf("\n");
    printf("***********************************");
}

重点

1.第一个循环负责打空格,这个要弄不明白,就举几个例子,count为0,不打空格,count是几就打几个空格。

2.日期打印

记住每打印七次七个就要换一次行,而且这个次数是包括前面的空格的!!!!

3.最后的if判断换行,因为如果最后一行日期正好是七个,那他在循环里会打印换行,而最后的***********直接打印就好,但如果最后一行日期不是七个,那你就要自己在打印换行,不然就会这样

pta6-6万年历显示函数_第1张图片

很明显“*************”没换行

4.我还加了个循环,这样使用起来查找多个数据会更方便

最后答案公布

#include 
#include 
int IsLeapYear(int y);   /*判断是否闰年,细节不表*/
int GetDaysofMonth(int y, int m); /*确定某个月的天数,细节不表*/
int GetTotalDays(int y, int m); /*计算从1900年1月开始到给定年月间的天数,不包含给定月的天数,细节不表*/
int GetFirstDayInTable(int y, int m); /*计算给定年月的第一天在日历表中的位置,返回值为0对应Sun位置,返回值为6对应Sta位置,细节不表*/
void ShowDate(int y, int m); /*显示日历*/
int month[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
int main()
{
    printf("只限于查找1900年之后\n");
    int y, m,x=1;
   do
    {
       printf("查询日历输入1,结束程序输入0:->");
       scanf("%d", &x);
       if (x)
       {
           printf("输入查询年份月数");
           scanf("%d%d", &y, &m);
           ShowDate(y, m);
           printf("\n");
       }
       else
           return 0;
   } while (x);
}
int IsLeapYear(int y)   /*判断是否闰年,细节不表*/
{
    if (!(y % 4) && y % 100 || !(y % 400))
        return 1;
    return 0;
}
int GetDaysofMonth(int y, int m)/*确定某个月的天数,细节不表*/
{
    if (IsLeapYear(y) && m == 2)
        return 29;
    return month[m];
}
int GetTotalDays(int y, int m) /*计算从1900年1月开始到给定年月间的天数,不包含给定月的天数,细节不表*/
{
    int sum = 0,i;
    for ( i = 1900; i < y; i++)
    {
        sum = sum + 365 + IsLeapYear(i);
    }
    for (i = 1; i < m; i++)
        sum += month[i];
    if (IsLeapYear(y) && m > 2)
        sum++;
    return sum;
}
int GetFirstDayInTable(int y, int m)/*计算给定年月的第一天在日历表中的位置,返回值为0对应Sun位置,返回值为6对应Sta位置,细节不表*/
{
    int sum= GetTotalDays(y, m);
    sum %=7;
    if (sum == 6)
        return 0;
    return sum+1;
}
void ShowDate(int y, int m)
{
    printf("***********************************\n");
    printf("  Sun  Mon  Tue  Wen Thur  Fri  Sta\n");
    int count = GetFirstDayInTable(y, m);
    int i;
    for (i = 0; i < count; i++)
        printf("     ");
    for (i = 1; i <= GetDaysofMonth(y, m); i++)
    {
        printf("%5d", i);
        count++;
        if (count % 7 == 0)
            printf("\n");
    }
   /* if (count % 7 != 0)
        printf("\n");*/
    printf("***********************************");
}

总结

感觉很多时候敲代码很多部分都可以找到一点又一点的小小的优化,找啊找代码就变简洁了

如果那里写错了希望在评论区提一下,我会尽快改的

如果你觉得有用就点个赞支持一下吧!谢谢啦

pta6-6万年历显示函数_第2张图片

你可能感兴趣的:(pta,c语言,排序算法,算法)