c语言万年历并计算是一年中第几天

c语言实现万年历

	万年历打印是学习c语言路上的一次小小试炼,这也是经典练习例程
	本文实现的万年历包含的内容和功能:
		1. 判断日期输入是否正确
		2. 判断某天是星期几(基姆拉尔森计算公式)
		3. 判断某天是一年的第几天
		4. 如果只输入年份,显示整年历
		5. 如果输入年和月,显示月历
		6. 如果输入年月日,显示当月月历并显示是一年的第几天

	代码注释比较完整,本人c语言小白,以下直接上代码

主函数main.c

#include <stdio.h>
#include <stdbool.h>

bool Jugdate(int year, int month, int day);  //判断日期是否输入正确
void dismonth(int year, int month);          //显示某月的日历
int Jugweek(int year, int month, int day);   //计算某一天是星期几
int Jugsday(int year, int month, int day);   //计算是一年中的第几天

int main()
{
    int year,month,day,sday;     //分别是输入的年月日,接收计算一年第几天函数的返回值
    year=month=day=0;            //全部初始化为0,方便判断输入的日期的类型
    printf("请输入日期( 格式 : 2008/8/8 ):");
    scanf("%d/%d/%d",&year,&month,&day);
    while(getchar()!='\n');        //清空缓冲区
    //只输入了年份,显示全年的日历
    if(month == 0){                
        if(year<1)printf("error!\n");
        else
            for(int i = 1; i < 13; i++){
                dismonth(year,i);   
                puts("");
            }
    }
    //输入了年和月,显示一整月的日历
    else if(day == 0){            
        if(year<1 || month<1 || month>12) printf("error!\n");
        else dismonth(year,month);
    }
    //输入了年、月、日,显示一整月的日历并且显示是一年的第几天
    else{
        if(Jugdate(year,month,day)){    
            sday = Jugsday(year,month,day); 
            printf("\n公元%6d年%3d月%3d日是一年的第 %-4d 天\n\n",year,month,day,sday);
            dismonth(year,month);
        }
        else printf("error!\n");
    }
    return 0;
}

日期判断函数

bool Jugdate(int year, int month, int day)
{
    if(year<1 || month<1 || month>12 || day < 1){  //年和日不能小于1,月在1-12之间
        return false;
    }
    else {
        if(year%4 == 0 && year%100 != 0 || year%400 == 0){
            if(month == 2 && day>29) {   //闰年的2月份,天数大于29,返回false
                return false;
            }
        }
        else if(month == 2 && day>28) {   //平年的2月份,天数大于28,返回false
            return false;
        }
        switch(month)
        {
        case 4:case 6:case 9:case 11:     //小月天数大于30,返回false  
            if(day>30){
                return false;
            }
        case 1:case 3:case 5:case 7:case 8:case 10:case 12:  //大月天数大于31,返回false
            if(day>31){
                return false;
            }
        }
    }
    return true;  //经过考验说明日期正确,返回true
}

显示整月月历函数

void dismonth(int year, int month)
{
    int enter;  //接收判断星期几的返回值,用于换行显示
    int monD[12] = {31,28,31,30,31,30,31,31,30,31,30,31};//平年每月天数数组
    int monL[12] = {31,29,31,30,31,30,31,31,30,31,30,31};//润年每月天数数组
    int *mon;   //根据是否闰年,选择指向每月天数的数组
    enter = Jugweek(year,month,1);  //计算每月1号是星期几
    char head[2][40] = {"*  *  *  *  *  *  *  *  *  *  *  *  *",
                        "   Sun  Mon Tues  Wed Thur  Fri  Sat"};
    puts(head[0]);
    printf("%15d 年 %d 月\n",year,month);
    puts(head[0]);
    puts(head[1]);
    if(year%4 == 0 && year%100 != 0 || year%400 == 0){
        mon = monL;  //闰年指针指向monL数组
    }
    else {
        mon = monD;  //闰年指针指向monD数组
    }
    printf("%*s",enter*5,""); //根据1号星期几,打印不同空格,实现日历开始打印位置
    for(int i = 1; i <= mon[month-1]; i++){
        printf("%5d",i);   //循环打印每一天
        enter++;
        if(enter>6){       //到周六就换行
            puts("");
            enter = 0;
        }
    }
    puts("");
    puts(head[0]);
    return;
}

星期判断函数

int Jugweek(int year, int month, int day)
{
    int weekday;//保存星期计算结果,0表示星期天,1表示星期一,2表示星期二...
    if(1==month || 2==month) {   //如果是1、2月按照前一年的13、14月计算
        month+=12; 
        year--;
    }   
    weekday = (day+1+2*month+3*(month+1)/5+year+year/4-year/100+year/400)%7;//基姆拉尔森计算公式
    return weekday;
}

判断某天是一年的第几天

int Jugsday(int year, int month, int day)
{
    int sday,leap=0;//sday:一年第几天计算结果,leap:闰年为1,平年为0
    int sumday[12] = {0,31,59,90,120,151,181,212,243,273,304,334};//前n个月总共有多少天的数组
    if(year%4 == 0 && year%100 != 0 || year%400 == 0)
        leap = 1; //闰年赋值给leap为1
    if(month<3)
        sday = sumday[month-1] + day; //前两月取数组中的值和天数相加
    else
        sday = sumday[month-1] + day + leap; //后面月份需要加上leap,解决闰年多一天
    return sday;
}

运行效果展示

		测试时,我添加了一个死循环,使其一直运行方便测试,一年的年历就是将
	每个月都打印,内容过多就不一一展示了,根据示例,可以看出万年历的基本
	功能已经实现了
请输入日期( 格式 : 2008/8/8 ):2008/13/32
error!
请输入日期( 格式 : 2008/8/8 ):2022/2/29
error!
请输入日期( 格式 : 2008/8/8 ):2022/8
*  *  *  *  *  *  *  *  *  *  *  *  *
           20228*  *  *  *  *  *  *  *  *  *  *  *  *
   Sun  Mon Tues  Wed Thur  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
*  *  *  *  *  *  *  *  *  *  *  *  *

请输入日期( 格式 : 2008/8/8 ):1949/10/1

公元  1949101日是一年的第 274*  *  *  *  *  *  *  *  *  *  *  *  *
           194910*  *  *  *  *  *  *  *  *  *  *  *  *
   Sun  Mon Tues  Wed Thur  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
*  *  *  *  *  *  *  *  *  *  *  *  *
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值