当前时区为 UTC + 8 小时



发表新帖 回复这个主题  [ 14 篇帖子 ] 
作者 内容
1 楼 
 文章标题 : 一个农历软件,求测试。
帖子发表于 : 2013-09-07 18:27 
头像

注册: 2008-08-13 8:48
帖子: 26407
地址: 东海硇州,一双管钥。
系统: Fundu i64
送出感谢: 50
接收感谢: 344
最近在一个网站找的一个查农历的代码,听作者介绍说信息是来自香港天文台的。
代码:
//table.h
#define YEAR_SRT 1901
#define YEAR_NUM 200
#define THIS_YEAR(x) Year_Info[x - YEAR_SRT]

static long Year_Info[YEAR_NUM] = {
/*
   YEAR:LC:ZY:ZYDAY:L:LEAP:MONTHS
   1901:01:10:10011:0:0000:010010101111
   年   立 春 春    闰闰无 十非的
   份   春 节 节    月月则 二闰大
             日 阳 阳    大月为 个月小
             偏 历 历    小份零
             移 月 日
             量 份 期
*/
0x1A604AF, 0x2900A57, 0x27A554D, 0x2A00D27, 0x1880D95, //1901-1905
0x2734655, 0x29A056B, 0x28409AD, 0x16C255D, 0x29404AF, //1906-1910
0x27C6A5B, 0x2A40A4D, 0x18C0D25, 0x1755D25, 0x29C0B55, //1911-1915
0x2860D6A, 0x16E2ADA, 0x196095B, 0x2837497, 0x2A80497, //1916-1920
0x1900A4B, 0x1785B4B, 0x2A006A5, 0x28A06D5, 0x1714AB5, //1921-1925
0x19A02B7, 0x2840957, 0x26E252F, 0x1940497, 0x17C6656, //1926-1930
0x2A20D4A, 0x28C0EA5, 0x17556A9, 0x19C05AD, 0x28802B7, //1931-1935
0x271386E, 0x196092E, 0x17F7C8D, 0x2A60C95, 0x2900D4B, //1936-1940
0x1776D8A, 0x19E0B55, 0x28A056B, 0x2734A5B, 0x19A025D, //1941-1945
0x184092D, 0x16C2D2B, 0x2940A95, 0x17A7B55, 0x1A206CB, //1946-1950
0x18C0B55, 0x2775535, 0x19C04DB, 0x1860A5B, 0x1713457, //1951-1955
0x298052B, 0x17E8A9B, 0x1A40E95, 0x19006AB, 0x2786AEA, //1956-1960
0x19E0AB5, 0x18A04B7, 0x1724AAE, 0x29A0A57, 0x1840527, //1961-1965
0x16A3F26, 0x1920D95, 0x27C75B5, 0x1A2056B, 0x18C096D, //1966-1970
0x17654DD, 0x29E04AD, 0x1860A4D, 0x16E4D4D, 0x1960D25, //1971-1975
0x27E8D55, 0x1A40B55, 0x18E0B6A, 0x179695A, 0x2A0095B, //1976-1980
0x18A049B, 0x1724A97, 0x19A0A4B, 0x184AB27, 0x1A806A5, //1981-1985
0x19206D5, 0x17A6AF4, 0x1A20AB6, 0x18C0957, 0x17654AF, //1986-1990
0x19E0497, 0x188064B, 0x16E374A, 0x1940EA5, 0x17E86B5, //1991-1995
0x1A605AD, 0x18E0AB6, 0x178596D, 0x1A0092F, 0x18A0C96, //1996-2000
0x1704D95, 0x1980D4B, 0x1820DA5, 0x16C2755, 0x192056B, //2001-2005
0x17A7ABB, 0x1A4025D, 0x18E092D, 0x1745CAB, 0x19C0A95, //2006-2010
0x1860B4B, 0x16E4BAA, 0x1940AD5, 0x17E955D, 0x1A604BB, //2011-2015
0x1900A5B, 0x0796517, 0x1A0052B, 0x18A0A93, 0x1724795, //2016-2020
0x09806AB, 0x1820AD5, 0x16C25B5, 0x19404B7, 0x07A6A6E, //2021-2025
0x1A20A4E, 0x18C0D26, 0x1745EA6, 0x09A0D53, 0x18605AB, //2026-2030
0x16E376A, 0x196096D, 0x07EB4AF, 0x1A604AD, 0x1900A4D, //2031-2035
0x1796D0B, 0x09E0D25, 0x1880D53, 0x0705BD4, 0x1980B5A, //2036-2040
0x082056D, 0x16C255B, 0x194049B, 0x17C7A57, 0x0A20A4B, //2041-2045
0x18C0AA5, 0x1755B25, 0x19C06D3, 0x0840ADA, 0x06F34B6, //2046-2050
0x1960937, 0x182849F, 0x0A60497, 0x090064B, 0x179668A, //2051-2055
0x19E0EA5, 0x08806AB, 0x0714A6C, 0x0980AAE, 0x184092E, //2056-2060
0x06A3D2E, 0x0920C96, 0x17A7D55, 0x1A20D4B, 0x08A0DA5, //2061-2065
0x07455D5, 0x19C056B, 0x1860A6D, 0x06E455D, 0x096052D, //2066-2070
0x17E8A9B, 0x1A60A95, 0x08E0B4B, 0x0766B6A, 0x19E0AD5, //2071-2075
0x18A055B, 0x0704ABA, 0x0980A5B, 0x184052B, 0x16C3B27, //2076-2080
0x0920693, 0x07A7733, 0x0A206AB, 0x18C0AD5, 0x07554B5, //2081-2085
0x09C04B7, 0x0860A57, 0x170454E, 0x0940D16, 0x07C8E96, //2086-2090
0x0A40D52, 0x18E0DAA, 0x07766AA, 0x09E056D, 0x08A04AF, //2091-2095
0x1724A9D, 0x0980A2D, 0x0820D15, 0x06A2F25, 0x1920D53  //2096-2100
};

