一个日历核心算法的实现 前传1:日历算法C语言实现

这段代码是去年5月花了2天写的,主要是日历、星期的算法试验 。今天碰巧翻出来看到了,若不是随意一翻,真都差点忘掉。
忘掉可不好,可能哪天用上,还是在此做个记录免得忘掉。
记得前面写了篇日历算法相关的文章( 一个日历核心算法的实现),没写完,那个就是根据这个来写的。做这个实际上是为了写JavaScript日历实现,先贴代码,等过段时间有空了,再回头补充这两篇文章。

/**
 * 日历,星期 算法试验
 * @version 2009-05-06 ~ 07 yhl.lxrm@gmail.com
 */

#include <stdio.h>
#include <stdlib.h>

/**
* 构造日子数据结构
*/
struct DayNode{
    int isEmpty;
    int day;
    int week;
    int safeType;
};
typedef struct DayNode SafeDayNode;
/**
 * 日期存放结构
 */
struct dateNode{
  int year;
  int month;
  int day;
};
typedef struct dateNode DateNode;
// 给定年月获取当月天数
int getMDay(int y, int m)
{
  int mday[12]=  {31,28,31,30,31,30,31,31,30,31,30,31} ;
  if (( 0 == y % 4 && 0 != y % 100) || 0 == y % 400)
      mday[1] = 29;
  return mday[m-1];
}

// 获取星期数,0对应星期天 ,1对应星期一,其他类推
int week(int y, int m, int d)
{

    int wk ,date_offset=d,im,tmp=0;
    if (m < = 12 && m >=1 )
    {
      for(im=1; im < m; ++im)
      {
         date_offset += getMDay(y,im);
      }
    }
    //printf("日期偏移量 C = %d \n",date_offset);
    /*根据日期计算星期的公式*/
    wk = (y-1 + (y - 1)/ 4 - (y - 1) / 100  + (y - 1) / 400  + date_offset ) % 7;
    //printf("星期 %d :\n",wk);
    return wk;
}

以上是需要用到的功能函数,下面给出日历核心算法的具体实现:
Continue reading

Posted in C学习笔记心得, 算法研究 | Leave a comment

解除烦人的 nm-applet keyring 密码输入提示

我的本本每次连无线网时都得经过nm-applet,烦不胜烦,今天实在忍不住了,Google了一下,照着这位老兄提供的一个解决办法搞定,原文在这:

使用NetworkManager来管理的话,有一个令人厌烦的地方是,每次启动后 gnome-keyring会提醒你输入密码,可以安装pam_keyring来解决;装完 pam_keyring后,编辑文件 /etc/pam.d/gdm,加入如下内容:
auth optional pam_keyring.so try_first_pass
session optional pam_keyring.so
如果不幸你曾经输入的keyring密码和你的登录密码不一致,因为当前的 gnome-keyring没有机制修改密码,所以你需要首先杀死gnome-keyring-daemon进程,然后删除keyring文件 ~/.gnome2/keyrings,然后重新登录设置匹配的密码。

我是这样来的:
1. 安装pam_keyring

$sudo yum -y install pam_keyring
$sudo vim /etc/pam.d/gdm
#在文件最后加入
auth optional pam_keyring.so try_first_pass
session optional pam_keyring.so
$sudo rm ~/.gnome2/keyrings/login.keyring
#杀进程
$ps -aux | grep gnome-keyring-daemon
$kill 进程ID
#OK,完成,下次联网时就不会有keyring来烦人啦

Posted in 日常管理 | Leave a comment

linux下打造LAMP开发环境[从源码安装]

最近要搞个采集来耍耍,所以必须得弄个环境。但自打从上一个公司离开后,8个多月没直接在linux上干活了。今年8月份的时候,打算在机子上装个LAMP环境的,但只把Apache和MySQL编译到了机器上,而MySQL仅仅是安装到了指定目录,并未运行起来。由于懒惰,结果到了想用机器做点东西时才想起还有这回事。

O、环境交代

  • OS: Fedora 11
  • 编译环境: gcc (GCC) 4.4.0 20090506 (Red Hat 4.4.0-4)
  • 文本编辑器:vi vim emacs 等
  • 其他:YUM RPM tar gzip ….等基础工具基本具备

