首页 文章

使用月份和年份输入在C中打印Julian日历?

提问于
浏览
2

我正在尝试用C语言输出一个日历,我想我的格式已经缩小了,但我遇到了麻烦:

  • 验证用户输入(I 've commented out the potential solution, but it hasn' t已正确编译 . 它始终打印"invalid year/month selected"并且break语句不起作用 . )

  • 在一周的正确日期开始日历日(2018年5月开始于星期二,而不是星期日)

我目前的输出:

Enter month: 5
Enter year: 2018

 Su   M  Tu   W  Th   F  Sa
  1   2   3   4   5   6   7
  8   9  10  11  12  13  14
 15  16  17  18  19  20  21
 22  23  24  25  26  27  28
 29  30  31

我想要的输出:

Enter month: 5 
Enter year: 2018 

Su   M  Tu   W  Th   F  Sa
         1   2   3   4   5 
 6   7   8   9  10  11  12 
13  14  15  16  17  18  19 
20  21  22  23  24  25  26 
27  28  29  30  31

这是我的计划:

#include <stdio.h>
#include <stdlib.h>

/* #defines */
#define BEGIN 1900
#define DAYS_IN_WEEK 7

/* function prototypes */
void getMonthYear(int *month, int *year);
int toJulian(int month, int day, int year);
int daysInMonth(int month, int year);
int leapYear(int year);
long yearsToDays(int year);
void printCalendar(int startDay, int numDays);
void printHeader();

/* Calendar.c:  Prints monthly calendar.  Lab 4 / Week 9 */
void main(void)
{
    int month, year;
    int startDay;   // what day is first day of month.  1/1/1900 was Monday, so...
                    // day 1 is Mon, day 2 is Tue, ... , day 0 is Sun

    getMonthYear(&month, &year);
    startDay = (toJulian(month, 1, year) + yearsToDays(year)) % DAYS_IN_WEEK;
    printCalendar(startDay, daysInMonth(month, year));
}
void getMonthYear(int *month, int *year) {
    printf("Enter month: ");
    scanf("%d", month);
    /*if (month < 1 || month > 12) {
        printf("Invalid month selected");
        //break;
    }*/
    printf("Enter year: ");
    scanf("%d", year);
    /* if (year < BEGIN) {
        printf("Invalid year selected");
        //break;
    }*/
    printf("\n"); 
}
int toJulian(int month, int day, int year) {
    int count;
    for(count = 1; count < month; ++count) {
        day += daysInMonth(month, year);    
    }
    return day;
}
int daysInMonth(int month, int year) {
    int numDays;


switch (month) {
    case 1: numDays = 31;
        break;
    case 2: numDays = 28;
        break;
    case 3: numDays = 31;
        break;
    case 4: numDays = 30;
        break;
    case 5: numDays = 31;
        break;
    case 6: numDays = 30;
        break;
    case 7: numDays = 31;
        break;
    case 8: numDays = 31;
        break;
    case 9: numDays = 30;
        break;
    case 10: numDays = 31;
        break;
    case 11: numDays = 30;
        break;
    case 12: numDays = 31;
        break;
    }
    return numDays;
}
int leapYear(int year) {
    if (year % 400 == 0 && (year % 100 != 0 || year % 400 == 0)) {
        return 1;
    }
    else {
        return 0;
    }
}
long yearsToDays(int year) {
    int count;
    long days;
    for (count = BEGIN; count < year; ++count) {
        days = 365 + leapYear(year);
    }
    return days;
}
void printCalendar(int startDay, int numDays) {
    int dayid;
    printHeader();
    // Shifts position for the first date... sort of
        for ( dayid = 0; dayid < startDay; dayid++ ) {
            printf(" ");
        }

        // Supposedly prints all the dates for one month
        for ( dayid = 1; dayid <= numDays; dayid++ ) {
            printf("%3d", dayid );

            // If the day is not before Saturday, start next line on Sun
            if ( ( dayid + startDay ) % DAYS_IN_WEEK > 0 ) {
                printf(" ");
            }
            else {
                printf("\n" );
            }
        }
}
void printHeader() {
    printf(" Su   M  Tu   W  Th   F  Sa\n");
}