[/c]
[c]
//lunar.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include "table.h"

#ifndef uint
typedef unsigned int uint;
#endif

uint dayofspring(const uint year)
{
   if (((THIS_YEAR(year) & 0xC00000) >> 22) == 1)
      return ((THIS_YEAR(year) & 0x3E0000) >> 17) - 1;
   return ((THIS_YEAR(year) & 0x3E0000) >> 17) - 1 + 31;
}

uint dayofyear(const uint year, const uint mon, const uint mday)
{
   static int monofday[12] = {0, 31, 59, 90, 120, 151,
      181, 212, 243, 273, 304, 334};
   uint day = 0;
   day = monofday[mon - 1] + mday - 1;
   if ((mon > 2) &&
         ((((year % 4) == 0) && ((year % 100) != 0)) ||
         ((year % 400) == 0)))
      day++;
   return day;
}

uint dayoffset(const uint year, const uint mon, const uint mday)
{
   uint yday = dayofyear(year, mon, mday);
   uint dspr = dayofspring(year);

   if (yday >= dspr) return (yday - dspr);

   uint last = dayoffset(year - 1, 12, 31);
   if (mon == 1) return (last + mday);
   return (last + 31 + mday);
}

uint monday(const uint year, const uint dayoffset)
{
   uint months = 12;
   uint monday = 0;
   uint leap = ((THIS_YEAR(year) & 0xF000) >> 12);
   uint nleap = ((THIS_YEAR(year) & 0x10000) >> 16);
   uint lmon = 0x1000;

   if (leap) {
      months = 13;
      monday |= (leap << 9);
      monday |= (nleap << 13);
   }

   uint i = 0;
   uint left = dayoffset;

   for (i = 1; i <= months ; i++)
   {
      uint mdays = 0;
      if (!leap || (i != (leap + 1))) {
         mdays = ((lmon >> i) & THIS_YEAR(year))? 30 : 29;
      } else {
         i--;
         leap = 0;
         months = 12;
         mdays = (nleap? 30 : 29);
         if (left < mdays) i = 0;
      }
      if (left < mdays) {
         monday |= (i << 5);
         monday |= left;
         return monday;
      }
      left -= mdays;
   }

   return 0;
}

