Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Доработать календарь, Не реагирует на нажатие стрелок  
:(
    Опции темы
zeitgeistz
Дата 3.5.2013, 16:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Awaiting Authorisation
Сообщений: 36
Регистрация: 23.4.2013

Репутация: нет
Всего: нет



Здравствуйте, ниже представленный код рисует календарь. Мне нужно, чтобы при нажатии клавиши влево - показывался предыдущий месяц, вправо - следующий. На kbhit не реагирует, что я делаю не так? Как это исправить?

Код

/*Задача программы - построить календарь на выбранный месяц выбранного года. 
Кроме месяца и года нам известно, что 1 января 2008 года был вторник и 2008-й год был високосным. 
Единственное, что нам нужно для построения календаря - знать, на какой день недели приходится 
первое число выбранного месяца выбранного года, а также число дней в месяце. 
Собственно, основная задача, возложенная на формулы - получить день недели. Для этого удобно использовать целочисленное деление на 7. 
DaysDist - переменная, в которой я собираюсь получить разницу в днях между 1 января 2008 года и 
1-м числом месяца, для которого я собираюсь строить календарь. Остаток от деления на 7 этой 
разницы и будет днём недели этого самого 1-го числа.
 
 
 
Про iMonth: пользователь вводит месяцы с 1 до 12, а индексация в массиве - с 0 до 11. 
Поэтому чтобы введенное пользователем число преобразовать в индекс массива я вычитаю из него 1
 
  
 
 В зависимости от того, прошлое это или будущее (т.е. DaysDist > 0 или меньше нуля)
  используются два варианта расчёта дня недели. либо это прошлое - DayOfMonth= 7 - (5-DaysDist)%7; либо это будущее - 
  DayOfMonth = (DaysDist+1)%7 + 1;
 
Например, 1 января 2008 года был вторник. значит 365 дней назад был 7 - ( 5 - (-365))%7 = 7 - (370)%7 = 7 - 6 = 1 (понедельник). 
 
Основная мысль календаря в том, что не нужно итеративно высчитывать день недели относительно какого-то там года.
 у нас есть число лет и число месяцев. зная это число лет и число месяцев мы можем в несколько операций умножения 
 и целочисленного деления получить день недели. а формулы могут меняться в зависимости от того, какой день мы берём 
 за отправную точку. я взял 1 января 2008 года, это был вторник (поэтому и формулы малость странные, т.к. 
 не с понедельника начинается отсчёт). 
 
 
*/
 
#include <iostream>
#include <conio.h>
#include <graphics.h>
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <Windows.h>
 
 
using namespace std;
 
int DaysPerMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // 31 день в январе, 28 в феврале, 31 в марте и т.д.
int DayForw[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; // 0 - начало года, 31 - конец января, 59 - февраля и т.д.
char cMonths[] = "Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec"; // имена месяцев по батюшке
int DaysPerYear = 365; // дней в году
 
int main()
{
    cout << "Enter the month & the year for calendar (mm yyyy): "; // просим ввести месяц и год...
    int iMonth, iYear;
    //int* Direction; 
    cin >> iMonth >> iYear; // записываем в iMonth месяц и в iYear год
    cout << endl;
    int iCorrect, DaysDist; /*DaysDist - переменная, в которой я собираюсь получить разницу в днях между 1 января 2008 года и 
1-м числом месяца, для которого я собираюсь строить календарь. Остаток от деления на 7 этой 
разницы и будет днём недели этого самого 1-го числа.*/
 
    DaysDist = (iYear - 2008);
    //Direction = &DayForw[0]; 
 
    iCorrect = (DaysDist)/4; // запоминаем количество високосных лет, для коррекции дней недели...
    if (DaysDist>0)
        iCorrect++;
    if ((DaysDist)%4 == 0) // если високосный год, то корректируем вспом. массивы...
    {
        if (DaysDist>0)
            iCorrect--;
        for (int i=2; i < 12; i++) // массив для коррекции по месяцу...
            DayForw[i]++;
        DaysPerMonth[1]++; // массив количеств дней в месяце...
    }
    
/*Например, 1 января 2008 года был вторник. значит 365 дней назад был 
7 - ( 5 - (-365))%7 = 7 - (370)%7 = 7 - 6 = 1 (понедельник). */
 
    DaysDist = DaysDist*365+iCorrect+DayForw[iMonth-1]; /* записываем в DaysDist разницу в годах, умножив на 365 получаем 
    разницу в днях. Каждые четыре года набегает один день. Если год меньше 2008-го, то день вычитается каждые четыре года. 
    Например, была разница в -4 года, поэтому -4 * 365 + ( -1 ) + 59 = 1402 дня разницы между 1-м января 2008 года и 
    1 марта 2004 года. iMonth -1, т.к. 12 месяцев от 0 до 11    */
    
    int DayOfMonth;
    if (DaysDist < 0) //Если года в отрицательную сторону от 2008
        DayOfMonth= 7 - (5-DaysDist)%7; // Пятёрка, т.к. вторник второй день недели, 7 - 2 = 5;
    else
        DayOfMonth = (DaysDist+1)%7 + 1; //Если больше 2008
    cout << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl << endl;
    cout << "\tMon\tTue\tWed\tThu\tFri\tSat\tSun" << endl << endl;
    for (int i=1; i<DayOfMonth; i++)
        cout << "\t";
    for (int i=0; i<DaysPerMonth[iMonth-1]; DayOfMonth++, i++)
    {
        cout << "\t" << i+1;
        if (DayOfMonth==7)
        {
            DayOfMonth=0;
            cout << endl << endl;
        }
    }
    cout << endl << endl << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl;
    cin >> iYear;
 
 
// НЕ РАБОТАЮЩИЙ КУСОК КОДА ПРЕДСТАВЛЕН НИЖЕ
 
/*
//if (kbhit()) 
while (!_kbhit());
{
  int key = getch(); 
  if (key == 0) key = getch(); 
  switch (key) 
{
         case KEY_RIGHT :
         {
           system("cls");
           iMonth+=1;
           
           cout << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl << endl;
           cout << "\tMon\tTue\tWed\tThu\tFri\tSat\tSun" << endl << endl;
            for (int i=1; i<DayOfMonth; i++)
                  cout << "\t";
            for (int i=0; i<DaysPerMonth[iMonth-1]; DayOfMonth++, i++)
             {
                cout << "\t" << i+1;
                if (DayOfMonth==7)
                {
                 DayOfMonth=0;
                  cout << endl << endl;
                }
             }
              cout << endl << endl << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl;
              cin >> iYear; 
             
         }break;
         
         case KEY_LEFT : 
         {
         system("cls");
                     iMonth-=1;
           cout << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl << endl;
           cout << "\tMon\tTue\tWed\tThu\tFri\tSat\tSun" << endl << endl;
            for (int i=1; i<DayOfMonth; i++)
                  cout << "\t";
            for (int i=0; i<DaysPerMonth[iMonth-1]; DayOfMonth++, i++)
             {
                cout << "\t" << i+1;
                if (DayOfMonth==7)
                {
                 DayOfMonth=0;
                  cout << endl << endl;
                }
             }
              cout << endl << endl << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl;
              cin >> iYear;     
         }break; 
} 
*/
 
 
    return 0;
}
}

PM   Вверх
feodorv
Дата 3.5.2013, 17:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Честно, не знаю, что за константы такие KEY_RIGHT и KEY_LEFT...

Цитата(zeitgeistz @  3.5.2013,  17:00 Найти цитируемый пост)
while (!_kbhit());

Зачем так извращаться? Пользуйтесь _getch()...
Код

while( (key = _getch()) != 27 )
{
  ...
}



Цитата(zeitgeistz @  3.5.2013,  17:00 Найти цитируемый пост)
 На kbhit не реагирует

Ну так у Вас там:
Цитата(zeitgeistz @  3.5.2013,  17:00 Найти цитируемый пост)
    cin >> iYear;

Сначала этот iYear введите, а уж потом к kbhit приступайте...


По поводу дня недели, можно посмотреть здесь...

Добавлено через 7 минут и 47 секунд
Да, когда iMonth++ или iMonth-- делаете, не забывайте проверять диапазон 1 <= iMonth <= 12 (изменяя год, если нужно)


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
zeitgeistz
Дата 3.5.2013, 19:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Awaiting Authorisation
Сообщений: 36
Регистрация: 23.4.2013

Репутация: нет
Всего: нет



Я не заметил, что пишу после 
Код

 cin >> iYear;
 smile

Перед ним написал

Код

if ((key = _getch() ==77) // 77 - стрелка вправо, 75 для стрелки влево

и всё это впихнул в бесконечный цикл
Код

int key;
do {
   /* что-нибудь делаем */
} while(1)

только не знаю как два if'a там примирить, если один if, то работает, если два if'а, то работает какой-то один. что я делаю не так?

Код

do{
if ((key = _getch() ==77)
{
 system("cls");
                     iMonth+=1;
           cout << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl << endl;
           cout << "\tMon\tTue\tWed\tThu\tFri\tSat\tSun" << endl << endl;
            for (int i=1; i<DayOfMonth; i++)
                  cout << "\t";
            for (int i=0; i<DaysPerMonth[iMonth-1]; DayOfMonth++, i++)
             {
                cout << "\t" << i+1;
                if (DayOfMonth==7)
                {
                 DayOfMonth=0;
                  cout << endl << endl;
                }
             }
              cout << endl << endl << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl;
}


else if ((key = _getch() ==75)
{
 system("cls");
                     iMonth-=1;
           cout << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl << endl;
           cout << "\tMon\tTue\tWed\tThu\tFri\tSat\tSun" << endl << endl;
            for (int i=1; i<DayOfMonth; i++)
                  cout << "\t";
            for (int i=0; i<DaysPerMonth[iMonth-1]; DayOfMonth++, i++)
             {
                cout << "\t" << i+1;
                if (DayOfMonth==7)
                {
                 DayOfMonth=0;
                  cout << endl << endl;
                }
             }
              cout << endl << endl << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl;
}
}while(1);

при таком раскладе: вводим 5 2013, рисуется май, если жмакаем стрелку влево - рисуется апрель, ещё раз влево - март, всё как и надо, но стрелка вправо просто так не работает: нужно нажать enter и потом стрелка вправо сработает, как миновать нажатия enter'а?

Это сообщение отредактировал(а) zeitgeistz - 3.5.2013, 20:01
PM   Вверх
feodorv
Дата 3.5.2013, 20:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(zeitgeistz @  3.5.2013,  20:27 Найти цитируемый пост)
do{
if ((key = _getch() ==77)
  ...
else if ((key = _getch() ==75)
  ...
}
{

Ну это не правильно же... На каждый if свой  _getch()??? Вот и приходится жать, чего не поподя...
Код

do
{
  key = _getch();
  if( key == 0 || key == 0xe0 ) key = _getch();

  if( key == 77 )
    ...
  else if( key == 75 )
    ...
  else if( key == 27 ) // Escape
    break;
}


Добавлено через 3 минуты и 22 секунды
Как насчет
Цитата(feodorv @  3.5.2013,  18:02 Найти цитируемый пост)
Да, когда iMonth++ или iMonth-- делаете, не забывайте проверять диапазон 1 <= iMonth <= 12 (изменяя год, если нужно) 

?


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
zeitgeistz
Дата 3.5.2013, 20:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Awaiting Authorisation
Сообщений: 36
Регистрация: 23.4.2013

Репутация: нет
Всего: нет



Да, Вы правы, теперь стрелки как положено заработали. Сейчас с годом помудрю и отпишусь минут через 15. Только я так и не понял, почему в том случае приходилось enter нажимать перед стрелкой, в чём дело было?
PM   Вверх
feodorv
Дата 3.5.2013, 21:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(zeitgeistz @  3.5.2013,  21:36 Найти цитируемый пост)
Только я так и не понял, почему в том случае приходилось enter нажимать перед стрелкой, в чём дело было? 

Трудно сказать с уверенностью, поскольку сами стрелки порождают последовательность { 0xe0, 75/77 }, да ещё и в каждый if было запихнуто по _getch()'у (то есть на каждый if нужно было ввести по своему символу)...


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
zeitgeistz
Дата 3.5.2013, 21:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Awaiting Authorisation
Сообщений: 36
Регистрация: 23.4.2013

Репутация: нет
Всего: нет



А что такое 0xe0?

Насчёт года, для стрелки влево дописал
Код

         if (iMonth < 0) 
           {
                      iYear-=1;
                      iMonth=12;
           }

для вправо наоборот.

Только для стрелки вправо немного неправильно написал, при переходе на след. год появляется промежуточное пустое окошко с заголовками дней недели, после ещё одной стрелки отрисовывается январь

Как от этого избавиться можно?

Код

#include <iostream>
#include <conio.h>
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>



using namespace std;

int DaysPerMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // 31 день в январе, 28 в феврале, 31 в марте и т.д.
int DayForw[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; // 0 - начало года, 31 - конец января, 59 - февраля и т.д.
char cMonths[] = "Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec"; // имена месяцев по батюшке
int DaysPerYear = 365; // дней в году

int main()
{
    cout << "Enter the month & the year for calendar (mm yyyy): "; // просим ввести месяц и год...
    int iMonth, iYear;
    //int* Direction; 
    cin >> iMonth >> iYear; // записываем в iMonth месяц и в iYear год
    cout << endl;
    int iCorrect, DaysDist; /*DaysDist - переменная, в которой я собираюсь получить разницу в днях между 1 января 2008 года и 
1-м числом месяца, для которого я собираюсь строить календарь. Остаток от деления на 7 этой 
разницы и будет днём недели этого самого 1-го числа.*/

    DaysDist = (iYear - 2008);
    //Direction = &DayForw[0]; 

    iCorrect = (DaysDist)/4; // запоминаем количество високосных лет, для коррекции дней недели...
    if (DaysDist>0)
        iCorrect++;
    if ((DaysDist)%4 == 0) // если високосный год, то корректируем вспом. массивы...
    {
        if (DaysDist>0)
            iCorrect--;
        for (int i=2; i < 12; i++) // массив для коррекции по месяцу...
            DayForw[i]++;
        DaysPerMonth[1]++; // массив количеств дней в месяце...
    }
    
/*Например, 1 января 2008 года был вторник. значит 365 дней назад был 
7 - ( 5 - (-365))%7 = 7 - (370)%7 = 7 - 6 = 1 (понедельник). */

    DaysDist = DaysDist*365+iCorrect+DayForw[iMonth-1]; /* записываем в DaysDist разницу в годах, умножив на 365 получаем 
    разницу в днях. Каждые четыре года набегает один день. Если год меньше 2008-го, то день вычитается каждые четыре года. 
    Например, была разница в -4 года, поэтому -4 * 365 + ( -1 ) + 59 = 1402 дня разницы между 1-м января 2008 года и 
    1 марта 2004 года. iMonth -1, т.к. 12 месяцев от 0 до 11    */
    
    int DayOfMonth;
    if (DaysDist < 0) //Если года в отрицательную сторону от 2008
        DayOfMonth= 7 - (5-DaysDist)%7; // Пятёрка, т.к. вторник второй день недели, 7 - 2 = 5;
    else
        DayOfMonth = (DaysDist+1)%7 + 1; //Если больше 2008
    cout << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl << endl;
    cout << "\tMon\tTue\tWed\tThu\tFri\tSat\tSun" << endl << endl;
    for (int i=1; i<DayOfMonth; i++)
        cout << "\t";
    for (int i=0; i<DaysPerMonth[iMonth-1]; DayOfMonth++, i++)
    {
        cout << "\t" << i+1;
        if (DayOfMonth==7)
        {
            DayOfMonth=0;
            cout << endl << endl;
        }
    }
    cout << endl << endl << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl;
 
 
 // ПЕРЕКЛЮЧЕНИЕ СТРЕЛКАМИ
 

    
 int key;
        
        do
{
      key = _getch();
      
      if ( key == 0 || key == 0xe0 ) key = _getch();
                 
            if (key == 77)
           {
           system("cls");
           iMonth+=1;
           if (iMonth > 12) 
           {
                      iYear+=1;
                      iMonth=0;
           }
           cout << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl << endl;
           cout << "\tMon\tTue\tWed\tThu\tFri\tSat\tSun" << endl << endl;
              for (int i=1; i<DayOfMonth; i++)
                  cout << "\t";
              for (int i=0; i<DaysPerMonth[iMonth-1]; DayOfMonth++, i++)
              {
                  cout << "\t" << i+1;
                  if (DayOfMonth==7)
                  {
                         DayOfMonth=0;
                         cout << endl << endl;
                  }
               }
           cout << endl << endl << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl;
              
}

           else if (key == 75)
{
           system("cls");
           iMonth-=1;
           if (iMonth <= 0) 
           {
                      iYear-=1;
                      iMonth=12;
           }
           cout << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl << endl;
           cout << "\tMon\tTue\tWed\tThu\tFri\tSat\tSun" << endl << endl;

            for (int i=1; i<DayOfMonth; i++)
                  cout << "\t";
            for (int i=0; i<DaysPerMonth[iMonth-1]; DayOfMonth++, i++)
             {
                  cout << "\t" << i+1;
                  if (DayOfMonth==7)
                  {
                         DayOfMonth=0;
                         cout << endl << endl;
                  }
             }
              cout << endl << endl << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl;
              
}

}while(1);
             


    cin >> iYear;
    return 0;
}


Это сообщение отредактировал(а) zeitgeistz - 3.5.2013, 21:20
PM   Вверх
feodorv
Дата 3.5.2013, 21:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(zeitgeistz @  3.5.2013,  22:07 Найти цитируемый пост)
         if (iMonth < -1) 

Цитата(zeitgeistz @  3.5.2013,  22:07 Найти цитируемый пост)
i<DaysPerMonth[iMonth-1]

Ну если уже значение 0 неприемлемо для iMonth, то почему if (iMonth < -1)???
Код

if( iMonth <= 0 ) ...


Посмотрел начало кода:
Цитата(zeitgeistz @  3.5.2013,  22:07 Найти цитируемый пост)
    if ((DaysDist)%4 == 0) // если високосный год, то корректируем вспом. массивы...
    {
        if (DaysDist>0)
            iCorrect--;
        for (int i=2; i < 12; i++) // массив для коррекции по месяцу...
            DayForw[i]++;
        DaysPerMonth[1]++; // массив количеств дней в месяце...
    }

Это в корне не верно, если Вы собираетесь показывать календарь и для другого года. У Вас должны быть два набора неизменяемых массивов - для невисокосного года и отдельно для високосного.
Соответственно, когда год меняется, нужно определить подходящий набор.

Потом. Високосность не определяется простым делением на 4 (например, 1900 год не был високосным), правило сложнее


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
zeitgeistz
Дата 3.5.2013, 21:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Awaiting Authorisation
Сообщений: 36
Регистрация: 23.4.2013

Репутация: нет
Всего: нет



Там для стрелки влево я ещё до Вашего ответа отредактировал, вправо стрелка не так работает, давайте с этим разберёмся, а потом за високосный возьмёмся
PM   Вверх
zeitgeistz
Дата 3.5.2013, 22:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Awaiting Authorisation
Сообщений: 36
Регистрация: 23.4.2013

Репутация: нет
Всего: нет



Ну чевой там, есть идеи?
PM   Вверх
feodorv
Дата 3.5.2013, 22:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Ну совершенно аналогично:
Цитата(zeitgeistz @  3.5.2013,  22:07 Найти цитируемый пост)
                      iMonth=0;

Почему 0? Ведь месяцы начинаем отсчитывать от 1...

Добавлено через 35 секунд
Цитата(zeitgeistz @  3.5.2013,  23:02 Найти цитируемый пост)
Ну чевой там, есть идеи? 

Да, лечь спать)))


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
zeitgeistz
Дата 3.5.2013, 22:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Awaiting Authorisation
Сообщений: 36
Регистрация: 23.4.2013

Репутация: нет
Всего: нет



Ай спасибо большое! Заработало как надо!
Рано ещё спать, високосные криво работают smile Попробовал правильную формулу адаптировать сюда

Код

#include <iostream>
#include <conio.h>
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>


using namespace std;

int DaysPerMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int DayForw[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; 
int DayPerMonthLeap[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 
int DayForwLeap[] = {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335};
char cMonths[] = "Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec"; 
int DaysPerYear = 365; 
int* DaysPerMonthUniversal = DaysPerMonth;
int* DayForwUniversal =  DayForw;


int main()
{
    cout << "Enter the month & the year for calendar (mm yyyy): "; 
    int iMonth, iYear;

    cin >> iMonth >> iYear; 
    if (iMonth > 12)
    {
               do{
               system ("cls");
               cout << "Month incorrect! \n\nEnter the month & the year for calendar (mm yyyy): ";
               cin >> iMonth >> iYear;
               }while(iMonth > 12 || iMonth == 0 || iMonth <1) ;
    }
    else cout << endl;
    
    int iCorrect, DaysDist; 
    DaysDist = (iYear - 2008);

    iCorrect = (DaysDist)/4; 
    if (DaysDist>0)
        iCorrect++;
    if    ((((DaysDist)  % 4)  == 0)  &&    (((DaysDist)  % 100)  != 0)  ||   (((DaysDist)  % 400)  == 0)) 
    {
        if (DaysDist>0)
            iCorrect--;
        DaysPerMonthUniversal = DayPerMonthLeap;
        DayForwUniversal =  DayForwLeap;
    }


    DaysDist = DaysDist*365+iCorrect+DayForw[iMonth-1]; 
    
    
    int DayOfMonth;
    if (DaysDist < 0) 
        DayOfMonth= 7 - (5-DaysDist)%7; 
    else
        DayOfMonth = (DaysDist+1)%7 + 1; 
    cout << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl << endl;
    cout << "\tMon\tTue\tWed\tThu\tFri\tSat\tSun" << endl << endl;
    for (int i=1; i<DayOfMonth; i++)
        cout << "\t";
    for (int i=0; i<DaysPerMonthUniversal[iMonth-1]; DayOfMonth++, i++)
    {
        cout << "\t" << i+1;
        if (DayOfMonth==7)
        {
            DayOfMonth=0;
            cout << endl << endl;
        }
    }
    cout << endl << endl << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl;
 
 

 

    
 int key;
        
        do
{
      key = _getch();
      
      if ( key == 0 || key == 0xe0 ) key = _getch();
                 
            if (key == 77) // Right
           {
           system("cls");
           iMonth+=1;
           if (iMonth > 12) 
           {
                      iYear+=1;
                      iMonth=1;
           }
           cout << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl << endl;
           cout << "\tMon\tTue\tWed\tThu\tFri\tSat\tSun" << endl << endl;
              for (int i=1; i<DayOfMonth; i++)
                  cout << "\t";
              for (int i=0; i<DaysPerMonthUniversal[iMonth-1]; DayOfMonth++, i++)
              {
                  cout << "\t" << i+1;
                  if (DayOfMonth==7)
                  {
                         DayOfMonth=0;
                         cout << endl << endl;
                  }
               }
           cout << endl << endl << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl;
              
}

           else if (key == 75) // Left
{
           system("cls");
           iMonth-=1;

           DaysDist = (iYear - 2008);

    iCorrect = (DaysDist)/4; 
    if (DaysDist>0)
        iCorrect++;
    if ((((DaysDist)  % 4)  == 0)  &&    (((DaysDist)  % 100)  != 0)  ||   (((DaysDist)  % 400)  == 0))
    {
        if (DaysDist>0)
            iCorrect--;
        DaysPerMonthUniversal = DayPerMonthLeap;
        DayForwUniversal =  DayForwLeap;
    }


    DaysDist = DaysDist*365+iCorrect+DayForw[iMonth-1]; 
    }

    DaysDist = DaysDist*365+iCorrect+DayForw[iMonth-1];
           if (DaysDist < 0) 
                     DayOfMonth= 7 - (5-DaysDist)%7; 
           else
                     DayOfMonth = (DaysDist+1)%7 +1;
       
           if (iMonth <= 0) 
           {
                      iYear-=1;
                      iMonth=12;
           }
           cout << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl << endl;
           cout << "\tMon\tTue\tWed\tThu\tFri\tSat\tSun" << endl << endl;

            for (int i=1; i<DayOfMonth; i++)
                  cout << "\t";
            for (int i=0; i<DaysPerMonthUniversal[iMonth-1]; DayOfMonth++, i++)
             {
                  cout << "\t" << i+1;
                  if (DayOfMonth==7)
                  {
                         DayOfMonth=0;
                         cout << endl << endl;
                  }
             }
              cout << endl << endl << "\t    ************ " << cMonths+(iMonth-1)*4 << " " << iYear << " ************" << endl;

}while(1);
             


    cin >> iYear;
    return 0;
}
Откомпилируйте у себя, что тут не так, что исправить? Помогите, пожалуйста

Это сообщение отредактировал(а) zeitgeistz - 4.5.2013, 14:00
PM   Вверх
zeitgeistz
Дата 4.5.2013, 12:23 (ссылка) |   (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Awaiting Authorisation
Сообщений: 36
Регистрация: 23.4.2013

Репутация: нет
Всего: нет



up
PM   Вверх
feodorv
Дата 4.5.2013, 14:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Гм. Я бы поправил всё)))) Первым делом - оформление кода. Вторым - ввёл бы подпрограмму отрисовки месяца календаря:
Код

void showMonth( int month, int year)
{
  int weekDay = dayOfWeek( month, year);
  int dayMax = isLeapYear(year) ? DayPerMonthLeap[month-1] : DaysPerMonth[month-1];
  int day;

  system( "cls" );
  cout << "\t    ************ " << &cMonths[(month-1)*4] << " " << year << " ************" << endl << endl;
  cout << "\tMon\tTue\tWed\tThu\tFri\tSat\tSun" << endl << endl;

  for( day = 1; day < weekDay; day++) cout << "\t";

  for( day = 0; day < dayMax; weekDay++, day++)
  {
      cout << "\t" << day+1;
      if( weekDay == 7 )
      {
          weekDay = 0;
          cout << endl << endl;
      }
  }

  cout << endl << endl << "\t    ************ " << &cMonths[(month-1)*4] << " " << year << " ************" << endl;
}

Тогда программа значительно упроститься и приобретёт более благородный вид. Например:
Код

  do
  {
     int key = _getch();
     if( key == 0 || key == 0xe0 ) key = _getch();
                 
     if( key == 77 )
     {
        if( ++month > 12 )
        {
           month = 1;
           ++year;
        }
        showMonth( month, year);
     }
     else if( key == 75 )
     {
        if( month == 1 )
        {
           if( year > 1 )
           {
              month = 12;
              --year;
           }
        }
        else
           --month;
        showMonth( month, year);
     }
     else if( key == '\r' )
     {
        enterYearMonth( &month, &year);
        showMonth( month, year);
     }
     else if( key == 27 )
        break;
  } while(1);


В-третих, я бы поправил определение дня недели у текущего месяца - оно делается неверно: два смежных месяца не стыкуются друг с другом по дням недели. То есть написал бы dayOfWeek для произвольного месяца-года.

В-четвёртых, я бы сразу показывал бы текущий месяц, а ввод произвольного месяца-года убрал бы внутрь цикла.

Править текущий код я не могу - ничего в нём не понимаю)))

Это сообщение отредактировал(а) feodorv - 4.5.2013, 14:38


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
zeitgeistz
Дата 4.5.2013, 14:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Awaiting Authorisation
Сообщений: 36
Регистрация: 23.4.2013

Репутация: нет
Всего: нет



А как isLeapYear будет выглядеть?
PM   Вверх
feodorv
Дата 4.5.2013, 15:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Так, например:
Код

inline int isLeapYear( int year )
{
  return ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) ? 1 : 0;
}


