Форум программистов, компьютерный форум CyberForum.ru

Как исправить функцию нормализации даты в программе "Календарь"? - C++

Восстановить пароль Регистрация
 
Dimsssss
0 / 0 / 0
Регистрация: 13.06.2013
Сообщений: 20
09.06.2014, 02:27     Как исправить функцию нормализации даты в программе "Календарь"? #1
Собственно, программа
C++ (Qt)
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
#include <iostream>
#include <conio.h>
#include <time.h>
#include <math.h>
using namespace std;
 
class Date { //Класс "Дата"
    int year; //Год
    int month; //Месяц
    int day; //День
public:
    Date(int year, int month, int day); //Конструктор даты с заданными значениями
    bool is_leap_year(); //Функция, которая возвращает true, если год високосный и false в ином случае
    int get_year(); //Возвращаем значение года
    int get_month(); //Возвращаем значение месяца
    int get_day(); //Возвращаем значение дня
    friend class Calendar; //Дружественный класс "Календарь"
};
 
class Calendar { //Класс "Календарь"
    Date * date; //Указатель на текущую дату в календаре
    int months_duration[12]; //Массив, содержащий длительности месяцев в високосном году
    void normalize_months(); //Функция, приводящая в порядок номер месяца
    void normalize();//Функция, приводящая в порядок всю дату
    void normalize_days(); //нормализация дней
    void fill_months_duration(); //Функция, которая заполняет массив months_duration
public:
    Calendar(); //Конструктор по умолчанию. По умолчанию выставляется текущая дата
    Calendar(int year, int month, int day); //Конструктор с конкретной датой
    ~Calendar(); //Деструктор
    void set_date(int year, int month, int day); //Функция, которая задаёт дате значения
    void print(); //Функция, которая выводит дату
    void print_week_day(); //Функция, которая выводит день недели
    void add_year(int adding_year); //Функция, которая добавляет определённое кол-во лет к дате
    void add_month(int adding_month); //Функция, которая добавляет определённое кол-во месяцев к дате
    void add_day(int adding_day); //Функция, которая добавляет определённое кол-во дней к дате
    Date get_date(); //Функция, которая возвращает дату как объект
    int abs(int val);
};
 
int main() {
 
    Calendar * calendar = new Calendar(2014, 5, 28); //Создаём объект класса календарь под указателем calendar
    //Выводим список действий
    cout << "1 - set date" << endl << "2 - get current date" << endl
        <<"3 - print date (\"year.month.day\")" << endl
        << "4 - print week day" << endl << "5 - add day"
        << endl << "6 - add month" << endl << "7 - add year" << endl
        << "8 - exit" << endl;
    int q = 0; //В переменной q будем хранить выбор пользователя
    while (q != 8) { //Пока q не равно 8. (8 сответствует выходу из программы)
        q = _getch() - 48; //Считываем q
        switch (q) { //Делаем действия соответственно значению q
        case 1: //Пользователь устанавливает дату в календаре
            cout << "year month day: ";
            int day, month, year;
            cin >> year >> month >> day;
            calendar->set_date(year, month, day);
            break;
        case 2: //Устанавливаем текущую системную дату
            //calendar->set_current_date();
            cout << "Current date: ";
        case 3: //Выводим календарь
            calendar->print();
            break;
        case 4: //Выводим день недели
            calendar->print_week_day();
            break;
        case 5: //Пользователь добавляет определённое кол-во дней к дате
            cout << "how many days do you want to add? ";
            int days;
            cin >> days;
            calendar->add_day(days);
            break;
        case 6: //Пользователь доавляет определённое кол-во месяцев к дате
            cout << "how many months do you want to add? ";
            int months;
            cin >> months;
            calendar->add_month(months);
            break;
        case 7: //Пользователь добавляет определённое кол-во лет к дате
            cout << "how many years do you want to add? ";
            int years;
            cin >> years;
            calendar->add_year(years);
            break;
        case 8: //Выходим из программы. (цикл не продолжится, если q == 8)
            break;
        default: //Если же q не сответствует ни одной из опций, то выводим сообщение об ошибке
            cout << "Wrong command! Try again." << endl;
            break;
        }
    }
    delete calendar; //Удаляем календарь
    return 0;
}
 
Date::Date(int year, int month, int day) {
    //Присваиваем дате переданные значения
    this->year = year;
    this->month = month;
    this->day = day;
}
 
bool Date::is_leap_year() {
    //2012 - високосный
    //Если остаток от деления года на 4 равен 0, то этот год високосный и возвращаем true. В ином случае false.
    if (((year % 4 == 0) && !(year % 100 == 0)) || (year % 400 == 0))
        return 1;
    else
        return 0;
}
 