uint getrealmonday(const uint year, const uint mon, const uint mday)
{
   if (dayofyear(year, mon, mday) >= dayofspring(year)) {
      return (monday(year, dayoffset(year, mon, mday)));
   }
   return (monday(year - 1, dayoffset(year, mon, mday)));
}

void ganzhi(const uint year, const uint mon, const uint mday)
{
   static char* tgGB[] = { "甲", "乙", "丙", "丁", "戊",
      "己", "庚", "辛", "壬", "癸" };
   static char* dzGB[] = { "子", "丑", "寅", "卯", "辰",
      "巳", "午", "未", "申", "酉", "戌", "亥" };

   uint i = 6, j = 8;
   uint realyear = year;
   uint lcoffset = ((0x3000000 & THIS_YEAR(year)) >> 24);

   //懒得算立春日了 -_-||
   if (dayofyear(year, mon, mday) < (31 + 2 + lcoffset))
      realyear -= 1;

   uint noun = realyear % 60;
   i += noun;
   i %= 10;
   j += noun;
   j %= 12;
   printf("%s%s年", tgGB[i], dzGB[j]);
}

void printmonday(uint monday)
{
   static char* numGB[] = { "初一", "初二", "初三", "初四", "初五",
      "初六", "初七", "初八", "初九", "初十",
      "十一", "十二", "十三", "十四", "十五",
      "十六", "十七", "十八", "十九", "二十",
      "廿一", "廿二", "廿三", "廿四", "廿五",
      "廿六", "廿七", "廿八", "廿九", "三十" };
   static char* monGB[] = { "正月", "二月", "三月", "四月", "五月",
      "六月", "七月", "八月", "九月", "十月", "冬月", "腊月" };
   uint mon = ((monday >> 5) & 0xF);
   uint mday = (monday & 0x1F);

   if (!mon) {
      printf("闰%s%s\n", monGB[((monday >> 9) & 0xF) - 1], numGB[mday]);
   } else {
      printf("%s%s\n", monGB[mon - 1], numGB[mday]);
   }
}

void usage(char* argv)
{
   fprintf(stderr, "%s [%d-%d] [1-12] [1-31]\n", argv,
         YEAR_SRT, YEAR_SRT + YEAR_NUM - 1);
   return;
}

int isdate(const uint year, const uint mon, const uint mday)
{
   if (mon > 12) return 0;
   if (mon == 2) {
      if ((((year % 4) ==  0) && ((year % 100) != 0)) ||
         ((year % 400) == 0)) {
         if (mday > 29) return 0;
         return 1;
      }
      if (mday > 28) return 0;
      return 1;
   }
   if ((mon == 1) || (mon == 3) || (mon == 5) || (mon == 7) || (mon == 8) ||
         (mon == 10) || (mon == 12)) {
      if (mday > 31) return 0;
      return 1;
   }
   if ((mon == 2) || (mon == 4) || (mon == 6) || (mon == 9) || (mon == 11)) {
      if (mday > 30) return 0;
      return 1;
   }
   return 0;
}

int main(int argc, char* argv[])
{
   if ((argc != 1) && (argc != 4)) {
      usage(argv[0]);
      return 1;
   }
   uint year = 0, mon = 0, mday = 0;

   int i = 1, j =0;
   if (argc == 4) {
      for (i = 1; i < 4; i++) {
         for (j = 0; j < strlen(argv[i]); j++) {
               if (!isdigit(* (argv[i] + j))) {
                  usage(argv[0]);
                  return 1;
               }
         }
      }
      year = atoi(argv[1]);
      mon = atoi(argv[2]);
      mday = atoi(argv[3]);
      if (!isdate(year, mon, mday)) {
         usage(argv[0]);
         return 1;
      }
   }

   if(argc == 1) {
      time_t cur_t = 0;
      time(&cur_t);
      struct tm* cur_tm = NULL;
      cur_tm = localtime(&cur_t);
      year = (cur_tm->tm_year) + 1900;
      mon = (cur_tm->tm_mon) + 1;
      mday = cur_tm->tm_mday;
   }

   if ((year < YEAR_SRT) || (year > (YEAR_SRT + YEAR_NUM - 1))) {
      usage(argv[0]);
      return 1;
   }

   if ((year == YEAR_SRT) &&
         (dayofyear(year, mon, mday) < dayofspring(year))) {
      usage(argv[0]);
      return 1;
   }

   ganzhi(year, mon, mday);
   uint monday = getrealmonday(year, mon, mday);
   if (monday) printmonday(monday);

   return 0;
}