Добавлено через 1 минуту и 25 секунд
Или так...


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
feodorv
Дата 4.5.2013, 19:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Смотрю, энтузиазм угас)))

Вот моё видение программы:
Код

#include <iostream>
#include <windows.h>
#include <conio.h>

using namespace std;

const int DaysPerMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
const int DayForw[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
const int DayPerMonthLeap[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
const int DayForwLeap[] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
const char cMonths[] = "Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec";

inline int isLeapYear( int year )
{
  return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0);
}

int dayOfWeek( int month, int year)
{
  int weekDay = year - 1 + (isLeapYear(year) ? DayForwLeap[month-1] : DayForw[month-1]);
  --year;
  weekDay += year / 4 - year / 100 + year / 400;
  return weekDay % 7 + 1;
}

void showMonth( int month, int year)
{
  int weekDay = dayOfWeek( month, year);
  int dayMax = isLeapYear(year) ? DayPerMonthLeap[month-1] : DaysPerMonth[month-1];
  int day;

  system( "cls" );
  cout << "\t    ************ " << &cMonths[(month-1)*4] << " " << year << " ************" << endl << endl;
  cout << "\tMon\tTue\tWed\tThu\tFri\tSat\tSun" << endl << endl;

  for( day = 1; day < weekDay; day++) cout << "\t";

  for( day = 0; day < dayMax; weekDay++, day++)
  {
    cout << "\t" << day+1;
    if( weekDay == 7 )
    {
      weekDay = 0;
      cout << endl << endl;
    }
  }

  cout << endl << endl << "\t    ************ " << &cMonths[(month-1)*4] << " " << year << " ************" << endl;
}

void getCurrentMonth( int& month, int& year)
{
  SYSTEMTIME lt;

  GetLocalTime( &lt );

  month = lt.wMonth;
  year = lt.wYear;
}

void enterYearMonth( int& month, int& year)
{
  for( ;; )
  {
    cout << endl << "Please, enter the month & the year for calendar (mm yyyy): ";
    cin >> month >> year;
    if( cin.fail() )
    {
      cout << "Invalid input!\n\n";
      cin.clear();
      cin.sync();
    }
    else if( month > 12 || month < 1 )
      cout << "Month is incorrect!\n\n";
    else if( year <= 0 )
      cout << "Year is incorrect!\n\n";
    else
      return;
  }
}

int main( void )
{
  int month, year;

  getCurrentMonth( month, year);
  showMonth( month, year);

  for( ;; )
  {
    int key = _getch();
    if( key == 0 || key == 0xe0 ) key = _getch();

    if( key == 77 )
    {
      if( ++month > 12 )
      {
         month = 1;
         ++year;
      }
      showMonth( month, year);
    }
    else if( key == 75 )
    {
      if( month == 1 )
      {
         if( year > 1 )
         {
            month = 12;
            --year;
         }
      }
      else
         --month;
      showMonth( month, year);
    }
    else if( key == 81 )
    {
      if( year > 0 ) --year;
      showMonth( month, year);
    }
    else if( key == 73 )
    {
      if( ++year <= 0 ) year = 1;
      showMonth( month, year);
    }
    else if( key == '\r' )
    {
      enterYearMonth( month, year);
      showMonth( month, year);
    }
    else if( key == 27 )
      break;
  }

  return 0;
}


Можно сходить к вечному календарю, провериться...

Это сообщение отредактировал(а) feodorv - 4.5.2013, 23:56


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
zeitgeistz
Дата 4.5.2013, 22:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Awaiting Authorisation
Сообщений: 36
Регистрация: 23.4.2013

Репутация: нет
Всего: нет



Не угас smile Решил отвлечься просто, погулял.

Я не сильно долго сиплюсплюсю, поясните пожалуйста, что за штуки такие

в 
Код

inline int isLeapYear( int year )
{
  return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0);
}

 что inline слово выполняет, для чего оно и почему без него нельзя?