int Date::get_year() {
    return year; //Возвращаем значение года
}
 
int Date::get_month() {
    return month; //Возвращаем значение месяца
}
 
int Date::get_day() {
    return day; //Возвращаем значение дня
}
 
void Calendar::fill_months_duration() {
    //Задаём массив, в котором будем хранить кол-во дней в месяцах в високосном году
    int months[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    //Копируем каждый элемент заданного массива в массив объекта календарь.
    for (int i = 0; i < 12; i++)
        months_duration[i] = months[i];
    //По другому с массивами никак не получается - компилятор ругается :(
}
 
Calendar::Calendar() {
    fill_months_duration(); //Заполняем массив months_duration
    //set_current_date(); //Устанавливаем текущую дату
}
 
Calendar::Calendar(int year, int month, int day) {
    fill_months_duration(); //Заполняем массив months_duration
    set_date(year, month, day); //Устанавливаем дату согласно переданным значениям
}
 
Calendar::~Calendar() {
    delete this->date; //Удаляем дату
}
 
 
 
void Calendar::set_date(int year, int month, int day) {
    //Если день больше нуля и не больше кол-ва дней в этом месяце и месяц нах-ся в промежутке от 1 до 12,
    //а также если это не 29 февраля невисокосного года
    if (day > 0 && day <= months_duration[month-1] && month > 0 && month < 13 && !(month == 2 && day == 29 && (((year % 4 == 0) && !(year % 100 == 0)) || (year % 400 == 0)) )) {
        delete this->date; //Удаляем дату
        this->date = new Date(year, month, day); //Создаём под указателем даты новую дату с заданной датой
    } else cout << "Error in date!" << endl; //Иначе пишем сообщение об ошибке
}
 
 
void Calendar::add_day(int adding_day) {
    date->day += adding_day; //Увеличиваем кол-во дней на введённое пользователем значение
    normalize(); //Приводим в порядок Дату
}
 
void Calendar::add_year(int adding_year) {
    date->year += adding_year; //Прибавляем к году введённое пользователем значение
    //Проверяем, не получилось ли у нас 29 февраля в невисокосном году
    if (date->month == 2 && date->day == 29 && !date->is_leap_year())
        //Если это так, то уменьшим кол-во дней на 1
            date->day--;
}
 
void Calendar::add_month(int adding_month) {
    date->month += adding_month; //Прибавляем к месяцу значение, которое ввёл пользователь
    normalize();  //Приводим в порядок Дату
}
 
void Calendar::print() {
    //Выводим дату в формате "Год.Месяц.День"
    cout << "\"" << date->year << "." << date->month << "." << date->day << "\"" << endl;
}
 
int Calendar::abs(int val) {
    return val < 0 ? -val : val;
}
 
void Calendar::print_week_day() {
    //2013-01-01 = Вторник - известная дата с днём недели
    int days_difference; //Переменная, в которую запишем разницу в днях от заданной даты до известной
 
    int years_difference = date->year - 2013; //Вычисляем разницу в годах между заданной и известной датой
    int leap_years_count = abs(years_difference / 4); //Вычисляем сколько в этом годовом промежутке високосных лет
    if (date->is_leap_year()) //Если же сама наша дата является високосным годом
        leap_years_count++; //Увеличиваем счётчик високосных лет на один
    //Если заданный год меньше известного и 2012 год остался неучтённым в качестве високосного
    if (years_difference < 0 && years_difference > -4 && date->year != 2012)
        leap_years_count++; //Увеличиваем счётчик високосных лет на один
    //Умножаем разницу в годах на кол-во дней в невисокосном году и записываем результат в переменную
    days_difference = years_difference * 365;
    if (days_difference >= 0) //Если разница в днях неотрицательна
        //Прибавляем к переменной кол-во високосных лет, по сути учитываем то, что в високосном году на 1 день больше
            days_difference += leap_years_count;
    //В ином случае наоборот вычитаем кол-во високосных лет
    else days_difference -= leap_years_count;
 
    //Учитываем разницу в месяцах.
    for (int i = 0; i < date->month - 1; ++i) {
        if (i == 1 && !date->is_leap_year()) //Если год невисокосный и i соответствует февралю
            days_difference += 28; //Увеличиваем переменную на 28
        //В ином случае увеличиваем переменную на соответствующее месяцу кол-во дней
        else days_difference += months_duration[i];
    }
 
    //Учитываем разницу в днях(день месяца)
    days_difference += date->day; //Прибавляем к переменной номер дня в месяце
    days_difference--; //Вычитаем 1, тк базовый день - первое число месяца
 
 
    //(days_difference + 1) и (days_difference - 5) потому что базовый день - вторник
    //По особым формулам, учитывающим, что разница в днях может быть как отрицательной, так и положительной,
    //а также то, что базовым днём является вторник, получаем в переменной число от 0 до 6, которое и покажет
    //нам день недели
    if (days_difference > 0)
        days_difference = (days_difference + 1) % 7;
    else days_difference = 6 + (days_difference - 5) % 7;
 
    //Каждой цифре от 0 до 6 соответствует день недели. Выводим соответствующий день недели.
    switch (days_difference) {
    case 0: cout << "Monday";
        break;
    case 1: cout << "Tuesday";
        break;
    case 2: cout << "Wednesday";
        break;
    case 3: cout << "Thursday";
        break;
    case 4: cout << "Friday";
        break;
    case 5: cout << "Saturday";
        break;
    case 6: cout << "Sunday";
        break;
        //Если переменная по каким-то причинам оказалась не в промежутке от 0 до 6, то
        //выведем это число и сообщение об ошибке :(.
    default: cout << "Error! days difference = " << days_difference;
        break;
    }
    cout << endl;
}
 
void Calendar::normalize_months() {
    if (date->month > 12 || date->month < 1) { //Если номер месяца больше 12 или меньше одного
        date->year += date->month / 12; //Прибавляем столько лет, сколько раз в месяцах укладывается по 12
        date->month %= 12; //Месяцам присваиваем значение, равное остатку от их деления на 12
        if (date->month < 1) { //Если месяц меньше одного
            date->year--; //Уменьшаем год на 1
            date->month += 12; //Прибавляем к месяцу 12
        }
    }
}
 
void Calendar::normalize_days() {
    int flag = 1; //  флаг: 1 - дней больше, чем дней в месяце; 2 - дней меньше, чем 0; 3 - нормас все
    if (flag == 1) {
    while (date->day > months_duration[date->month - 1]) {
        switch (date->month){
        case 2: if (date->is_leap_year()) {
            date->day -= 29;
            date->month = 3;
            }
            if (!(date->is_leap_year())) {
                date->day -= 28;
                date->month = 3;
            }
        case 12: date->day -= 31;
            date->year += 1;
            date->month = 1;
        default: date->day -= months_duration[date->month - 1];
            date->month++;
        }
    }
    if (date->day < 0) {
        flag = 2;
    }
    }
    if (flag == 2) {
        while (date->day <= 0) {
            switch (date->month){
            case 2: if (date->is_leap_year()) {
                date->day += 29;
                date->month = 1;
                }
                if (!(date->is_leap_year())) {
                    date->day += 28;
                    date->month = 1;
                }
            case 1: date->day += 31;
                date->year -= 1;
                date->month = 12;
            default: date->day -= months_duration[date->month - 1];
                date->month--;
            }
            if (date->day > 0) {
                if (date->day < months_duration[date->month - 1])
                flag = 3;
            }
        }
    }
    if (flag == 3)
        cout << endl;
}
 
void Calendar::normalize() {
    normalize_months(); //Вызываем функцию, которая приводит в порядок номер месяца
    normalize_days();
}
 
Date Calendar::get_date() {
    return * date; //Возвращаем разыменованную ссылку на дату
}
Хотелось бы получить помощь в реализации функции void Calendar::normalize_days(). Ее задача - если к дате были добавлены дни и их количество было больше, чем дней в годах, то привести дату в нормальный вид. В моей реализации она работает некорректно, но проблема в том, что она должна быть написана без циклов, желательно с применением конструкции switch-case. Форумчане, я очень рассчитываю на вашу помощь, и было бы здорово, если бы вы не оказались равнодушными.
По сабжу - у меня горит уже от этой проги
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.06.2014, 02:27     Как исправить функцию нормализации даты в программе "Календарь"?
Посмотрите здесь:

Исправить ошибку в строках "case 3:zadacha(Uch,Pr,Ocen);break;" и " return 0;" C++
C++ Исправить ошибки в программе "Hello, World"
C++ Как заменить функцию printf из "С" в "С++"?
C++ Исправить ошибку:error C2678: бинарный ">>": не найден оператор, принимающий левый операнд типа "std::istream"
C++ Написать функцию выбора пунктов меню стрелками "вверх" "вниз"
Как исправить ошибку: Неинициализированная переменная "а"? C++
Как исправить ошибку "error LNK1120: 1 неразрешенных внешних элементов"? C++
Как в этой программе правильно вывести матрицу? а то она у меня "пляшет" C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Ответ Создать тему
Опции темы

Текущее время: 03:14. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru