Если я что-то не так понимаю, единственное, что вас беспокоит, это как выровнять первую неполную неделю чисел под заголовками дней недели. Поскольку первый день каждого месяца является первым, вы можете просто сконцентрироваться на weekDay(year,month,1)
.
Кроме того, поскольку все дни разделены 8 символами (один нормальный tab
ширина), вы можете просто вставьте 8 пробелов для каждого смещения дня недели. Таким образом, вам необходимо добавить первый день для общего числа пробелов:
padding = weekDay(year,month,1) * 8;
Это позволяет вам исключить l oop и просто использовать field-width модификатор, который устанавливается 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
вы можете просто l oop это количество раз выводить пробелы Например,
padding = weekDay(year,month,1) * 8;
while (padding--)
putchar (' ');
Тот же результат в любом случае.
Пример Использование / Вывод
Это похоже на то, что вы пытаетесь, например
за март 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
===================================================
за апрель 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
===================================================
за май 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
===================================================
Добавление заполнителей в начале и в конце
Если вы хотите добавить "-- "
заполнители для пустых дат, то для добавления заполнителей в начале вы можете просто l oop столько раз заполнять с полной строкой, например,
padding = weekDay(year,month,1);
while (padding--)
fputs ("-- ", stdout);
И в конце, пересчитать заполнение от последнего дня до конца, например,
* 104 6 *
Пример использования / вывода
С заполнителем вы получите:
Фев, 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 -- -- -- --
===================================================
Март, 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 -- -- -- --
===================================================
Апрель, 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 -- --
===================================================
То, что проверка по моему календарю кажется правильной. Полный код, который я использовал для проверки:
( обновлено: исправлено 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);
}
Invalid weekDay()
Расчет
Проблема с календарем на январь или февраль заключается в неправильной настройке 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)
, что теперь верно, поскольку вы только что добавили + 10
, поэтому вы делаете m = mh - 2
, что приводит к неправильному значению для mh
.
Пример использования / Вывод
за январь 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 --
===================================================
за февраль 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
===================================================
за март , 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 -- -- -- --
===================================================
Дайте мне знать, если у вас есть какие-либо вопросы.