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

时间:2014-11-01 04:19:14

标签: c loops calendar

我试图用C语言输出一个日历,我觉得我的格式有所下降,但我遇到了麻烦:

  1. 验证用户输入(我已经注释了潜在的解决方案,但它还没有正确编译。它总是打印"选择无效的年/月"并且break语句没有& #39; t work。)
  2. 在一周的正确日期开始日历日(2018年5月开始于星期二,而不是星期日)
  3. 我目前的输出:

    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 个答案:

答案 0 :(得分:2)

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

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

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

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

一种可能性是从getMonthYear()

返回有效性
bool valid_input = 0;
while (!valid_input) {
    valid_input = getMonthYear(&month, &year);
}

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

答案 1 :(得分:1)

以下功能中存在错误:

  1. toJulian

    int toJulian(int month, int day, int year) {
        int count;
        for(count = 1; count < month; ++count) {
            day += daysInMonth(month, year);    
        }
        return day;
    }
    
    1. 您在每次通话中都使用month。您需要使用count
    2. 您不需要输入参数day。您可以拥有一个在循环开始之前初始化为0的局部变量。
    3. 更新版本:

      int toJulian(int month, int year) {
          int count;
          int days = 0;
          for(count = 1; count < month; ++count) {
              days += daysInMonth(count, year);    
          }
          return days;
      }
      
    4. 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;
      }
      
    5. yearsToDays

      long yearsToDays(int year) {
          int count;
          long days;
          for (count = BEGIN; count < year; ++count) {
              days = 365 + leapYear(year);
          }
          return days;
      }
      
      1. 您尚未初始化days
      2. 您没有累积天数。你只是分配一个值。返回最后返回的值而不是累计的天数。
      3. 您在循环中使用year而不是count的参数中的leapYear
      4. 以下是更新版本:

        long yearsToDays(int year) {
            int count;
            long days = 0;
            for (count = BEGIN; count < year; ++count) {
                days += 365;
                days += leapYear(count);
            }
            return days;
        }
        
      5. 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" );
                    }
                }
        }
        
        1. 在打印当月的日期时,您使用了四个空格 - "%3d"" "。您需要在第一个startDay循环中为每天写入四个空格,直到for。否则,第一行输出将无法正确对齐。
        2. 您需要使用:

                  for ( dayid = 0; dayid < startDay; dayid++ ) {
                      printf("    ");
                  }
          
        3. 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的界面。