问题描述:设计一个C语言程序,实现桌面日历的功能,要求:
- 按照输入的年份,显示这一年每月日历;
2、按照输入的年份和月份,显示这个月的日历;
3、显示当月的日历,日历显示形式同挂历。
解决思路:设计几个函数,分别用于实现判断是否为闰年、该月有多少天,该月第一天是星期几、遍历等等,在主函数里用switch语句实现不同功能,在while语句里循环。
功能模块图
代码:
#include <stdio.h>
#include <time.h>
// 判断是否为闰年函数
int isLeapYear(int);
// 判断某年某月的第一天是周几的函数
int daysWeek(int, int);
// 判断月份有几天函数
int monthDays(int, int);
// 输出某年某月日历函数
void monthCalendar(int, int);
int main() {
int Year, Month,day;
// 模式选择,ll
int mode;
while(1) {
Year=0,Month=0,mode=0;
printf("-----------------------------------------\n");
printf("| 简易桌面日历 |\n");
printf("-----------------------------------------\n");
printf("| (1) 输入年份打印出全年历 |\n");
printf("-----------------------------------------\n");
printf("| (2) 输入年份月份打印出月日历 |\n");
printf("-----------------------------------------\n");
printf("| (3) 打印出当前月的日历 |\n");
printf("-----------------------------------------\n");
printf("| (4) 退出程序 |\n");
printf("-----------------------------------------\n");
printf("| 请输入数字1 2 3 4以选择要使用的功能 |\n");
printf("-----------------------------------------\n");
printf("输入数字:");
scanf("%d", &mode);
rewind(stdin);
printf("\n");
switch(mode) {
case 1:
// 实现第一个功能
printf("请输入年份: ");
scanf("%d", &Year);
rewind(stdin);
if(Year<1900){
printf("\n无法查询1900年前的日历,输入无效!\n");
printf("\n");
}else{
// 从1遍历到12月 代表1月到十二月
for (int i = 1; i <= 12; i++) {
printf("--------------------------------------------------\n");
printf("%d 年 %d 月\n", Year, i);
monthCalendar(Year, i);
}
}
break;
case 2:
printf("请输入年份: ");
scanf("%d", &Year);
rewind(stdin);
printf("请输入月份: ");
scanf("%d", &Month);
rewind(stdin);
//判断输入的月份是否符合常理
if(Month>12||Month<1||Year<1900) {
printf("\n无此月份或无法查询1900年前的日历,输入无效!\n");
printf("\n");
} else{
printf("%d 年 %d 月\n", Year, Month);
monthCalendar(Year, Month);
}
break;
case 3:
// 固定格式
time_t timep;
struct tm *p;
time(&timep);
p = gmtime(&timep);
Year = 1900 + p->tm_year;
Month = 1 + p->tm_mon;
day=p->tm_mday;
printf("当前时间为:%d年%d月%d日\n", Year, Month,day);
printf("--------------------------------------------------\n");
printf("%d 年 %d 月\n", Year, Month);
monthCalendar(Year, Month);
break;
case 4:
printf("退出成功!");
return 0;
default:
printf("请输入数字1 2 3 4选择功能 输入其他字符无效!\n\n");
}
}
}
// 判断是否为闰年
int isLeapYear(int Year) {
// 如果能整除4且不能整除100或能整除400,则为闰年
return (Year % 4 == 0 && Year % 100 != 0) || Year % 400 == 0;
}
// 判断月份有几天
int monthDays(int Year, int Month) {
if (Month == 1 || Month == 3 || Month == 5 || Month == 7 || Month == 8 || Month == 10 || Month == 12) {
return 31;
} else if (Month == 4 || Month == 6 || Month == 9 || Month == 11) {
return 30;
} else {
if (isLeapYear(Year)) {
return 29;
}
// 如果不是闰年 天数为28天
return 28;
}
}
// 判断某年某月的第一天是周几
int daysWeek(int Year, int Month) {
// day用于记录总天数
// day1记录每月的天数,结合下面代码理解
int day = 0, day1 = 0;
// 得到从1900年到某年的天数
for (int i = 1900; i < Year; i++) {
// 判断闰年
if (isLeapYear(i)) {
day = day + 366;
} else {
day = day + 365;
}
}
//获得1900年到该月份的天数
for (int m = 1; m < Month; m++) {
day1 = monthDays(Year, m);
// 计算天数
day =day+ day1;
}
// week为某年某月第一天的周几m
int week = day % 7;
return week;
}
// 具体实现打印某年某月日历
void monthCalendar(int Year, int Month) {
printf("--------------------------------------------------\n");
printf("一\t二\t三\t四\t五\t六\t日\n");
//判断这个月的第一天是星期几
int t = daysWeek(Year, Month);
// 判断月份有几天
int day1 = monthDays(Year, Month);
for (int i = 0; i < t; i++) {
printf("\t");
}
//控制输出格式
for (int i = 1; i <= day1; i++) {
printf("%d\t", i);
if ((i + t) % 7 == 0) {
printf("\n");
}
}
printf("\n");
printf("--------------------------------------------------\n");
printf("\n");
}
遇到的问题:
scanf("%d", &mode);scanf要去输入一个整形的数赋值给变量mode,但如果你输入一个非法字符,就会出错,mode不会被赋值,还是上一个的值。解决方案是给mode在scanf赋值之前一个不影响程序的值,或将变量mode声明成char类型。