C语言结构体的应用——万年历

文章目录

  • 万年历简述
  • 代码

万年历简述

万年历——就是输入一个日期可以查询是星期几,这个功能看起来很普通,但是如果用程序时间的话,还是药费一番周折:

  1. 我们需要保存一个固定的日期,存放它是星期几,输入一个自定义的日期,通过二者的日期差推断出输入日是星期几
  2. 我们需要考虑每一年是闰年还是平年,这个关系我们的日期差到底是几。所以需要创建一个返回bool型变量的函数bool isleapyear(int year)
  3. 我们使用的语言是C语言不是Visual Basic。在VB里面是有日期类型(date)的变量的,加减非常方便,但是C里面没有,我们可以通过结构体定义一个
      typedef struct{int year;typedef struct{int year;int month;int day;enum Weekdays weekday;} Date;

将一个时间点的年、月、日、星期建立联系,方便我们后面的输出和查找。

  1. 每个月的天数是不一样的,而这个日期的分布规律又过于复杂,我们不妨设一个数组来存放月份的天数。2月份的天数初始化的时候可以设为28,如果isleapyear(int year)==true,再将2月份天数改为29,否则设为28。
  2. 计算两个日期的日期差,如果两个日期的年份>2,则需要通过闰年判断函数对每个年份判断,并确定应该分别加多少,而对零头(也就是一年中的哪一天),我们需要另外设一个函数int count_days(int *days,Date *datetime);,通过传递days月份天数数组和一个日期,来计算该日期在该年是哪一天。假设参考日期在所在年的天数是day1,所在年天数为year1,输入日期在所在年的天数是day2,所在年天数为year2,两年所隔的年份总天数为是years,则相隔日期Δ\DeltaΔdays=year1-day1+years+day2;
  3. 我们在程序里面设计一个逻辑性变量bool next,每次运行完一个循环都扫描一下逻辑变量的值,如果用户输入1代表继续(其实非零值均可),输入0代表结束,整个过程使用do…whie循环控制,并且在循环体末尾要加上扫描是否继续的选择到next逻辑变量中的语句,即:
do{
...
printf("\n是否继续?(是:1,否:0): ")
scanf("%d",&next);
fflush(stdin);//在循环中使用scanf必须要清空输入缓存区,否则执行完1次循环会跳过循环体中的第一个scanf
)while(next);

使用一个判断是否继续的变量可以更好地实现人机交互的功能,同时也可以一次性多次测试代码的正确性。
7. 由于日期差值是负的还是整的关系到我们的计算结果,直接不管正负地模7取余是有问题的,所有我们保存7个参考日期,如果相减可以被7整除就代表是星期几。

代码

#include <stdio.h>
#include <stdbool.h>
#include <malloc.h>
#include <math.h>
#define LEN sizeof(Date)
enum Weekdays{Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday 
};//定义weekday枚举型变量
typedef struct {int year;int month;int day;enum Weekdays weekday;
}Date;//定义日期的结构体变量 
int days[12]={31,28,31,30,31,30,31,31,30,31,30,31};//平年的日期,可以借助modify_year修改
Date refdate[7];//定义7个参考日期,依次为周一到周日
int datedistract(Date date1,Date date2); //日期相减的函数 
bool isleapyear(int year);//判断闰年的函数 
void modify_days(int *days,int year);//通过闰年对月份日期修改的函数 
void findweekday(Date *datetime);
void weekdayprint(enum Weekdays weekday);
int count_days(int *days,Date *datetime); //计算结构体日期变量在一年中处于哪一天 
int main()
{printf("************日期计算实验****************\n");bool next;//是否继续do{Date *datetime=malloc(LEN);//定义Date类型的结构体指针datetime,同时开辟一段内存(不开辟内存会使程序崩溃)int i;for(i=0;i<7;i++){refdate[i].year=2018;refdate[i].month=12;refdate[i].day=10+i;}//refdate结构体数组存放了2018/12/20~2018/12/26的7个日期,他们正好是周一到周日 printf("请输入一个日期(year/month/day): ");scanf("%d/%d/%d",&datetime->year,&datetime->month,&datetime->day);printf("该日期所在年份中的天数为%d\t",count_days(days,datetime)); findweekday(datetime);weekdayprint(datetime->weekday);printf("\n是否继续?(是:1,否:0):  ");//是否继续的判断如下scanf("%d",&next); fflush(stdin);//刷新标准输入流,否则循环的时候会跳过第一个scanf } while(next);return 0; 
}
bool isleapyear(int year)
{if(year%4==0){if(year%100==0){if(year%400==0)return true;else return false;}else return true;}else return false;
}
//闰年修改函数 
void modify_days(int *days,int year)
{if(isleapyear(year)==true)days[1]=29;else days[1]=28;
}
int count_days(int *days,Date *datetime)//将该年各月份日期已经结构体变量录入,计算在该年的天数 
{int i,count=0;modify_days(days,datetime->year);for(i=0;i<datetime->month-1;i++)count+=days[i];count+=datetime->day;return count; 
}
int datedistract(Date date1,Date date2)
{int year,month,day,count=0;bool cmp;//比较两个日期哪个在前面,方便写循环Date temp;//作为交换变量的中间变量if(date1.year>date2.year)cmp=true;else if(date1.year<date2.year)cmp=false;else if(date1.month>date2.month)cmp=true;else if(date1.month<date2.month)cmp=false;else if(date1.day>date2.day)cmp=true;else cmp=false;if(cmp){temp=date1;date1=date2;date2=temp;}//如果date1在date2后面,则交换二者,保证date1始终比date2小for(year=date1.year;year<date2.year;year++)count+=isleapyear(year)?366:365;//按照是否为闰年书累加count+=count_days(days,&date2)-count_days(days,&date1);//计算零头return abs(count);//返回所差日期
}
void findweekday(Date *datetime)
{int i;for(i=0;i<7;i++){if(datedistract(*datetime,refdate[i])%7==0){datetime->weekday=i;break;}}
}
void weekdayprint(enum Weekdays weekday)
{switch(weekday){case 0:printf("星期一");break;case 1:printf("星期二");break;case 2:printf("星期三");break;case 3:printf("星期四");break;case 4:printf("星期五");break;case 5:printf("星期六");break;case 6:printf("星期日");break;}
}

输出结果如下图,可以多次输入,一次性查找多个日期:
万年历运行结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/544544.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

@Value竟然能玩出这么多花样

前言对于从事java开发工作的小伙伴来说&#xff0c;spring框架肯定再熟悉不过了。spring给开发者提供了非常丰富的api&#xff0c;满足我们日常的工作需求。如果想要创建bean实例&#xff0c;可以使用Controller、Service、Repository、Component等注解。如果想要依赖注入某个对…

C语言实现线性动态(单向)链表【详细步骤】

文章目录什么是链表为什么不用结构体数组链表的操作创建表删除元素插入元素代码及运行结果什么是链表 链表是数据结构里面的一种&#xff0c;线性链表是链表的一种&#xff0c;线性链表的延伸有双向链表和环形链表。在编程语言中优化数据结构可以在处理大数据时大大降低程序的…

移动前端经验小结

1. 移动端头部标签 head meta <!DOCTYPE html> <!-- 使用 HTML5 doctype&#xff0c;不区分大小写 --> <html lang"zh-cmn-Hans"> <!-- 更加标准的 lang 属性写法 http://zhi.hu/XyIa --> <head><!-- 声明文档使用的字符编码 -->…

再见收费的Navicat!操作所有数据库靠它就够了!

为了快速管理数据库&#xff0c;我们一般都会选择一款顺手的数据库管理工具。Navicat、DataGrip虽然很好用&#xff0c;但都是收费的。今天给大家推荐一款免费、功能强大的数据库管理工具DBeaver&#xff0c;希望对大家有所帮助&#xff01;DBeaver简介 DBeaver是一款开源的数据…

查找两个字符串中相同字符串_使两个字符串相同的最低成本

查找两个字符串中相同字符串Problem statement: 问题陈述&#xff1a; Given two strings string1 and string2 find the minimum cost required to make the given two strings identical. We can delete characters from both the strings. The cost of deleting a characte…

Matlab对指定参数的曲线进行非线性拟合

Matlab拟合曲线的方式 Matlab拟合曲线的方式有很多种&#xff0c;有三次样条插值、线性插值、多项式拟合等等。多项式拟合由于函数由f(x)anxnan−1xn−1...a1xa0f(x)a_nx^na_{n-1}x^{n-1}...a_1xa_0f(x)an​xnan−1​xn−1...a1​xa0​组成&#xff0c;若采用最小二乘法拟合&a…

MyBatis原生批量插入的坑与解决方案!

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;前面的文章咱们讲了 MyBatis 批量插入的 3 种方法&#xff1a;循环单次插入、MyBatis Plus 批量插入、MyBatis 原生批量插入…

系统结构图 数据结构_数据结构图简介

系统结构图 数据结构What you are going to learn? 你要学什么&#xff1f; In this article, we learn about the introduction to Graphs in Data Structure and Algorithm. 在本文中&#xff0c;我们将了解图在数据结构和算法中的介绍 。 What are the components in Gra…

Matlab仿真PID控制(带M文件、simulink截图和参数分析)

文章目录0.符号说明1.如何根据连续系统建立差分方程1.1.获取连续系统的传递函数1.2.获取离散系统的传递函数1.3.转换为差分方程2.基本PID控制原理3.比较PID输出&#xff0c;分析参数产生的影响4.改进PID算法&#xff08;遇限削弱积分法&#xff09;5.simulink仿真0.符号说明 y…

再见 Postman!Apifox 才是 YYDS!

作为开软件开发从业者&#xff0c;API 调试是必不可少的一项技能&#xff0c;在这方面 Postman 做的非常出色。但是在整个软件开发过程中&#xff0c;API 调试只是其中的一部分&#xff0c;还有很多事情 Postman 无法完成&#xff0c;或者无法高效完成&#xff0c;比如&#xf…

Matlab【可视化作图】绘制线电压相电压辅助线

目录引言绘图原理采点绘图设置坐标轴标尺引言 学习电力电子的同学可能在私下里练习的时候非常需要三相线电压和相电压的辅助线。最近我随便找了一本书把Matlab可视化编程恶补了一下&#xff0c;给大家介绍一下这个波形辅助线是怎么做的。 三相线电压辅助线就是一组相位相差60的…

SpringBoot实现Excel导入导出,好用到爆,POI可以扔掉了!

在我们平时工作中经常会遇到要操作Excel的功能&#xff0c;比如导出个用户信息或者订单信息的Excel报表。你肯定听说过POI这个东西&#xff0c;可以实现。但是POI实现的API确实很麻烦&#xff0c;它需要写那种逐行解析的代码&#xff08;类似Xml解析&#xff09;。今天给大家推…

Facebook升级到MySQL 8.0付出的代价

近日&#xff0c;Facebook 官博公布了他们的数据库版本从 MySQL 5.6 升级到了 MySQL 8.0&#xff0c;并且在官博记录了复盘详细的升级过程。Facebook 称&#xff0c;他们最近的一次大版本升级到 MySQL 5.6 花了一年多时间才完成&#xff0c;还在 5.6 版上开发 LSM 树存储引擎&a…

Matlab制作朱利表

朱利判据 其中 {bn−kan−k−ana0∗akcn−kbn−k−bnb0∗bk...qn−kpn−k−pnp0∗pk\begin{cases} b_{n-k}a_{n-k}-\frac{a_n}{a_0}*a_k\\ c_{n-k}b_{n-k}-\frac{b_n}{b_0}*b_k\\ ...\\ q_{n-k}p_{n-k}-\frac{p_n}{p_0}*p_k \end{cases}⎩⎪⎪⎪⎨⎪⎪⎪⎧​bn−k​an−k​−a0…

高并发下秒杀商品,必须知道的9个细节

高并发下如何设计秒杀系统&#xff1f;这是一个高频面试题。这个问题看似简单&#xff0c;但是里面的水很深&#xff0c;它考查的是高并发场景下&#xff0c;从前端到后端多方面的知识。秒杀一般出现在商城的促销活动中&#xff0c;指定了一定数量&#xff08;比如&#xff1a;…

最小拍控制系统详细解读(阶跃输入+速度输入2个案例)【Simulink仿真】

目录索引1.符号说明与结构框图2.最小拍控制系统构造原则2.1数字控制器D(z)的构造3.简单控制对象的最小拍控制器设计3.1阶跃输入3.2速度输入1.符号说明与结构框图 y(k)——系统响应输出的离散值u(k)——数字PID控制输出的离散值r(k)——期望输出的离散值&#xff08;事先已知&a…

SpringBoot官方热部署和远程调试神器,真带劲!

平时使用SpringBoot开发应用时&#xff0c;修改代码后需要重新启动才能生效。如果你的应用足够大的话&#xff0c;启动可能需要好几分钟。有没有什么办法可以加速启动过程&#xff0c;让我们开发应用代码更高效呢&#xff1f;今天给大家推荐一款SpringBoot官方的热部署工具spri…

【Python】输入任意个数元素并保存至列表

目录1.导入任意个数元素到列表1.1.编程思路1.2.代码片2.查找一个重复元素在列表中的所有位置2.1.编程思路2.2代码片1.导入任意个数元素到列表 1.1.编程思路 输入未知个数的元素需要用列表来存储&#xff0c;由于Python具有内存的动态分配能力&#xff0c;列表不需要手动动态分…

MySQL 性能优化的 9 种姿势,面试再也不怕了!

大家好&#xff0c;我是磊哥&#xff01;今天给大家分享一些简单好用的数据库优化方式&#xff01;1、选择最合适的字段属性Mysql是一种关系型数据库&#xff0c;可以很好地支持大数据量的存储&#xff0c;但是一般来说&#xff0c;数据库中的表越小&#xff0c;在它上面执行的…

Excel的规划求解【详细步骤】

本文目录1.说明2.准备加载项步骤1步骤2步骤33.线性规划问题步骤4步骤5步骤61.说明 使用Lingo程序也可以实现线性规划、非线性规划以及0-1规划&#xff0c;但是在缺少Lingo程序的情况下&#xff0c;我们使用Excel照样可以很容易地完成。在这里我给大家提供了解决此类问题的详细…