Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > вычисление дня недели


Автор: magadan87 9.11.2007, 14:26
Вот такая интересная проблема появилась, нужно сделать что-то навроде календаря.

Допустим нам известная сегодняшняя дата
magadan@home:~$ date
Чтв Ноя  8 16:53:10 NOVT 2007


от этой(ну или любой другой "сегодняшней") даты мы будем отталкиваться..
задача: зная сегодняшню дату определить название дня недели (понедельник, вторник, etc) только по введёным пользователем данным
 
число --> 08
месяц --> 11
год --> 2689(или 1978) 


я так понимаю надо будет использовать http://www.one-gog.ru/learn/pschool/books/kr/b.html#b10?

Есть так же практически таже самая программа на http://www.codenet.ru/progr/alg/Leap-Year.php.
(пробовал p2c("Output from p2c 1.21alpha-07.Dec.93, the Pascal-to-C translator" (с) p2c), но чушь какая-то получается...)

Есть и алгоритм(с википедии взят):

a = (14 − месяц) / 12
y = год − a
m = месяц + 12 * a − 2
ДеньНедели = (7000 + (день + y + y / 4 − y / 100 + y / 400 + (31 * m) / 12)) ОСТАТОК 7


Как бы теперь всё это "оформить" на сях...
(ЯП: С , не С++ )

что-то ничего в голову не приходит, кроме как 
Код


#include <stdio.h>
#include <time.h>

main()
{
  time_t t = time(NULL);
  char *s  = ctime(&t);
  printf("%s", s);
}


Автор: MAKCim 9.11.2007, 15:03
Код

int get_week_day(int year, int month, int day) {
    struct tm tm;
    memset(&tm, 0, sizeof(tm));
    tm.tm_year = year - 1900;
    tm.tm_mon = month;
    tm.tm_mday = day;
    time_t date = mktime(&tm);
    struct tm * result = gmtime(&date);
    return result -> tm_wday;

Автор: magadan87 9.11.2007, 16:03
Цитата(MAKCim @ 9.11.2007,  15:03)
Код

int get_week_day(int year, int month, int day) {
    struct tm tm;
    memset(&tm, 0, sizeof(tm));
    tm.tm_year = year - 1900;
    tm.tm_mon = month;
    tm.tm_mday = day;
    time_t date = mktime(&tm);
    struct tm * result = gmtime(&date);
    return result -> tm_wday;


Эм... если честно мало что понятно -_-'

сделал просто, без затей...
(правда пришлось заменить "get_week_day" на просто "main", т.к. компилятор начинал жутко ругаться
$ gcc time.c -o time
time.c: В функции 'get_week_day'
time.c:7: предупреждение: incompatible implicit declaration of built-in function 'memset'
time.c:14:2: warning: no newline at end of file
/usr/lib/gcc/i486-slackware-linux/4.1.2/../../../crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
collect2: выполнение ld завершилось с кодом возврата 1




Код

#include <stdio.h>
#include <time.h>

int main(int year, int month, int day)
{
    struct tm tm;
    memset(&tm, 0, sizeof(tm)); //?
    tm.tm_year = year - 1900;
    tm.tm_mon = month;
    tm.tm_mday = day;
    time_t date = mktime(&tm);
    struct tm * result = gmtime(&date); //?
    return result -> tm_wday;
}


можно слегка прокоментировать?

Автор: Fin 9.11.2007, 16:32
Код

int main(int year, int month, int day)

Можно спросить, а где описана такая структура функции main?

Добавлено @ 16:39
Это я творил когда то календарик на JavaScript
Код

      function IsLeap(year)
      {
         if ((year % 4 !=0) || ((year % 100 == 0) && (year % 400 != 0))) return false;
         else return true;
      }
      
      function MaxDay(month, year)
      {
         var days = [31,28,31,30,31,30,31,31,30,31,30,31];
         var res=0;
         if ((month>=1) && (month <=12)) 
         {
            res=days[month-1];
            if ((month == 2) && IsLeap(year)) res++;
         }
         return res;
      }
      
      function CalculateFirstDay(month, year)
      {
         var days =     [31, 28, 31, 30,  31,  30,  31,  31,  30,  31,  30,  31];
         var daycount = [ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
         var pref= Math.abs(year % 400);

         // Count of day for First of January
         var countDay=5+pref*365;
         for (var i=0; i<pref; i++)
         {
            if (IsLeap(i)) countDay++;
         }
         countDay+=daycount[month-1];
         if (IsLeap(year) && (month >2) ) countDay++;
         var res = countDay % 7;
         return res;
      }

CalculateFirstDay Вычисляеет, на какой день недели апмзодится первый день месяца. Вычисления происходят относительно Григорианского стиля.

Автор: magadan87 9.11.2007, 17:12
Цитата(Fin @  9.11.2007,  16:32 Найти цитируемый пост)
Можно спросить, а где описана такая структура функции main?

Хм. Не знаю. )
Работает же. ^^ По крайней мере компилируется точно. )

За календарик на JavaScript спасибо, поковыряю. ^^

P.S. извиняюсь если что, просто C изучаю методом тыка, параллельно читая  хрестоматию по программированию на Си в Unix Андрея Богатырёва. )

Автор: Fin 9.11.2007, 17:48
Ну вообше то тебя компилятор поздравил
Цитата

/usr/lib/gcc/i486-slackware-linux/4.1.2/../../../crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'

Так что, как оно у тебя компилирется, я не знаю.

Автор: magadan87 9.11.2007, 18:12
Цитата(Fin @  9.11.2007,  17:48 Найти цитируемый пост)
Так что, как оно у тебя компилирется, я не знаю.

Цитата(magadan87 @  9.11.2007,  16:03 Найти цитируемый пост)
(правда пришлось заменить "get_week_day" на просто "main", т.к. компилятор начинал жутко ругаться


Он ругался на get_week_day. Когда увидел "undefined reference to `main'" решил заменить get_week_day на main и каким-то образом всё заработало. Мистика. )
логики в этих действиях мало.. но тем не менее, работает же. )

