我在C中编写了一个非常简单的日历。它以年份作为输入,然后计算该年份的日期和工作日。 假设日期0001-01-01是星期一。 除了在一个地方,我已经让它工作得很好。当它即将打印出所有第31个日期的行。 基本上出了什么问题,当它要检查是否有什么东西要打印到31日(没有)时,它会破坏工作日变量。这使得以下第31个日期错了。 是否有人可以看到我做错了什么或者想帮助我? :)
编辑忘了提及它是一个没有任何计算日期代码等公式的任务。允许使用的唯一参考是0001-01-01的日期是星期一。
继承我的代码。 (是的,它有点凌乱,但我还在学习。)
int isLeapYear(int year){
if(((year%4==0) && (year%100!=0)) || (year%400==0)){
return 1;
}
else
return 0;
}
int getYear(){
int year = 0;
while(year==0 || year < 0){
printf("Enter year: ");
scanf("%d", &year);
if(year > 0){
break;
}
printf("Invalid input. Try again.\n\n");
}
return year;
}
void printWeekday(int w){
switch(w){
case 0:
printf("Sun");
break;
case 1:
printf("Mon");
break;
case 2:
printf("Tue");
break;
case 3:
printf("Wed");
break;
case 4:
printf("Thu");
break;
case 5:
printf("Fri");
break;
case 6:
printf("Sat");
break;
}
}
void printMonth(int m){
switch(m){
case 1:
printf("Jan");
break;
case 2:
printf(" Feb");
break;
case 3:
printf(" Mar");
break;
case 4:
printf(" Apr");
break;
case 5:
printf(" May");
break;
case 6:
printf(" Jun");
break;
case 7:
printf(" Jul");
break;
case 8:
printf(" Aug");
break;
case 9:
printf(" Sep");
break;
case 10:
printf(" Oct");
break;
case 11:
printf(" Nov");
break;
case 12:
printf(" Dec\n");
break;
}
}
void calendar(int year){
int y = 1;
int m = 1;
int d = 1;
int loop = 1;
int day = 1;
int days_in_month[14] = {0,31,28,31,30,31,30,31,31,30,31,30,31,0};
if(isLeapYear(year)){
days_in_month[1] = 29;
}
for(m=1; m<=12; m++){
printMonth(m);
}
while(loop){
int weekday = 1;
for(y=1; y<=year; y++){
for(m=1; m<=12; m++){
for(d=1; d<=31; d++){
if(weekday%7 == 0){
// printf("h");
weekday = 0;
}
if(y==year){
if(day>days_in_month[m]){
printf(" ");
printf("%d", weekday);
break;
}else if(d == day){
//printf("%d", weekday);
if(m == 1){
printf("%02d ", d);
printWeekday(weekday);
}else if(m == 12){
printf(" %02d ", d);
printWeekday(weekday);
printf("\n");
}else{
printf(" %02d ", d);
printWeekday(weekday);
}
}
}
if(d<=days_in_month[m]){
weekday = weekday + 1;
}
}
}
}
day++;
if(day == 32){
break;
}
}
}
int main()
{
int end = 1;
while(end){
int year = getYear();
printf(" %d\n", year);
calendar(year);
printf("\nEnter 0 to quit: ");
scanf("%d", &end);
//system("cls");
}
return 0;
}
答案 0 :(得分:0)
不是持有工作日变量,而是可以调用一个函数来计算给定日期的星期几。为此,您可以使用Tomohiko Sakamoto的星期几算法。
int dayofweek(int d, int m , int y){
static int t[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
y -= m < 3;
return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
}
// 0 - Sunday
// 1 - Monday and so on
如果您想了解此算法,可以在此处查看详细说明:https://www.quora.com/How-does-Tomohiko-Sakamotos-Algorithm-work
但是既然你是初学者,我就不会重新考虑它:)它有点令人困惑。
执行此操作后,您可以将日历功能简化为
void calendar(int year) {
int days_in_month[14] = { 0,31,28,31,30,31,30,31,31,30,31,30,31,0 };
if (isLeapYear(year)) {
days_in_month[2] = 29;
}
for (int m = 1; m<=12; m++) {
printMonth(m);
}
for (int d = 1; d<=31; d++) {
for (int m = 1; m<=12; m++) {
if (d <= days_in_month[m]) {
int weekday = dayofweek(d, m, year);
printf("%02d ", d);
printWeekday(weekday);
printf(" ");
}
else {
printf(" ");
}
}
printf("\n");
}
}
这实际上是一种更有效的方式来产生工作日而不是整年的循环
答案 1 :(得分:0)
这里,在calendar()
函数内部添加以下代码:
if(day>days_in_month[m] /*Add this code: */ && d>days_in_month[m]){
printf(" ");
printf("%d", weekday);
break;
}else if(d == day){...
在迭代结束时(我的意思是for(d=1; d<=31; d++){
循环)你迭代工作日。所以4月初应该是星期天。如果您检查结果,这是有效的。
但是,你按星期几计算工作日。因此,当我们在3月3日打印31时,我们的day
变量等于31.
现在,3月结束了(我们打印3月31日),我们周日的工作日开始了。我们去计算四月的日子。但是看看你的代码,在for(d=1; d<=31; d++)
循环内,你有if(day>days_in_month[m]) {break;}
。
当我们的程序检查4月的第一天,并且day
等于31时,它将使用break
指令停止计算4月的天数。我们去计算五月的日子。但我们的工作日仍然是周日。如果您看到有效代码,则可能应该是星期二。但是当day
变量等于31时,首先可以从星期日开始。从5月1日开始,所有日子计算错误。
与LEAPS年有关的问题: 因为你使用这个:
if(isLeapYear(year)){
days_in_month[2] = 29;
}
每年增加第29天(所以你在前三年增加了第29天,你会看到第4年1月1日结果:))。
要解决此问题,请删除这些代码。在循环内部持续数月,添加代表天数的变量:
for(m=1; m<=12; m++){
int monthDays = days_in_month[m]; /*Add this variable*/
if (m==2 && isLeapYear(y))
monthDays++; // Add 29th day to feb. of leap year
for(d=1; d<=31; d++){...
在功能内部,将所有days_in_month[m]
替换为monthDays