一、Apache 安装
Apache我没有使用源码包和RPM包,而是系统自带的。有个好处就是依赖问题自动解决,省力省事。缺点就是,如有特别需要的模块或者功能,可能需要编译安装才能达到要求。那么,开始吧,不过我先讲讲简单的yum安装和移除httpd吧。下面简单记录下安装过程中使用到的命令:

# 安装如下,非常非常的easy!
$ sudo yum -y install httpd
#升级也是如此
$ sudo yum -y update httpd
#当然,卸载更是如此了,哈哈
$ sudo yum erase httpd
# 注:为啥 我把参数-y从命令中取消呢? 因为此选项每次遇到问题都回答yes,由于卸载事关重大,所以就保险点吧,不然其他依赖是怎么被删掉的都还不知道。

好了,自动安装工具使用了,果然简单的所,哈哈。可是,优越性一下子就让我发愁了,那些我能用,那些功能我还不能用,这些都不是很清楚,要达到此目的,就必须从源码按需编译了,呵呵。另外一个原因呢,是我想要这个软件和我之后其他的软件都放到一个目录下,便于管理。
apache的编译安装过程还算比较简单,可照如下方式进行:

# 哦,哦,差点忘了,东西都还没下载,所以下载了再开始吧
$sudo wget -O /usr/local/src/web-tools/tars/httpd-2.2.14.tar.bz2 http://labs.xiaonei.com/apache-mirror/httpd/httpd-2.2.14.tar.bz2
$cd /usr/local/src/web-tools/tars
$tar -xjf httpd-2.2.14.tar.bz2 -C ../extracted-dirs/
$cd ../extracted-dirs/httpd-2.2.14/
#开始了,不过,我要模块化,所以选项里有个–enable-so,其他的,字面意思即可,或者翻configure帮助吧。
$ sudo ./configure –prefix=/usr/local/webserver/apache2_2 –enable-so –enable-cgi –enable-rewrite –enable-mods-shared=all –enable-ssl –with-ssl –with-port=80
$sudo make
$sudo make install

安装完毕后,使用apachectl命令来管理httpd进程。为了每次启动机器后自动开启apache httpd服务,只需编辑下面这个文件,在后面添加一行启动命令即可。如下:

$vi /etc/rc.d/rc.local
#…略…
apachectl -k start
# 或者 /sbin/service httpd start
#…略…

当然,按照源码安装的方式,系统并不会自动为apache建立apache账户,还需手动要为apache运行开辟账户才对,这里来补充一下:

$sudo groupadd apache
$sudo useradd -g apache apache

Continue reading

Posted in LAMP环境, linux | 1 Comment

PHP session 刷新丢失问题

1、客户端禁用了cookie
2、浏览器出现问题,暂时无法存取cookie
3、php.ini中的session.use_trans_sid = 0或者编译时没有打开–enable-trans-sid选项

浏览器禁用cookie后的后果就是,$_COOKIE变量内容为空,每次刷新页面后,session id值随之改变。

Posted in PHP开发 | Leave a comment

linux 为普通用户添加sudo权限

我的Federal 11 用了也快3个多月了,一直都没有好好整理下命令行的东东。每次安装个软件,都要用su切换到root,关键是还要输入密码,实在是太不方便了。于是,终于想起了可爱的sudo。好吧,下面就将自己的主要用户添加到sudo用户中去吧。
无奈,还得先切换到root权限。

$ su

然后会提示输入root用户的密码,正确,则进入root模式。

# visudo

注:这里是用的visudo命令,直接编辑/etc/sudoer。也可直接vi这个文件
打开了/etc/sudoer这个文件,然后( Shift + g ) 命令直接跳到文本的末尾。
OK,新开一行,参考无需输密码就可使用root权限的命令的方式,在末尾加入这样的一行:


## Allows yhl execute root command
yhl ALL=(ALL) NOPASSWD: ALL