由于鄙人不会C语言,不过想了解一下是怎么实现的,所以想求各位大大解释一下这些代码的意思,先谢谢了。 :em02


_________________
◎当我站在道德的高度上俯视别人的时候,发现自己是多么渺小。
♥执着但不偏激,反对而不排斥,坚决捍卫矛盾体的存在方式。
★★★天气预报★★★
fcitx-yatable一个可以使用的码表输入法
[教程]几个实例攻克软件编译难关
Gentoo Development Guide
字体相关


页首
 用户资料  
 
2 楼 
 文章标题 : Re: 一个农历软件,求测试。
帖子发表于 : 2013-09-07 18:31 

注册: 2007-01-14 16:23
帖子: 4349
送出感谢: 0 次
接收感谢: 109
不懂C没啥,这个其实就是根据农历的推算方法(叫历法比较准确点?)来写的,说白了就是和计算机讲农历怎么计算,就像数学里面让你算闰年似的(算闰年的算法比农历简单多啦)


_________________
#include <stdio.h>
void main()
{
double world;
unsigned letter;
short stay;
long memories;
printf("I miss you.\n");
}



_________________
评价: 3.7% YeLee
 
页首
 用户资料  
 
3 楼 
 文章标题 : Re: 一个农历软件,求测试。
帖子发表于 : 2013-09-07 18:35 

注册: 2007-01-14 16:23
帖子: 4349
送出感谢: 0 次
接收感谢: 109
不过这个软件……算的是200年的,从1901到2100年的,用法应该是编译以后执行,然后输入年月日(空格分开)
代码:
void usage(char* argv)
{
        fprintf(stderr, "%s [%d-%d] [1-12] [1-31]\n", argv,
                        YEAR_SRT, YEAR_SRT + YEAR_NUM - 1);
        return;
}

然后计算的


_________________
#include <stdio.h>
void main()
{
double world;
unsigned letter;
short stay;
long memories;
printf("I miss you.\n");
}


页首
 用户资料  
 
4 楼 
 文章标题 : Re: 一个农历软件,求测试。
帖子发表于 : 2013-09-07 18:41 
头像

注册: 2008-08-13 8:48
帖子: 26407
地址: 东海硇州,一双管钥。
系统: Fundu i64
送出感谢: 50
接收感谢: 344
谢谢onlylove了。 :em05


_________________
◎当我站在道德的高度上俯视别人的时候,发现自己是多么渺小。
♥执着但不偏激,反对而不排斥,坚决捍卫矛盾体的存在方式。
★★★天气预报★★★
fcitx-yatable一个可以使用的码表输入法
[教程]几个实例攻克软件编译难关
Gentoo Development Guide
字体相关


页首
 用户资料  
 
5 楼 
 文章标题 : Re: 一个农历软件,求测试。
帖子发表于 : 2013-09-07 18:53 

注册: 2007-01-14 16:23
帖子: 4349
送出感谢: 0 次
接收感谢: 109
轮子居然点了感谢,吓坏了 :em20


_________________
#include <stdio.h>
void main()
{
double world;
unsigned letter;
short stay;
long memories;
printf("I miss you.\n");
}


页首
 用户资料  
 
6 楼 
 文章标题 : Re: 一个农历软件,求测试。
帖子发表于 : 2013-09-12 16:22 
头像

