功能:编写一个基于日期的行程安排系统。
基本功能:
1、菜单界面,包含查询某一年的年历、查询某一月的月历、查询某一天的日历、增、删、该、查行程安排、退出的选项,由用户输入选项选择测试类型。
2、日历查询,由用户输入对应的选项,根据提示正确输入想要查询的年、月或日,对应的日历便会打印在屏幕上供用户浏览。
3、行程安排,由用户输入对应的选项,根据提示进行添加、修改、查询与删除行程安排,实现记事本的功能。
4、系统测试范围要求如下:
(1)日历查询,年历查询的范围在公元1912年到公元2500年。
(2)行程安排,行程安排的内容字数限制在100字以内且其中不要出现空格,月与日按照常理分别限制在1月到12月与1日到31日。
相关知识:图形绘制、蔡勒和其它数学公式、结构体、动态链表、函数与文件操作等。
功能扩充:1)增加统计安排行程日期功能,利用Easy-x插件功能绘制折线图,产生更直观的统计效果;2)具备储存日历功能,将所查询日历以文本文件的形式储存,从而达到随时查阅的目的。
编译器:VC++6.0(已安装Easy-x插件)
运行主界面:
折线图(模块8):
附录 源程序清单
#include<stdio.h>
#include<string.h>
#include<conio.h>
#include<stdlib.h>
#include<graphics.h>
//定义变量
int a[13];
int year,month,day;
int tempyear1,tempmonth1,tempday1;
int currentYear,currentMonth,currentDay;
char temptext[100];
//定义数组
int daysOfMonth[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
//获取当前时间
void getCurrentDate();
//判断是否为闰年
int isLeapYear(int year);
//计算星期
int computerWeek(int year,int month,int day);
//显示菜单选项
int showMenu_choice();
/*定义一个日期类型*/
typedef struct datetime//命名一个新类型代表结构体类型
{
int year1;
int month1;
int day1;
char text[100];
struct datetime* next;//下一个日期的指针
}Date;
Date* datetimes;//日期链表,定义结构体指针变量datetimes,指向此结构体类型数据
char* dateInfo="C:\\Users\\jl\\Desktop\\mydata.txt";//行程安排信息存储的文件
//打印年日历
void showCalendarOfYear(int year);
//打印月历
void showCalendarOfMonth();
//指定年月日,打印日历
void showDateDetail(int year,int month,int day);
//打印节假日
void printHolidays(int month, int day);
//打印周几详情
void printWeekDetail(int week);
//储存日期
void reserveDate();
void initFromTxt(void);//初始化
void deleteInfo(int year1,int month1,int day1);//删除信息
void reWrite(void);//重写
void insert2txt(Date* date);//插入文本
int addinfo(int year1,int month1,int day1,char* text);//增加信息
void modify(int year1,int month1,int day1,char* text);//修改信息
int checkAdd(int year1,int month1,int day1);//判断日期输入
Date* findInfo(int year1,int month1,int day1);//查找信息
Date* findInfo1(int year1,int month1,int* a);//统计信息
void picture(int* c);//折线图
/***************主函数***************/
void main()
{
char c;
int mon;
initFromTxt();
do
{
system("cls");
switch(showMenu_choice())
{
case 1:
showCalendarOfYear(year);
break;
case 2:
showCalendarOfMonth();
break;
case 3:
showDateDetail(year,month,day);
break;
case 4:
printf("请输入年、月、日与行程安排,数据以空格隔开(例如:2019 7 1 提交中期报告):");
scanf("%d%d%d%s",&tempyear1,&tempmonth1,&tempday1,temptext);
addinfo(tempyear1, tempmonth1,tempday1, temptext);
break;
case 5:
printf("请输入年、月、日与行程安排,数据以空格隔开(例如:2019 7 1 提交中期报告):");
scanf("%d%d%d%s",&tempyear1,&tempmonth1,&tempday1,temptext);
modify(tempyear1, tempmonth1,tempday1, temptext);
break;
case 6:
printf("请输入年、月与日,数据以空格隔开(例如:2019 7 1):");
scanf("%d%d%d",&tempyear1,&tempmonth1,&tempday1);
deleteInfo(tempyear1,tempmonth1,tempday1);
break;
case 7:
printf("请输入年、月与日,数据以空格隔开(例如:2019 7 1),若想按年(2019 0 0)、年+月(2019 7 0)或日(2019 7 4)查询,只需输入想查询的有效部分,其余输入0::");
scanf("%d%d%d",&tempyear1,&tempmonth1,&tempday1);
findInfo(tempyear1,tempmonth1,tempday1);
break;
case 8:
printf("请输入您所要统计的年份:");
scanf("%d", &tempyear1);
for(mon=1;mon<=12;mon++)
{
findInfo1(tempyear1,mon,a);
}
printf("回车键输出统计图: ");
picture(a);
break;
case 9:
reserveDate();
break;
case 0:
exit(0);
}
printf("是否继续查询(是:Y或y,否:N或n):\n");
scanf("%s",&c);
if(c=='N'||c=='n')
{
break;
}
}while(c=='Y'||c=='y');
}
/***************判断闰年函数***************/
int isLeapYear(int year)
{
if(year%400==0||(year%100!=0&&year%4==0))
{
return 1;
}
else
{
return 0;
}
}
/***************计算星期几的函数***************/
int computeWeek(int year,int month,int day)
{
int week,result;
int yearLast=year%100;
int tempYear=year/100;
int tempMonth=month;
if(month==1)
{
yearLast-=1;
tempMonth=13;
}
else if(month==2)
{
yearLast-=1;
tempMonth=14;
}
week=(yearLast+yearLast/4+tempYear/4-2*tempYear+26*(tempMonth+1)/10+day-1);
if(week<0)
{
result=(week%7+7)%7;
}
else
{
result=week%7;
}
return result;
}
/***************显示菜单选项函数***************/
int showMenu_choice()
{
int i;
do
{
printf("********************菜单选项*******************\n");
printf("* *\n");
printf("*---> 1.查询某一年的年历 *\n");
printf("*---> 2.查询某一月的月历 *\n");
printf("*---> 3.查询某一天的日历 *\n");
printf("*---> 4.添加行程安排 *\n");
printf("*---> 5.修改行程安排 *\n");
printf("*---> 6.删除行程安排 *\n");
printf("*---> 7.查询行程安排 *\n");
printf("*---> 8.统计安排行程的日期 *\n");
printf("*---> 9.储存日历 *\n");
printf("*---> 0.退出 *\n");
printf("* *\n");
printf("***********************************************\n");
printf("请输入您的选择:\n");
scanf("%d",&i);
}
while(i<0||i>10);//控制范围
return(i);
}
/***************查询年历函数***************/
void showCalendarOfYear(int year)
{
int i,k,x,firstWeek;
printf("请输入待查询的年份(格式如2019):");
scanf("%d",&year);
while(year>2500||year<1912)
{
printf("输入有误,请重新输入年份(格式如2019):");
fflush(stdin);//刷新缓存
scanf("%d",&year);
}
printf("\n====================%d年====================\n",year);
printf("\n");
if(isLeapYear(year))
{
daysOfMonth[1]=29;
}
else
{
daysOfMonth[1]=28;
}
for(i=1;i<13;i++)
{
firstWeek=computeWeek(year,i,1);//确定第一天对应的是星期几
printf("=====================%d月历如下====================\n",i);
printf("Sun\tMon\tTue\tWed\tThu\tFri\tSat\n");
for(x=1;x<=firstWeek;x++)
{
printf("\t");
if(x%7==0)
{
printf("\n");
}
}
for(k=1;k<=daysOfMonth[i-1];k++)
{
printf("%d\t",k);
if(x%7==0)
{
printf("\n");
}
x++;
}
printf("\n");
printf("\n");
printf("\n");
}
}
/***************查询月历函数***************/
void showCalendarOfMonth()
{
int k,x,firstWeek;
printf("请输入想要查询的年月(格式如2019 6):");
scanf("%d %d",&year,&month);
while(month<1||month>12||year>2500||year<1912)
{
printf("输入错误!!!请重新输入待查询的年月(格式如2017 6):");
fflush(stdin);
scanf("%d %d",&year,&month);
}
printf("\n======================%d年%d月===================\n",year,month);
if(isLeapYear(year))
{
daysOfMonth[1]=29;
}
else
{
daysOfMonth[1]=28;
}
firstWeek=computeWeek(year,month,1);
printf("Sun\tMon\tTue\tWed\tThu\tFri\tSat\n");
for(x=1;x<=firstWeek;x++)
{
printf("\t");
if(x%7==0)
{
printf("\n");
}
}
for(k=1;k<=daysOfMonth[month-1];k++)
{
printf("%d\t",k);
if(x%7==0)
{
printf("\n");
}
x++;
}
printf("\n");
}
/***************日期查阅函数***************/
void showDateDetail(int year,int month,int day)
{
int week;
printf("请输入待查询的年月日(格式为:2019 6 25):");
scanf("%d %d %d",&year,&month,&day);
while(day<0||day>31||month<1||month>12||year>2500||year<1912)
{
printf("输入错误!!!请重新输入年月日(格式如2019 6 25):");
fflush(stdin);//刷新输入缓存区
scanf("%d% d% d",&year,&month,&day);
}
if(isLeapYear(year))//判断闰年
{
daysOfMonth[1]=29;
}
week=computeWeek(year,month,day);//调用函数 计算第一天是星期几
printf("\n");
printHolidays(month,day);//判断是否为特殊假日
printf("\n");
printf("%d年%d月%d日是:",year,month,day);
printWeekDetail(week);//判断所查找天使星期几
printf("\n");
}
/***************打印节日函数***************/
void printHolidays(int month,int day)
{
switch(month)
{
case 1:
switch(day)
{
case 1:
printf("元旦");
break;
default:
printf("非特殊节日");
}
break;
case 2:
switch(day)
{
case 14:
printf("情人节");
break;
default:
printf("非特殊节日");
}
break;
case 3:
switch(day)
{
case 8:
printf("妇女节");
break;
case 12:
printf("植树节");
break;
default:
printf("非特殊节日");
}
break;
case 4:
switch(day)
{
case 1:
printf("愚人节");
break;
case 5:
printf("清明节");
break;
default:
printf("非特殊节日");
}
break;
case 5:
switch(day)
{
case 1:
printf("愚人节");
break;
case 4:
printf("中国青年节");
break;
default:
printf("非特殊节日");
}
break;
case 6:
switch(day)
{
case 1:
printf("儿童节");
break;
default:
printf("非特殊节日");
}
break;
case 7:
switch(day)
{
case 1:
printf("建党节");
break;
default:
printf("非特殊节日");
}
break;
case 8:
switch(day)
{
case 1:
printf("建军节");
break;
default:
printf("非特殊节日");
}
break;
case 9:
switch(day)
{
case 10:
printf("教师节");
break;
default:
printf("非特殊节日");
}
break;
case 10:
switch(day)
{
case 1:
printf("国庆节");
break;
case 31:
printf("万圣节");
default:
printf("非特殊节日");
}
break;
case 11:
switch(day)
{
case 8:
printf("中国记者日");
break;
case 10:
printf("世界青年节");
default:
printf("非特殊节日");
}
break;
case 12:
switch(day)
{
case 25:
printf("圣诞节");
break;
default:
printf("非特殊节日");
}
break;
}
}
/***************打印星期详情函数***************/
void printWeekDetail(int week)
{
switch(week)
{
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;
}
}
/***************储存日期函数***************/
void reserveDate()
{
int i,k,x,a,firstWeek;
char c='\n';
char month1[5],year1[5],filename[30]="C:\\Users\\jl\\Desktop\\";
FILE *fp;
printf("请选择您想存储为年历(输入:1)还是月历(输入:2):");
scanf("%d",&i);
if(i==2)
{
printf("请输入想要储存的年月(格式如2019 6):");
scanf("%d %d",&year,&month);
while(month<1||month>12||year>2500||year<1912)
{
printf("输入错误!!!请重新输入待查询的年月(格式如2017 6):");
fflush(stdin);
scanf("%d %d",&year,&month);
}
if(isLeapYear(year))
{
daysOfMonth[1]=29;
}
else
{
daysOfMonth[1]=28;
}
firstWeek=computeWeek(year,month,1);
itoa(year,year1,10);
itoa(month,month1,10);
strcat(year1,"年"); //拼接字符串使文件以查询内容命名
strcat(month1,"月");
strcat(year1,month1);
strcat(year1,".txt");
strcat(filename,year1);
if((fp=fopen(filename,"a"))==NULL)
{
printf("the file can not open");
}
fprintf(fp,"================%d年%d月=================\n",year,month);
fprintf(fp,"Sun\tMon\tTue\tWed\tThu\tFri\tSat\n");
for( x=1;x<=firstWeek;x++)
{
fprintf(fp,"\t");
if(x%7==0)
{
printf("\n");
}
}
for( k=1;k<=daysOfMonth[month-1];k++)
{
fprintf(fp,"%d\t",k);
if(x%7==0)
{
fprintf(fp,"%c",c);
}
x++;
}
fprintf(fp,"%c%c",c,c);
printf("日历写入成功!\n");
fclose(fp);
}
else
{
printf("请输入想要储存的年(格式如2019):");
scanf("%d",&year);
while(year>2500||year<1912)
{
printf("输入错误!!!请重新输入待查询的年月(格式如2017):");
fflush(stdin);
scanf("%d",&year);
}
if(isLeapYear(year))
{
daysOfMonth[1]=29;
}
else
{
daysOfMonth[1]=28;
}
itoa(year,year1,10);
strcat(year1,"年");
strcat(year1,".txt");
strcat(filename,year1);
for(a=1;a<=12;a++)
{
firstWeek=computeWeek(year,a,1);
if((fp=fopen(filename,"a"))==NULL)
{
printf("the file can not open");
}
fprintf(fp,"================%d年%d月=================\n",year,a);
fprintf(fp,"Sun\tMon\tTue\tWed\tThu\tFri\tSat\n");
for( x=1;x<=firstWeek;x++)
{
fprintf(fp,"\t");
if(x%7==0)
{
printf("\n");
}
}
for( k=1;k<=daysOfMonth[a-1];k++)
{
fprintf(fp,"%d\t",k);
if(x%7==0)
{
fprintf(fp,"%c",c);
}
x++;
}
fprintf(fp,"%c%c",c,c);
fclose(fp);
}
printf("日历写入成功!\n");
}
}
/***************初始化文件函数***************/
void initFromTxt(void)
{
datetimes = (Date*)malloc(sizeof(Date));//给链表的头节点分配内存
datetimes->next = NULL;//指向设为空
FILE* file;
file = fopen(dateInfo, "r");//打开信息文件
if (file == NULL)
{
printf("[initFromTxt]打开文件失败!");
return;
}
Date* s = datetimes;//当前结点
while (1)
{
Date* date = (Date*)malloc(sizeof(Date));
//从文本读入日期信息,存进date中
if(fscanf(file,"%d %d %d %s",&(date->year1) ,&(date->month1),&(date->day1),&(date->text)) == EOF)
{
//如果读入为EOF,也就说为读入为空,那么刚刚新建的date就不要了,释放分配的内存
free(date);
break;
}
date->next = NULL;
s->next = date;//将当前节点和新建的节点链接起来
s = date;//调整当前节点为新节点
}
fclose(file);
}
/***************删除信息函数***************/
void deleteInfo(int year1,int month1,int day1)
{
Date* date = datetimes->next;//当前节点
Date* pre = datetimes;//当前节点的父节点
int isFound = 0;//是否找到日期
while (date != NULL)
{
if (((date->year1)==year1)&&((date->month1)==month1)&&((date->day1)==day1))
{
pre->next = date->next;
free(date);
reWrite();//重写进文件
isFound = 1;
break;
}
pre = pre->next;
date = date->next;
}
if (isFound)
{
printf("删除成功!\n");
}
else
{
printf("没有找到该记录!\n");
}
}
/***************重写信息函数***************/
void reWrite(void)
{
Date* date = datetimes->next;
FILE* file = fopen(dateInfo, "w");//清空文件
fclose(file);
if (date == NULL)//这个代表当前没有相应的行程安排,直接返回
{
return;
}
while (date != NULL)
{
insert2txt(date);
date = date->next;
}
}
/***************插入行程安排函数***************/
void insert2txt(Date* date)
{
FILE* file;
file=fopen(dateInfo,"a");
if (file == NULL)
{
printf("[insert2txt]文件写入不成功!");
return;
}
fprintf(file, "%-8d%-8d%-8d%-8s\n", date->year1,date->month1,date->day1, date->text);
fclose(file);
}
/***************添加行程安排函数***************/
int addinfo(int year1,int month1,int day1,char* text)
{
if (!checkAdd(year1,month1,day1))
{
int i;
printf("该天已有行程安排,请您确定是否添加?(是:1;否:0):\n");
scanf("%d",&i);
if(i==0)
{
printf("您已放弃添加!\n");
return 0;
}
else
printf("正在添加……\n");
}
Date* newinfo = (Date*)malloc(sizeof(Date));//新建一个新节点
newinfo->next = NULL;
//给新节点赋值
newinfo->year1=year1;
strcpy(newinfo->text, text);
newinfo->month1 = month1;
newinfo->day1 = day1;
//调整p到最后一个节点
Date* p = datetimes;
while (p->next!=NULL)
{
p = p->next;
}
//p链接新节点
p->next = newinfo;
//插入新信息
insert2txt(newinfo);
printf("添加成功!\n");
return 1;
}
/***************修改行程函数***************/
void modify(int year1,int month1,int day1,char*text)
{
//修改信息是先删除再添加
deleteInfo(year1,month1,day1);
if(addinfo(year1,month1,day1,text))
printf("修改成功!");
else
printf("修改失败!");
}
/***************检查日期是否重复函数***************/
int checkAdd(int year1,int month1,int day1)
{
Date* date = datetimes->next;
while (date != NULL)
{
if (((date->year1)==year1)&&((date->month1)==month1)&&((date->day1)==day1))
return 0;
date = date->next;
}
return 1;
}
/***************查找行程安排函数***************/
Date* findInfo(int year1,int month1,int day1)
{
Date* date = datetimes->next;
int i;
printf("请输入您所要查询的组合类型(年:1;年+月:2;年+月+日:3):");
scanf("%d",&i);
while (date != NULL)
{
if(i==1)
{
if (date->year1==year1)
printf("%d\t%d\t%d\t%s\n",date->year1,date->month1,date->day1,date->text);
}
else if(i==2)
{
if (((date->year1)==year1)&&((date->month1)==month1))
printf("%d\t%d\t%d\t%s\n",date->year1,date->month1,date->day1,date->text);
}
else if(i==3)
{
if (((date->year1)==year1)&&((date->month1)==month1)&&((date->day1)==day1))
printf("%d\t%d\t%d\t%s\n",date->year1,date->month1,date->day1,date->text);
}
else
printf("请您正确输入数字1、2、3进行查询:");
date = date->next;
}
printf("以上为所有的行程安排,若没显示则说明没有相关的行程安排!\n");
return NULL;
}
/***************统计日期函数***************/
Date* findInfo1(int year1,int month1,int* a)
{
int i=0;
Date* date = datetimes->next;
while (date != NULL)
{
if (((date->year1)== year1)&&((date->month1)==month1))
{
printf("%d\t%d\t%d\t%s\n",date->year1,date->month1,date->day1,date->text);
i++;
}
date = date->next;
}
a[month1]=i;
return NULL;
}
/***************绘制图表函数***************/
void picture(int* c)
{
int a1[13]={0,1,2,3,4,5,6,7,8,9,10,11,12};
int i,sum=0;
float average;
char s1[5],s2[5];
char str[10];
getch();
initgraph(900, 700);
//x轴单位长度
for(i=1;i<=12;i++)
{
itoa(a1[i],str,10);
outtextxy(60*i,640, str);
}
//y轴单位长度
for(i=1;i<=11;i++)
{
itoa(a1[i]-1,str,10);
outtextxy(10,640-50*i,str);
}
//折点
for(i=1;i<=12;i++)
{
sum+=c[i];
setfillcolor( LIGHTMAGENTA );
fillcircle(60*i,590-50*c[i], 5);
itoa(c[i],s1,10);
itoa(i,s2,10);
strcat(s2,",");
strcat(s2,s1);
outtextxy(60*i+5,590-50*c[i], s2);
}
average=float(sum/12.0);
//x轴
setlinecolor( LIGHTRED );
line(30,630,800,630);
//x轴箭头
line(800,630,780,620);
line(800,630,780,640);
outtextxy(800,640, "x / 月份");
//y轴
setlinecolor( LIGHTBLUE );
line(30,40,30,630);
//y轴箭头
line(30,40,20,60);
line(30,40,40,60);
outtextxy(20,20, "y / 所安排行程天数");
//折线图
setlinecolor(LIGHTGREEN);
line(60,590-50*c[1],120,590-50*c[2]);
line(120,590-50*c[2],180,590-50*c[3]);
line(180,590-50*c[3],240,590-50*c[4]);
line(240,590-50*c[4],300,590-50*c[5]);
line(300,590-50*c[5],360,590-50*c[6]);
line(360,590-50*c[6],420,590-50*c[7]);
line(420,590-50*c[7],480,590-50*c[8]);
line(480,590-50*c[8],540,590-50*c[9]);
line(540,590-50*c[9],600,590-50*c[10]);
line(600,590-50*c[10],660,590-50*c[11]);
line(660,590-50*c[11],720,590-50*c[12]);
//平均值线
setlinecolor( LIGHTCYAN );
line(60,int(590-50*average),720,int(590-50*average));
outtextxy(730,int(590-50*average),"平均值拟合线");
getch();
closegraph();
}