вот это ещё
Код

for( ;; )


Я повыше уже спрашивал, Вы, наверно, не заметили, что такое 0xe0?


PM   Вверх
feodorv
Дата 4.5.2013, 22:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(zeitgeistz @  4.5.2013,  23:04 Найти цитируемый пост)
что inline слово выполняет, для чего оно и почему без него нельзя?

С этим ключевым словом подпрограмма встраивается в код в месте вызова (то есть сколько вызовов, столько раз возникает код данной подпрограммы). Замена #define'а в С (хотя в C тоже можно инлайнить). Без инлайна можно, сильно хуже не будет. Не нравится это ключевое слово - удаляйте...


Цитата(zeitgeistz @  4.5.2013,  23:04 Найти цитируемый пост)
вот это ещё

Это бесконечный цикл, аналог while(1){ } или Вашего do{ }while(1); Выглядит попроще, вот и предпочитаю его...
Цитата

      Синтаксис:     for([начальное-выражение];   
                         [условное-выражение];   
                         [выражение-цикла]) ...

Здесь все внутренние выражения можно опустить, остаются одни точки с запятыми, вот и получается for(;;){ }


Цитата(zeitgeistz @  4.5.2013,  23:04 Найти цитируемый пост)
Я повыше уже спрашивал, Вы, наверно, не заметили, что такое 0xe0?