注册: 2008-08-13 8:48
帖子: 26407
地址: 东海硇州,一双管钥。
系统: Fundu i64
送出感谢: 50
接收感谢: 344
有没有人会的?难道这论坛就没有高手了吗? :em20


_________________
◎当我站在道德的高度上俯视别人的时候,发现自己是多么渺小。
♥执着但不偏激,反对而不排斥,坚决捍卫矛盾体的存在方式。
★★★天气预报★★★
fcitx-yatable一个可以使用的码表输入法
[教程]几个实例攻克软件编译难关
Gentoo Development Guide
字体相关


页首
 用户资料  
 
7 楼 
 文章标题 : Re: 一个农历软件,求测试。
帖子发表于 : 2013-09-12 20:24 
头像

注册: 2010-04-23 20:40
帖子: 1950
地址: 浙江·杭州
系统: Arch Linux
送出感谢: 2
接收感谢: 31
表示解释代码是一种痛苦……

Sent from Android 4.0


_________________
我是 Giumo Clanjor(哆啦比猫/兰威举)
Where there is a hacker, there is art. | Develop for Developers. (C & perl5)
博客 | Clanjor Prods.
类 C 语言到 brainfuck 编译器


页首
 用户资料  
 
8 楼 
 文章标题 : Re: 一个农历软件,求测试。
帖子发表于 : 2013-09-12 23:24 
头像

注册: 2008-08-13 8:48
帖子: 26407
地址: 东海硇州,一双管钥。
系统: Fundu i64
送出感谢: 50
接收感谢: 344
是不是这问题太难了,所以大家都不会啊? :em20


_________________
◎当我站在道德的高度上俯视别人的时候,发现自己是多么渺小。
♥执着但不偏激,反对而不排斥,坚决捍卫矛盾体的存在方式。
★★★天气预报★★★
fcitx-yatable一个可以使用的码表输入法
[教程]几个实例攻克软件编译难关
Gentoo Development Guide
字体相关


页首
 用户资料  
 
9 楼 
 文章标题 : Re: 一个农历软件,求测试。
帖子发表于 : 2013-09-13 11:33 
头像

注册: 2005-08-14 21:55
帖子: 58428
地址: 长沙
送出感谢: 4
接收感谢: 274
算了干嘛,直接网站获取。
另外,用C处理字符串,你在找虐。


_________________
● 鸣学


页首
 用户资料  
 
10 楼 
 文章标题 : Re: 一个农历软件,求测试。
帖子发表于 : 2013-09-13 11:52 
头像

注册: 2008-08-13 8:48
帖子: 26407
地址: 东海硇州,一双管钥。
系统: Fundu i64
送出感谢: 50
接收感谢: 344
ee难道不知道c假如加一个libcurl的话,代码量又要拖多长来着……更何况我只是靠程序自己算的,也不用花多少时间采集数据吧。 :em01
另,用C处理字串,我倒不觉得有什么自作孽的,反正之前写过一个字串操作的库,动态分配字串这些东西都直接扔给库处理了。
更重要的一点,不知ee有没有留意,其实这段代码里面压根就没有什么复杂的字串操作之类的,甚至连个动态内存的东西都没有,多的只是位操作。
C的位运算我倒觉得弄起来非常有意思,起码比你们家的perl好多了。 :em05


_________________
◎当我站在道德的高度上俯视别人的时候,发现自己是多么渺小。
♥执着但不偏激,反对而不排斥,坚决捍卫矛盾体的存在方式。
★★★天气预报★★★
fcitx-yatable一个可以使用的码表输入法
[教程]几个实例攻克软件编译难关
Gentoo Development Guide
字体相关


页首
 用户资料  
 
11 楼 
 文章标题 : Re: 一个农历软件,求测试。
帖子发表于 : 2013-09-13 11:59 
头像

注册: 2005-07-02 14:41
帖子: 4160
系统: Ubuntu 14.04 (Kylin)
送出感谢: 64
接收感谢: 12
源里有lunar这个包的。


_________________
https://weakish.github.io


页首
 用户资料  
 
