<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>云海游鱼的Blog</title>
	<atom:link href="http://www.fishonsky.com/feed" rel="self" type="application/rss+xml" />
	<link>http://www.fishonsky.com</link>
	<description>记录生活的点滴，记录学习的足迹</description>
	<lastBuildDate>Mon, 06 Feb 2012 01:01:07 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>地址端口检测</title>
		<link>http://www.fishonsky.com/archives/37941.html</link>
		<comments>http://www.fishonsky.com/archives/37941.html#comments</comments>
		<pubDate>Sat, 04 Feb 2012 13:11:50 +0000</pubDate>
		<dc:creator>flyingfish</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Unix]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[地址检测]]></category>

		<guid isPermaLink="false">http://www.fishonsky.com/archives/37941.html</guid>
		<description><![CDATA[       有时候我们需要对某些服务器是否可用进行判断，一般可以通过telnet ip  port  的方式来实现，这时如果返回的是Connection refused或是Escape character is &#8216;^]，则表示这个端口是开放的，不过前者拒绝该请求，而后者则可以正常联通。如果我们需要一次性检测一批端口是否开放，这时如果一条条输telnet命令可能就有些累了。下面说一下如何用脚本来实现。
      首先我们需要一个可以探测端口的程序，这个我是用c语言来实现的（参考了网上的代码，如果谁发现可用的命令欢迎告诉我哦），通过编译后就可以运行，不过它只实现扫描一个端口的功能。后面会再介绍个shell脚本来实现多次调用该程序来实现扫描多个地址的目的。
      具体c语言的代码如下：
#include &#60;stdlib.h&#62;
#include &#60;stdio.h&#62;
#include &#60;unistd.h&#62;
#include &#60;fcntl.h&#62;
#include &#60;sys/types.h&#62;
#include &#60;sys/socket.h&#62;
#include &#60;netinet/in.h&#62;
#include &#60;errno.h&#62;
#include &#60;time.h&#62;
#include &#60;arpa/inet.h&#62;

/* 该代码可以用来测试某个端口是否联通，使用方法 a.out 128.32.171.33 23
*  然后查看$?的值，如果是0，则表示该端口可以联通，否则不可以联通
*  可以和shell脚本结合使用
*  文件名：detect_ip_port.c
*/

int main(int argc, char *argv[])
{
 int fd, retval;
 struct sockaddr_in addr;
 struct timeval timeo = {3, 0};
 char buf[1024];
 int i;
 socklen_t len;
 fd_set set;

 fd = socket(AF_INET, SOCK_STREAM, 0);
 addr.sin_family = AF_INET;
 addr.sin_addr.s_addr = inet_addr(argv[1]);
 addr.sin_port = htons(atoi(argv[2]));
 if [...]]]></description>
			<content:encoded><![CDATA[<p>       有时候我们需要对某些服务器是否可用进行判断，一般可以通过telnet ip  port  的方式来实现，这时如果返回的是Connection refused或是Escape character is &#8216;^]，则表示这个端口是开放的，不过前者拒绝该请求，而后者则可以正常联通。如果我们需要一次性检测一批端口是否开放，这时如果一条条输telnet命令可能就有些累了。下面说一下如何用脚本来实现。</p>
<p>      首先我们需要一个可以探测端口的程序，这个我是用c语言来实现的（参考了网上的代码，如果谁发现可用的命令欢迎告诉我哦），通过编译后就可以运行，不过它只实现扫描一个端口的功能。后面会再介绍个shell脚本来实现多次调用该程序来实现扫描多个地址的目的。</p>
<p>      具体c语言的代码如下：</p>
<pre class="brush: cpp">#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
#include &lt;unistd.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;sys/socket.h&gt;
#include &lt;netinet/in.h&gt;
#include &lt;errno.h&gt;
#include &lt;time.h&gt;
#include &lt;arpa/inet.h&gt;

/* 该代码可以用来测试某个端口是否联通，使用方法 a.out 128.32.171.33 23
*  然后查看$?的值，如果是0，则表示该端口可以联通，否则不可以联通
*  可以和shell脚本结合使用
*  文件名：detect_ip_port.c
*/

int main(int argc, char *argv[])
{
 int fd, retval;
 struct sockaddr_in addr;
 struct timeval timeo = {3, 0};
 char buf[1024];
 int i;
 socklen_t len;
 fd_set set;

 fd = socket(AF_INET, SOCK_STREAM, 0);
 addr.sin_family = AF_INET;
 addr.sin_addr.s_addr = inet_addr(argv[1]);
 addr.sin_port = htons(atoi(argv[2]));
 if ((i=connect(fd, (struct sockaddr*)&amp;addr, sizeof(addr))) == 0)
 {
  close(fd);
  perror("connected success:");
  return 0;
 }
 perror("connected error:");
 close(fd);
 return 1;
}</pre>
<p>可以通过执行shell命令,来生成可执行文件：</p>
<pre class="brush: bash">gcc –o detect_one_addr  detect_ip_port.c</pre>
<p>为了实现一次扫描多个地址的目的，我首先采用一个txt文件来保存需要扫描的ip 和port等信息，具体txt的内容大致如下：</p>
<pre class="brush: bash">192.168.0.1 8000 01 服务器1
192.168.0.2 8000 02 服务器2
192.168.0.3 8000 03 服务器3
192.168.0.4 8000 04 服务器4
192.168.0.5 8000 05 服务器5</pre>
<p>其中每一行中包括ip  port  编号  名称，每个字段用空格或tab分隔。在此我们假设该文件名称为：servers.txt</p>
<p>接下来使用shell脚本来实现扫描多个地址的目的：</p>
<pre class="brush: bash">#!/usr/bin/sh

# file name : detect_all.sh

detect_one_addr()
{
 ip=`echo $line |  awk '{print $1}'`
 port=`echo $line |  awk '{print $2}'`
 entr_no=`echo $line |  awk '{print $3}'`
 entr_name=`echo $line |  awk '{print $4}'`

 ./detect_ip_port $ip $port
 if [ $? == 0 ] ; then
 	echo "$entr_no  $entr_name  is OK"
 else
 	echo "$entr_no $entr_name is Failed"
 fi
}

testfile="servers.txt"
while read -r line
do
    detect_one_addr $line
done &lt; $testfile</pre>
<p>然后在命令行中执行detect_all.sh即可实现该扫描的功能。你可能会发现如果某个端口不开放，该程序需要过好长时间才会超时，这个超时时间是由系统来决定的，具体是TCP连接的超时时间，一般不建议修改。我也经常遇到连接一个端口经过好久最后联通的情况，因为首次连接需要进行ARP、或是路由器会帮你建立连接（因为这个连接好久不用可能已经休息了，呵呵），所以耐心等待就好。</p>
<p>PS：经过上述程序可以看出，我们可以通过shell或是其他高级语言，如ruby，perl等来做高级的工作，然后我们用c/c++、java等实现底层的功能，这样可以更有效率的解决问题，充分发挥各个语言的优点</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fishonsky.com/archives/37941.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HP-UX 新建用户</title>
		<link>http://www.fishonsky.com/archives/37937.html</link>
		<comments>http://www.fishonsky.com/archives/37937.html#comments</comments>
		<pubDate>Fri, 06 Jan 2012 12:48:24 +0000</pubDate>
		<dc:creator>flyingfish</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Unix]]></category>
		<category><![CDATA[新建用户，Linux]]></category>

		<guid isPermaLink="false">http://www.fishonsky.com/archives/37937.html</guid>
		<description><![CDATA[在UNIX下建立用户并不像Linux那么简单，主要是需要创建逻辑卷和文件系统。具体过程如下：


#建立新的逻辑卷

lvcreate -L 2560 -n lvcsspkm /dev/vg00 

fstyp /dev/vg00/lvcsspkm # 查看dev/vg00/lvcsspkm的文件系统类型

#前面记得加r，否则会提示newfs: /dev/vg00/lvcsspkm is not a character device

#下面这一步如果不做，可能发现设备上的文件是其他用户的旧文件

newfs -F vxfs -o largefiles /dev/vg00/rlvcsspkm

mkdir /home/user/csspkm

mount /dev/vg00/lvcsspkm /home/user/csspkm

#下面这一步是为了系统重启时自动挂载分区

vi /etc/fstab

#建立用户，并指定默认home目录和默认群组

useradd -d /home/user/csspkm -G dba csspkm

#更给原来文件夹的所有者，注意用：分隔群组而是:号

chown -R csspkm:dba csspkm

#设置密码，不设置的话不能登录

passwd csspkm

&#160;&#160;&#160;&#160;&#160; 在建立过程中我查找了hp-unix的参考手册还有网上的一些资料。我发现自己电脑上有我们用的系统和软件的参考手册是很重要的，这样如果生产环境出问题，你才能快速的查找资料，从而做出反应。有时候上互联网并不是一件容易的事情。

]]></description>
			<content:encoded><![CDATA[<blockquote><p>在UNIX下建立用户并不像Linux那么简单，主要是需要创建逻辑卷和文件系统。具体过程如下：</p>
<pre class="brush:bash">

#建立新的逻辑卷

lvcreate -L 2560 -n lvcsspkm /dev/vg00 

fstyp /dev/vg00/lvcsspkm # 查看dev/vg00/lvcsspkm的文件系统类型

#前面记得加r，否则会提示newfs: /dev/vg00/lvcsspkm is not a character device

#下面这一步如果不做，可能发现设备上的文件是其他用户的旧文件

newfs -F vxfs -o largefiles /dev/vg00/rlvcsspkm

mkdir /home/user/csspkm

mount /dev/vg00/lvcsspkm /home/user/csspkm

#下面这一步是为了系统重启时自动挂载分区

vi /etc/fstab

#建立用户，并指定默认home目录和默认群组

useradd -d /home/user/csspkm -G dba csspkm

#更给原来文件夹的所有者，注意用：分隔群组而是:号

chown -R csspkm:dba csspkm

#设置密码，不设置的话不能登录

passwd csspkm
</pre>
<p>&#160;&#160;&#160;&#160;&#160; 在建立过程中我查找了hp-unix的参考手册还有网上的一些资料。我发现自己电脑上有我们用的系统和软件的参考手册是很重要的，这样如果生产环境出问题，你才能快速的查找资料，从而做出反应。有时候上互联网并不是一件容易的事情。</p>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.fishonsky.com/archives/37937.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>新年新气象</title>
		<link>http://www.fishonsky.com/archives/37934.html</link>
		<comments>http://www.fishonsky.com/archives/37934.html#comments</comments>
		<pubDate>Sun, 01 Jan 2012 02:19:49 +0000</pubDate>
		<dc:creator>flyingfish</dc:creator>
				<category><![CDATA[日志]]></category>
		<category><![CDATA[新年好]]></category>

		<guid isPermaLink="false">http://www.fishonsky.com/?p=37934</guid>
		<description><![CDATA[&#160;&#160;&#160;&#160;&#160; 转眼又过了一年，现在已经工作了。博客好久不更新了，刚开始是因为找工作比较忙，后来就慢慢忘记了。现在工作大概有半年了，工作不是很辛苦，自己也会抽时间学习点东西，也会记录一些学习的笔记，但是和博客的内容相比还是差了好多，很多都缺乏整理。很多知识都在于整理，整理的过程也是重新学习，更新认识的过程。
&#160;&#160;&#160;&#160;&#160; 在新的一年里，我将会努力学习新知识，充实自己，坚持写博客，记录自己的学习历程（呵呵，希望能坚持吧~~~）。另外也祝大家在新的一年里，生活多姿多彩，工作一帆风顺&#160; ^_^
]]></description>
			<content:encoded><![CDATA[<p>&#160;&#160;&#160;&#160;&#160; 转眼又过了一年，现在已经工作了。博客好久不更新了，刚开始是因为找工作比较忙，后来就慢慢忘记了。现在工作大概有半年了，工作不是很辛苦，自己也会抽时间学习点东西，也会记录一些学习的笔记，但是和博客的内容相比还是差了好多，很多都缺乏整理。很多知识都在于整理，整理的过程也是重新学习，更新认识的过程。</p>
<p>&#160;&#160;&#160;&#160;&#160; 在新的一年里，我将会努力学习新知识，充实自己，坚持写博客，记录自己的学习历程（呵呵，希望能坚持吧~~~）。另外也祝大家在新的一年里，生活多姿多彩，工作一帆风顺&#160; ^_^</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fishonsky.com/archives/37934.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>递归与回溯算法</title>
		<link>http://www.fishonsky.com/archives/37926.html</link>
		<comments>http://www.fishonsky.com/archives/37926.html#comments</comments>
		<pubDate>Wed, 01 Sep 2010 15:54:52 +0000</pubDate>
		<dc:creator>flyingfish</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[日志]]></category>
		<category><![CDATA[回溯]]></category>
		<category><![CDATA[楼梯问题]]></category>
		<category><![CDATA[迭代]]></category>
		<category><![CDATA[递归]]></category>

		<guid isPermaLink="false">http://www.fishonsky.com/archives/37926.html</guid>
		<description><![CDATA[&#160;&#160;&#160;&#160;&#160; 长久以来一直对递归一知半解。最近看面试方面的书，在数据结构中有很多算法是和递归有关的，另外一些经典问题：打靶问题、8皇后问题、0-1背包问题也和递归有关，在有些算法中递归甚至是必不可少的，因此很有必要把递归算法再重新学一下。
&#160;&#160;&#160;&#160;&#160; 首先说一下递归和迭代的区别。迭代是反复的意思，有时候也指重复执行和反复执行。迭代一般是通过循环执行一组指令，并且在每次执行后都会从变量的原值推出它的新值。迭代往往需要一个迭代表达式，如f(n+1)=f(n)+f(n-1)。大家可以看出递归中的经典案例N！也可以通过迭代来做，而且更高效（因为迭代相比递归一般要高效很多）。
&#160;&#160;&#160;&#160;&#160; 下面就来谈递归。递归的基本思想是把规模大的问题转化为规模小的相似的子问题来解决。在函数实现时，因为解决大问题的方法和解决小问题的方法往往是同一个方法，所以就产生了函数调用它自身的情况。另外这个解决问题的函数必须有明显的结束条件，这样就不会产生无限递归的情况了。文[1]中对于递归讲解比较细致，大家可以参考。下面展示两段代码[1]：
返回一个二叉树的深度：


int depth(Tree t){
  &#160;&#160;&#160; if(!t) return 0; 

&#160;&#160;&#160; else { 

&#160;&#160;&#160;&#160;&#160;&#160;&#160; int a=depth(t.right); 

&#160;&#160;&#160;&#160;&#160;&#160;&#160; int b=depth(t.left); 

&#160;&#160;&#160;&#160;&#160;&#160;&#160; return (a&#62;b)?(a+1):(b+1); 

&#160;&#160;&#160; } 

}

判断一个二叉树是否平衡：


int isB(Tree t){
  &#160;&#160;&#160; if(!t) return 0; 

&#160;&#160;&#160; int left=isB(t.left); 

&#160;&#160;&#160; int right=isB(t.right); 

&#160;&#160;&#160; if( left &#62;=0 &#38;&#38; right &#62;=0 &#38;&#38; left - right &#60;= 1 &#124;&#124; left -right [...]]]></description>
			<content:encoded><![CDATA[<p>&#160;&#160;&#160;&#160;&#160; 长久以来一直对递归一知半解。最近看面试方面的书，在数据结构中有很多算法是和递归有关的，另外一些经典问题：打靶问题、8皇后问题、0-1背包问题也和递归有关，在有些算法中递归甚至是必不可少的，因此很有必要把递归算法再重新学一下。</p>
<p>&#160;&#160;&#160;&#160;&#160; 首先说一下递归和迭代的区别。迭代是反复的意思，有时候也指重复执行和反复执行。迭代一般是通过循环执行一组指令，并且在每次执行后都会从变量的原值推出它的新值。迭代往往需要一个迭代表达式，如f(n+1)=f(n)+f(n-1)。大家可以看出递归中的经典案例N！也可以通过迭代来做，而且更高效（因为迭代相比递归一般要高效很多）。</p>
<p>&#160;&#160;&#160;&#160;&#160; 下面就来谈递归。递归的基本思想是把规模大的问题转化为规模小的相似的子问题来解决。在函数实现时，因为解决大问题的方法和解决小问题的方法往往是同一个方法，所以就产生了函数调用它自身的情况。另外这个解决问题的函数必须有明显的结束条件，这样就不会产生无限递归的情况了。文[1]中对于递归讲解比较细致，大家可以参考。下面展示两段代码[1]：</p>
<p>返回一个二叉树的深度：</p>
<pre class="brush:cpp">

int depth(Tree t){
  &#160;&#160;&#160; if(!t) return 0; 

&#160;&#160;&#160; else { 

&#160;&#160;&#160;&#160;&#160;&#160;&#160; int a=depth(t.right); 

&#160;&#160;&#160;&#160;&#160;&#160;&#160; int b=depth(t.left); 

&#160;&#160;&#160;&#160;&#160;&#160;&#160; return (a&gt;b)?(a+1):(b+1); 

&#160;&#160;&#160; } 

}
</pre>
<p>判断一个二叉树是否平衡：</p>
<pre class="brush:cpp">

int isB(Tree t){
  &#160;&#160;&#160; if(!t) return 0; 

&#160;&#160;&#160; int left=isB(t.left); 

&#160;&#160;&#160; int right=isB(t.right); 

&#160;&#160;&#160; if( left &gt;=0 &amp;&amp; right &gt;=0 &amp;&amp; left - right &lt;= 1 || left -right &gt;=-1) 

&#160;&#160;&#160;&#160;&#160;&#160;&#160; return (left&lt;right)? (right +1) : (left + 1); 

&#160;&#160;&#160; else return -1; 

} 
</pre>
<p>&#160;&#160;&#160; 第一个算法还是比较好理解的，但第二个就不那么好理解了。第一个算法的思想是：如果这个树是空，则返回0；否则先求左边树的深度，再求右边数的深度，然后对这两个值进行比较哪个大就取哪个值+1。而第二个算法，首先应该明白isB函数的功能，它对于空树返回0，对于平衡树返回树的深度，对于不平衡树返回-1。明白了函数的功能再看代码就明白多了，只要有一个函数返回了-1，则整个函数就会返回-1。（具体过程只要认真看下就明白了）</p>
<p>&#160;&#160;&#160; 对于递归，<strong>最好的理解方式便是从函数的功能意义的层面来理解</strong>。了解一个问题如何被分解为它的子问题，这样对于递归函数代码也就理解了。这里有一个误区（我也曾深陷其中），就是通过分析堆栈，分析一个一个函数的调用过程、输出结果来分析递归的算法。这是十分要不得的，这样只会把自己弄晕，其实递归本质上也是函数的调用，调用的函数是自己或者不是自己其实没什么区别。在函数调用时总会把一些临时信息保存到堆栈，堆栈只是为了函数能正确的返回，仅此而已。我们只要知道递归会导致大量的函数调用，大量的堆栈操作就可以了。</p>
<p>&#160;&#160;&#160; 下面介绍和递归密切相关的算法：回溯算法。回溯算法是一种搜索算法，它可以通过对问题从一个状态出发，搜索从该状态出发的所有状态，当一条路走到尽头时，再后退一步继续搜索，直到所有路径都试探过。回溯算法通常由递归来实现，因为递归结束时会返回调用处（上一步），回溯结束时也是返回上一步，两者可以很好的契合。文[2]中对于回溯的讲解挺详细的，大家可以参考下。这里引用文中的一段话，我觉得写的挺好的：“通过把递归结束的条件设置到搜索的最后一步，就可以借用递归的特性来回溯了。因为合法的递归调用总是要回到它的上一层调用的，那么在回溯搜索中，回到上一层调用就是回到了前一个步骤。当在当前步骤找不到一种符合条件情况时，那么后续情况也就不用考虑了，所以就让递归调用返回上一层（也就是回到前一个步骤）找一个以前没有尝试过的情况继续进行。当然有时候为了能够正常的进行继续搜索，需要恢复以前的调用环境。”。下面通过一个例子来介绍递归回溯的实现</p>
<p>楼梯问题：假设一个楼梯共有10级台阶，一个人可以选择一次走1级或2级台阶，请问总共有多少种不同走法？</p>
<p>&#160;&#160;&#160; 这个问题是之前一个师兄跟我说的，当时考虑了好久也不得其解，现在通过递归回溯算法来解决它。具体代码如下：</p>
<pre class="brush:cpp">

#include &lt;iostream&gt; 

using namespace std; 

const int STAIRS=10;
  const int MAX_STEP=2; 

int result_number=1;
  int steps[STAIRS]; 

void print_result(){
  &#160;&#160;&#160; cout&lt;&lt;&quot;This is the &quot;&lt;&lt;result_number++&lt;&lt;&quot; result: &quot;&lt;&lt;endl;

&#160;&#160;&#160; for(int i=0;i&lt;STAIRS;i++){

&#160;&#160;&#160;&#160;&#160;&#160;&#160; if(steps[i]==0){

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; break;

&#160;&#160;&#160;&#160;&#160;&#160;&#160; }

&#160;&#160;&#160;&#160;&#160;&#160;&#160; cout&lt;&lt;steps[i]&lt;&lt;&quot; &quot;;

&#160;&#160;&#160; }

&#160;&#160;&#160; cout&lt;&lt;endl;

} 

void do_step(int stairs,int step_number){
  &#160;&#160;&#160; if(stairs==1){

&#160;&#160;&#160;&#160;&#160;&#160;&#160; steps[step_number]=1;

&#160;&#160;&#160;&#160;&#160;&#160;&#160; print_result();

&#160;&#160;&#160;&#160;&#160;&#160;&#160; steps[step_number]=0;

&#160;&#160;&#160;&#160;&#160;&#160;&#160; steps[step_number-1]=0;

&#160;&#160;&#160;&#160;&#160;&#160;&#160; return;

&#160;&#160;&#160; }

&#160;&#160;&#160; else if(stairs==0){

&#160;&#160;&#160;&#160;&#160;&#160;&#160; print_result();

&#160;&#160;&#160;&#160;&#160;&#160;&#160; steps[step_number-1]=0;

&#160;&#160;&#160;&#160;&#160;&#160;&#160; return;

&#160;&#160;&#160; }

&#160;&#160;&#160; else{

&#160;&#160;&#160;&#160;&#160;&#160;&#160; for(int i=1;i&lt;=MAX_STEP;i++){

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160;&#160; if(stairs-i&lt;0){

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; break;

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; steps[step_number]=i;

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; do_step(stairs-i,step_number+1);

&#160;&#160;&#160;&#160;&#160;&#160;&#160; }

　&#160;&#160;&#160; }

} 

int main(){
  &#160;&#160;&#160; cout&lt;&lt;&quot;the program started...&quot;&lt;&lt;endl;

&#160;&#160;&#160; do_step(STAIRS,0);

&#160;&#160;&#160; cout&lt;&lt;&quot;there are &quot;&lt;&lt;result_number-1&lt;&lt;&quot; results.&quot;&lt;&lt;endl;

}
</pre>
<p>&#160;&#160;&#160;&#160; do_step函数的功能是：当执行时如果参数stairs为1，或0，则直接输出结果，并且把steps[]恢复到上一步的状态，退出函数。如果stairs大于1，则尝试分别走1步和2步，此后问题转化为原问题的子问题。明白了函数的功能就很容易看懂代码了。该函数中出现了for循环嵌套 递归的情况，大家只要认为是多次执行其中的代码就可以了（那个我们不理解的复杂的函数堆栈调用关系可以正确无误的实现我们要求的函数调用，呵呵）。程序会列出每个结果，总的可行走法共89种。</p>
<p>&#160;&#160;&#160; 大家了解了回溯算法后就可以解决一大类问题了，包括上面说的打靶问题、8皇后问题等。大家也可以尝试通过回溯算法来解决“数独”问题，通过搜索来查找可行的数独解（也算是个小小的挑战吧，^_^）。&#160; </p>
<p>参考资料：</p>
<p>[1] 漫谈递归思想 <a title="http://www.cnblogs.com/BLoodMaster/archive/2010/03/23/1692641.html" href="http://www.cnblogs.com/BLoodMaster/archive/2010/03/23/1692641.html" target="_blank">http://www.cnblogs.com/BLoodMaster/archive/2010/03/23/1692641.html</a></p>
<p>[2] 递归回溯总结 <a title="http://hi.baidu.com/sulipol/blog/item/32411851bb9724551138c2eb.html" href="http://hi.baidu.com/sulipol/blog/item/32411851bb9724551138c2eb.html" target="_blank">http://hi.baidu.com/sulipol/blog/item/32411851bb9724551138c2eb.html</a></p>
<p>[3] 《程序员面试宝典》第8章 循环、递归与概率</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fishonsky.com/archives/37926.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>fedora下gruff的安装使用</title>
		<link>http://www.fishonsky.com/archives/37912.html</link>
		<comments>http://www.fishonsky.com/archives/37912.html#comments</comments>
		<pubDate>Mon, 09 Aug 2010 06:22:19 +0000</pubDate>
		<dc:creator>flyingfish</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[日志]]></category>
		<category><![CDATA[fedora]]></category>
		<category><![CDATA[gruff安装]]></category>
		<category><![CDATA[数据图表]]></category>
		<category><![CDATA[示例]]></category>

		<guid isPermaLink="false">http://www.fishonsky.com/?p=37912</guid>
		<description><![CDATA[最近一段时间一直在准备着找工作，学各种东西。期间还是感觉很有收获的，等有时间整理一下然后发布出来。实验室的项目也还在进行，不过我的工作相对少了很多（因为快要毕业了嘛，还是很感激老师能体谅我们的，^_^）。
目前我在项目中的任务是做一个系统的图形界面。当初也不知道怎么想的，竟然想用web形式来实现，也许是为了不让自己之前学的ruby和rails不要白费吧，呵呵。现在想想Web GUI的想法的确挺好的，由于ruby的类库丰富，开发相对还是比较轻松的，不过为了让C++系统和rails的能正常交互消息还是需要学一下http类库libcurl方面的知识（这些知识它的官网上有很多，也很详细）。
由于项目的需要，我们的图形界面上需要显示一些数据的分析图表，使用ruby的gruff工具包可以绘制很好的数据分析图表。下面说下linux环境下gruff的安装和使用，安装过程如下：
1、首先安装ruby-1.8.6环境以及ruby gems，大家可以在网上找相关的教程。
2、安装ImageMagick的库，gruff的运行依赖于这些库
yum install ImageMagick

yum install ImageMagick-devel
3、安装TrueType字体。ImageMagick在画图时需要用到这个库。有些linux版本会默认安装，那样的话大家就可以跳过这步了
wget http://www.osresources.com/files/centos-windows-fonts/msfonts.tbz

mkdir /usr/share/fonts/default/TrueType

tar xvjpf msfonts.tbz -C /usr/share/fonts/default/TrueType/
4、安装 rmagick 的gem包
gem install rmagick
5、安装gruff所需的gem包。gruff包会依赖以下包：json_pure、rubyforge、hoe、rake
gem install gruff
至此gruff就安装完成了。下面介绍一个gruff的代码实例，实例中会绘制一个柱状图，其他类型的图的画法请参考gruff的rdoc文档。
示例代码如下：
require 'rubygems'
require 'gruff'

g = Gruff::Bar.new(600)        # The graph will be 600 pixels wide.
g.bar_spacing = 0.5   # the bars' space
g.title = 'The Nodes\'s Load'
g.theme_37signals        # The best-looking theme, in my options.

load_info_1=[21,3,6,14,7,11,19]   #the data information, you can use you [...]]]></description>
			<content:encoded><![CDATA[<p>最近一段时间一直在准备着找工作，学各种东西。期间还是感觉很有收获的，等有时间整理一下然后发布出来。实验室的项目也还在进行，不过我的工作相对少了很多（因为快要毕业了嘛，还是很感激老师能体谅我们的，^_^）。</p>
<p>目前我在项目中的任务是做一个系统的图形界面。当初也不知道怎么想的，竟然想用web形式来实现，也许是为了不让自己之前学的ruby和rails不要白费吧，呵呵。现在想想Web GUI的想法的确挺好的，由于ruby的类库丰富，开发相对还是比较轻松的，不过为了让C++系统和rails的能正常交互消息还是需要学一下http类库libcurl方面的知识（这些知识它的官网上有很多，也很详细）。</p>
<p>由于项目的需要，我们的图形界面上需要显示一些数据的分析图表，使用ruby的gruff工具包可以绘制很好的数据分析图表。下面说下linux环境下gruff的安装和使用，安装过程如下：</p>
<p>1、首先安装ruby-1.8.6环境以及ruby gems，大家可以在网上找相关的教程。</p>
<p>2、安装ImageMagick的库，gruff的运行依赖于这些库</p>
<pre class="brush:bash">yum install ImageMagick

yum install ImageMagick-devel</pre>
<p>3、安装TrueType字体。ImageMagick在画图时需要用到这个库。有些linux版本会默认安装，那样的话大家就可以跳过这步了</p>
<pre class="brush:bash">wget http://www.osresources.com/files/centos-windows-fonts/msfonts.tbz

mkdir /usr/share/fonts/default/TrueType

tar xvjpf msfonts.tbz -C /usr/share/fonts/default/TrueType/</pre>
<p>4、安装 rmagick 的gem包</p>
<pre class="brush:bash">gem install rmagick</pre>
<p>5、安装gruff所需的gem包。gruff包会依赖以下包：json_pure、rubyforge、hoe、rake</p>
<pre class="brush:bash">gem install gruff</pre>
<p>至此gruff就安装完成了。下面介绍一个gruff的代码实例，实例中会绘制一个柱状图，其他类型的图的画法请参考gruff的rdoc文档。</p>
<p>示例代码如下：</p>
<pre class="brush:ruby">require 'rubygems'
require 'gruff'

g = Gruff::Bar.new(600)        # The graph will be 600 pixels wide.
g.bar_spacing = 0.5   # the bars' space
g.title = 'The Nodes\'s Load'
g.theme_37signals        # The best-looking theme, in my options.

load_info_1=[21,3,6,14,7,11,19]   #the data information, you can use you own data here.
load_info_2=[8,27,13,4,9,14,10]

range = (1..7)
g.data('Node 1', range.collect { |x| load_info_1[x-1] })
g.data('Node 2', range.collect { |x| load_info_2[x-1]})

g.labels = {2 =&gt; 'n=2', 4 =&gt; 'n=4', 6 =&gt;'n=6' }
g.write('load_info_bar.png')</pre>
<p>输出结果图片如下：</p>
<p><a href="http://www.fishonsky.com/wp-content/uploads/2010/08/load_info_bar1.png"><img style="display: block; float: none; margin-left: auto; margin-right: auto; border-width: 0px;" title="load_info_bar" src="http://www.fishonsky.com/wp-content/uploads/2010/08/load_info_bar_thumb1.png" border="0" alt="load_info_bar" width="604" height="454" /></a></p>
<p>可以看出，gruff生成的图片还是挺漂亮的。我这里的数据是自己任意写的，没什么实际的意义。</p>
<p>PS：我个人还是很喜欢Ruby语言的，它的语法优美，代码看起来很像伪代码，很易读；它有丰富的类库，对文本处理的功能很强。大家如果想学一门脚本语言的话建议学习Ruby，可以很好的提高你的工作效率，呵呵</p>
<p>参考资料：</p>
<p>[1]<a title="http://hi.baidu.com/rainchen/blog/item/089ef7364497de320a55a9a3.html" href="http://hi.baidu.com/rainchen/blog/item/089ef7364497de320a55a9a3.html">http://hi.baidu.com/rainchen/blog/item/089ef7364497de320a55a9a3.html</a></p>
<p>[2] Ruby Cookbook:  Recipe 12.4. Graphing Data</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fishonsky.com/archives/37912.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>blog主题更新</title>
		<link>http://www.fishonsky.com/archives/37908.html</link>
		<comments>http://www.fishonsky.com/archives/37908.html#comments</comments>
		<pubDate>Thu, 01 Jul 2010 06:08:24 +0000</pubDate>
		<dc:creator>flyingfish</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[日志]]></category>
		<category><![CDATA[WP Theme]]></category>
		<category><![CDATA[WP 插件]]></category>

		<guid isPermaLink="false">http://www.fishonsky.com/?p=37908</guid>
		<description><![CDATA[&#160;&#160;&#160;&#160; 鼓捣了好久wordpress主题，发现还是最开始的主题比较好。之前换其他主题主要是因为文章栏太窄了，当显示前面的游戏的时候显示不完整。之后在网上下了很多别人推荐的主题，包括Stripey、BlackGelly、Manly、pyrmont等，这些主题初看起来的确不错，漂亮的外观和字体，但当真正使用时才发现各种问题。因为我的blog现在装了很多插件，如代码显示还有评论表情，嵌套评论等，当采用新主题时，要么插件不能使用，要么显示错误。而且这些主题也有不同的缺点，页面的边栏中的内容要么太少，要么太多。
&#160;&#160;&#160;&#160; 现在才明白，真正好用的主题还得自己动手改。自己花了段时间对页面的布局进行调整，主要是修改背景图片和css样式。幸运的是在网上找到了这个主题的头部的图像的psd文件，可以方便的对图像进行缩放等简单的修改而不损失图像质量。我现在的主题是glossyblue，最初在yo2的时候也是用的这个主题。目前安装的插件如下：

Akismet :用来抵制垃圾评论的。装上这个插件后垃圾评论少了好多，我的邮箱也清净好多。 
Custom Smiles：用来评论中使用表情的，挺好用的 
Add From Server：用来往wordpress中上传文件的，比wordpress自带的上传工具要好用得多 
Syntax Highlighter and Code Prettifier Plugin for WordPress :用来显示代码的插件，这个插件的功能还是比较强大的，可以支持各种语言，c/cpp, bash、java、ruby等 
Wordpress Thread Comment ：由于我的主题自身不支持嵌套评论，所以用了这个插件 
WP SlimStat ：wordpress的统计工具，可以统计博客的访问量，有哪些页面比较流行，访问者所用的浏览器，最近的关键词等，信息很多，很好用 

&#160;&#160;&#160;&#160; 另外推荐一个网址 一些不错的WordPress主题下载站 ，上面有好多很好的主题，大家可以根据自己的需要修改。大家如果有什么关于WP主题的问题或意见欢迎交流。
&#160;&#160;&#160;&#160; PS：最近在试用Windows Live Writer，一个wordpress的离线编辑器，目前感觉还是挺好用的，大家也可以试试。。。
]]></description>
			<content:encoded><![CDATA[<p>&#160;&#160;&#160;&#160; 鼓捣了好久wordpress主题，发现还是最开始的主题比较好。之前换其他主题主要是因为文章栏太窄了，当显示前面的游戏的时候显示不完整。之后在网上下了很多别人推荐的主题，包括Stripey、BlackGelly、Manly、pyrmont等，这些主题初看起来的确不错，漂亮的外观和字体，但当真正使用时才发现各种问题。因为我的blog现在装了很多插件，如代码显示还有评论表情，嵌套评论等，当采用新主题时，要么插件不能使用，要么显示错误。而且这些主题也有不同的缺点，页面的边栏中的内容要么太少，要么太多。</p>
<p>&#160;&#160;&#160;&#160; 现在才明白，真正好用的主题还得自己动手改。自己花了段时间对页面的布局进行调整，主要是修改背景图片和css样式。幸运的是在网上找到了这个主题的头部的图像的psd文件，可以方便的对图像进行缩放等简单的修改而不损失图像质量。我现在的主题是glossyblue，最初在yo2的时候也是用的这个主题。目前安装的插件如下：</p>
<ul>
<li>Akismet :用来抵制垃圾评论的。装上这个插件后垃圾评论少了好多，我的邮箱也清净好多。 </li>
<li>Custom Smiles：用来评论中使用表情的，挺好用的 </li>
<li>Add From Server：用来往wordpress中上传文件的，比wordpress自带的上传工具要好用得多 </li>
<li>Syntax Highlighter and Code Prettifier Plugin for WordPress :用来显示代码的插件，这个插件的功能还是比较强大的，可以支持各种语言，c/cpp, bash、java、ruby等 </li>
<li>Wordpress Thread Comment ：由于我的主题自身不支持嵌套评论，所以用了这个插件 </li>
<li>WP SlimStat ：wordpress的统计工具，可以统计博客的访问量，有哪些页面比较流行，访问者所用的浏览器，最近的关键词等，信息很多，很好用 </li>
</ul>
<p>&#160;&#160;&#160;&#160; 另外推荐一个网址 <a href="http://www.zhukun.net/archives/1370">一些不错的WordPress主题下载站</a> ，上面有好多很好的主题，大家可以根据自己的需要修改。大家如果有什么关于WP主题的问题或意见欢迎交流。</p>
<p>&#160;&#160;&#160;&#160; PS：最近在试用Windows Live Writer，一个wordpress的离线编辑器，目前感觉还是挺好用的，大家也可以试试。。。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fishonsky.com/archives/37908.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux程序输入、输出重定向</title>
		<link>http://www.fishonsky.com/archives/37897.html</link>
		<comments>http://www.fishonsky.com/archives/37897.html#comments</comments>
		<pubDate>Tue, 29 Jun 2010 07:55:23 +0000</pubDate>
		<dc:creator>flyingfish</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[输入]]></category>
		<category><![CDATA[输出]]></category>
		<category><![CDATA[重定向]]></category>

		<guid isPermaLink="false">http://www.fishonsky.com/?p=37897</guid>
		<description><![CDATA[对于输出重定向大家应该都比较了解了，一般都是指把输出重定向到一个文件中，而对于输入重定向一般就不是很常用了。暂时的一个应用就是实现程序的脚本控制，比如你用脚本启动另一个程序，然后又需要给这个启动的程序发送命令，这时就需要采用输入重定向了，这对于一些服务类型的程序还是很有用的。要实现真正意义的输入重定向还是比较麻烦的，需要用到管道。
下面用一个简单的示例来实现程序的输入，输出重定向。
//file_name:shi_li.cpp
#include &#60;stdio.h&#62;
#include &#60;stdlib.h&#62;
#include &#60;unistd.h&#62;
#include &#60;sys/types.h&#62;
#include &#60;sys/stat.h&#62;
#include &#60;fcntl.h&#62;
#include &#60;string.h&#62;
#include &#60;signal.h&#62;

#define MAX_LINE 80
#define PIPE_STDIN  0
#define PIPE_STDOUT 1

int main(){
 int child_pid;

 char outPath[30];
 strcpy(outPath,"./out.file");

 int pfds[2];
 if (pipe(pfds)== 0){
  child_pid=fork();
  //in child process the return pid==0
  if ( child_pid == 0 ) {

   //input file,may be used later.
   //char inPath[30];
   //strcpy(inPath,"./in.file");

   //int inFd = open(inPath,O_RDWR&#124;O_CREAT,S_IRUSR&#124;S_IWUSR);
   int outFd = open(outPath,O_WRONLY&#124;O_APPEND&#124;O_CREAT,S_IRUSR);

   close(0);
   dup2( pfds[PIPE_STDIN], 0);
   dup2(outFd,1);
   close(pfds[PIPE_STDOUT]);
   execl("./getstring","getstring",NULL);
   printf("start getstring: error!!!");
   exit(1);
          }
  else {

   close(pfds[PIPE_STDIN]);
       char msg[MAX_LINE];
         int b=1;
        for(b=1;b&#60;6;b++){              
         [...]]]></description>
			<content:encoded><![CDATA[<p>对于输出重定向大家应该都比较了解了，一般都是指把输出重定向到一个文件中，而对于输入重定向一般就不是很常用了。暂时的一个应用就是实现程序的脚本控制，比如你用脚本启动另一个程序，然后又需要给这个启动的程序发送命令，这时就需要采用输入重定向了，这对于一些服务类型的程序还是很有用的。要实现真正意义的输入重定向还是比较麻烦的，需要用到管道。</p>
<p>下面用一个简单的示例来实现程序的输入，输出重定向。</p>
<pre class="brush:cpp">//file_name:shi_li.cpp
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;unistd.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;sys/stat.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;string.h&gt;
#include &lt;signal.h&gt;

#define MAX_LINE 80
#define PIPE_STDIN  0
#define PIPE_STDOUT 1

int main(){
 int child_pid;

 char outPath[30];
 strcpy(outPath,"./out.file");

 int pfds[2];
 if (pipe(pfds)== 0){
  child_pid=fork();
  //in child process the return pid==0
  if ( child_pid == 0 ) {

   //input file,may be used later.
   //char inPath[30];
   //strcpy(inPath,"./in.file");

   //int inFd = open(inPath,O_RDWR|O_CREAT,S_IRUSR|S_IWUSR);
   int outFd = open(outPath,O_WRONLY|O_APPEND|O_CREAT,S_IRUSR);

   close(0);
   dup2( pfds[PIPE_STDIN], 0);
   dup2(outFd,1);
   close(pfds[PIPE_STDOUT]);
   execl("./getstring","getstring",NULL);
   printf("start getstring: error!!!");
   exit(1);
          }
  else {

   close(pfds[PIPE_STDIN]);
       char msg[MAX_LINE];
         int b=1;
        for(b=1;b&lt;6;b++){              
           sleep(1);
             sprintf(msg,"2+%d\n",b); 
             write( pfds[PIPE_STDOUT], msg, strlen(msg) );              
                 }
         close(pfds[PIPE_STDOUT]);
         sleep(2);
         printf("all done.\n");
         }
       }
 return 0;
} </pre>
<p>接下来是一个很简单的程序输入:</p>
<pre class="brush:cpp">//file_name: getstring.cpp

#include &lt;unistd.h&gt;
#include &lt;iostream&gt;
using namespace std;

int main(){ 
 string tmp;

 while(cin &gt;&gt; tmp,!cin.eof()){
  if(cin.bad()){  
   cerr&lt;&lt;"io stream error"&lt;&lt;endl;
   exit(1); 
  }
  if(cin.fail()){
   cerr&lt;&lt;"io stream error"&lt;&lt;endl;
   cin.clear(istream::failbit);
   continue;
  }
  //ok to process 
  cout&lt;&lt;"all done well:"&lt;&lt;tmp&lt;&lt;endl;
 }
}</pre>
<p>编译并运行：</p>
<pre class="brush:bash">#g++ -o getstring getstring.cpp
#g++ -o shi_li shi_li.cpp
#./shi_li</pre>
<p>上述代码包括两个小程序，getstring简单的接收输入的字符串并在终端上回显。shi_li程序负责启动getstring并把输入重定向到管道，输出重定向到out.file文件。执行代码后我们可以查看out.file文件来获得程序执行的结果。</p>
<p>上述小程序可以用在脚本时对向子程序发送命令，从而完成程序测试的自动化。上述代码只是个demo，如果想在实际测试中可用还需要根据自己的情况进行些许修改。</p>
<p>参考资料：</p>
<p>[1] http://blog.chinaunix.net/u/19573/showart_1225848.html</p>
<p>[2]http://www.opengroup.org/onlinepubs/009695399/</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fishonsky.com/archives/37897.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[转]Manufactoria：非常好玩的自动机编程游戏</title>
		<link>http://www.fishonsky.com/archives/37881.html</link>
		<comments>http://www.fishonsky.com/archives/37881.html#comments</comments>
		<pubDate>Wed, 09 Jun 2010 08:48:24 +0000</pubDate>
		<dc:creator>flyingfish</dc:creator>
				<category><![CDATA[BrainStorm]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[编程游戏]]></category>

		<guid isPermaLink="false">http://www.fishonsky.com/?p=37881</guid>
		<description><![CDATA[这是我在Matrix67上看到的一个很好玩的自动机编程游戏。很遗憾我自己还没玩通关，呵呵。
游戏介绍：它是真正意义上的程序设计游戏，游戏不但提供了完备的读写和流程控制功能，甚至还引入了随机测试数据。游戏很快就会引入算法的思想，因为玩家渐渐会发现，这些谜题并不是单靠模拟就能解决的；后面的谜题则越发困难，需要相当有技巧性的算法设计，对脑力绝对是一个大挑战。如果你热爱算法与程序设计，你一定会爱上这个游戏的。

原文地址：http://www.matrix67.com/blog/archives/3306
游戏来源：http://jayisgames.com/games/manufactoria/
]]></description>
			<content:encoded><![CDATA[<p>这是我在<a title="Matrix67" href="http://www.matrix67.com" target="_blank">Matrix67</a>上看到的一个很好玩的自动机编程游戏。很遗憾我自己还没玩通关，呵呵。</p>
<p><strong>游戏介绍</strong>：它是真正意义上的程序设计游戏，游戏不但提供了完备的读写和流程控制功能，甚至还引入了随机测试数据。游戏很快就会引入算法的思想，因为玩家渐渐会发现，这些谜题并不是单靠模拟就能解决的；后面的谜题则越发困难，需要相当有技巧性的算法设计，对脑力绝对是一个大挑战。如果你热爱算法与程序设计，你一定会爱上这个游戏的。</p>
<p><object id="flashobj" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="640" height="480" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="align" value="middle" /><param name="allowScriptAccess" value="sameDomain" /><param name="allowFullScreen" value="false" /><param name="quality" value="high" /><param name="src" value="http://www.fishonsky.com/wp-content/uploads/2010/06/manufactoria.swf" /><param name="name" value="flashcontent" /><param name="allowfullscreen" value="false" /><embed id="flashobj" type="application/x-shockwave-flash" width="640" height="480" src="http://www.fishonsky.com/wp-content/uploads/2010/06/manufactoria.swf" name="flashcontent" quality="high" allowfullscreen="false" allowscriptaccess="sameDomain" align="middle"></embed></object></p>
<p>原文地址：<a href="http://www.matrix67.com/blog/archives/3306" target="_blank">http://www.matrix67.com/blog/archives/3306</a></p>
<p>游戏来源：<a href="http://jayisgames.com/games/manufactoria/" target="_blank">http://jayisgames.com/games/manufactoria/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.fishonsky.com/archives/37881.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ubuntu下成功安装sfslite</title>
		<link>http://www.fishonsky.com/archives/37875.html</link>
		<comments>http://www.fishonsky.com/archives/37875.html#comments</comments>
		<pubDate>Tue, 01 Jun 2010 11:56:59 +0000</pubDate>
		<dc:creator>flyingfish</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[chord]]></category>
		<category><![CDATA[gcc-4.1.2]]></category>
		<category><![CDATA[sfslite]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.fishonsky.com/?p=37875</guid>
		<description><![CDATA[之前曾采用MIT的开源chord来开发P2P的系统，由于chord依赖于sfslite的一些库文件，所以需要安装sfslite-0.8.16。自此带来了很多问题，因为sfslite需要gcc-4.1.2才能编译，用最新的gcc-4.3或4.4都会编译失败，而且它好像还和操作系统有关，在fedora 7下可以正常编译。如果您不想使用fedora 7这种老版本的系统那就麻烦了。
最近新安装了ubuntu 10，突然想在ubuntu下尝试一下，这样后续的开发就不用再装fedora 7的虚拟机了，而且也可以方便程序的移植。下面简要介绍安装的过程：
首先安装gcc-4.1.2,具体安装过程参考“在ubuntu中编译、安装gcc 4.1.1过程以及遇到的问题”，上面讲的很详细。主要有一个地方需要注意，gcc-4.1.2依赖texinfo库，默然configure不支持texinfo 4.10+，需要修改configure文件。在其中找到&#8217;texinfo[^0-9]*([1-3][0-9]&#124;4\.[2-9]&#124;[5-9])&#8217;编辑成&#8217;texinfo[^0-9]*([1-3][0-9]&#124;4\.[2-9]&#124;4\.[1-9][0-9]*&#124;[5-9])&#8217;后保存，编译通过。[注] 无需修改LD_LIBRARY_PATH变量，在ubuntu下没有这个变量，因为已经被废除了，直接安装好后就可以使用了。
[tips]可以使用ubuntu中自带的 update-alternatives 命令来方便的进行多个gcc版本之间的切换（具体命令使用可以在google上搜）。
接下来就是使用gcc 4.1.2来编译sfslite，首先下载sfslite-0.8.16的tar包。（不要使用sfslite-0.8.17，编译会出错）
然后解压，进入源文件根目录，输入 ./configure &#8211;with-sfsmisc (with前是两个-) 只要这一个选项就可以了，不用输&#8211;with-dmalloc
接下来如果直接make的话会出错，会提示 unknown sizeof  ucred 。在网上找了很久，终于发现只有在编译时加上-D_GNU_SOURCE才可以。在gcc编译选项中增加 -D_GNU_SOURCE,这需要改makefile文件。具体为async和arpc目录下的Makefile文件中找到“ECFLAGS =” 改为：“ECFLAGS = -D_GNU_SOURCE”
然后编译安装即可。
]]></description>
			<content:encoded><![CDATA[<p>之前曾采用MIT的开源chord来开发P2P的系统，由于chord依赖于sfslite的一些库文件，所以需要安装sfslite-0.8.16。自此带来了很多问题，因为sfslite需要gcc-4.1.2才能编译，用最新的gcc-4.3或4.4都会编译失败，而且它好像还和操作系统有关，在fedora 7下可以正常编译。如果您不想使用fedora 7这种老版本的系统那就麻烦了。</p>
<p>最近新安装了ubuntu 10，突然想在ubuntu下尝试一下，这样后续的开发就不用再装fedora 7的虚拟机了，而且也可以方便程序的移植。下面简要介绍安装的过程：</p>
<p>首先安装gcc-4.1.2,具体安装过程参考“<a href="http://hi.baidu.com/jakmax/blog/item/c114d1d1b69634df562c845a.html" target="_blank">在ubuntu中编译、安装gcc 4.1.1过程以及遇到的问题</a>”，上面讲的很详细。主要有一个地方需要注意，gcc-4.1.2依赖texinfo库，默然configure不支持texinfo 4.10+，需要修改configure文件。在其中找到&#8217;texinfo[^0-9]*([1-3][0-9]|4\.[2-9]|[5-9])&#8217;编辑成&#8217;texinfo[^0-9]*([1-3][0-9]|4\.[2-9]|4\.[1-9][0-9]*|[5-9])&#8217;后保存，编译通过。<strong>[注] </strong>无需修改LD_LIBRARY_PATH变量，在ubuntu下没有这个变量，因为已经被废除了，直接安装好后就可以使用了。</p>
<p>[tips]可以使用ubuntu中自带的 update-alternatives 命令来方便的进行多个gcc版本之间的切换（具体命令使用可以在google上搜）。</p>
<p>接下来就是使用gcc 4.1.2来编译sfslite，首先下载sfslite-0.8.16的tar包。（不要使用sfslite-0.8.17，编译会出错）</p>
<p>然后解压，进入源文件根目录，输入 ./configure &#8211;with-sfsmisc (with前是两个-) 只要这一个选项就可以了，不用输&#8211;with-dmalloc</p>
<p>接下来如果直接make的话会出错，会提示 unknown sizeof  ucred 。在网上找了很久，终于发现只有在编译时加上-D_GNU_SOURCE才可以。在gcc编译选项中增加 -D_GNU_SOURCE,这需要改makefile文件。具体为async和arpc目录下的Makefile文件中找到“ECFLAGS =” 改为：“ECFLAGS = -D_GNU_SOURCE”</p>
<p>然后编译安装即可。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fishonsky.com/archives/37875.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C++静态工厂模式（采用shared_ptr）</title>
		<link>http://www.fishonsky.com/archives/37869.html</link>
		<comments>http://www.fishonsky.com/archives/37869.html#comments</comments>
		<pubDate>Thu, 06 May 2010 08:13:42 +0000</pubDate>
		<dc:creator>flyingfish</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[shared_ptr]]></category>
		<category><![CDATA[静态工厂模式]]></category>

		<guid isPermaLink="false">http://www.fishonsky.com/?p=37869</guid>
		<description><![CDATA[    今天介绍另一个比较常用的设计模式：工厂模式。工厂模式是指通过声明一个工厂的接口，然后定义该接口的各个实现类来具体实现不同的工厂。这里不打算写这种一般的方式，而只是写一种简单的工厂模式：静态工厂模式。这种模式的扩展性不如一般工厂模式那么好，但对于我们一般的应用已经足够了（而且系统设计的太复杂也不是好事，呵呵），静态工厂在实际中还是很常用的。
    值得说明的是这次没有像一般工厂模式那样采用普通的指针，而是采用之前介绍的shared_ptr，这是因为采用智能指针就不必担心工厂中创建的对象的释放问题，因为智能指针会帮你做好这一切，^_^
       下面是示例代码，代码中每个类按照不同文件进行放置，这样也可以了解工厂模式的一个好处，减小使用者和创建的产品类之间的依赖关系，这会在后面说明。
FileName: product.h
#ifndef _PRODUCT_H_
#define _PRODUCT_H_

class Product{
 public:
  virtual void myFunc()=0;
};

#endif
FileName: product_one.h
#ifndef _PRODUCT_ONE_H_
#define _PRODUCT_ONE_H_

#include "product.h"

class ProductOne:public Product{
 public:
  ProductOne();
  ~ProductOne();
  void myFunc();
};
#endif
FileName: product_one.cpp
#include "product_one.h"
#include &#60;iostream&#62;

using namespace std;

ProductOne::ProductOne(){
 cout&#60;&#60;"product one: i have been builded."&#60;&#60;endl;
}

ProductOne::~ProductOne(){
  cout&#60;&#60;"Product one: i have been destroyed."&#60;&#60;endl;

}
void ProductOne::myFunc(){
 cout&#60;&#60;"product one myFunc done!"&#60;&#60;endl;
}
FileName: product_two.h
#ifndef _PRODUCT_TWO_H_
#define _PRODUCT_TWO_H_

#include "product.h"

class ProductTwo:public Product{
 public:
  ProductTwo();
  ~ProductTwo();
  void myFunc();
};

#endif
FileName: product_two.cpp
#include "product_two.h"
#include &#60;iostream&#62;

using namespace std;

ProductTwo::ProductTwo(){
 cout&#60;&#60;"product two: i have been builded."&#60;&#60;endl;
}

ProductTwo::~ProductTwo(){
  cout&#60;&#60;"Product [...]]]></description>
			<content:encoded><![CDATA[<p>    今天介绍另一个比较常用的设计模式：工厂模式。工厂模式是指通过声明一个工厂的接口，然后定义该接口的各个实现类来具体实现不同的工厂。这里不打算写这种一般的方式，而只是写一种简单的工厂模式：静态工厂模式。这种模式的扩展性不如一般工厂模式那么好，但对于我们一般的应用已经足够了（而且系统设计的太复杂也不是好事，呵呵），静态工厂在实际中还是很常用的。</p>
<p>    值得说明的是这次没有像一般工厂模式那样采用普通的指针，而是采用之前介绍的shared_ptr，这是因为采用智能指针就不必担心工厂中创建的对象的释放问题，因为智能指针会帮你做好这一切，^_^</p>
<p>       下面是示例代码，代码中每个类按照不同文件进行放置，这样也可以了解工厂模式的一个好处，减小使用者和创建的产品类之间的依赖关系，这会在后面说明。</p>
<p>FileName: product.h</p>
<pre class="brush:cpp">#ifndef _PRODUCT_H_
#define _PRODUCT_H_

class Product{
 public:
  virtual void myFunc()=0;
};

#endif</pre>
<p>FileName: product_one.h</p>
<pre class="brush:cpp">#ifndef _PRODUCT_ONE_H_
#define _PRODUCT_ONE_H_

#include "product.h"

class ProductOne:public Product{
 public:
  ProductOne();
  ~ProductOne();
  void myFunc();
};
#endif</pre>
<p>FileName: product_one.cpp</p>
<pre class="brush:cpp">#include "product_one.h"
#include &lt;iostream&gt;

using namespace std;

ProductOne::ProductOne(){
 cout&lt;&lt;"product one: i have been builded."&lt;&lt;endl;
}

ProductOne::~ProductOne(){
  cout&lt;&lt;"Product one: i have been destroyed."&lt;&lt;endl;

}
void ProductOne::myFunc(){
 cout&lt;&lt;"product one myFunc done!"&lt;&lt;endl;
}</pre>
<p>FileName: product_two.h</p>
<pre class="brush:cpp">#ifndef _PRODUCT_TWO_H_
#define _PRODUCT_TWO_H_

#include "product.h"

class ProductTwo:public Product{
 public:
  ProductTwo();
  ~ProductTwo();
  void myFunc();
};

#endif</pre>
<p>FileName: product_two.cpp</p>
<pre class="brush:cpp">#include "product_two.h"
#include &lt;iostream&gt;

using namespace std;

ProductTwo::ProductTwo(){
 cout&lt;&lt;"product two: i have been builded."&lt;&lt;endl;
}

ProductTwo::~ProductTwo(){
  cout&lt;&lt;"Product two: i have been destroyed."&lt;&lt;endl;
}

void ProductTwo::myFunc(){
 cout&lt;&lt;"product two myFunc done!"&lt;&lt;endl;
}</pre>
<p>FileName: product_factory.h</p>
<pre class="brush:cpp">#ifndef _PRODUCT_FACTORY_H_
#define _PRODUCT_FACTORY_H_

#include "product.h"
#include &lt;tr1/memory&gt;
#include &lt;string&gt;

class ProductFactory{
 public:
  static  std::tr1::shared_ptr&lt;Product&gt;  createProduct(std::string productDescript);
};

#endif</pre>
<p>FileName: product_factory.cpp</p>
<pre class="brush:cpp">#include "product_factory.h"
#include "product_one.h"
#include "product_two.h"

using namespace std;
using namespace std::tr1;

shared_ptr&lt;Product&gt; ProductFactory::createProduct(string productDescription){

 if(productDescription=="one"){
  shared_ptr&lt;Product&gt; productOne(new ProductOne());
  return productOne; 
  //you can also do like below.
  //return shared_ptr&lt;Product&gt; (new ProductOne());
 }
 else if(productDescription=="two"){
  shared_ptr&lt;Product&gt; productTwo(new ProductTwo());
  return productTwo; 
  //you can also do like below.
  //return shared_ptr&lt;Product&gt; (new ProductTwo());
 }
}</pre>
<p>FileName: test_factory.cpp</p>
<pre class="brush:cpp">#include "product.h"
#include "product_factory.h"
#include &lt;string&gt;
#include &lt;iostream&gt;
#include &lt;tr1/memory&gt;

using namespace std;
using namespace std::tr1;

int main(){
 cout&lt;&lt;"test 1 start..."&lt;&lt;endl;
 shared_ptr&lt;Product&gt; myProduct=ProductFactory::createProduct("one");

 myProduct-&gt;myFunc();

 cout&lt;&lt;endl&lt;&lt;"test 2 start..."&lt;&lt;endl;
 myProduct=ProductFactory::createProduct("two");
 myProduct-&gt;myFunc();
 { 
  cout&lt;&lt;endl&lt;&lt;"test 3 start..."&lt;&lt;endl;
  shared_ptr&lt;Product&gt; myProduct2=ProductFactory::createProduct("one");
  myProduct2-&gt;myFunc(); 
 }
 cout&lt;&lt;"all test done."&lt;&lt;endl&lt;&lt;endl;;
}</pre>
<p>编译然后运行：</p>
<pre class="brush:bash"># g++ -o test_factory  test_factory.cpp  product_one.cpp  product_two.cpp  product_factory.cpp
# ./test_factory</pre>
<p>运行结果如下：</p>
<pre class="brush:bash">test 1 start...
product one: i have been builded.
product one myFunc done!

test 2 start...
product two: i have been builded.
Product one: i have been destroyed.
product two myFunc done!

test 3 start...
product one: i have been builded.
product one myFunc done!
Product one: i have been destroyed.
all test done.

Product two: i have been destroyed.</pre>
<p>    从上面结果可以看出通过使用工厂模式，可以使实例对象的生成由工厂来完成，减小使用者test_factory与实例产品product_one、product_two的依赖，这样也有利于后续程序的维护，即使product_one后来取消了，改动的代码也不会很大。大家看下test_factory.cpp的包含文件可以看出使用者不需要知道实际的产品子类（不直接知道），减小了编译的依赖。</p>
<p>    通过采用shared_ptr智能指针，可以避免使用者忘记释放掉new产生的实例类。这也使得代码更加安全，不容易造成内存泄露，也更容易编写异常安全或异常中立的代码。</p>
<p>   [题外话]也可以看出shared_ptr对于继承派生有很好的支持，^_^</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fishonsky.com/archives/37869.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

