Fearless_Wolf
Fearless_Wolf

Reputation: 50

How i can print dates under right weekdays?

#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===================================================");
}

When i input 2/2015 it gives infinity loop.(Now i don't have problems with infinity loop)

Example: Input: 2 2020 | Output:

===================================================
                    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
===================================================

Input: 02 2015 | Output:

===================================================
                      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      --      --      
===================================================

I have problems only with output

More details,More details,More details,More details,More details,More details,More details,More details,More details,More details,More details

Upvotes: 0

Views: 97

Answers (1)

David C. Rankin
David C. Rankin

Reputation: 84599

Unless I'm misunderstanding something, the only thing you are worried about is how to align the first partial week of numbers under the weekday headings. Since the first day of every month is the 1st, you can just concentrate on weekDay(year,month,1).

Additionally, since the days are all separated by 8-characters (one normal tab width), you can simply insert 8-spaces for each weekday offset. So you essentially need to pad the first day for a total number of spaces:

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

That allows you to eliminate your loop and simply use a field-width modifier that is set by padding as the first argument to printf when outputting a space, e.g.

       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, " ");

Or after computing the padding, you could simply loop that number of times outputting spaces, e.g.

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

Same result either way.

Example Use/Output

That appears to do what it is you are attempting, e.g.

For March, 2020

$ ./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
===================================================

For April, 2020:

$ ./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
===================================================

For May, 2020:

$ ./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
===================================================

Adding Placeholders At Beginning & End

If you want to add the "-- " placeholders for empty dates, then to add placeholders at the beginning you could just loop that many times padding with the full string, e.g.

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

And at the end, recalculate the padding from the last day to the end, e.g.

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

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

Example Use/Output

With the placeholder, you would have:

Feb, 2020:

$ ./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      --      --      --      --
===================================================

March, 2020:

$ ./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      --      --      --      --
===================================================

April, 2020:

$ ./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      --      --
===================================================

Which verifying with my calendar appears correct. The full code I used to test was:

(updated: to fix weekDay() calculation)

#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);
} 

Invalid weekDay() Calculation

The problem with your calendar for Jan or Feb is the incorrect adjustment of m = mh; You have:

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

You need:

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

Reason: after you adjust Jan or Feb as m = mh + 10; you check again, if (mh <= 12 || mh >= 3) which is now true since you just added + 10, so you then do m = mh - 2 resulting in the wrong value for mh.

Example Use/Output

For Jan, 2020

$ ./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      --
===================================================

For Feb, 2020

$ ./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

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

For March, 2020

$ ./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      --      --      --      --
===================================================

Let me know if you have any questions.

Upvotes: 2

Related Questions