вот всё что выдаёт компилятор после замены
$ gcc time.c -o tame
time.c: В функции 'main'
time.c:7: предупреждение: incompatible implicit declaration of built-in function 'memset'
time.c:14:2: warning: no newline at end of file


Автор: MAKCim 9.11.2007, 21:02
magadan87, 
Код

#include <time.h>
#include <string.h>
#include <stdio.h>

int get_week_day(int year, int month, int day) {
    struct tm tm;
    memset(&tm, 0, sizeof(tm));
    tm.tm_year = year - 1900;
    tm.tm_mon = month - 1;
    tm.tm_mday = day;
    time_t date = mktime(&tm);
    struct tm * result = gmtime(&date);
    return result -> tm_wday;
}

int main() {
    printf("day = %d", get_week_day(2007, 11, 9));
    return 0;
}

Автор: magadan87 10.11.2007, 18:27
Цитата(MAKCim @ 9.11.2007,  21:02)
magadan87, 
Код

#include <time.h>
#include <string.h>
#include <stdio.h>

int get_week_day(int year, int month, int day) {
    struct tm tm;
    memset(&tm, 0, sizeof(tm));
    tm.tm_year = year - 1900;
    tm.tm_mon = month - 1; // зачем?
    tm.tm_mday = day;
    time_t date = mktime(&tm);
    struct tm * result = gmtime(&date);
    return result -> tm_wday;
}

int main() {
    printf("day = %d", get_week_day(2007, 11, 9));
    return 0;
}

спасибо, кой с чем уже разобрался и появился ещё один вопрос...


magadan@home:day$ gcc day.c -o day
magadan@home:day$ ./day
day = 5


(это при get_week_day(2007, 11, 10))

вроде бы должно было быть day = 6 (суббота), т.к.

tm_wday  день недели   0..6  (0 - Воскресенье)

а если дату изменяю "get_week_day(2980, 11, 10)" то выдаёт "day = 3", что то же неверно (если верить col'у)
можно конечно сделать     tm.tm_mday = day + 1; но это неправильно же будет? )

Автор: MAKCim 10.11.2007, 19:11
magadan87, 
Цитата

       tm_mday
              The day of the month, in the range 1 to 31.

       tm_mon The number of months since January, in the range 0 to 11.

       tm_year
              The number of years since 1900.

       tm_wday
              The number of days since Sunday, in the range 0 to 6.

       tm_yday
              The number of days since January 1, in the range 0 to 365.


0 - понедельник
6 - воскресенье
аналогично
0 - январь
11 - декабрь
поэтому
month - 1

Автор: magadan87 10.11.2007, 20:05
Цитата(MAKCim @  10.11.2007,  19:11 Найти цитируемый пост)
0 - понедельник
6 - воскресенье
аналогично
0 - январь
11 - декабрь
поэтому
month - 1 

Спасибо, вопросов больше не имею. )

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)