2 回答

  • 1

    您在以下函数中有错误:

    • toJulian
    int toJulian(int month, int day, int year) {
        int count;
        for(count = 1; count < month; ++count) {
            day += daysInMonth(month, year);    
        }
        return day;
    }
    
    • 您在每次通话中都使用 month . 你需要使用 count .

    • 您不需要输入参数 day . 您可以在循环开始之前将局部变量初始化为 0 .

    更新版本:

    int toJulian(int month, int year) {
        int count;
        int days = 0;
        for(count = 1; count < month; ++count) {
            days += daysInMonth(count, year);    
        }
        return days;
    }
    
    • leapYear .
    int leapYear(int year) {
        if (year % 400 == 0 && (year % 100 != 0 || year % 400 == 0)) {
            return 1;
        }
        else {
            return 0;
        }
    }
    

    if 语句中的逻辑不正确 . 它需要是:

    (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
    

    使用以下命令可以使函数更易读,更不容易出错:

    int leapYear(int year) {
       int ret = 0;
       if ( year % 4 != 0 )
       {
          ret = 0;
       }
       else 
       {
          if ( year % 100 != 0 )
          {
             ret = 1;
          }
          else 
          {
             ret = (year % 400 == 0);
          }
       }
    
       return ret;
    }
    
    • yearsToDays
    long yearsToDays(int year) {
        int count;
        long days;
        for (count = BEGIN; count < year; ++count) {
            days = 365 + leapYear(year);
        }
        return days;
    }
    
    • 您尚未初始化 days .

    • 您没有累积天数 . 你只是分配一个值 . 返回最后返回的值而不是累计的天数 .

    • 您在循环中使用 year 而不是 leapYear 的参数中的 count .

    这是更新版本:

    long yearsToDays(int year) {
        int count;
        long days = 0;
        for (count = BEGIN; count < year; ++count) {
            days += 365;
            days += leapYear(count);
        }
        return days;
    }
    
    • printCalendar
    void printCalendar(int startDay, int numDays) {
        int dayid;
        printHeader();
        // Shifts position for the first date... sort of
            for ( dayid = 0; dayid < startDay; dayid++ ) {
                printf(" ");
            }
    
            // Supposedly prints all the dates for one month
            for ( dayid = 1; dayid <= numDays; dayid++ ) {
                printf("%3d", dayid );
    
                // If the day is not before Saturday, start next line on Sun
                if ( ( dayid + startDay ) % DAYS_IN_WEEK > 0 ) {
                    printf(" ");
                }
                else {
                    printf("\n" );
                }
            }
    }
    
    • 打印当月的日期时,您正在用完四个空格 - "%3d"" " . 在第一个 for 循环中,您需要为每天写入四个空格,直到 startDay . 否则,第一行输出将无法正确对齐 .

    你需要使用:

    for ( dayid = 0; dayid < startDay; dayid++ ) {
                printf("    ");
            }
    
    • main

    这条线

    startDay = (toJulian(month, 1, year) + yearsToDays(year)) % DAYS_IN_WEEK;
    

    应该

    startDay = (1 + toJulian(month, year) + yearsToDays(year)) % DAYS_IN_WEEK;
    

    考虑(1)1900-Jan-01属于星期一,(2)改为 toJulian 的界面 .

  • 2

    break 用于退出循环或切换语句 . 它只能在当前函数范围内的循环内使用 .

    因此,即使 getMonthYear()main() (它不是)中的循环内被调用,它内部的 break 也不会退出该循环 .

    实际上,你根本没有循环,也没有 getMonthYear() ,也没有导致它的调用序列,所以 break 将是一个无操作 .

    你必须问自己“当他们无效录入时我真正想做什么?”

    一种可能性是从 getMonthYear() 返回有效性

    bool valid_input = 0;
    while (!valid_input) {
        valid_input = getMonthYear(&month, &year);
    }
    

    为了解决让一天变得正确的问题,您可能需要自己进行一些调试:将print语句放在有计算的所有位置,打印出中间结果,然后找出出错的地方 .

相关问题