C语言-日历与日期相关问题
1.给出年月日,计算该日是星期几
#include <stdio.h>
#include <Windows.h>
/*
<程序说明>
1.给出年月日(如:2022 3 6),系统会自动计算出该日的星期(如:星期天)
2.数学公式:
S = x - 1 + (x - 1)/4 - (x - 1)/100 + (x - 1)/400 + C
参数说明:
(1)S%7 --> 计算出来的星期(如:0表示星期天,1表示星期一,...,等)
(2)x --> 该日期(输入的日期)
(3)C --> 该日期为这一年的第几天(从元旦到该日,包括元旦与该日期) ===>难点!!
3.拓展知识:
(1)闰年计算:
每4年且不是100的整数,即为闰年(2月29天)
(2)闰年计算:
每400年是一个闰年
*/
int main(){
int year,month,day;//年月日
int numberOfDays;//天数
int week;//星期
int num;//公式算出来的结果
printf("请输入日期(格式:2022 3 6):");
scanf("%d%d%d",&year,&month,&day);//输入日期
//根据月份来计算天数
switch(month){
case 12:
numberOfDays += 30;//加上一个月的总天数,否则会差一天(差的一天是1月份的)
case 11:
numberOfDays += 31;
case 10:
numberOfDays += 30;
case 9:
numberOfDays += 31;
case 8:
numberOfDays += 31;
case 7:
numberOfDays += 30;
case 6:
numberOfDays += 31;
case 5:
numberOfDays += 30;
case 4:
numberOfDays += 31;
case 3:
//判断是否是闰年
if((year % 4 == 0 && year / 100 != 0) || (year % 400 == 0)){
numberOfDays += 29;
}else{
numberOfDays += 28;
}
case 2:
numberOfDays += 31;
case 1:
numberOfDays += day;
break;
default:
printf("输入年份有误!\n");
exit(0);//退出程序
}
//计算公式:S = x - 1 + (x - 1)/4 - (x - 1)/100 + (x - 1)/400 + C
num = year - 1 + (year - 1)/4 - (year - 1)/100 + (year - 1)/400 + numberOfDays;
//计算星期几
week = num % 7;
printf("\n");
switch(week){
case 0:
printf("%d年%d月%d日,是星期天\n",year,month,day);
break;
case 1:
printf("%d年%d月%d日,是星期一\n",year,month,day);
break;
case 2:
printf("%d年%d月%d日,是星期二\n",year,month,day);
break;
case 3:
printf("%d年%d月%d日,是星期三\n",year,month,day);
break;
case 4:
printf("%d年%d月%d日,是星期四\n",year,month,day);
break;
case 5:
printf("%d年%d月%d日,是星期五\n",year,month,day);
break;
case 6:
printf("%d年%d月%d日,是星期六\n",year,month,day);
break;
}
return 0;
}
2.给出年份,计算该年元旦那天是星期几
#include <stdio.h>
/*
<程序说明>
1.给出年(如:2022),系统会自动计算出该年元旦的星期(如:2022年元旦是星期六)
2.数学公式:
S = [x + (x - 1)/4 - (x - 1)/100 + (x - 1)/400] % 7
参数说明:
(1)S --> 计算出来的星期(如:0表示星期天,1表示星期一,...,等)
(2)x --> 该日期(输入的日期)
3.拓展知识:
(1)闰年计算:
每4年且不是100的整数,即为闰年(2月29天)
(2)闰年计算:
每400年是一个闰年
*/
int main(){
int year;
int week;
printf("请输入年份(如:2022):");
scanf("%d",&year);
//计算公式: S = [x + (x - 1)/4 - (x - 1)/100 + (x - 1)/400] % 7
week = (year + (year - 1)/4 - (year - 1)/100 + (year - 1)/400)%7;
switch(week){
case 0:
printf("%d年,是星期天\n",year);
break;
case 1:
printf("%d年,是星期一\n",year);
break;
case 2:
printf("%d年,是星期二\n",year);
break;
case 3:
printf("%d年,是星期三\n",year);
break;
case 4:
printf("%d年,是星期四\n",year);
break;
case 5:
printf("%d年,是星期五\n",year);
break;
case 6:
printf("%d年,是星期六\n",year);
break;
}
return 0;
}
3.计算某年某月某日是本年度第几天
#include <stdio.h>
#include <Windows.h>
/*
<程序说明>
1.给出年月日(如:2022 3 6),系统会自动计算出该日是该年的第几天(如:65天)
2.函数(用函数将其封装起来)
(1)计算天数
int sumDays(int year,int month,int day);
利用for循环,将上一个月的天数加起来,即可求解!
如果是1月份的话,就直接返回day参数
返回值为int型
(2)计算该年是否是闰年
bool isLeap(int year);
如果是闰年,返回true;否则返回false.
3.拓展知识:
(1)闰年计算:
每4年且不是100的整数,即为闰年(2月29天)
(2)闰年计算:
每400年是一个闰年
*/
int sumDays(int year,int month,int day);//传入参数:month ==> 该年的月份 , day ==> 该年的日数
bool isLeap(int year);//传入参数:year ==> 该年的年份
int main(){
int year,month,day;//年月日
int numberOfDays;//计算天数
printf("请输入年月日(如:2022 3 6):");
scanf("%d%d%d",&year,&month,&day);
numberOfDays = sumDays(year,month,day);//代入函数,求得天数
printf("\n%d年%d月%d日,是%d年的第%d天\n",year,month,day,year,numberOfDays);
return 0;
}
//计算天数(从该年的元旦开始记起)
int sumDays(int year,int month,int day){
int daysOfTheMonth[12] = {0,31,28,31,30,31,30,31,31,30,31,30};//并未将12月份的天数加进来
bool monthFlag = false;//假设传入的参数有误
bool dayFlag = false;//两个传入的参数(month day)都满足才能继续执行程序
//判断传入的参数,是否有误
for(int i = 1;i <= 12;i++){
if(month == i){//传入的月份在1到12数字之间,传入数字正确
monthFlag = true;
}
}
if(month == 1 || month == 3 || month == 5 ||
month == 7 || month == 8 || month == 10 || month == 12){//月份都有31天的情况
for(int i = 1; i <= 31;i++){
if(day == i){ //传入的日份在1到31数字之间,传入数字正确
dayFlag = true;
}
}
}else if(month == 2){//2月份的情况
if(isLeap(year)){
for(int i = 1; i <= 29;i++){
if(day == i){ //传入的日份在1到31数字之间,传入数字正确
dayFlag = true;
}
}
}else{
for(int i = 1; i <= 28;i++){
if(day == i){ //传入的日份在1到31数字之间,传入数字正确
dayFlag = true;
}
}
}
}else{//其他月份的情况,都为30天
for(int i = 1; i <= 30;i++){
if(day == i){ //传入的日份在1到31数字之间,传入数字正确
dayFlag = true;
}
}
}
//情况总结,如果传入参数无误,flag为true,则!flag == false,就不会执行下面语句
if(!monthFlag || !dayFlag){
printf("传入参数有误!请重新检查!\n");
exit(0);//传入参数有误,并退出程序
}
for(int i = 1; i < month;i++){
if(i == 2){//添加2月份的全部天数
if(isLeap(year)){
//该年是闰月
day += 29;
continue;//加了29天后,跳出当前循环,进入下一循环!
}
}
day += daysOfTheMonth[i];
}
return day;//返回天数
}
//判断该年是否是闰年
bool isLeap(int year){
return (year % 4 == 0 && year / 100 != 0) || (year % 400 == 0);
}
4.求指定日期距离出生日期的天数
#include <stdio.h>
#include <windows.h>
/*
<程序说明>
1.给出"指定年月日"(如:2022 3 6),给出"出生年月日"(如:2000 1 1),
系统会自动计算出指定年月日到出生日有多少天(如:xxx天)
2.思路
(1) 计算指定年月日到出生年的1月1日的天数(详细步骤可见上一程序)
(2) 计算出指定年月日与出生年月日的分别在当年的第几天(详见:3.给出年月日,计算出该日是该年的第几天)
(3) 减去出生年中出生日期之前的天数(见下面的图)
|------birth~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~today|
birth:2000-02-01
today:2022-03-06
头:2000-01-01 (出生年的元旦) 尾:today
①根据第一步(1)操作后,我们可以计算出这一整条线段
②根据第二步(2)操作后,我们可以计算出[birth - 头]这一段"短横线"所代表在这一年并未出生的阶段
③所以[birth - today]这一段,可以通过(1)(2)问相减可得!
3.拓展知识:
(1)闰年计算:
每4年且不是100的整数,即为闰年(2月29天)
(2)闰年计算:
每400年是一个闰年
(3)初始化问题
声明的变量一定要初始化,否则预计的结果会跟预料的结果不一样!(不信?可以试试!)
*/
//定义一个结构体 ==> 表示日期
typedef struct datatime{
int year;
int month;
int day;
}DATETIME;
int totalDays(DATETIME date,int birth_year);//传入参数:日期
int currentYearDays(DATETIME date);//计算指定日期在该年是第几天
bool isLeap(int year);//传入参数:year ==> 该年的年份
bool isMonthError(int month);//判断月份是否出错(月份应处于[1,12]区间内)
bool isDayError(int year,int month,int day);//判断日期是否出错(day应处于[1,31]之间,根据不同月份而有所不同)
int main(){
DATETIME specifiedDate;//指定日期
DATETIME birthday;//出生日期
printf("请输入现在的日期(如:2022-3-6):");
scanf("%d-%d-%d",&specifiedDate.year,&specifiedDate.month,&specifiedDate.day);//输入指定日期
printf("\n请输入出生的日期(如:2000-8-21):");
scanf("%d-%d-%d",&birthday.year,&birthday.month,&birthday.day);//输入出生日期
int overall_days;//从现在的日期到出生年元旦的总共天数
overall_days = totalDays(specifiedDate,birthday.year); //计算出思路(1)的结果,即整个线段的长度
//计算出生日到出生年有多少天(包括出生日) --> 等价于思路中的短横线阶段,计算思路(2)的步骤
int birth_before = currentYearDays(birthday);
//整个线段 - 出生前(短横线的阶段) ===> 现在年月日到出生日的天数,计算思路(2)
int birth_to_today = overall_days - birth_before;
if(birth_to_today < 0){
//现在年月日小于出生年月日,说明还未出生
printf("还未出生呢~!\n");
exit(0);
}
int age = birth_to_today/365;//计算年龄:出生日期到现在日期经历的天数 除以 一年 ==> 年龄
printf("\n现在%d年%d月%d日,你已经%d岁了!(%d天)\n",specifiedDate.year,specifiedDate.month,
specifiedDate.day,age,birth_to_today); //打印输出信息
return 0;
}
//计算经过了多少天
int totalDays(DATETIME date,int birth_year){
int total_day = 0;
//先计算过了多少年
for(int oldYear = birth_year;oldYear < date.year;oldYear++){
if(isLeap(date.year)){
total_day += 366;
}else{
total_day += 365;
}
}
//再计算该日是该年的第几天
total_day += currentYearDays(date); //包括指定日期的那一天
return total_day;//返回总的计算天数
}
//计算天数(从该年的元旦开始记起)
int currentYearDays(DATETIME date){
int daysOfTheMonth[12] = {0,31,28,31,30,31,30,31,31,30,31,30};//并未将12月份的天数加进来
int sum_days = 0;//计算出来的天数
//判断传入的参数,是否有误
if(!isMonthError(date.month) || !isDayError(date.year,date.month,date.day)){
printf("传入参数有误!请重新检查!\n");
exit(0);//传入参数有误,并退出程序
}
for(int i = 1; i < date.month;i++){
if(i == 2){//添加2月份的全部天数
if(isLeap(date.year)){
//该年是闰月
sum_days += 29;
continue;//加了29天后,跳出当前循环,进入下一循环!
}
}
sum_days += daysOfTheMonth[i];
}
sum_days += date.day;//将当前月份已经经过的天数算上(包括指定日期)
return sum_days;//返回计算出来的天数
}
//判断输入的月份是否超过数值范围
bool isMonthError(int month){
for(int i = 1;i <= 12;i++){
if(month == i){
return true;//传入的月份在1到12数字之间,传入数字正确
}
}
return false;//传入数字,不在[1,12]区间内,传入参数错误
}
//判断输入的日期是否超过数值范围
bool isDayError(int year,int month,int day){
if(month == 1 || month == 3 || month == 5 ||
month == 7 || month == 8 || month == 10 || month == 12){//月份都有31天的情况
for(int i = 1; i <= 31;i++){
if(day == i){
return true;//传入的日份在1到31数字之间,传入数字正确
}
}
}else if(month == 2){//2月份的情况
if(isLeap(year)){
for(int i = 1; i <= 29;i++){
if(day == i){
return true;//传入的日份在1到31数字之间,传入数字正确
}
}
}else{
for(int i = 1; i <= 28;i++){
if(day == i){
return true;//传入的日份在1到31数字之间,传入数字正确
}
}
}
}else{//其他月份的情况,都为30天
for(int i = 1; i <= 30;i++){
if(day == i){
return true;//传入的日份在1到31数字之间,传入数字正确
}
}
}
return false;//传入参数错误,不符合日期规范
}
//判断是否是闰年
bool isLeap(int year){
return (year % 4 == 0 && year / 100 != 0) || (year % 400 == 0);
}
5.求指定日期距离1970年1月1日的天数
#include <stdio.h>
#include <windows.h>
/*
<程序说明>
1.给出年月日(如:2022 3 6),系统会自动计算出该日是距离1970年1月1日有多少天(如:xxx天)
2.思路
(1)计算天数
totalDays(int year,int month,int day)
①指定日期与1970年中间的一些年,相加起来
②通过年月日,计算出指定日期是该年的第几天
③第一步与第二步相加即可得最终解
(2)计算该年是否是闰年
bool isLeap(int year);
如果是闰年,返回true;否则返回false.
3.拓展知识:
(1)闰年计算:
每4年且不是100的整数,即为闰年(2月29天)
(2)闰年计算:
每400年是一个闰年
(3)初始化问题
声明的变量一定要初始化,否则预计的结果会跟预料的结果不一样!(不信?可以试试!)
*/
//定义一个结构体 ==> 表示日期
typedef struct datatime{
int year;
int month;
int day;
}DATETIME;
long long totalDays(DATETIME date);//传入参数:日期
int currentYearDays(DATETIME date);//计算指定日期在该年是第几天
bool isLeap(int year);//传入参数:year ==> 该年的年份
bool isMonthError(int month);//判断月份是否出错(月份应处于[1,12]区间内)
bool isDayError(int year,int month,int day);//判断日期是否出错(day应处于[1,31]之间,根据不同月份而有所不同)
int main(){
DATETIME specifiedDate;//指定日期
printf("请输入日期(如:2022-3-6):");
scanf("%d-%d-%d",&specifiedDate.year,&specifiedDate.month,&specifiedDate.day);//输入指定日期
printf("\n%d年%d月%d日距离1970年1月1日,有%lld天\n",specifiedDate.year,
specifiedDate.month,specifiedDate.day,totalDays(specifiedDate));
printf("\n%d年%d月%d日距离1970年1月1日,有%lld毫秒\n",specifiedDate.year,
specifiedDate.month,specifiedDate.day,totalDays(specifiedDate)*24*60*60*1000);
return 0;
}
//计算经过了多少天
long long totalDays(DATETIME date){
int total_day = 0;
//先计算过了多少年
for(int oldYear = 1970;oldYear < date.year;oldYear++){
if(isLeap(date.year)){
total_day += 366;
}else{
total_day += 365;
}
}
//再计算该日是该年的第几天
total_day += currentYearDays(date); //包括指定日期的那一天
return total_day;//返回总的计算天数
}
//计算天数(从该年的元旦开始记起)
int currentYearDays(DATETIME date){
int daysOfTheMonth[12] = {0,31,28,31,30,31,30,31,31,30,31,30};//并未将12月份的天数加进来
int sum_days = 0;//计算出来的天数
//判断传入的参数,是否有误
if(!isMonthError(date.month) || !isDayError(date.year,date.month,date.day)){
printf("传入参数有误!请重新检查!\n");
exit(0);//传入参数有误,并退出程序
}
for(int i = 1; i < date.month;i++){
if(i == 2){//添加2月份的全部天数
if(isLeap(date.year)){
//该年是闰月
sum_days += 29;
continue;//加了29天后,跳出当前循环,进入下一循环!
}
}
sum_days += daysOfTheMonth[i];
}
sum_days += date.day;//将当前月份已经经过的天数算上(包括指定日期)
return sum_days;//返回计算出来的天数
}
//判断输入的月份是否超过数值范围
bool isMonthError(int month){
for(int i = 1;i <= 12;i++){
if(month == i){
return true;//传入的月份在1到12数字之间,传入数字正确
}
}
return false;//传入数字,不在[1,12]区间内,传入参数错误
}
//判断输入的日期是否超过数值范围
bool isDayError(int year,int month,int day){
if(month == 1 || month == 3 || month == 5 ||
month == 7 || month == 8 || month == 10 || month == 12){//月份都有31天的情况
for(int i = 1; i <= 31;i++){
if(day == i){
return true;//传入的日份在1到31数字之间,传入数字正确
}
}
}else if(month == 2){//2月份的情况
if(isLeap(year)){
for(int i = 1; i <= 29;i++){
if(day == i){
return true;//传入的日份在1到31数字之间,传入数字正确
}
}
}else{
for(int i = 1; i <= 28;i++){
if(day == i){
return true;//传入的日份在1到31数字之间,传入数字正确
}
}
}
}else{//其他月份的情况,都为30天
for(int i = 1; i <= 30;i++){
if(day == i){
return true;//传入的日份在1到31数字之间,传入数字正确
}
}
}
return false;//传入参数错误,不符合日期规范
}
//判断是否是闰年
bool isLeap(int year){
return (year % 4 == 0 && year / 100 != 0) || (year % 400 == 0);
}
完