注:yhl ,指的是需要使用sudo命令的用户; ALL=(ALL) ,表示该用户可以执行root所能执行的命令和操作;NOPASSWD: ALL,则表示使用sudo命令时,无需输入sudo命令使用密码。
ok,编辑完刚才的文件,按 ESC 键, 接着按下( Shift + : )进入vi命令模式,在冒号后面敲上wq,表示存储并退出编辑。大功告成。回到命令行,敲入exit命令,退出root用户环境。然后

$ sudo service httpd status

这样,httpd服务的状态就可以随时查看了。当然,httpd等其他需要root权限的操作都可以通过在命令前面加个sudo来执行了。不用我说,实在是方便之极。

参考资料:http://fedora.linuxsir.org/main/?q=node/91

Posted in 基本命令 | Leave a comment

一个日历核心算法的实现

这里是搬家过来的原创文章,本文是09年5月份写的(还没写完:重要的实现算法还没介绍),有点旧了,但总算有个家。于是发到这里。

上周由于工作需要,要做一个带标注的日历查询的JS程序。到网上也搜了不少日历相关的JS代码,但是发现都比较复杂,完全不适合本次开发的需要,于是乎萌生了自己开发一个日历算法的想法。

虽然这个程序的算法难度一般,但是还是冒死放出来溜溜,免得今后忘记了。大家都知道,日历主要是解决星期和日期之间的关系,另外就是一个排版的问题,如何将日期和星期一一对应,这个也是要考虑的重点。那么总结一下要解决的问题:

  1. 给定日期,求出对应星期
  2. 给定日期,求出该月的日历。

一、给定日期,求星期

  • 首先,要知道星期怎么来的,星期从哪天算起,即找到一个计算“原点”,这样之后星期计算就可以有依据了。对于这个问题,其实可以采取反推的办法来实现,找到比如公元元年的星期日(便于求余计算直接得到星期数)的日期。
  • 其次,在知道第一个星期对应的年月日的基础上,求得当前日期是有星期以来多少天,然后用这个间隔天数对一周的天数7取模运算即可求出当前星期几。
  • 因为存在闰年,所以还需要计算有多少个闰年,把这个加上去才能得到间隔天数。

其实这个算法早已存在,下面就这个最常见的公式:

W = [Y-1] + [(Y-1)/4] – [(Y-1)/100] + [(Y-1)/400] + D Y是年份数,D是这一天在这一年中的累积天数,也就是这一天在这一年中是第几天,用个计算机术语就叫相对年初的第0天的偏移量了。

这里就不对这个公式进行推导了,详细推导过程可以到这里下载PDF文档(以下简称PDF):http://download.csdn.net/source/1308663 这个可能要扣一点资源费(莫BS我),表示支持俺的辛苦搜集。

有了上面的公式,接下来就是获得公式里的参数了,其中Y比较容易(地球人人都知道),麻烦的地方在D(其实PDF中Zeller给出了比较简单的算法),不过这里偶比较好奇,所以非要实现D的算法。

为了求D(也就是偏移量),需要计算当前月之前所有月的∑值,以及当前日在当月的偏移量(简称M),那么

D = ∑m + M

其中,∑m 是当年第一月到M所在月前一月的各月天数之和,这个比较简单,关键是确定每个月的天数。原本十二个月每个月天数既定,除了二月份的闰年和平年不一样,这就要根据是否闰年来判断了。根据公里年闰年的算法:则有下面大家所熟知的通用公式。

LeapYear = ( Year / 4   == 0 && Year / 100  !=0) || Year / 400 == 0

下面是给定月份天数算法的C程序实现:

// 给定年月获取当月天数

int getMDay(int y, int m)
{
	int mday[12]=  {31,28,31,30,31,30,31,31,30,31,30,31} ;
	if (( 0 == y % 4 && 0 != y % 100) || 0 == y % 400)
		mday[1] = 29;

	return mday[m-1];
}

有了这个函数,就可以准确得知某日所在月份的天数了。那么计算D就好办了,这样给定日期求星期的算法就完全解决,看代码:

// 获取星期数,0对应星期天 ,1对应星期一,其他类推

int week(int y, int m, int d)
{
	int wk ,date_offset=d,im,tmp=0;
	if (m <= 12 && m >=1 )
	{
		for(im=1; im < m; ++im)
		{
			date_offset += getMDay(y,im);
		}
	}

	/*根据日期计算星期的公式*/
	wk = (y-1 + (y-1)/4 - (y-1)/100  + (y-1)/400  + date_offset)%7;

	return wk;
}