Это Вы у Microsoft спросите, не меня:
Цитата

The _getch and_getwch functions read a single character from the console without echoing the character. None of these functions can be used to read CTRL+C. When reading a function key or an arrow key, each function must be called twice; the first call returns 0 or 0xE0, and the second call returns the actual key code.

Взято отсюда. Согласно этому описанию и проводится проверка на 0xe0...


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
zeitgeistz
Дата 4.5.2013, 22:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Awaiting Authorisation
Сообщений: 36
Регистрация: 23.4.2013

Репутация: нет
Всего: нет



А можете подробнее рассказать о формулах в dayOfWeek? Тяжело понимается, особенно первая строка внутри скобок

Код

int dayOfWeek( int month, int year)
{
  int weekDay = 6 + year + (isLeapYear(year) ? DayForwLeap[month-1] : DayForw[month-1]);
  --year;
  weekDay += year / 4 - year / 100 + year / 400;
  return weekDay % 7 + 1;
}

PM   Вверх
feodorv
Дата 4.5.2013, 23:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(zeitgeistz @  4.5.2013,  23:56 Найти цитируемый пост)
особенно первая строка внутри скобок

Распишите подробнее:
Код

const int* DayForwUniversal =  DayForw;
if( isLeapYear(year) ) DayForwUniversal = DayForwLeap;
int weekDay = 6 + year + DayForwUniversal[month-1];
...


