使用 C 语言的日历






4.83/5 (23投票s)
C 程序用于显示任意给定月份和年份(mm-yyyy)的日历
引言
和许多人一样,我也是从 C 语言开始学习计算机编程的,C 语言是有史以来使用最广泛的编程语言之一。:)
在这篇文章中,我将解释一个 C 程序,它接受任何月份年份并显示该月份的日历。我们将添加更多功能,例如,如果用户按下
- 左箭头键 - 转到上个月。
- 右箭头键 - 转到下个月。
- 上箭头键 - 转到下一年。
- 下箭头键 - 转到上一年。
- I - 插入新的月份年份。
- P - 将月份打印到文本文件中。
- Esc - 退出程序。
这个简单的例子对初学者和中级开发人员都很有帮助,可以帮助他们理解一些基本概念,例如声明数组、使用函数、循环、使用 goto 语句、打印输出文件、处理按键等。
请随时分享您的评论/建议并评价这篇文章。:)
背景
- 我们将通过向用户显示一个输入屏幕来开始程序,该屏幕将以 mm-yyyy 格式接受月份和年份,如下所示
- 一旦用户输入有效的月份年份并按下 Enter 键,它应该显示输入月份的日历,如下所示
- 如果用户按下左箭头键,它将显示上个月(即 2014 年 5 月)的日历,如下所示
- 同样,如果用户按下右箭头键,它将在屏幕上显示下个月(即 2014 年 7 月)
一旦用户按下上箭头键,它将在屏幕上显示下一年的月份(即 2015 年 6 月)
- 如果用户按下下箭头键,它将在屏幕上显示上一年的月份(即 2013 年 6 月)
- 如果用户按下 I 键,它将显示用户输入屏幕并要求输入另一个月份年份。
- 如果按下 P 键,它将把月份详细信息导出到名为“JUN2014.txt”的文本文件中,如下所示
- 一旦用户按下 Esc 键,程序将关闭。
注意:我使用了 Turbo C++ / C 编译器来创建这个程序。请访问以下链接下载
适用于 Windows XP / 7 / 8 / 8.1 的 Turbo C++ / C 编译器
使用代码
让我们首先在 main() 函数中创建输入屏幕
textcolor(WHITE); clrscr(); printf("\n\tThis program shows calendar of \n"); printf("\n\ta given month. Enter month, year...format is mm-yyyy.\n");
代码解释
textcolor() 函数用于更改 C 程序中绘制文本的颜色。
声明:- void textcolor(int color);
其中 color 是一个整型变量。例如,0 表示黑色,1 表示蓝色,2 表示绿色等等。您也可以使用适当的颜色而不是整数。例如,您可以写入 textcolor(YELLOW); 将文本颜色更改为黄色。但只能使用大写字母的颜色。
clrscr() 函数用于清除屏幕。
接下来的两行只是用于在控制台输出上显示消息。
/* taking input */
while(TRUE)
{
fflush(stdin);
printf("\n\n\tEnter mm-yyyy: ");
scanf("%d-%d", &Month, &Year);
if(Year < 0)
{
printf("\nInvalid year value...");
continue;
}
if(Year < 100)
Year += 1900;
if(Year < 1582 || Year > 4902)
{
printf("\nInvalid year value...");
continue;
}
if(Month < 1 || Month > 12)
{
printf("\nInvalid month value...");
continue;
}
break;
} /* End of while loop */
代码解释
我们从一个 while(TRUE) 循环开始,这是一个无限循环,因此您必须显式地中断循环。否则它将无限循环。这个循环的原因是为了确保我们接受用户有效的输入。如果用户输入无效,则显示错误消息并再次提示输入。
fflush(stdin);
printf("\n\n\tEnter mm-yyyy: ");
scanf("%d-%d", &Month, &Year);
fflush(stdin); - 此函数用于清除输入缓冲区。
其他行用于接受用户输入到两个变量中,Month 和 Year。
if(Year < 0)
{
printf("\nInvalid year value...");
continue;
}
if(Year < 100)
Year += 1900;
if(Year < 1582 || Year > 4902)
{
printf("\nInvalid year value...");
continue;
}
if(Month < 1 || Month > 12)
{
printf("\nInvalid month value...");
continue;
}
break;
我们编写了一些数据验证代码,例如年份必须大于 0。如果用户输入 yy 格式的年份(例如,98),它将加上 1900 变为 1998。程序将接受 1952 年到 4902 年之间的年份。超出此范围的任何年份都不会被接受为有效年份。
月份必须在 1 到 12 的范围内。超出此范围的任何输入都不会被接受为有效的月份。
如果所有条件都不满足,将执行 break; 语句,程序流程将继续。
注意:在每次验证失败消息之后,都会写入 continue; 语句,以确保循环内的其余代码不会执行。
在继续 main 方法的其余部分之前,让我们声明一些常量并编写所需的函数。
#define LEAP_YEAR ((Year%4==0 && Year%100 != 0)||Year%400==0)
#define TRUE 1
#define CH '-'
#define MAX_NO 91
#define 指令用于在 C 编程语言中定义常量或创建宏。第一条语句定义了一个宏,它接受 Year 作为输入参数并返回 TRUE/FALSE。如果年份是闰年,它返回 TRUE,否则返回 FALSE。
其他三行用于定义常量。
int MonthDay[] = {31,28,31,30,31,30,31,31,30,31,30,31};
char *MonthName[]={"January","February","March","April","May","June","July",
"August","September","October","November","Decembeer"};
char *MonthName1[]={"JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP",
"OCT","NOV","DEC"};
我们声明了三个数组。MonthDay[] 将用于确定一个月中的天数。我们将单独处理闰年。*MonthName[] 和 *MonthName1[] 是字符串数组。
注意:字符串数组可以通过两种方式声明
- char array[ROW][COL]; - 当您知道行数 ROW 和列数 COL 时。
- char *array[ROW]; - 这种方式,您只需提供行数。如果您在声明时用值初始化数组,则行号变为可选。
在我们的例子中,我们没有提供行数,因为我们只在声明时用值初始化了数组。
让我们继续添加所需的函数
/*================ FUNCTION TO CALCULATE ZELLER'S ALGORITHM =============*/
int getZeller(int Month,int Year)
{
int Day = 1, ZMonth, ZYear, Zeller;
if(Month < 3)
ZMonth = Month+10;
else
ZMonth = Month-2;
if(ZMonth > 10)
ZYear = Year-1;
else
ZYear = Year;
Zeller = ((int)((13*ZMonth-1)/5)+Day+ZYear%100+
(int)((ZYear%100)/4)-2*(int)(ZYear/100)+
(int)(ZYear/400)+77)%7;
return Zeller;
}
蔡勒算法(Zeller's Algorithm)可用于确定过去、现在或未来任何日期(1582 年至 4902 年之间)的星期几。我们使用此函数来获取给定月份第一天的星期几。
/*==================== FUNCTION TO GET KEY CODE =========================*/
getkey()
{
union REGS i,o;
while(!kbhit())
;
i.h.ah = 0;
int86(22,&i,&o);
return (o.h.ah);
}
kbhit() - 当用户按下按键时返回整数值的函数。我们将使用此函数来捕获用户输入,例如左箭头键、右箭头键、上箭头键、下箭头键、I、P 等。
void printchar(char c)
{
int i;
printf("\n\t");
for(i=1;i<=51;i++)
printf("%c",c);
printf("\n");
}
printchar(); - 它接受一个字符并将其打印 51 次在一行上。此函数将用于对输出进行一些格式化。
void PrintFile(int M,int Y, int Z)
{
int i, j;
char filename[12];
char stryear[5];
FILE *stream;
strcpy(filename, MonthName1[M-1]);
itoa(Y, stryear, 10);
strcat(filename, stryear);
strcat(filename, ".txt");
if((stream=fopen(filename,"w"))==NULL)
{
printf("\nError-cannot create file.");
getch();
exit(1);
}
fprintf(stream, "\n\t\t\t%s %d\n\n\t", MonthName[M-1], Y);
for(i=1; i<=MAX_NO; i++)
fprintf(stream, "-");
fprintf(stream, "\n\tSUN\tMON\tTUE\tWED\tTHU\tFRI\tSAT\n\t");
for(i=1; i<=MAX_NO; i++)
fprintf(stream, "-");
/* setting starting position */
fprintf(stream, "\n");
for(i = 1; i <= Z; i++)
fprintf(stream, "\t -");
j = Z;
/* printing dates */
for(i = 1; i <= MonthDay[M-1]; i++)
{
if(j++ % 7 == 0)
fprintf(stream, "\n");
fprintf(stream, "\t%2d", i);
}
fprintf(stream, "\n\t");
for(i=1; i<=MAX_NO; i++)
fprintf(stream, "-");
fprintf(stream, "\n\n\t\tCreated by: Debabrata Das [debabrata.dd@gmail.com]");
fclose(stream);
}
代码解释
PrintFile(); - 函数将用于将输出打印到文本文件并保存到磁盘。
int i, j;
char filename[12];
char stryear[5];
FILE *stream;
变量声明部分,我们声明了两个整型变量 - i, j,两个字符数组 - filename, stryear 和一个 FILE 指针,用于在 C 语言中与文件通信。
strcpy(filename, MonthName1[M-1]);
itoa(Y, stryear, 10);
strcat(filename, stryear);
strcat(filename, ".txt");
strcpy(des, src); - 此函数用于将 src 字符串复制到 des 字符串。这里月份名称将被复制到 filename 变量。月份名称将用于创建文本文件名。
itoa(); - 用于将整数转换为字符串。我们将给定年份转换为字符串,以便它可以与月份名称连接并形成输出文本文件名。
strcat(str1, str2); - 此函数用于将 str2 连接到 str1。最初我们将月份名称复制到 filename 变量中。现在我们将年份与月份名称连接起来,使文件名如下所示:“JUN2014”
我们再次使用 strcat() 来附加文件的“.txt”扩展名。最终文件名将包含一个完整的文件名,如下所示:“JUN2014.txt”
if((stream = fopen(filename,"w"))==NULL)
{
printf("\nError-cannot create file.");
getch();
exit(1);
}
上述代码将尝试以只写模式("w")打开文件。如果由于任何原因无法打开文件,fopen() 函数将返回 NULL 值。然后我们可以显示消息“Error-cannot create file。”
getch(); - 此函数用于从控制台输入(即键盘)获取一个字符/按键。程序会等待直到用户按下键盘上的任何键。
exit(1); - 将退出程序。
fprintf(stream, "\n\t\t\t%s %d\n\n\t", MonthName[M-1], Y);
for(i=1; i<=MAX_NO; i++)
fprintf(stream, "-");
fprintf(stream, "\n\tSUN\tMON\tTUE\tWED\tTHU\tFRI\tSAT\n\t");
for(i=1; i<=MAX_NO; i++)
fprintf(stream, "-");
/* setting starting position */
fprintf(stream, "\n");
for(i = 1; i <= Z; i++)
fprintf(stream, "\t -");
j = Z;
/* printing dates */
for(i = 1; i <= MonthDay[M-1]; i++)
{
if(j++ % 7 == 0)
fprintf(stream, "\n");
fprintf(stream, "\t%2d", i);
}
fprintf(stream, "\n\t");
for(i=1; i<=MAX_NO; i++)
fprintf(stream, "-");
fprintf(stream, "\n\n\t\tCreated by: Debabrata Das [debabrata.dd@gmail.com]");
以上几行用于以适当的格式打印该月的日期。
fclose(stream);
一旦所有内容都写入文件,就会调用 fclose() 函数以正确关闭文件。
现在我们已经完成了所有必需的函数。让我们完成 main 方法中的逻辑。
do
{
/* calculating day of 1st date of given month */
Zeller = getZeller(Month,Year);
clrscr();
printf("\n\n\t\t\t");
/* printing the corresponding month name */
textbackground(Month);
cprintf("%s %d\n",MonthName[Month-1],Year);
textbackground(BLACK);
/* adjusting February in case of Leap Year */
MonthDay[1] = LEAP_YEAR ? 29 : 28;
/* giving output */
printchar(CH);
textcolor(12); /* LIGHTRED */
printf("\t");cprintf("SUN");
textcolor(LIGHTGREEN);
cprintf(" MON TUE WED THU FRI SAT");
textcolor(7);
printchar(CH);
/* setting starting position */
for(i = 1; i <= Zeller; i++)
printf("\t -");
j = Zeller;
/* printing dates */
for(i = 1; i <= MonthDay[Month-1]; i++)
{
if(j++ % 7 == 0)
{
printf("\n\t");
textcolor(12);
cprintf("%2d",i);
textcolor(WHITE);
}
else
printf(" %2d",i);
}
printchar(CH);
printf("\n\n\t\t(*) Use Left,Right,Up & Down Arrow.");
printf("\n\n\t\t(*) Press I for New Month & Year.");
printf("\n\n\t\t(*) Press P for Print to File.");
printf("\n\n\t\t(*) Press ESC for Exit.\n\n\n\t\t");
textcolor(11);
textbackground(9);
cprintf("Created by: Debabrata Das [debabrata.dd@gmail.com]");
textcolor(WHITE);
textbackground(BLACK);
KeyCode = getkey(); /* getting Key Code */
if(KeyCode == 72) /* Up Arrow */
Year++;
if(KeyCode == 80) /* Down Arrow */
Year--;
if(KeyCode == 77) /* Right Arrow */
{
Month++;
if(Month > 12)
{
Month = 1;
Year++;
}
}
if(KeyCode == 75) /* Left Arrow */
{
Month--;
if(Month < 1)
{
Month = 12;
Year--;
}
}
if(KeyCode == 25) /* Code of P */
PrintFile(Month,Year,Zeller);
if(KeyCode == 23) /* Code of I */
goto Top;
}while(KeyCode != 1); /* End of do-while loop */
代码解释
textbackground(); - 此函数用于在文本模式下更改当前背景颜色。
/* adjusting February in case of Leap Year */
MonthDay[1] = LEAP_YEAR ? 29 : 28;
如前所述,这里我们正在计算二月份的天数。如果是闰年,则考虑 29 天,否则 28 天。
其余代码非常直观,因此不再解释每一行代码。
让我们编译并执行程序。希望您喜欢这篇文章。请留下您的评论/建议,别忘了评分。:)
编码愉快 :)
历史
在此处保持您所做的任何更改或改进的实时更新。