12 楼 
 文章标题 : Re: 一个农历软件,求测试。
帖子发表于 : 2013-09-13 12:23 
头像

注册: 2008-08-13 8:48
帖子: 26407
地址: 东海硇州,一双管钥。
系统: Fundu i64
送出感谢: 50
接收感谢: 344
之前看过lunar的代码,由于立春日与干支的问题鄙人目前仍混淆不清,故没有采用。 :em01
更何况这东西只是弄给conky看的,要那么多输出干嘛?我还想用一个更舒服的办法来实现。
呵呵,扯远了,反正这年头也不少缺轮子,我这里不过是提供自己的算法而已。 :em01


_________________
◎当我站在道德的高度上俯视别人的时候,发现自己是多么渺小。
♥执着但不偏激,反对而不排斥,坚决捍卫矛盾体的存在方式。
★★★天气预报★★★
fcitx-yatable一个可以使用的码表输入法
[教程]几个实例攻克软件编译难关
Gentoo Development Guide
字体相关


页首
 用户资料  
 
13 楼 
 文章标题 : Re: 一个农历软件,求测试。
帖子发表于 : 2013-09-18 17:27 

注册: 2009-11-25 1:38
帖子: 61
送出感谢: 0 次
接收感谢: 6
主要就是 table.h 里的内容,写的很清楚了,竖着看。

代码:
/*
        YEAR:LC:ZY:ZYDAY:L:LEAP:MONTHS
        1901:01:10:10011:0:0000:010010101111
        年   立 春 春    闰闰无 十非的
        份   春 节 节    月月则 二闰大
             日 阳 阳    大月为 个月小
             偏 历 历    小份零
             移 月 日
             量 份 期
*/


把每年推算信息(春节对应阳历日,润月月分,大小,非润月大小)都放到一个数字里了,用的时候根据年份查表。

知道了春节的阳历日期,就知道了阴历的第一天在哪里。知道了润月是哪几月,大小月,得到每个月的天数,就可以从第一天(春节)推算出相应的阴历月和阴历日。其他都是细节,比如春节前的日子使用前一年的信息,都是常识。所以理解了那个表的意思,自己根据常识就可以推算了,不必懂C。

至于干支,网上查一下,干支历的开始是从立春开始的,不是春节,所以干支年就要考虑那一天是立春前还是立春后,而不是跟春节做比较。他好像没有算干支的月和日。

所以其实不是什么推算,只是算好基本信息,然后查表后做简单推算。


页首
 用户资料  
 
14 楼 
 文章标题 : Re: 一个农历软件,求测试。
帖子发表于 : 2015-02-25 12:14 
头像

注册: 2008-08-13 8:48
帖子: 26407
地址: 东海硇州,一双管钥。
系统: Fundu i64
送出感谢: 50
接收感谢: 344
回来一看,发现自己之前居然写过一些这么糟糕的代码啊。 :em01


_________________
◎当我站在道德的高度上俯视别人的时候,发现自己是多么渺小。
♥执着但不偏激,反对而不排斥,坚决捍卫矛盾体的存在方式。
★★★天气预报★★★
fcitx-yatable一个可以使用的码表输入法
[教程]几个实例攻克软件编译难关
Gentoo Development Guide
字体相关


页首
 用户资料  
 
显示帖子 :  排序  
发表新帖 回复这个主题  [ 14 篇帖子 ] 

当前时区为 UTC + 8 小时


在线用户

正在浏览此版面的用户:没有注册用户 和 3 位游客


不能 在这个版面发表主题
不能 在这个版面回复主题
不能 在这个版面编辑帖子
不能 在这个版面删除帖子
不能 在这个版面提交附件

前往 :  
本站点为公益性站点,用于推广开源自由软件,由 DiaHosting VPSBudgetVM VPS 提供服务。
我们认为:软件应可免费取得,软件工具在各种语言环境下皆可使用,且不会有任何功能上的差异;
人们应有定制和修改软件的自由,且方式不受限制,只要他们自认为合适。

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
简体中文语系由 王笑宇 翻译