0
#include <stdio.h>
#include <math.h>
.
.
.
void calendar(int year, int month){

    int days, wd;

    puts("===================================================");
    printf("                      %c%c%c/%d\n",month_str[month][0],month_str[month][1],month_str[month][2],year);
    puts("\nSUN     MON     TUE     WED     THU     FRI     SAT");

    if(month == 2)
    {
        if(isLeap(year)==1)
            days = 29;
        if(isLeap(year)==0)
            days = 28;
    }
    else
        days = days_in_months[month];

// i need to correct this part
    //print dates
    for (int d = 1; d <= 1 + weekDay(year,month,d) * 5; d++ )
        {
            printf("    ");
        }
    for (int i = 1; i <=days; i++)
    {
       wd = weekDay(year,month, i);
       printf("%.2d",i);

       if ((wd+1) % 7 == 0)
            printf("\n");
        else
            printf("      ");    
    }
    puts("\n===================================================");
}

当我输入 2/2015 时,它给出了无限循环。(现在我没有无限循环的问题)

示例:输入:2 2020 | 输出:

===================================================
                    FEB/2020
SUN     MON     TUE     WED     THU     FRI     SAT
--      --      --      --      --      --      01
02      03      04      05      06      07      08
09      10      11      12      13      14      15
16      17      18      19      20      21      22
23      24      25      26      27      28      29
===================================================

输入: 02 2015 | 输出:

===================================================
                      APR/2020

SUN     MON     TUE     WED     THU     FRI     SAT
--      --      --      01      02      03      04
05      06      07      08      09      10      11
12      13      14      15      16      17      18
19      20      21      22      23      24      25
26      27      28      29      30      --      --      
===================================================

我只有输出有问题

更多细节,更多细节,更多细节,更多细节,更多细节,更多细节,更多细节,更多细节,更多细节,更多细节,更多细节

4

1 回答 1

2

除非我误解了什么,否则您唯一担心的是如何在工作日标题下对齐第一部分的数字。由于每个月的第一天是第一天,你可以专注于weekDay(year,month,1)

此外,由于日期都由 8 个字符(一个正常tab宽度)分隔,因此您可以简单地为每个工作日偏移量插入 8 个空格。因此,您基本上需要在第一天填充空格总数:

padding = weekDay(year,month,1) * 8;

这使您可以消除循环并简单地使用设置的字段宽度修饰符作为输出空格时padding的第一个参数,例如printf

       int days, wd, padding;     /* add padding variable */
       ...

//     for (int d = 1; d <= 1 + weekDay(year,month,d) * 5; d++)
//     {
//         printf("    ");
//     }
    if ((padding = weekDay(year,month,1) * 8))
        printf ("%*s", padding, " ");

或者在计算 之后padding,您可以简单地循环输出空格的次数,例如

    padding = weekDay(year,month,1) * 8;
    while (padding--)
        putchar (' ');

无论哪种方式,结果都是一样的。

示例使用/输出

这似乎做了你正在尝试的事情,例如

2020 年 3 月

$ ./bin/calendar
enter mm yyyy : 3 2020
===================================================
                      MAR/20

SUN     MON     TUE     WED     THU     FRI     SAT
01      02      03      04      05      06      07
08      09      10      11      12      13      14
15      16      17      18      19      20      21
22      23      24      25      26      27      28
29      30      31
===================================================

2020 年 4 月:

$ ./bin/calendar
enter mm yyyy : 4 2020
===================================================
                      APR/20

SUN     MON     TUE     WED     THU     FRI     SAT
                        01      02      03      04
05      06      07      08      09      10      11
12      13      14      15      16      17      18
19      20      21      22      23      24      25
26      27      28      29      30
===================================================

2020 年 5 月:

$ ./bin/calendar
enter mm yyyy : 5 2020
===================================================
                      MAY/20

SUN     MON     TUE     WED     THU     FRI     SAT
                                        01      02
03      04      05      06      07      08      09
10      11      12      13      14      15      16
17      18      19      20      21      22      23
24      25      26      27      28      29      30
31
===================================================

在开头和结尾添加占位符

如果您想"-- "为空日期添加占位符,那么要在开头添加占位符,您可以循环多次填充完整的字符串,例如

    padding = weekDay(year,month,1);
    while (padding--)
        fputs ("--      ", stdout);

最后,重新计算从最后一天到最后的填充,例如

    padding = 7 - weekDay(year,month,days) - 1;
    while (padding--)
        fputs ("--      ", stdout);

    puts("\n===================================================");

示例使用/输出

使用占位符,您将拥有:

2020 年 2 月:

$ ./bin/calendar
enter mm yyyy : 2 2020
===================================================
                      FEB/20

SUN     MON     TUE     WED     THU     FRI     SAT
--      --      01      02      03      04      05
06      07      08      09      10      11      12
13      14      15      16      17      18      19
20      21      22      23      24      25      26
27      28      29      --      --      --      --
===================================================

2020 年 3 月:

$ ./bin/calendar
enter mm yyyy : 3 2020
===================================================
                      MAR/20

SUN     MON     TUE     WED     THU     FRI     SAT
01      02      03      04      05      06      07
08      09      10      11      12      13      14
15      16      17      18      19      20      21
22      23      24      25      26      27      28
29      30      31      --      --      --      --
===================================================

2020 年 4 月:

$ ./bin/calendar
enter mm yyyy : 4 2020
===================================================
                      APR/20

SUN     MON     TUE     WED     THU     FRI     SAT
--      --      --      01      02      03      04
05      06      07      08      09      10      11
12      13      14      15      16      17      18
19      20      21      22      23      24      25
26      27      28      29      30      --      --
===================================================

使用我的日历进行的验证似乎是正确的。我用来测试的完整代码是:

更新:修复weekDay()计算)

#include <stdio.h>
#include <math.h>

const char weekday_str[7][4] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
const char month_str[13][4] = {"", "JAN", "FEB", "MAR", "APR", "MAY", "JUN","JUL", 
                                "AGO", "SEP", "OCT", "NOV", "DEC"};
const int days_in_months[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

int weekDay (int yr, int mh, int d)
{
    int y, c, m, w;

    if (mh == 1 || mh == 2)
        yr--;

    y = yr % 100;
    c = (yr - y) / 100;

    if (mh == 1 || mh == 2)
        m = mh + 10;
    else if (mh <= 12 || mh >= 3)
        m = mh - 2;

    w = ((d + floor(2.6*m - 0.2) + y + floor(0.25*y) + floor(0.25*c) - 2*c ));
    w = w % 7;

    if(w < 0)
        w += 7;

    return w;
}

int isLeap (int year)
{
    if (year%4 != 0)
        return 0;
    else if (year%100 != 0)
        return 1;
    else if (year%400 != 0)
        return 0;
    else
        return 1;
}

void calendar (int year, int month)
{
    int days, wd, padding;

    puts ("===================================================");
    printf ("                      %c%c%c/%d\n",
            month_str[month][0],month_str[month][1],month_str[month][2],year);
    puts ("\nSUN     MON     TUE     WED     THU     FRI     SAT");

    if (month == 2) {
        if (isLeap(year) == 1)
            days = 29;
        if (isLeap(year) == 0)
            days = 28;
    }
    else
        days = days_in_months[month];

    padding = weekDay(year,month,1);
    while (padding--)
        fputs ("--      ", stdout);

    for (int i = 0; i < days; i++) {
        wd = weekDay(year,month, i + 1);
        printf("%.2d", i + 1);

        if ((wd+1) % 7 == 0)
            printf("\n");
        else
            printf("      ");    
    }

    padding = 7 - weekDay(year,month,days) - 1;
    while (padding--)
        fputs ("--      ", stdout);

    puts("\n===================================================");
}

int main (void) {

    int mm, yyyy;

    fputs ("enter mm yyyy : ", stdout);
    if (scanf ("%d %*c%d", &mm, &yyyy) != 2) {
        fputs ("error: invalid format.\n", stderr);
        return 1;
    }

    calendar (yyyy, mm);
} 

无效weekDay()计算

1 月或 2 月日历的问题是 m = mh;您有:

    if (mh == 1 || mh == 2)
        m = mh + 10;
    if (mh <= 12 || mh >= 3)
        m = mh - 2;

你需要:

    if (mh == 1 || mh == 2)
        m = mh + 10;
    else if (mh <= 12 || mh >= 3)
        m = mh - 2;

原因:在您调整后Jan或再次检查时,Feb由于您刚刚添加,现在是正确的,因此您确实导致了错误的值。m = mh + 10;if (mh <= 12 || mh >= 3)+ 10m = mh - 2mh

示例使用/输出

2020 年 1 月

$ ./bin/calendar
enter mm yyyy : 1 2020
===================================================
                      JAN/20

SUN     MON     TUE     WED     THU     FRI     SAT
--      --      --      01      02      03      04
05      06      07      08      09      10      11
12      13      14      15      16      17      18
19      20      21      22      23      24      25
26      27      28      29      30      31      --
===================================================

2020 年 2 月

$ ./bin/calendar
enter mm yyyy : 2 2020
===================================================
                      FEB/20

SUN     MON     TUE     WED     THU     FRI     SAT
--      --      --      --      --      --      01
02      03      04      05      06      07      08
09      10      11      12      13      14      15
16      17      18      19      20      21      22
23      24      25      26      27      28      29

===================================================

2020 年 3 月

$ ./bin/calendar
enter mm yyyy : 3 2020
===================================================
                      MAR/20

SUN     MON     TUE     WED     THU     FRI     SAT
01      02      03      04      05      06      07
08      09      10      11      12      13      14
15      16      17      18      19      20      21
22      23      24      25      26      27      28
29      30      31      --      --      --      --
===================================================

如果您有任何问题,请告诉我。

于 2020-04-24T17:56:17.373 回答