二、给定日期,求出该月的日历

其实上面的都不是本文的重点,本文重点在于如何生成一个日历来,当然方法很多,这里我也给出一个自己的思路,如有雷同,纯属巧合!

由于时间问题,今天就不写了,给下次写留点空间。(看这篇文章的算法实现前传

Posted in 算法研究 | Leave a comment

PHP实现遍历目录下的所有文件,统计目录大小

这里是搬家过来的原创文章,本文是两年前写的,有点旧了,但总算有个家。于是发到这里。

终于写完了文件管理程序,说不上什么心得,这得那得。在这个过程中,把使用到的一点东东拿出来献宝,算是一个交代,大家不要见笑哈..

php里使用的是 readdir($dir_handle) ,该函数一次仅读一个文件,返回文件名称。她首先从文件 ‘.’ 读起,然后再读 ‘..’ ,读完这两个之后就是’.'(当前)目录下的文件了。按名称升序顺次读取。这里需要使用循环语句才能把当前目录下的所有文件都遍历一遍。

/**
 *        本函数实现了目录大小的统计功能。参数$dir即目录路径名。
 */
function directory_traverse($dir){
	if(is_dir($dir)){
		if($dir_handle = opendir($dir)){
			while (false !== ($file_name = readdir($dir_handle)) ){
				$file_type = filetype($dir.'/'.$file_name);
				if($file_name=='.' or $file_name =='..'){
					continue;
				}else{
					if('dir' == $file_type){
						directory_traverse($dir.'/'.$file_name);
					}elseif('file' == $file_type){
						$file_size += filesize($dir.'/'.$file_name);
					}
				} // if
			}// while
		}// if
	}elseif(is_file($dir)){
		$size = filesize($dir);
	}

	return $file_size ;
}

遍历文件并非难点,难点在于如何统计目录大小。文件大小用函数 filesize($filename)即可搞定。由于PHP函数库里并没有统计目录大小的函数,所以统计目录大小时需要自行设计这样的函数。而要获取整 个目录(包括子目录)的大小,则需递归实现文件大小的计算。

而上面那个函数仅仅统计了一个目录下所有非目录文件的大小,要把目录大小也统计了需要写下文件夹遍历后的大小统计,然后加上文件大小,就是整个目录的大小了。改进后,程序如下:

function directory_traverse($dir){
	if(is_dir($dir)){
		if($dir_handle = opendir($dir)){
			while (false !== ($file_name = readdir($dir_handle)) ){
				$file_type = filetype($dir.'/'.$file_name);
				if($file_name=='.' or $file_name =='..'){
					continue;
				} else {
					if('dir' == $file_type){
						$dir_size +=directory_traverse($dir.'/'.$file_name);
					} elseif('file' == $file_type){
						$file_size += filesize($dir.'/'.$file_name);
					}
				} // if
			}// while
		}// if
	}elseif(is_file($dir)){
		$size = filesize($dir);
	}

	return $file_size+$dir_size ;
}

在递归时,需要注意的地方是 文件名的取法,注意分割线 ‘/’ ,对文件的操作要非常小心这个东东的使用,一不小心就有可能陷入困境。上面的函数只是简单的一个实现,要实现更复杂的功能,可以在这个基础上进行扩展,具体方法嘛,^_^ 自己琢磨咯……

虽然,目录大小也统计出来了,但是这个函数相当耗资源。不是说文件多,而是当文件夹级数较深的时候,其局限性就被夸张的放大了,甚至1分钟后才有计算结 果。所以在这里要向各位达人请教啊, 相信你还有更好的方法,贴出来吧,让我们都过把瘾。

Posted in PHP开发 | Leave a comment

Hello world!

     进入网络行业即将满3年,也做了大大小小不少的站点,但这个才是属于我自己的站点。这里,将是一个新的开始。很多事情,过了,就容易忘记,那么就让这个地方来记录思想的点滴吧,也许翻一翻,还是有值得留恋的东西。

Posted in 我的生活 | 2 Comments