Что за формула?
Вычисляется число дней, прошедших с 1 января 1-го года нашей эры по 1-е число интересующего нас месяца, при том что известно, что 01.01.0001 - это понедельник (сходите в тот же "вечный календарь").
Чему равно число таких дней? Если бы не было поправок на високосность, то просто (year-1)*365 + (число дней от начала года до начала месяца). 
Потом мы всё равно будем делать %7 (это если, как следует порядочным программистам C/C++, отсчитывать от нуля: 0-понедельник, 1-вторник, ..., 6-воскресенье). Поскольку 365 % 7 = 1, то формула упрощается до безобразия: year-1+yDay (здесь yDay - то самое число дней от начала года до начала интересующего нас месяца, то есть DayForwUniversal[month-1]). (У меня, кстати, неправильно написано year+6 smile ) 
Осталось учесть високосность. Високосным год признаётся, если он без остатка делится на 4, за исключением особых лет, которые делятся на 100, но не делятся на 400 (без остатка). То есть, например, 1600 и 2000 - високосные года, а 1700, 1800, 1900 - не високосные. Сколько же дополнительных високосных дней, случившихся за период с 01.01.0001 по начало текущего года, нужно учесть? Во-первых, високосность текущего года уже учтена, когда определялась переменная DayForwUniversal, следовательно номер текущего года нужно сократить на 1 (например, чтобы для какого-либо месяца 2012 года не учитывать ещё раз високосность этого 2012 года):
Цитата(feodorv @  4.5.2013,  20:58 Найти цитируемый пост)
  --year;

