-
Автор темы
- #1
В поисках нового материала для форума, я нашел одну интересную практическую работу по теме "Функции". Суть заключается в выводе календаря на указанный пользователем год. Думаю, это достаточно хорошее задание для только изучающих C++ людей. Вы можете попробовать свои силы и написать данный прак с нуля, но обязательно поделитесь результатом в теме, мне будет очень интересно :).
Задание имеет 2 уровня сложности: "easy" и "hard". Разница заключается только в формате вывода календаря.
Решать мы, конечно, будем hard версию .
В итоге вся "сложность" работы заключена в заполнении столбиком и выводе месяцев группами по 4. Думаю, вы понимаете, что создание подобного алгоритма не составляет труда, если знать лишь пару основных идей:
В первую очередь я хочу предложить написать этот небольшой практикум именнно вам - и вы лишний раз испытаете свои знания, и я, может быть, найду что-нибудь для себя новое в других решениях.
Для особо умных: использовать сторонние классы, помимо
Мой вариант решения
Задание имеет 2 уровня сложности: "easy" и "hard". Разница заключается только в формате вывода календаря.
Решать мы, конечно, будем hard версию .
В итоге вся "сложность" работы заключена в заполнении столбиком и выводе месяцев группами по 4. Думаю, вы понимаете, что создание подобного алгоритма не составляет труда, если знать лишь пару основных идей:
- 1 января 1 года - это понедельник (это можно использовать для определения дня недели даты)
- Максимальное занимаемое количество недель в месяце - 6, минимальное - 4 (необходимо для правильного "центрирования" месяцев)
Date
:
C++:
struct Date {
long long Year;
long long Month;
long long Day;
};
Для особо умных: использовать сторонние классы, помимо
iostream
, iomanip
и string
, нельзя.Мой вариант решения
C++:
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
struct Date {
long long Year;
long long Month;
long long Day;
};
#pragma region Functions
bool IsLeap(Date date) {
if (!(date.Year % 4)) {
if (!(date.Year % 100))
return false;
if (!(date.Year % 400))
return true;
return true;
}
return false;
}
int YearDaysCount(Date date) {
return IsLeap(date) ? 366 : 365;
}
int MonthDaysCount(Date date) {
if (date.Month == 2)
return IsLeap(date) ? 29 : 28;
else if (date.Month == 1 || date.Month == 3 || date.Month == 5 || date.Month == 7 || date.Month == 8 || date.Month == 10 || date.Month == 12)
return 31;
return 30;
}
int DaysFromJan(Date date) {
int TotalDays = date.Day - 1;
for (int i = 0; i < date.Month - 1; i++)
TotalDays += MonthDaysCount(Date{ date.Year, i + 1, 1 });
return TotalDays;
}
long long DaysFrom1st(Date date) {
int FromJan = DaysFromJan(Date{ date.Year, date.Month, date.Day });
return (--date.Year) / 4 - date.Year / 100 + date.Year / 400 + date.Year * 365 + FromJan;
}
long long DatesDeltaDays(Date date1, Date date2) {
auto _1 = DaysFrom1st(date1) - DaysFrom1st(date2);
return _1;
}
int NextDateDayOfWeek(Date date1, Date date2, int dayOfWeek) {
int tmp = (dayOfWeek + DatesDeltaDays(date1, date2) % 7) % 7;
return tmp >= 1 ? tmp : 7 + tmp;
}
#pragma endregion
Date today = { 2021, 1, 22 };
string Months[]{ "Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь" };
string Days[]{ "ПН", "ВТ", "СР", "ЧТ", "ПТ", "СБ", "ВС" };
int main() {
setlocale(LC_ALL, "ru");
while (1) {
try {
system("cls");
int year = 0;
bool spaces = false;
char c;
cout << "Введите год для отображения календаря: ";
while (c = cin.get(), c != '\n') {
if (year == -1)
continue;
if (spaces) {
if (c == ' ')
continue;
else if (!year)
spaces = false;
else
year = -1;
}
else if (c == ' ') {
spaces = true;
continue;
}
if (c >= '0' && c <= '9')
year = year == 0 ? c - '0' : year * 10 + c - '0';
else
year = -1;
}
if (year <= 0)
throw exception("Неверный тип входных данных");
Date newDate = { year, 1, 1 };
int months[12][7][6] = { 0 };
int _1stIndex = NextDateDayOfWeek(newDate, today, 5) - 1;
for (int m = 0; m < 12; m++) {
int day = 1;
int week = 0;
for (int i = 0; i < 7 && day <= MonthDaysCount(Date{ year, m + 1, 1 }); i++) {
if (!week && i < _1stIndex)
continue;
months[m][i][week] = day++;
if (i == 6) {
week++;
i = -1;
}
}
if (m != 11)
_1stIndex = NextDateDayOfWeek(Date{ year, m + 2, 1 }, today, 5) - 1;
}
system("cls");
cout << "Календарь на " << year << " год\n\n";
for (int j = 0; j < 12; j++) {
cout << setw(26) << left << Months[j];
if (!((j + 1) % 4)) {
cout << "\n";
for (int i = 0; i < 7; i++) {
cout << setw(3) << left << Days[i];
for (int m = j / 4 * 4; m < j + 1; m++) {
for (int z = 0; z < 6; z++)
cout << setw(3) << left << (months[m][i][z] ? to_string(months[m][i][z]) : "");
if (m != j)
cout << setw(0) << left << " " << Days[i] + " ";
}
cout << "\n";
}
cout << "\n";
}
}
}
catch (exception ex) {
cout << "Ошибка во время выполнения программы: " << ex.what() << "\n\n";
goto end;
}
end:
system("pause");
continue;
}
}
Последнее редактирование: