前 言
这是我在嵌入式学习的第一阶段——C语言基础的学习过程中完成的一个项目,如果对您有帮助的话,可以点赞,收藏,关注哦,有其他问题可以私聊交流。
项目还有需要改进优化的地方,也可以添加其他有趣的功能,期待各位大佬的指点和交流。
目 录
一、项目简介
项目名:日历
功能:1.输入日期查询 2.按键翻页查询
介绍:这个项目的主要目的是为用户提供一个方便查看日期信息的工具,同时也作为一个C语言学习阶段前期的实践项目。它支持用户通过翻页来查看不同月份的日历,并提供了其他一些实用的功能。
二、功能介绍
1.输入日期查询
进入程序后可以输入年份和月份(两个数据中间用空格隔开)查看日历,作用与电脑桌面的日历的部分功能一致;
tips:仅支持1970年1月1日以后
2.按键翻页查询
在功能1的基础上,我加入了按键翻页功能,即查询指定年月后可以通过按键 ‘ + ’ 查看下个月的日历,通过 ‘ - ’ 查看上个月的日历;
三、技术实现
1.界面设计
运行界面参考电脑桌面日历界面,按照6行,一行7天,一共42天的设计。
2.代码设计
2.1预处理包含头文件
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
2.2搭建主函数框架
int main(void)
{
return 0;
}
2.3在主函数中定义变量
//变量声明
int year,month;
int monthdays; // 本月总天数
int days = 0; // year年month月1日距离1970-1-1的相差的天数
int i; // 循环变量
int week; // year年month月1日星期几
int lastnum; // 上个月的数据个数
int lastyear; // 上个月的年份
int lastmonth; // 上个月的月份
int lastdays; // 上个月的天数
int nextnum; // 下个月的数据个数
int cont = 0; // 输出计数 --- 7天换1行
char key; // 翻页按键
2.4写入死循环函数,使代码重复运行
while(1)
{
}
2.5提示用户输入年份、月份,并判断输入内容是否满足条件,不满足则返回重新输入
//提示用户输入年月
STAR:
printf("请输入要查询的年月\n");
scanf("%d%d",&year,&month);
system("cls"); // 清屏函数
//判断区间年份是否在1970年后,月份是否是1-12月
if(year<1970 || (month<1 || month >12))
{
system("cls");
printf("输入有误,请重新输入\n");
goto STAR;
}
2.6打印日历表头和星期
printf(" %d年%d月\n",year,month); // 打印年月于表头居中
printf("一 二 三 四 五 六 日\n"); // 打印对应星期几
2.7计算已经过完了的整年
//过完的整年
for(i=1970;i<year;i++)
{
//闰年判断:1.能被4整除而不能被100整除 2.能被400整除
if((i%4==0 && i%100!=0) || i%400==0)
{
days += 366;
}
else
{
days += 365;
}
}
2.8计算(year年1月)到(month-1月)的天数
for(i=1;i<month;i++)
{
switch(i)
{
case 1:days = days + 31;break;
case 2:
if(year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
{
days = days + 29;
}
else
{
days = days + 28;
}
break;
case 3:days = days + 31;break;
case 4:days = days + 30;break;
case 5:days = days + 31;break;
case 6:days = days + 30;break;
case 7:days = days + 31;break;
case 8:days = days + 31;break;
case 9:days = days + 30;break;
case 10:days = days + 31;break;
case 11:days = days + 30;break;
case 12:days = days + 31;break;
}
}
2.9计算本月1号为星期几
//本月1日 星期几
week = (days%7)<4 ? (days%7)+4 : (days%7)-3; // 1970.1.1 --- 星期四
2.10计算日历中需要打印的上个月的数据的个数
//上个月数据个数
lastnum = week -1;
2.11计算上个月总天数
//上个月总天数
if(month == 1)
{
lastyear = year -1;
lastmonth = 12;
}
else
{
lastyear = year;
lastmonth = month - 1;
}
switch(lastmonth)
{
case 1:lastdays = 31;break;
case 2:
if(lastyear % 4 == 0 && lastyear % 100 != 0 || lastyear % 400 == 0)
{
lastdays = 29;
}
else
{
lastdays = 28;
}
break;
case 3: lastdays = 31;break;
case 4: lastdays = 30;break;
case 5: lastdays = 31;break;
case 6: lastdays = 30;break;
case 7: lastdays = 31;break;
case 8: lastdays = 31;break;
case 9: lastdays = 30;break;
case 10:lastdays = 31;break;
case 11:lastdays = 30;break;
case 12:lastdays = 31;break;
}
2.12计算本月天数
//本月天数
switch(month)
{
case 1:monthdays = 31;break;
case 2:
if(year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
{
monthdays = 29;
}
else
{
monthdays = 28;
}
break;
case 3: monthdays = 31;break;
case 4: monthdays = 30;break;
case 5: monthdays = 31;break;
case 6: monthdays = 30;break;
case 7: monthdays = 31;break;
case 8: monthdays = 31;break;
case 9: monthdays = 30;break;
case 10:monthdays = 31;break;
case 11:monthdays = 30;break;
case 12:monthdays = 31;break;
}
2.13计算需要打印的下个月的天数
//下个月天数
nextnum = 42 - lastnum - monthdays; // 电脑桌面日历为42天,6行6*7
2.14打印日历天数
//上个月的数据是从 (lastDay - lastNum + 1) 到 (lastDay)
for(i=lastdays - lastnum + 1;i<=lastdays;i++)
{
printf("%2d ",i);
cont++;
if(cont == 7) //满7天换行
{
printf("\n");
cont = 0;
}
}
//本月数据
for(i=1;i<=monthdays;i++)
{
printf("%2d ",i);
cont++;
if(cont == 7) //满7天换行
{
printf("\n");
cont = 0;
}
}
//下个月数据
for(i=1;i<=nextnum;i++)
{
printf("%2d ",i);
cont++;
if(cont == 7) //满7天换行
{
printf("\n");
cont = 0;
}
}
2.15按键翻页
tips:按键‘ - ’(减号)显示上个月日历
按键‘ + ’(加号)显示下个月日历
//翻页
//-:上个月 +:下个月
printf("-:上个月 +:下个月");
key =getch();
if(key == '-')
{
month--;
system("cls");
goto STAR_2;
}
else if(key == '+')
{
month++;
system("cls");
goto STAR_2;
}
2.16翻页跳转,重新计算
tips:放在2.5和2.6中间
STAR_2:
days = 0; // 翻页时数值从0开始重新计算
if(month == 0) // 翻页时保证月份在1-12之间
{
year--;
month = 12;
}
else if(month == 13)
{
year++;
month = 1;
}
3.遇到的问题及解决方案
3.1
问题:在2.9计算星期时,忽略了days%7==4的可能,将其放入了假命题中,导致1号是星期一的部分月份第一行全是上个月的日期
解决方案:调换判断条件(把判断语句中的'>'改成'<'),同时调换真假表达式
3.2
问题:在翻页时容易出现越界,即12月的下个月变13的情况
解决方案:添加条件语句判断,防止越界
if(month == 0) // 翻页时保证月份在1-12之间
{
year--;
month = 12;
}
else if(month == 13)
{
year++;
month = 1;
}
四、整体代码
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
int main(void)
{
//变量声明
int year,month;
int monthdays; // 本月总天数
int days = 0; // year年month月1日距离1970-1-1的相差的天数
int i; // 循环变量
int week; // year年month月1日星期几
int lastnum; // 上个月的数据个数
int lastyear; // 上个月的年份
int lastmonth; // 上个月的月份
int lastdays; // 上个月的天数
int nextnum; // 下个月的数据个数
int cont = 0; // 输出计数 --- 7天换1行
char key; // 翻页按键
while(1)
{
//提示用户输入年月
STAR:
printf("请输入要查询的年月\n");
scanf("%d%d",&year,&month);
system("cls"); // 清屏函数
//判断区间年份是否在1970年后,月份是否是1-12月
if(year<1970 || (month<1 || month >12))
{
system("cls");
printf("输入有误,请重新输入\n");
goto STAR;
}
STAR_2:
days = 0; // 翻页时数值从0开始重新计算
if(month == 0) // 翻页时保证月份在1-12之间
{
year--;
month = 12;
}
else if(month == 13)
{
year++;
month = 1;
}
printf(" %d年%d月\n",year,month); // 打印年月于表头居中
printf("一 二 三 四 五 六 日\n"); // 打印对应星期几
//过完的整年
for(i=1970;i<year;i++)
{
if((i%4==0 && i%100!=0) || i%400==0) //闰年判断:1.能被4整除而不能被100整除 2.能被400整除
{
days += 366;
}
else
{
days += 365;
}
}
// (year年1月)到(month-1月)的天数
for(i=1;i<month;i++)
{
switch(i)
{
case 1:days = days + 31;break;
case 2:
if(year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
{
days = days + 29;
}
else
{
days = days + 28;
}
break;
case 3:days = days + 31;break;
case 4:days = days + 30;break;
case 5:days = days + 31;break;
case 6:days = days + 30;break;
case 7:days = days + 31;break;
case 8:days = days + 31;break;
case 9:days = days + 30;break;
case 10:days = days + 31;break;
case 11:days = days + 30;break;
case 12:days = days + 31;break;
}
}
//本月1日 星期几
week = (days%7)<4 ? (days%7)+4 : (days%7)-3; // 1970.1.1 --- 星期四
//上个月数据个数
lastnum = week -1;
//上个月总天数
if(month == 1)
{
lastyear = year -1;
lastmonth = 12;
}
else
{
lastyear = year;
lastmonth = month - 1;
}
switch(lastmonth)
{
case 1:lastdays = 31;break;
case 2:
if(lastyear % 4 == 0 && lastyear % 100 != 0 || lastyear % 400 == 0)
{
lastdays = 29;
}
else
{
lastdays = 28;
}
break;
case 3: lastdays = 31;break;
case 4: lastdays = 30;break;
case 5: lastdays = 31;break;
case 6: lastdays = 30;break;
case 7: lastdays = 31;break;
case 8: lastdays = 31;break;
case 9: lastdays = 30;break;
case 10:lastdays = 31;break;
case 11:lastdays = 30;break;
case 12:lastdays = 31;break;
}
//本月天数
switch(month)
{
case 1:monthdays = 31;break;
case 2:
if(year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
{
monthdays = 29;
}
else
{
monthdays = 28;
}
break;
case 3: monthdays = 31;break;
case 4: monthdays = 30;break;
case 5: monthdays = 31;break;
case 6: monthdays = 30;break;
case 7: monthdays = 31;break;
case 8: monthdays = 31;break;
case 9: monthdays = 30;break;
case 10:monthdays = 31;break;
case 11:monthdays = 30;break;
case 12:monthdays = 31;break;
}
//下个月天数
nextnum = 42 - lastnum - monthdays; // 电脑桌面日历为42天,6行6*7
//上个月的数据是从 (lastDay - lastNum + 1) 到 (lastDay)
for(i=lastdays - lastnum + 1;i<=lastdays;i++)
{
printf("%2d ",i);
cont++;
if(cont == 7)
{
printf("\n");
cont = 0;
}
}
//本月数据
for(i=1;i<=monthdays;i++)
{
printf("%2d ",i);
cont++;
if(cont == 7) //满7天换行
{
printf("\n");
cont = 0;
}
}
//下个月数据
for(i=1;i<=nextnum;i++)
{
printf("%2d ",i);
cont++;
if(cont == 7)
{
printf("\n");
cont = 0;
}
}
//翻页
//-:上个月 +:下个月
printf("-:上个月 +:下个月");
key =getch();
if(key == '-')
{
month--;
system("cls");
goto STAR_2;
}
else if(key == '+')
{
month++;
system("cls");
goto STAR_2;
}
}
return 0;
}
五、总结
这个日历项目是在他人带领下完成的,只是作为一个练手的实践项目,这里面用到了C语言基础中的基本数据类型,printf函数的使用,scanf函数的使用,运算符以及结构化编程。这并不是一个已经完全完善了的代码,需要补足的地方还有很多,如可以把部分代码封装成函数去调用,也可以通过代码写入其他功能,我就是在原来的基础上加入了翻页功能,你也可以根据自己需要写入合适的功能。
你们的支持和反馈对我来说非常重要。如果你有任何问题或建议,请通过私聊随时与我联系。别忘了点赞,收藏,关注哦!