И уже потом добавим число лет, делящихся на 4 без остатка:
Цитата(feodorv @  4.5.2013,  20:58 Найти цитируемый пост)
  weekDay += year / 4

Но из этого числа нужно вычесть года, чьи последние две цифры - нули:
Цитата(feodorv @  4.5.2013,  20:58 Найти цитируемый пост)
  weekDay += year / 4 - year / 100

Однако, делящиеся на 400 нужно оставить, получается полная формула:
Цитата(feodorv @  4.5.2013,  20:58 Найти цитируемый пост)
  weekDay += year / 4 - year / 100 + year / 400;


Ну а потом определяем день недели путём %7 (это в измерении 0-понедельник, 1-вторник, ..., 6-воскресенье). Чтобы перевести это в измерение 1-понедельник, 2-вторник, ..., 7-воскресенье (как у Вас), нужно добавить единицу:
Цитата(feodorv @  4.5.2013,  20:58 Найти цитируемый пост)
  return weekDay % 7 + 1;

Получаем день недели 1-го числа интересующего нас месяца интересующего нас года (из расчёта 1-понедельник, 2-вторник, ..., 7-воскресенье)
Добавлять к weekDay значение понедельника (то есть 0) не обязательно)))


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
zeitgeistz
Дата 5.5.2013, 00:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Awaiting Authorisation
Сообщений: 36
Регистрация: 23.4.2013

Репутация: нет
Всего: нет



Потрясающе, спасибо большое, как прозрел)

А возможно ли как-то реализовать выделение другим цветом праздничных дней?
PM   Вверх
feodorv
Дата 5.5.2013, 11:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(zeitgeistz @  5.5.2013,  01:19 Найти цитируемый пост)
А возможно ли как-то реализовать выделение другим цветом праздничных дней? 

Можно, через SetConsoleTextAttribute, но зачем? Тогда придётся придётся и праздничные дни выделять красным, а в России праздники непостоянны...


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
zeitgeistz
Дата 5.5.2013, 13:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Awaiting Authorisation
Сообщений: 36
Регистрация: 23.4.2013

Репутация: нет
Всего: нет



Ладно, закончим на этом, спасибо большое за помощь smile
PM   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0762 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.