<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[南斗工作组]]></title> 
<link>http://www.nd21.com/index.php</link> 
<description><![CDATA[很多东西不记下来,总归是回忘记的]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[南斗工作组]]></copyright>
<item>
<link>http://www.nd21.com/read.php/78.htm</link>
<title><![CDATA[PHP中贪心和非贪心匹配示范]]></title> 
<author>Model.King &lt;P.Qingliang@hotmail.com&gt;</author>
<category><![CDATA[PHP相关]]></category>
<pubDate>Tue, 12 Aug 2008 09:00:53 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/78.htm</guid> 
<description>
<![CDATA[ 
	问题是在PHPCHINA看到的.<br/><br/>[codes=php]<br/><?php<br/>$a = "abc?test&a=a&b=b&c=c&d=d&e=e&f=f&g=g&h=h";<br/>$b = "aadg&adgas";<br/>preg_match("/^(.+?)&(.+?)/",$a,$rs);<br/>var_dump($rs);<br/>preg_match("^(.+)&(.+)",$b,$rs);<br/>var_dump($rs);<br/>[/codes]<br/><br/>默认情况下，Perl 的正则表达式是“贪婪地”，也就是说它们将尽可能多地匹配字符。要改变匹配特点，只须简单地在量词（加号[+]或星号[*]）后面加一个问号（?）即可。<br/>Tags - <a href="http://www.nd21.com/go.php/tags/%25E8%25B4%25AA%25E5%25BF%2583/" rel="tag">贪心</a> , <a href="http://www.nd21.com/go.php/tags/%25E9%259D%259E%25E8%25B4%25AA%25E5%25BF%2583/" rel="tag">非贪心</a> , <a href="http://www.nd21.com/go.php/tags/%25E5%258C%25B9%25E9%2585%258D/" rel="tag">匹配</a>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/77.htm</link>
<title><![CDATA[一段时间(半个月左右)可能都将不更新]]></title> 
<author>Model.King &lt;P.Qingliang@hotmail.com&gt;</author>
<category><![CDATA[站点公告]]></category>
<pubDate>Tue, 12 Aug 2008 08:57:48 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/77.htm</guid> 
<description>
<![CDATA[ 
	由于住宿的问题,一段时间(半个月左右)可能都将不更新.
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/76.htm</link>
<title><![CDATA[[算法每日一学]-数据结构之串--2008.08.12]]></title> 
<author>Model.King &lt;P.Qingliang@hotmail.com&gt;</author>
<category><![CDATA[问题求解与算法]]></category>
<pubDate>Tue, 12 Aug 2008 07:51:21 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/76.htm</guid> 
<description>
<![CDATA[ 
	<strong>/*************************************************************<br/>** 作者：P.Qingliang (P.Qingliang at msn.com)<br/>** 创建时间： 2008-8-12<br/>** 声明：笔记不是教程，这是我系统学习算法的记录而已，如有错<br/>** 误，欢迎指正。<br/>**<br/>*************************************************************/</strong><br/><br/>串（string）也是一种特殊的线性表，它的每个节点都由一个字符组成。它由零个或多个有序的字符组成，组成形式为 S=”a1a2……an”，其中S为字符串名，a1a2……an为串值，””只是字符串的标示符而已。<br/>不包含任何字符的串称为空串（Empty string）<br/>只包含空格符的串称为空白串（Blank string）<br/>在程序中，串分为串常量和串变量<br/><br/><strong>1.串的基本操作</strong>string strcat(string to, string from)连接串<br/>int strchr(string haystack, string needle)查找串<br/>int strlen(string str)求串长<br/>string strcpy(string from, string to, int begin, int length)串复制<br/>int strcmp(string s1, string s2)串比较<br/><br/>绝大部分高级语言都内置或者通过其他方式扩展实现了串的操作。例如c语言string.h头文件中就定义了一套关于字符串操作的函数。<br/><br/><strong>2.串的存储方式</strong><br/>同样的分为顺序存储和链式存储<br/><br/><strong>2.1顺序存储</strong><br/><br/>顺序存储方式又可分为静态分配和动态分配<br/><br/><strong>2.1.1静态分配</strong><br/>[codes=c] #define STRING_SIZE 256<br/>typedef char[STRING_SIZE] string;<br/>string str;<br/>[/codes]<br/>由于字符串的最后一个位置要用来存放字符串结束标记’&#92;0’，所以实际上述string只能存放STRING_SIZE-1个字符。<br/><br/>[codes=c]<br/>#define STRING_SIZE 256<br/>typedef struct _string<br/>&#123;<br/>&nbsp;&nbsp;char[STRING_SIZE]&nbsp;&nbsp;str;<br/>&nbsp;&nbsp;int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; length;//用来标示字符串长度<br/>&#125;string;<br/>[/codes]<br/>这种定义在求串长的相关操作时比较优势。<br/>2.1.2动态分配<br/>[codes=c]<br/>typedef struct _string<br/>&#123;<br/>&nbsp;&nbsp;char *ch;<br/>&nbsp;&nbsp;int&nbsp;&nbsp; length;<br/>&#125;string;<br/><br/>typedef char* string;<br/>[/codes]<br/>2.2链式存储<br/>[codes=c]<br/>typedef struct _string<br/>&#123;<br/>&nbsp;&nbsp;char ch;<br/>&nbsp;&nbsp;struct _string * next;<br/>&#125;string;<br/>[/codes]<br/>为了提高空间利用率，可以在每个节点存储多个字符<br/>[codes=c]<br/>#define NUM 4<br/>typedef struct _string<br/>&#123;<br/>&nbsp;&nbsp;char[NUM] ch;<br/>&nbsp;&nbsp;struct _string *next;<br/>&#125;string;<br/>[/codes]<br/><br/>通常，将结点数据域存放的字符个数定义为结点的大小。结点的大小的值越大，存储密度越高。但是这种方式在查看、删除、插入操作时会比较费时。<br/><br/>3．对串的操作重点在子串匹配（子串定位）。<br/>串匹配就是对于合法的位置（又称合法的位移）0≤i≤n-m，依次将目标串中的子串"titi+1…ti+m-1"和模式串"p0p1p2…pm-1"进行比较：<br/>　　①若"titi+1…ti+m-1"＝"p0p1p2…pm-1"，则称从位置i开始的匹配成功，或称i为有效位移。<br/>　　②若"titi+1…ti+m-1"≠"p0p1p2…pm-1"，则称从位置i开始的匹配失败，或称i为无效位移。朴素的串匹配：即以一次循环来测试i是否为有效位移<br/>&nbsp;&nbsp;朴素的串匹配：即用一个循环来依次检查n-m+1个合法的位移i（0≤i≤n-m）是否为有效位移。<br/><br/>3.1顺序串上的串匹配算法<br/>[codes=c]<br/>#define MaxStrSize 256&nbsp;&nbsp;//该值依赖于应用，由用户定义<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typedef struct&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char ch[MaxStrSize]; //可容纳256个字符，并依次存储在ch[0..n]中<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int length;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;SeqString;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int Naive StrMatch(SeqString T,SeqString P)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#123;//找模式P在目标T中首次出现的位置，成功返回第1个有效位移，否则返回-1<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int i,j,k;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int m=P.length;&nbsp;&nbsp;//模式串长度<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int n=T.length;&nbsp;&nbsp;//目标串长度<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(i=0;i<=n-m;i++)&#123;&nbsp;&nbsp;//0<=i<=n-m是合法的位移<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j=0;k=i;&nbsp;&nbsp;//下面用while循环判定i是否为有效位移<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(j<m&&T.ch[k]==P.ch[j]&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; k++;j++;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(j==m)&nbsp;&nbsp;//既T[i..i+m-1]=P[0..m-1]<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return i;&nbsp;&nbsp;//i为有效位移，否则查找下一个位移<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#125;//endfor<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;&nbsp;&nbsp;//找不到有效位移，匹配失败<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#125;//NaiveStrMatch<br/>[/codes]<br/><br/>3.2链串上的子串定位运算<br/>[codes=c]<br/>LinkStrNode *LinkStrMatch(LinkString T,LinkString P)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;//在链串上求模式P在目标T首次出现的位置<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LinkStrNode * shift,*t,*p;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shift=T;&nbsp;&nbsp;//shift表示位移<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t=shift;p=P;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(t&&p)&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(t->data==p->data)&#123;&nbsp;&nbsp;//继续比较后续结点中字符<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t=t->next;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p=p->next;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else&#123;&nbsp;&nbsp;//已确定shift为无效位移<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shift=shift->next;&nbsp;&nbsp;//模式右移，继续判定shift是否为有效位移<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t=shift;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p=P;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;//endwhile<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(p==NULL)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return shift;&nbsp;&nbsp;//匹配成功<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return NULL;&nbsp;&nbsp;//匹配失败<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>[/codes]<br/><br/><br/>Tags - <a href="http://www.nd21.com/go.php/tags/%25E6%2595%25B0%25E6%258D%25AE%25E7%25BB%2593%25E6%259E%2584/" rel="tag">数据结构</a> , <a href="http://www.nd21.com/go.php/tags/%25E4%25B8%25B2/" rel="tag">串</a>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/75.htm</link>
<title><![CDATA[[算法每日一学]-数据结构之栈和队列--2008.08.11]]></title> 
<author>Model.King &lt;P.Qingliang@hotmail.com&gt;</author>
<category><![CDATA[问题求解与算法]]></category>
<pubDate>Mon, 11 Aug 2008 08:02:40 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/75.htm</guid> 
<description>
<![CDATA[ 
	栈和队列都是特殊的线性表，只是他们各自有更多的限制。<br/>栈只能在一端进行添加、删除操作，通常这一端称为栈顶（top），另一端称为栈底(bottom)，栈的一个标志性特点：first in last out或者last in first out；队列则只能在一端添加，另一端删除的，允许删除的一端称为队头（Front），允许添加的一端称为队尾（Rear），也就是说从队头出队（删除），从队尾入队（添加），特点是first in first out。<br/><br/>同线性表一样，栈和队列的存储方式也分为顺序存储和链式存储。<br/><br/>栈的顺序存储方式下的操作实现：<br/>stack.h文件<br/>[codes=c]<br/>#ifndef _HEAD_STACK_ND<br/>#define _HEAD_STACK_ND<br/><br/>//C99 bool宏定义<br/>#include <stdbool.h><br/><br/>#define QUEUE_SIZE 100<br/>//栈溢出（元素已满）<br/>#define STACK_OVERFLOW -1<br/>#define STACK_UNDERFLOW -2<br/><br/>typedef int DataType;<br/><br/>typedef struct _stack<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;DataType&nbsp;&nbsp;&nbsp;&nbsp;a[QUEUE_SIZE];<br/>&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; length;<br/>&#125;STACK;<br/><br/>//初始化栈<br/>void initStack(STACK *s);<br/>//栈是否为空？<br/>bool isEmpty(STACK *s);<br/>//栈是否已满？<br/>bool isFull(STACK *s);<br/>//压入一个值，返回当前栈的长度<br/>int push(STACK *s, DataType v);<br/>//返回一个top值<br/>DataType pop(STACK *s);<br/>//取出顶部值，但不改变内部状态<br/>DataType top(STACK *s);<br/><br/>#endif<br/>[/codes]<br/><br/><br/>stack.c文件<br/>[codes=c]<br/>#include <string.h><br/>#include "stack.h"<br/><br/>void initStack(STACK *s)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;memset(s->a, 0, QUEUE_SIZE*sizeof(DataType));<br/>&nbsp;&nbsp;&nbsp;&nbsp;s->length = 0;<br/>&#125;<br/><br/>bool isEmpty(STACK *s)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (s->length == 0)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return false;<br/>&#125;<br/><br/>bool isFull(STACK *s)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (s->length == QUEUE_SIZE)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return false;<br/>&#125;<br/><br/>int push(STACK *s, DataType v)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (isFull(s))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return STACK_OVERFLOW;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;s->a[s->length] = v;<br/>&nbsp;&nbsp;&nbsp;&nbsp;s->length++;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return s->length;<br/>&#125;<br/><br/>DataType pop(STACK *s)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (isEmpty(s))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return STACK_UNDERFLOW;//这里如何返回比较合适？char？ 如果值也是char呢？<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;s->length--;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return s->a[s->length];<br/>&#125;<br/><br/>DataType top(STACK *s)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (isEmpty(s))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return STACK_UNDERFLOW;//这里如何返回比较合适？char？ 如果值也是char呢？<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return s->a[s->length-1];<br/>&#125;<br/><br/>[/codes]<br/>上述代码测试<br/>[codes=c]<br/>#include <stdio.h><br/>#include <malloc.h><br/>#include "stack.h"<br/><br/>int main(void)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;STACK *s = (STACK*)malloc(sizeof(STACK));<br/>&nbsp;&nbsp;&nbsp;&nbsp;int i;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;initStack(s);<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (isEmpty(s))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Current stack is empty!&#92;n");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Current stack is not empty!&#92;n");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;push(s, 3);<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (isEmpty(s))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Current stack is empty!&#92;n");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Current stack is not empty!&#92;n");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;if (isFull(s))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Current stack is full!&#92;n");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Current stack is not full!&#92;n");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;for(i=0; i<100; i++)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push(s, i);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;if (isFull(s))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Current stack is full!&#92;n");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Current stack is not full!&#92;n");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;for(i=0; i<100; i++)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pop(s);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;if (isFull(s))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Current stack is full!&#92;n");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Current stack is not full!&#92;n");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;if (isEmpty(s))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Current stack is empty!&#92;n");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Current stack is not empty!&#92;n");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br/>&#125;<br/><br/>[/codes]<br/>栈的链式存储下的常用操作实现，由于链式存储的节点是动态分配的，所以不存在上溢问题，也就不需要实现isFull了。<br/>[codes=c]<br/>LinkStack.h<br/>#ifndef LINKSTACK_H_INCLUDED<br/>#define LINKSTACK_H_INCLUDED<br/><br/>#include <stdbool.h><br/><br/>#define STACK_DOWNFLOW -1<br/><br/>typedef int DataType;<br/><br/>typedef struct __linkStack<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;DataType&nbsp;&nbsp;&nbsp;&nbsp;v;<br/>&nbsp;&nbsp;&nbsp;&nbsp;struct __linkStack *pNext;<br/>&#125;LinkStack;<br/><br/>typedef struct __linkStack * StackHeader;<br/><br/>void initStack(StackHeader s);<br/>bool isEmpty(StackHeader s);<br/>DataType pop(StackHeader s);<br/>void push(StackHeader s, DataType x);<br/><br/>#endif // LINKSTACK_H_INCLUDED<br/><br/>LinkStack.c<br/>#include <malloc.h><br/>#include "LinkStack.h"<br/><br/>void initStack(StackHeader s)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;s->pNext = NULL;<br/>&#125;<br/><br/>bool isEmpty(StackHeader s)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (s->pNext == NULL)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return false;<br/>&#125;<br/><br/>DataType pop(StackHeader s)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (isEmpty(s))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return STACK_DOWNFLOW;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;LinkStack *tmp = (LinkStack *)malloc(sizeof(LinkStack));<br/>&nbsp;&nbsp;&nbsp;&nbsp;tmp = s->pNext;<br/>&nbsp;&nbsp;&nbsp;&nbsp;DataType rtn = s->pNext->v;<br/>&nbsp;&nbsp;&nbsp;&nbsp;free(s->pNext);<br/>&nbsp;&nbsp;&nbsp;&nbsp;s->pNext = tmp->pNext;<br/>&nbsp;&nbsp;&nbsp;&nbsp;free(tmp);<br/>&nbsp;&nbsp;&nbsp;&nbsp;return rtn;<br/>&#125;<br/><br/>void push(StackHeader s, DataType x)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;LinkStack *tmp = (LinkStack*)malloc(sizeof(LinkStack));<br/>&nbsp;&nbsp;&nbsp;&nbsp;tmp->v = x;<br/>&nbsp;&nbsp;&nbsp;&nbsp;tmp->pNext = s->pNext;<br/>&nbsp;&nbsp;&nbsp;&nbsp;s->pNext = tmp;<br/>&#125;<br/><br/>[/codes]<br/>测试代码：<br/>[codes=c]<br/>#include <stdio.h><br/>#include <stdlib.h><br/>#include "LinkStack.h"<br/><br/>int main(void)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;StackHeader sh;<br/>&nbsp;&nbsp;&nbsp;&nbsp;initStack(sh);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;if (isEmpty(sh))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("The stack is empty!&#92;n");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("The stack is not empty!&#92;n");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;LinkStack *s = (LinkStack *)malloc(sizeof(LinkStack));<br/>&nbsp;&nbsp;&nbsp;&nbsp;s->v = 1;<br/>&nbsp;&nbsp;&nbsp;&nbsp;s->pNext = NULL;<br/>&nbsp;&nbsp;&nbsp;&nbsp;sh->pNext = s;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;if (isEmpty(sh))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("The stack is empty!&#92;n");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("The stack is not empty!&#92;n");<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;int i;<br/>&nbsp;&nbsp;&nbsp;&nbsp;for(i=0; i<100; i++)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push(sh, i);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;for(i=0; i<100; i++)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("%d&#92;n", pop(sh));<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br/>&#125;<br/><br/>[/codes]<br/>队列实现类似于栈。<br/><br/>Tags - <a href="http://www.nd21.com/go.php/tags/%25E6%25A0%2588/" rel="tag">栈</a> , <a href="http://www.nd21.com/go.php/tags/%25E9%2598%259F%25E5%2588%2597/" rel="tag">队列</a>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/74.htm</link>
<title><![CDATA[[算法每日一学]-数据结构之线性表--2008-08-10]]></title> 
<author>Model.King &lt;P.Qingliang@hotmail.com&gt;</author>
<category><![CDATA[问题求解与算法]]></category>
<pubDate>Sun, 10 Aug 2008 10:58:03 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/74.htm</guid> 
<description>
<![CDATA[ 
	<strong>/*************************************************************<br/>** 作者：P.Qingliang (P.Qingliang at msn.com)<br/>** 创建时间： 2008-8-10<br/>** 声明：笔记不是教程，这是我系统学习算法的记录而已，如有错<br/>** 误，欢迎指正。<br/>**<br/>*************************************************************/</strong><br/><br/>线性表是最为常见的线性数据结构。<br/><br/>逻辑定义<br/>线性表由n(n>=0)个元素a0, a1, a2 …… an组成的有序序列：<br/>1.&nbsp;&nbsp;n为线性表的长度<br/>2.&nbsp;&nbsp;线性表记为(a1, a2, ……, an)<br/>3.&nbsp;&nbsp;ai(1<=i<=n)在不同情况下，具体含义可以不同，是个抽象的符号<br/><br/>逻辑结构特征<br/>1.&nbsp;&nbsp;每个线性表只有一个开始节点，该节点没有直接前驱节点，只有一个直接后继节点<br/>2.&nbsp;&nbsp;每个线性表只有一个结束节点，该节点只有一个直接前驱节点，没有直接后继节点<br/>3.&nbsp;&nbsp;除开始节点和结束节点之外，任意一个节点都有唯一的前驱节点和后继节点<br/><br/>常见的线性表基本运算<br/>1.&nbsp;&nbsp;初始化线性表：initList(L)<br/>2.&nbsp;&nbsp;获得线性表长度: getLength(L)<br/>3.&nbsp;&nbsp;获得线性表中第i个元素的值: getNode(L, i)<br/>4.&nbsp;&nbsp;查找线性表中是否有值x: locateValue(L, x)<br/>5.&nbsp;&nbsp;插入元素: insertValue(L, i, x)<br/>6.&nbsp;&nbsp;删除元素: deleteValue(L, i)<br/>7.&nbsp;&nbsp;清空线性表: emptyList(L)<br/><br/>具体如何去实现运算则需要在确定存储结构的基础上才能完成。其他的复杂运算则由基本运算组合来实现。<br/><br/>线性表的两种存储方式<br/>顺序存储和链式存储<br/><br/>顺序存储<br/>把线性表的节点元素存储在一组地址连续的存储单元中，以这种方式存储的线性表称为顺序表。<br/><br/>这种方式下我们很容易获得第i个元素的地址，进而获得它的值：<br/>location(ai) = locaction(a0) + sizeof(a0) * (i-1);<br/>由于可以在相同时间内获得顺序表的任意元素，所以这种顺序表也称随即存取结构。<br/><br/>到了这里我们就可以定义顺序表了(c语言描述)：<br/>[codes=c]<br/>#define SIZE 1000<br/>typedef int DataType;<br/>typedef struct node<br/>&#123;<br/>&nbsp;&nbsp;DataType&nbsp;&nbsp; arr[SIZE]; //存储元素<br/>&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;length; //已用存储单元长度<br/>&#125;NodeList;<br/>[/codes]<br/><br/>基本运算<br/>[codes=c]<br/>void initList(L)<br/>&#123;<br/>&nbsp;&nbsp;L->length = 0;<br/>&#125;<br/><br/>int getLength(L)<br/>&#123;<br/>&nbsp;&nbsp;return L->length;<br/>&#125;<br/><br/>DataType getNode(L, i)<br/>&#123;<br/>&nbsp;&nbsp;return L->arr[i-1];<br/>&#125;<br/><br/>int locateValue(L, x)<br/>&#123;<br/>&nbsp;&nbsp;int i = 0;<br/>&nbsp;&nbsp;for(i=0; i<L->length; i++)<br/>&#123;<br/>&nbsp;&nbsp;if (L->arr[i] == x)<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return i+1;<br/>&nbsp;&nbsp;&#125;<br/>&#125;<br/><br/>return -1;//表示未找到该值<br/>&#125;<br/><br/>void insertValue(L, i, x)<br/>&#123;<br/>&nbsp;&nbsp;if (i> L->length+1 &#124;&#124; L->length>=SIZE &#124;&#124; i<1)<br/>&nbsp;&nbsp;//最多只能已用存储的末尾插入，已用存储不能已经达到<br/>&nbsp;&nbsp;//储存空间限制<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return;<br/>&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;int a;<br/>&nbsp;&nbsp;for(a=L->length; a>=i; a--)<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;L->arr[a+1] = L->arr[a];<br/>&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;L->arr[i] = x;<br/>&#125;<br/><br/>void deleteValue(L, i)<br/>&#123;<br/>&nbsp;&nbsp;if (i>L->length &#124;&#124; i<1)<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return;<br/>&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;int a;<br/>&nbsp;&nbsp;for(a=i; a<L->length; a++)<br/>&#123;<br/>&nbsp;&nbsp;L->arr[a-1] = L->arr[a];<br/>&#125;<br/>L->length--;<br/>&#125;<br/>[/codes]<br/><br/>很明显的我们可以看到，对于顺序表的插入和删除操作是比较耗时的，插入和删除的最坏运行时间都为O(n)，最佳运行时间为O(1)。假设在任何位置进行删除和插入的概率相同，则平均运行时间为O(n/2)。<br/><br/>链式存储<br/>以链式方式存储的线性表称为链表，实际上就是单链表。链表用任意一段存储空间存储，不一定要连续的空间；链表中元素的逻辑结构同物理结构可能完全不同，为了实现逻辑结构中元素的关系，链表中存储了“指向后继元素的指针”。<br/>链表的c语言定义<br/>[codes=c]<br/>typedef int DataType; <br/>typedef stuct __node<br/>&#123;<br/>&nbsp;&nbsp;DataType&nbsp;&nbsp;a;<br/>&nbsp;&nbsp;struct __node *pNext;<br/>&#125;Node;<br/>typedef Node *NodeList;<br/>Node * p;<br/>NodelList head; <br/>[/codes]<br/><br/>链表的实现和操作方法由多种，例如：有的有头节点，有的没有。<br/>这里重点关注一下链表的插入操作（删除类似）。由于链表本身不能进行随即存取操作，所以插入和删除操作往往都是在头部或者尾部进行的，因为插入到指定位置对于链表来说基本没有任何实际意义。<br/>由于单链表只能单向定位，所以在链表结尾进行操作，都需要一个遍历的过程：<br/>[codes=c]<br/>while(p->pNext != NULL)<br/>&#123;<br/>&nbsp;&nbsp;p = p->pNext;<br/>&#125;<br/>[/codes]<br/><br/>链表有几个变形形态：循环链表和双向链表。<br/><br/>对比而言，规模较大时，顺序表的查找快过链表，删除和插入慢于链表。<br/><br/><br/>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/73.htm</link>
<title><![CDATA[[算法每日一学]-数据结构概论--2008-08-09]]></title> 
<author>Model.King &lt;P.Qingliang@hotmail.com&gt;</author>
<category><![CDATA[问题求解与算法]]></category>
<pubDate>Sun, 10 Aug 2008 10:56:30 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/73.htm</guid> 
<description>
<![CDATA[ 
	<strong>/*************************************************************<br/>** 作者：P.Qingliang (P.Qingliang at msn.com)<br/>** 创建时间： 2008-8-9<br/>** 声明：笔记不是教程，这是我系统学习算法的记录而已，如有错<br/>** 误，欢迎指正。<br/>**<br/>*************************************************************/</strong><br/><br/><strong>意义</strong><br/>数据结构是计算机的一门基础课程，众多实际应用问题的解决都需要配合适合的数据结构才能解决。<br/><br/><strong>概念</strong><br/>&nbsp;&nbsp;数据：广义的讲指存在于世界中的各类信息，对于计算机来说，则指能够被计算机识别、存储的各类信息，如字符、图片、声音等等。<br/>&nbsp;&nbsp;数据元素：组成数据的基本单位。<br/>&nbsp;&nbsp;数据项：组成数据元素的最小标示单位。<br/>&nbsp;&nbsp;数据结构：包含三个方面的内容，数据的组成关系，数据以及它们之间关系的存储方式，定义在数据上的各种操作。<br/>&nbsp;&nbsp;数据结构从逻辑结构上分为：线性和非线性<br/>&nbsp;&nbsp;数据结构从存储方式上分为：顺序、链接、索引、散列<br/>&nbsp;&nbsp;数据类型：可以认为是已经定义好的数据结构，例如 整数(int)。<br/>&nbsp;&nbsp;抽象数据类型（ADT）：数据的逻辑结构以及在逻辑结构上定义的各种操作。<br/><br/><strong>常用数据结构</strong><br/>&nbsp;&nbsp;线性表、栈和队列、串、多维数组、广义表、树、图.<br/><br/><br/>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/72.htm</link>
<title><![CDATA[[算法每日一学]-逆序数算法--2008-08-08]]></title> 
<author>Model.King &lt;P.Qingliang@hotmail.com&gt;</author>
<category><![CDATA[问题求解与算法]]></category>
<pubDate>Sat, 09 Aug 2008 11:06:59 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/72.htm</guid> 
<description>
<![CDATA[ 
	/*************************************************************<br/>** 作者：P.Qingliang (P.Qingliang at msn.com)<br/>** 创建时间： 2008-8-8<br/>** 声明：笔记不是教程，这只是我系统学习算法的记录而已，如有错<br/>** 误，欢迎指正。<br/>**<br/>*************************************************************/<br/><br/>逆序数定义：对于一个数字序列，a1, a2, ..., an ,如果（am, an）满足m<n, am>an，那么（am, an）称为逆序对，我们暂时称呼am为左值，an为右值。<br/>[codes=c]<br/><br/>#include <stdio.h><br/><br/>/**<br/>* 遍历求逆序数,其最坏运行时间为θ(n2)<br/>*/<br/>int nixu(int arr[], int size)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (size <= 1)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;int i = 0, j = 0, sum = 0, key;<br/>&nbsp;&nbsp;&nbsp;&nbsp;for(i=0; i<size-1; i++)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;key = arr[i];<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(j=i+1; j<size; j++)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (key > arr[j])<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sum++;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;return sum;<br/>&#125;<br/><br/><br/><br/>/**<br/>* 递归求求逆序数,其最坏运行时间为θ(n2)<br/>*/<br/>int nixu2(int arr[], int begin, int end)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (begin == end)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;int i = begin;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int key = arr[begin];<br/>&nbsp;&nbsp;&nbsp;&nbsp;int sum = 0;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;for(i=begin; i<=end; i++)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (key > arr[i])<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sum++;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;sum += nixu2(arr, begin+1, end);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;return sum;<br/>&#125;<br/><br/>int main(int argc, char** argv)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int arr[5] = &#123;3, 6, 2, 5, 4&#125;;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;printf("The result is %d&#92;n", nixu(arr, 5));<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;printf("The result is %d&#92;n", nixu2(arr, 0, 4));<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br/>&#125;<br/>[/codes]<br/>nixu()和nixu2()的运行时间是一样的（只从语句的执行次数来说），都是θ(n2)，如何实现运行时间为nlog2(n)的算法版本？这时我们需要从合并排序借鉴思路了,因为合并排序的运行时间就是nlog2(n)。<br/><br/>对于输入数组（假定以数组方式提供数字序列）每一个数，我们都希望从它之后的子序列中找出小于该数值的数的个数，这样循环一遍即可获得结果，这个思路同线性排序是相似的。因而我们可以像从“线性排序”到“合并排序”一样来思考上述问题。<br/>假设数组如下： arr[0...size-1]，划分为arr[0...mid] 和 arr[mid+1...size-1]，其中mid=(int)size>>1.那么逆序对数的个数为 f(0, size-1) = f(0, mid) + f(mid+1, size-1) + s(0, mid, size-1)，这里s(0, mid, size-1)代表左值在[0---mid]中，右值在[mid+1, size-1]中的逆序对数。由于两个子序列本身都已经排序，所以查找起来非常方便。到了这里，算法的思路就已经ok了，稍微修改合并排序算法即可。<br/>[codes=c]<br/>#include <stdio.h><br/>#include <malloc.h><br/><br/>#define ARRAY_MAX_SIZE 10000<br/>int num = 0;<br/><br/>/**<br/>* 打印数组内容<br/>*/<br/>void print_array(int arr[], int size)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int i;<br/>&nbsp;&nbsp;&nbsp;&nbsp;printf("********* Array print begin *********&#92;r&#92;n");<br/>&nbsp;&nbsp;&nbsp;&nbsp;for(i=0; i<size; i++)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("array[%d] = %d&#92;r&#92;n", i, arr[i]);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;printf("********* Array print end *********&#92;r&#92;n");<br/>&#125;<br/><br/><br/>void merge_array(int arr[], int begin ,int mid, int end)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int i, j, key;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;if (arr[mid+1] > arr[mid])<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//return;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;for(i=mid; i>=begin; i--)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;key = arr[i];<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j = i+1;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(j<=end && key > arr[j])<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arr[j-1] = arr[j];<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j++;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;num += j - i - 1;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arr[j-1] = key;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&#125;<br/><br/>void merge_sort(int arr[], int begin, int end)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int mid = (int)((begin+end)>>1);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;if (begin < end)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;merge_sort(arr, begin, mid);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;merge_sort(arr, mid+1, end);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;merge_array(arr, begin, mid, end);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&#125;<br/>int main(void)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int arr[6] = &#123;3, 2, 5, 7, 1, 6&#125;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;merge_sort(arr, 0, 5);<br/>&nbsp;&nbsp;&nbsp;&nbsp;printf("The result is %d&#92;n", num);<br/>&nbsp;&nbsp;&nbsp;&nbsp;print_array(arr, 6);<br/>&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br/>&#125;<br/>[/codes]<br/>该算法的运行时间为nlog2(n)<br/>Tags - <a href="http://www.nd21.com/go.php/tags/%25E9%2580%2586%25E5%25BA%258F%25E5%25AF%25B9%25E9%2580%2586%25E5%25BA%258F%25E5%25AF%25B9%25E6%2595%25B0/" rel="tag">逆序对逆序对数</a> , <a href="http://www.nd21.com/go.php/tags/%25E5%2590%2588%25E5%25B9%25B6%25E6%258E%2592%25E5%25BA%258F/" rel="tag">合并排序</a>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/71.htm</link>
<title><![CDATA[[c语言每日一学]Linux下c语言开发简介]]></title> 
<author>Model.King &lt;P.Qingliang@hotmail.com&gt;</author>
<category><![CDATA[VC/C++/C]]></category>
<pubDate>Fri, 08 Aug 2008 08:14:51 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/71.htm</guid> 
<description>
<![CDATA[ 
	<strong>/*************************************************************<br/>** 作者：P.Qingliang (P.Qingliang at msn.com)<br/>** 创建时间： 2008-8-7<br/>** 声明：笔记不是教程，这只是我系统c的记录而已，如有错<br/>** 误，欢迎指正。<br/>**<br/>*************************************************************/&nbsp;&nbsp;</strong><br/><br/><br/>Linux下c语言开发教程<br/><br/>概述<br/>机器语言  汇编语言  高级语言  第四代(4GL)，如sql，告诉计算机做什么而需要指挥计算机如何去做。<br/><br/>源代码  编译  连接  运行<br/><br/>C语言同时具有汇编语言和高级语言的优势，方便、灵活、效率高、功能强大<br/><br/>C语言适合于底层开发，如linux内核，嵌入式<br/><br/>Linux下c语言开发环境的构成<br/>GNU的gcc编译器，glibc等等<br/><br/>编辑器：VI<br/>编译器：选择GNU C/C++编译器gcc<br/>调试器：应用广泛的gdb<br/>函数库：glibc<br/>系统头文件：glibc_header<br/><br/>Gcc是GNU CCompiler的缩写，能够编译c/c++源码<br/><br/>.c 为后缀的文件，c语言源文件文件<br/>.h 头文件<br/>.i 已经预处理过的c源代码文件<br/>.o 编译后的目标文件<br/>.s 汇编语言源代码文件<br/><br/>文件名不具有绝对约束文件类型的能力<br/><br/>gcc使用指令<br/><br/>gcc –o hello hello.c 把hello.c编译成文件名为hello的可执行文件<br/>-c<br/>-g<br/><br/>glibc包含一些附加包，如linuxThreads,locale,crypt ，是提供系统调用和基本函数的c库，如open，malloc，printf等，所有动态连接的程序都需要用到它<br/><br/>gcc依赖binutils和cpp包，另外make包在编译中也是经常用到的，<br/>cpp,binutils,glibc,glibc kernheaders,glibc-common,glibc-devel,gcc,make<br/><br/>ls&nbsp;&nbsp;/lib/libc-*<br/>gcc –version<br/><br/>c程序包含可执行文件、包含文件、库文件，所以往往单独的拷贝一个可执行程序是无法正常运行的。<br/><br/>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/70.htm</link>
<title><![CDATA[[算法每日一学]-算法基础之函数增长--2008.08.06]]></title> 
<author>Model.King &lt;P.Qingliang@hotmail.com&gt;</author>
<category><![CDATA[问题求解与算法]]></category>
<pubDate>Thu, 07 Aug 2008 10:10:09 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/70.htm</guid> 
<description>
<![CDATA[ 
	/*************************************************************<br/>** 作者：P.Qingliang (P.Qingliang at msn.com)<br/>** 创建时间： 2008-8-6<br/>** 声明：笔记不是教程，这只是我系统学习算法的记录而已，如有错<br/>** 误，欢迎指正。<br/>**<br/>*************************************************************/&nbsp;&nbsp;<br/><br/>检测算法的时间效率往往是在大规模的输入（n）的情况下进行，当n足够大时，研究算法的运行时间就趋向于研究算法的渐进效率了，因为我们没有必要进行过于精确的计算。在计算机中，有几种标准的方法用于简化算法的渐进分析。<br/><br/>渐进符号<br/>&nbsp;&nbsp;用以表示算法的渐进时间记号是域为自然数的函数。有时域的范围可以适当的扩充以获得更广的益处。<br/><br/>三种渐进符号：ΘΩΟ<br/>f(n) = Θ(g(n)) 表示的是这样的一个集合：存在c1,c2，当n>n0时，有0 < c1g(n) <f(n) < c2g(n)。如下图所示：<br/><a href="http://www.nd21.com/attachment.php?fid=20" target="_blank"><img src="http://www.nd21.com/attachment.php?fid=20" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/> （图来自《算法导论》）<br/>它实际上是确定了一个算法的运行时间渐进上界和渐进下界。<br/><br/>对应的Ω用于确定算法的渐进下界（最佳运行时间），Ο用于确定算法的渐进上界（最坏运行时间）<br/><br/>需要注意的是，实际上运行时间并非是n的函数，对于某个特定的n来说，运行时间与具体的输入有关，当我们用渐渐符号来表示算法运行时间时，实际上是在某个特定条件约束下说明的。<br/><br/>方程中的渐进符号<br/>&nbsp;&nbsp;方程中的渐进符号实际上相当于一个匿名函数f(n)，用于表示我们不关注的部分，因为我们没有必要写出我们不关心而又繁琐的某些细节部分（如低阶项）。<br/><br/>对于非精确上界渐进用符号o(g(n))表示，例如2n=o( ),而精确上界渐进则用符号Ο(g(n))表示，例如 .<br/>w与Ω的关系同O与Ο。<br/><br/>Tags - <a href="http://www.nd21.com/go.php/tags/%25E7%25AE%2597%25E6%25B3%2595%25E5%2587%25BD%25E6%2595%25B0/" rel="tag">算法函数</a>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/69.htm</link>
<title><![CDATA[[算法每日一学]-算法基础入门--2008.08.06]]></title> 
<author>Model.King &lt;P.Qingliang@hotmail.com&gt;</author>
<category><![CDATA[问题求解与算法]]></category>
<pubDate>Wed, 06 Aug 2008 02:18:07 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/69.htm</guid> 
<description>
<![CDATA[ 
	/*************************************************************<br/>** 作者：P.Qingliang (P.Qingliang at msn.com)<br/>** 创建时间： 2008-8-5<br/>** 声明：笔记不是教程，这是我系统学习算法的记录而已<br/>**<br/>*************************************************************/<br/><br/>算法的定义<br/>算法（Algorithm）是指在有限步骤内解决问题的一组明确定义的规则，通俗的说，就是计算机解决问题的过程。<br/><br/>算法的特点<br/>&nbsp;&nbsp;有穷性、确切性、输入、输出、可行性<br/><br/>&nbsp;&nbsp;即使是错误的算法，当其错误率在可接受范围内时也就是认为是“正确”的算法。算法的描述一般是伪代码（类c，类c++，类pascal等等）来进行。<br/><br/>分析算法<br/>&nbsp;&nbsp;算法分析的重要内容：算法的复杂性，包括空间复杂性和时间复杂性，一般只讨论时间复杂性。所谓时间复杂性，简单的说就是指在一定的输入规模下算法执行的时间效率。通常我们分析算法时假定指令是一条接着一条的执行的，而没有并发操作，也就是所谓的RAM模型。<br/><br/>&nbsp;&nbsp;相关术语：输入规模，运行时间，最坏情况<br/><br/>算法从排序开始<br/>&nbsp;&nbsp;插入排序c语言实现：<br/>[codes=c]<br/>#include <stdio.h><br/><br/>/**<br/>* 插入排序算法 --- 从小到大<br/>*/<br/>void insertSort(int arr[], int size)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int key, i, j, k;<br/>&nbsp;&nbsp;&nbsp;&nbsp;for(i=1; i<size; i++)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j = i - 1;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;key = arr[i];<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(key<arr[j] && j>=0)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arr[j+1] = arr[j];//在遍历比较时就移动元素&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>j--;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arr[j+1] = key;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&#125;<br/><br/>/**<br/>* 打印数组内容<br/>*/<br/>void printArray(int arr[], int size)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int i;<br/>&nbsp;&nbsp;&nbsp;&nbsp;printf("********* Array print begin *********&#92;r&#92;n");<br/>&nbsp;&nbsp;&nbsp;&nbsp;for(i=0; i<size; i++)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("array[%d] = %d&#92;r&#92;n", i, arr[i]);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;printf("********* Array print end *********&#92;r&#92;n");<br/>&#125;<br/><br/>int main(void)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int arr[10] = &#123;22, 73, 54, 92, 14, 32, 65, 98, 55, 43&#125;;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;printArray(arr, 10);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;insertSort(arr, 10);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;printArray(arr, 10);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br/>&#125;<br/>[/codes]<br/><br/>运行结果<br/><br/>********* Array print begin *********<br/>array[0] = 22<br/>array[1] = 73<br/>array[2] = 54<br/>array[3] = 92<br/>array[4] = 14<br/>array[5] = 32<br/>array[6] = 65<br/>array[7] = 98<br/>array[8] = 55<br/>array[9] = 43<br/>********* Array print end *********<br/>********* Array print begin *********<br/>array[0] = 14<br/>array[1] = 22<br/>array[2] = 32<br/>array[3] = 43<br/>array[4] = 54<br/>array[5] = 55<br/>array[6] = 65<br/>array[7] = 73<br/>array[8] = 92<br/>array[9] = 98<br/>********* Array print end *********<br/><br/>Process returned 0 (0x0)&nbsp;&nbsp; execution time : 0.031 s<br/>Press any key to continue.<br/><br/>分析算法：<br/>[codes=c]<br/>void insertSort(int arr[], int n)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int key, i, j, k;&nbsp;&nbsp;// 执行1次，每次消耗时间t1<br/>&nbsp;&nbsp;&nbsp;&nbsp;for(i=1; i<size; i++) // n, c2<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j = i - 1; //n – 1, c3<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;key = arr[i]; // n – 1, c4<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(key<arr[j] && j>=0) // f(j, n), c5<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arr[j+1] = arr[j];//在遍历比较时就移动元素&nbsp;&nbsp;f(j, n) - 1, c6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>j--; // f(j, n) - 1, c7<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arr[j+1] = key; //n – 1, c8<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&#125;<br/>[/codes]<br/>这里我们假设计算机执行每一步基本运算代码的时间都是个常量，在这里也就是c1, c2, c3……c8都是常量。<br/>上面函数运行的时间总和是T = c1+ nc2+(n-1)c3+(n-1)c4+f(j, n)c5 + (f(j, n)-1)c6 + (f(j, n)-1)c7+(n-1)c8。<br/>其中f(j, n) 是关于j，n的函数，其值同数组的排序程度有关，通常我们都假设为最坏情况，这里的最坏情况为初始数组按从大到小排序，这样f(j, n) = <a href="http://www.nd21.com/attachment.php?fid=19" target="_blank"><img src="http://www.nd21.com/attachment.php?fid=19" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>最终我们得出 T = an*n + bn + c， a,b,c为常数。 <br/>利用高中的求极限的知识，我们得出T = f(n*n)，这样我们就得出了插入排序算法的时间复杂性公式。<br/><br/>算法设计<br/>增量法，分治法等等<br/><br/>排序算法分治版<br/>[codes=c]<br/>#include <stdio.h><br/>#include <malloc.h><br/><br/>#define ARRAY_SIZE 10000<br/>#define RAND_SIZE 10000<br/><br/>/**<br/>* 打印数组内容<br/>*/<br/>void printArray(int arr[], int size)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int i;<br/>&nbsp;&nbsp;&nbsp;&nbsp;printf("********* Array print begin *********&#92;r&#92;n");<br/>&nbsp;&nbsp;&nbsp;&nbsp;for(i=0; i<size; i++)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("array[%d] = %d&#92;r&#92;n", i, arr[i]);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;printf("********* Array print end *********&#92;r&#92;n");<br/>&#125;<br/><br/>int mergeArray(int arr[], int begin, int mid, int end)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (arr[mid+1] > arr[mid])<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;int i, j=mid+1;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int key;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;for(j=j; j<=end; j++)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;key = arr[j];<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i = j-1;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while( arr[i] > key && i >= begin )<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arr[i+1] = arr[i];<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i--;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arr[i+1] = key;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br/>&#125;<br/><br/>/**<br/>* 分治法排序，从小到大<br/>*/<br/>void divideSort(int arr[], int begin, int end)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int iMid;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (begin < end)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iMid = (int)((end + begin)/2);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;divideSort(arr, begin, iMid);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;divideSort(arr, iMid+1, end);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mergeArray(arr, begin, iMid, end);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&#125;<br/><br/>int main(void)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int *pArr = malloc(sizeof(int)*ARRAY_SIZE);<br/>&nbsp;&nbsp;&nbsp;&nbsp;int i = 0;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;srand(RAND_SIZE);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;for(i=0; i<RAND_SIZE; i++)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pArr[i] = rand();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;//printArray(arr, 10);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;divideSort(pArr, 0, 9);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;//printArray(arr, 10);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br/>&#125;<br/><br/>[/codes]<br/>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/68.htm</link>
<title><![CDATA[PHP变量安全小设置]]></title> 
<author>Model.King &lt;P.Qingliang@hotmail.com&gt;</author>
<category><![CDATA[PHP相关]]></category>
<pubDate>Thu, 17 Jul 2008 21:36:58 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/68.htm</guid> 
<description>
<![CDATA[ 
	示范代码：<br/>[codes=php]<br/><?php<br/>//服务器register_global打开情况下运行示范代码<br/>var_dump($a);<br/>if (@ini_get('register_globals'))<br/>&#123;<br/>&nbsp;&nbsp;foreach ($_REQUEST as $varName => $void)<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;unset($&#123;$varName&#125;);<br/>&nbsp;&nbsp;&#125;<br/>&#125;<br/>var_dump($a);<br/>var_dump($_GET['a']);<br/>[/codes]<br/><br/>$_REQUEST 包含了$_GET，$_POST 和 $_COOKIE 中的全部内容，但是他们之间是相对独立的，所以即使unset了$_REQUEST 依然可以GET等。<br/><br/>本机测试效果：<br/><br/>string 'hello' (length=5)<br/><br/>null<br/><br/>string 'hello' (length=5)<br/><br/>较为完整的代码如下：<br/>[codes=php]<br/>&nbsp;&nbsp;set_magic_quotes_runtime(0);<br/>&nbsp;&nbsp;&nbsp;&nbsp;//注销所有自动注册变量<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (@ini_get('register_globals'))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach ($_REQUEST as $varName => $void)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset($&#123;$varName&#125;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;//转义<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (!get_magic_quotes_gpc())<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;adds($_GET);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;adds($_POST);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;adds($_COOKIES);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;adds($_FILES);<br/>[/codes]<br/><br/>adds code:<br/>[codes=php]<br/><?php<br/>/**<br/> * 递归转义数组<br/> *<br/> * @param array $arr<br/> */<br/>function adds(array &$arr)<br/>&#123;<br/>&nbsp;&nbsp;foreach ($arr as $key=>$value)<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (is_array($value))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;adds($arr);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;else <br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$arr[$key] = addslashes($value);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&#125;<br/>&#125;<br/>[/codes]<br/>没有多少新意。对于转义可以用另一种方式：反转义自动转义字符串，在程序中所有需要的地方手工转义，至于这种方式有什么不同本人就不知道了。<br/>Tags - <a href="http://www.nd21.com/go.php/tags/php/" rel="tag">php</a> , <a href="http://www.nd21.com/go.php/tags/addslashes/" rel="tag">addslashes</a> , <a href="http://www.nd21.com/go.php/tags/%25E8%25BD%25AC%25E4%25B9%2589/" rel="tag">转义</a> , <a href="http://www.nd21.com/go.php/tags/%25E5%25AE%2589%25E5%2585%25A8/" rel="tag">安全</a>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/67.htm</link>
<title><![CDATA[“人无信则不立“想到的]]></title> 
<author>Model.King &lt;P.Qingliang@hotmail.com&gt;</author>
<category><![CDATA[一些感悟]]></category>
<pubDate>Wed, 16 Jul 2008 16:39:15 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/67.htm</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;声明：可能说的不太明白，欢迎讨论。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这是一个非常简单但又非常深刻的问题，说它简单是因为人人都明白这个道理，它看起来是如此的简单；说它深刻，是因为信的理解各不相同、做法各不相同、做到也十分的困难。一个人一旦有了“信”，别人对你的信任度就会增高，你在别人心目中的形象也会增高。例如在一个团队中，一个集体或者一个宿舍中，往往最有说服力的人都是有“信”的人。<br/>信可分为两种：<span style="color: #0000FF;">一是对别人，二是对自己</span>。 对别人，不食言、不欺骗等等。对自己，这个是我想重点讨论的。<br/><br/>平时的时候我们总有个这样那样的事情，我们自己回忆一下，发现完成了很多事情，失败了很多事情，也有很多事情依然拖拉着没有做或没有做完。我们习惯去制定计划，但是往往在热血沸腾之后再也没有去执行过自己的计划。统计数据表明一个某个领域内的专家所花的学习时间实际上是不超过2-5年的，这还不是绝对的时间，如果考虑到他每天真正的学习时间，假设每天有8个小时的时间在学习某个领域的课程，那么他花的时间也只有半年到1年多点的时间。但是实际当中很少有人能够在专业的领域花长时间专注的去学习，例如大学生，往往四年都是在各种各样的活动、娱乐中度过的（并不是说不娱乐，只不过娱乐也是有限度的，娱乐也是要有物质基础的），而能做到长时间坚持的人都成了“牛人”。经常性的有菜鸟问大牛：你是怎么学的？有什么好方法介绍么？ ，呵呵，这个时候除非是天才一类的人物（毕竟很少）一般都是懒得回答的，因为在他们看来，专注与勤奋实在是很简单的道理。<br/>从我的身边我收集不少做事不能坚持、不能按时完成的原因：1.总觉得世界在变，自己的计划跟不上变化 2.觉得有些事情并不如想象的那么重要 3.做了一段时间，觉得难度大，觉得厌烦，无法坚持 4.自身性格导致。 我希望能够就这些原因给出我自己的看法、体会等。<br/><span style="color: #0000FF;">1.&nbsp;&nbsp;总觉得世界在变，自己的计划跟不上变化</span><br/>世界在变这是毋庸置疑的，我是学计算机的，计算机的技术日新月异，各种新的专业名词母鸡下蛋似的出现。 <br/>假如，如果你觉得你的计划跟不上变化，那么你应该根据你执行计划中的所得去修改你的计划或者直接放弃原有计划重新开始另外一份计划，但是一定要有记录和原因说明，作为以后的参考。如果接二连三的你觉得你的计划还是跟不上变化，那么我想你在认知上本身是有些问题的：认识新潮流。很多时候我们没有一直跟着最新的潮流走，只要我们觉得我们所学有用即可；更何况，潮流往往是某一部分人的潮流。例如：众多同学在选择编程语言时都会问诸如：我是选C++好呢还是Java好呢？比较潮流的做法是选择Java，因为Java最近这些年的发展势头很好，市场占有率第一，而C++是比较古老的语言了。 没错这些都是对的，但这不是你选择语言时考虑的理由，或者说你不应该考虑这部分太多。每种语言都有其专长的领域，存在必然有其道理，往往抨击另外一种语言的人对他所抨击的语言都不是很了解，起码不是该语言的专家，他们的评论往往带有过多的感情色彩。在我看来，真正想要体会一门语言，自己学才是最好的方式，<br/>学习并不是只是一味的看、读、模仿等等，更多的是思考与实践。<br/><span style="color: #0000FF;">2.&nbsp;&nbsp;觉得有些事情并不如想象的那么重要</span><br/>这是很多人经常性遇到的问题，也是一类很正常的问题。对于这种问题，采用一种简单的方法可能比较好解决。在决定之前使用如下方法给予事情评断：标示重要程度：1.很重要而且立刻要做 2.很重要但不是马上要做 3.不重要但必须马上要做 4.不重要也不是必须要做&nbsp;&nbsp;&nbsp;&nbsp;判断先后顺序：1 >&nbsp;&nbsp;3 > 2 > 4 或者1 > 2 > 3 > 4，你可以在对事情的性质进行进一步的标示。 通常情况下，如果我们遇到4就直接放弃掉，除非时间非常充足或者其他特殊的原因。以此来去除一些不必要的决定。<br/><span style="color: #0000FF;">3.&nbsp;&nbsp;做了一段时间，觉得难度大，觉得厌烦，无法坚持</span><br/>这个也是常见的问题。很多事情都是如此，看起来简单，做起来相当的困难，这个时候除了自律之外，似乎没有什么好方法可以将计划执行下去。这里的自律法是指：相信自己能完成，觉得自己必须要完成，这个是自己对自己的挑战。同时可能还需要其他的一些辅助手段，例如：每次学习都必须达到2个小时，每次学习历程都必须完成8-16个循环等等。在我个人看来，很难的东西就算草草的学一遍对于以后也是有好处的，这是人类学习的特点导致的（人在看到某些熟悉的东西，尽管之前不能理解，也可能会很快的学会）。<br/><span style="color: #0000FF;">4.&nbsp;&nbsp;自身性格导致</span><br/>某些人的性格就是无法长时间的坚持某件事或者喜欢“勾三搭四”的或者就是喜欢拖拖拉拉的，这个在我看来是最难克服的一点，我在我自己的身上看到了它的影子。 有时我决定了第二天要把某件事情办好，因为我觉得我应该将那件事情办好，这是我自己的锻炼，可是到了第二天，我可能会想：没关系，反正不做也关系不大，以后可以再做，又或者一件另外的事情将它耽搁了，之后就忘记了，过了很多天才想起来。这样的例子非常的常见的，总的来说是由于没有养成“果断”的性格、平时缺少计划与思考导致的。做事不果断，很多事情就不能及时高效的完成，缺少思考和计划就可能会因为没有充分考虑某些事情，没有一个比较好的方案而延误时间，从而打断了原有的计划。<br/><br/>&nbsp;&nbsp;看了我说了这么多，很多人我想都会说：你就说说。 的确这些都是说起来容易，做起来难的事情，但并不是没有办法去解决的。最起码在我身上我已经看到了一些效果。如果你想克服上面的缺点，最少你应该有个方式来提醒你做的决定，然后是给自己适当的压力来完成自己的决定。 例如：将决定写成一张表格，挂在显眼处，然后告诉自己周围的人如女友，舍友等你的计划，让他们监督你。方法有很多，看你有没有那份决心。记住：没有人会笑话你上进，如果真的有人这样，那么不是玩笑就是嫉妒了。<br/><br/>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/65.htm</link>
<title><![CDATA[[原创]设计分发器（Dispatcher）--- PHP框架编写123]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[PHP相关]]></category>
<pubDate>Thu, 03 Jul 2008 14:28:00 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/65.htm</guid> 
<description>
<![CDATA[ 
	如何设计分发器（Dispatcher）<br/>有了对MVC模式的简单认识，我们就可以正式开始框架的设计了（参见http://www.nd21.com/read.php/61.htm）。<br/>从上面链接的示范代码中我们可以大致的了解分发器的职责：解析web端请求（GET方式）为某个控制的动作，也就是简单的路由功能。其次，分发器还需要将更多的请求参数传递给控制器，能够提供出错处理（当控制器或者控制器的方法不存在时），能够进行重定向等等功能。我们可以根据这些定义出分发器的基本框架：<br/><br/>[codes=php]<br/><?php<br/>class N_Dispatcher_Abstract<br/>&#123;<br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * 客户端的请求信息<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; * @var array<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;protected $_request;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * 请求信息备份<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; * @var array<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;protected $_requestBackup;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * 控制器名称<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; * @var string<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;protected $_controllerName;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * 动作名<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; * @var string<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;protected $_actionName;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * 获得请求的控制器名称<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;protected function _getController($ifAdmin = false)<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;$controllerKeyName = N::getAppIni('controllerTrigger');<br/>&nbsp;&nbsp;&nbsp;&nbsp;$this->_request = array_change_key_case($this->_request, CASE_LOWER);<br/>&nbsp;&nbsp;&nbsp;&nbsp;//如果没有指定controller，则使用默认的controller<br/>&nbsp;&nbsp;&nbsp;&nbsp;$this->_controllerName = !empty($this->_request[$controllerKeyName]) <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;? $this->_request[$controllerKeyName] <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: N::getAppIni('defaultController');<br/>&nbsp;&nbsp;&nbsp;&nbsp;//添加前缀<br/>&nbsp;&nbsp;&nbsp;&nbsp;$controllerNamePrefix = N::getAppIni('controllerNamePrefix');<br/>&nbsp;&nbsp;&nbsp;&nbsp;$this->_controllerName = $controllerNamePrefix.ucfirst(strtolower($this->_controllerName));<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;/**<br/>&nbsp;&nbsp;&nbsp;&nbsp; * 这里我们假设前台文件（控制器，模型，视图）都置于根目录的APP文件夹下<br/>&nbsp;&nbsp;&nbsp;&nbsp; * 后台文件全部置于根目录的ADMIN文件下<br/>&nbsp;&nbsp;&nbsp;&nbsp; * 如果希望前后台文件都位于同一个文件夹下，请修改N/Congfig/IniMapping.php下的ADMIN_MVC_ROOT_NAME选项，<br/>&nbsp;&nbsp;&nbsp;&nbsp; * 如果ADMIN_MVC_ROOT_NAME和APP_MVC_ROOT_NAME都设置为APP，则表示站点的前后台文件都位于根目录的APP文件<br/>&nbsp;&nbsp;&nbsp;&nbsp; * 夹下<br/>&nbsp;&nbsp;&nbsp;&nbsp; */<br/>&nbsp;&nbsp;&nbsp;&nbsp;$this->_controllerName = $ifAdmin <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;N::getAppIni('ADMIN_MVC_ROOT_NAME').'_'.$this->_controllerName <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: N::getAppIni('APP_MVC_ROOT_NAME').'_'.$this->_controllerName;<br/>&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * 从请求中获得action名<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;protected function _getAction()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;$actionKeyName = N::getAppIni('actionTriggerName');<br/>&nbsp;&nbsp;&nbsp;&nbsp;$actionPrefix = N::getAppIni('actionNamePrefix');<br/>&nbsp;&nbsp;&nbsp;&nbsp;//如果没有指定action，则使用默认的action<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (N::getAppIni('urlLowerCase'))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this->_actionName = $this->_request[$actionKeyName] ? $actionPrefix.ucfirst($this->_request[$actionKeyName]) : N::getAppIni('defaultAction');<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;else <br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this->_actionName = $this->_request[$actionKeyName] ? $actionPrefix.$this->_request[$actionKeyName] : N::getAppIni('defaultAction');<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * 路由请求<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;public function dispatching()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;//保存请求信息<br/>&nbsp;&nbsp;&nbsp;&nbsp;$this->_request = $_GET;<br/>&nbsp;&nbsp;&nbsp;&nbsp;$this->_requestBackup = $_GET;<br/>&nbsp;&nbsp;&nbsp;&nbsp;$ifAdmin = (isset($this->_request[N::getAppIni('adminTrigger')]) && !empty($this->_request[N::getAppIni('adminTrigger')]));<br/>&nbsp;&nbsp;&nbsp;&nbsp;$this->_getController($ifAdmin);<br/>&nbsp;&nbsp;&nbsp;&nbsp;$this->_getAction();<br/>&nbsp;&nbsp;&nbsp;&nbsp;try <br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this->_forward();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;catch (Exception $e)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (DEBUG_MODE)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print $e->getMessage();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this->_onControllerNotExists();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * 执行指定控制器的指定方法<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;protected function _forward()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;$controller = $this->_controllerName;<br/>&nbsp;&nbsp;&nbsp;&nbsp;N::LoadClass($controller);<br/>&nbsp;&nbsp;&nbsp;&nbsp;$action = $this->_actionName;<br/>&nbsp;&nbsp;&nbsp;&nbsp;$controllerObj = new $controller($this->_requestBackup, $action);<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (!method_exists($controllerObj, $action))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw new Exception('控制器'.$controller.'不存在方法'.$action);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;$controllerObj->$action($action);<br/>&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;<br/><br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * 控制器或其方法不存在时的异常处理函数<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;protected function _onControllerNotExists()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;/**<br/>&nbsp;&nbsp;&nbsp;&nbsp;$this->_controllerName = N::getAppIni('APP_MVC_ROOT_NAME').'_'.N::getAppIni('controllerNamePrefix').N::getAppIni('defaultController');<br/>&nbsp;&nbsp;&nbsp;&nbsp;$this->_actionName = N::getAppIni('defaultAction');<br/>&nbsp;&nbsp;&nbsp;&nbsp;$this->_requestBackup = array();<br/>&nbsp;&nbsp;&nbsp;&nbsp;$this->_forward();<br/>&nbsp;&nbsp;&nbsp;&nbsp;*/<br/>&nbsp;&nbsp;&nbsp;&nbsp;N::loadClass('N_Controller_Abstract');<br/>&nbsp;&nbsp;&nbsp;&nbsp;N_Controller_Abstract::redirectTo(N_Controller_Abstract::url('index'));<br/>&nbsp;&nbsp;&#125;<br/>?><br/><br/>[/codes]<br/>代码的执行过程很简单：<br/>分发器开始工作 --> 获得控制器 -->获得方法 -->执行指定的控制器的指定方法<br/>另外我们提供了一个_onControllerNotExists 方法，相当于一个回调函数（我们可以将它设计成一个回调函数），当控制器指定方法出错时会被调用。这样我们的分发器就可以工作了。<br/><br/>注意到我在类中很多方法和属性都设计成protected类型，用意是希望用户根据自己的要求派生分发器类，例如需要权限控制的分发器。<br/>Tags - <a href="http://www.nd21.com/go.php/tags/php/" rel="tag">php</a> , <a href="http://www.nd21.com/go.php/tags/framework/" rel="tag">framework</a> , <a href="http://www.nd21.com/go.php/tags/%25E6%25A1%2586%25E6%259E%25B6/" rel="tag">框架</a> , <a href="http://www.nd21.com/go.php/tags/%25E5%2588%2586%25E5%258F%2591%25E5%2599%25A8/" rel="tag">分发器</a> , <a href="http://www.nd21.com/go.php/tags/dispatch/" rel="tag">dispatch</a> , <a href="http://www.nd21.com/go.php/tags/dispatcher/" rel="tag">dispatcher</a>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/64.htm</link>
<title><![CDATA[[原创]一些基本设定和框架总体设计---PHP框架编写123]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[PHP相关]]></category>
<pubDate>Fri, 27 Jun 2008 16:50:09 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/64.htm</guid> 
<description>
<![CDATA[ 
	<span style="color: #0000FF;">一些基本的要求和设定</span><br/>为了使用某些比较特殊的功能以及交流上的方便，我们进行了一些约定。<br/>在这里，首先我们要求PHP的版本至少是5.0，我们推荐版本在5.1或以上， 5.1在性能上比5.0要快得多。其次，我们要进行一些基本的约定：<br/><span style="color: #0000FF;">1.&nbsp;&nbsp;类命名：</span><br/><br/>类的命名我们采用如下的方法：<br/>N_Controller_Abstract<br/>这个类的名字包含了它的路径，它应该位于导入的某个类路径（Class Path）下的N/Controller/Abstract.php文件中。<br/><br/><span style="color: #0000FF;">2.&nbsp;&nbsp;类路径（Class Path）：</span><br/><br/>你可以将类路径看成类似与include_path的一样东西，当我们寻找某个类时，我们会先根据类的名称产生一个类名称路径（类似上面的N/Controller/Abstract.php），然后依次在类路径下寻找。<br/><br/><span style="color: #0000FF;">3.&nbsp;&nbsp;命名方式：</span><br/><br/>我们采用的是类似这样的方法、函数命名方式：<br/>getFileExt<br/>而不是<br/>GetFileExt<br/>也不是<br/>get_file_ext<br/><br/><span style="color: #0000FF;">框架总体</span><br/>&nbsp;&nbsp;我们先简单的将MVC的执行过程封装起来，为次我们需要另外一个类，我们暂时命名为N，类实现放在N.php文件中，所有的文件都置于N文件夹下，它的所有方法我们都设计为静态方法，这样不需要实例化就可以直接调用它的方法：<br/><br/><br/>[codes=php]<br/><?php<br/>class N<br/>&#123;<br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * 是否首次运行程序<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; * @var boolean<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;static private $firstRun = true; <br/><br/>/**<br/>&nbsp;&nbsp; * MVC启动入口<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;static public function runMVC()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;$dispatcher = new $dispatcherClass();<br/>&nbsp;&nbsp;&nbsp;&nbsp;$dispatcher->dispatching();<br/>&nbsp;&nbsp;&#125; <br/><br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * 在程序的开始必须首先调用该函数，用以初始化各种参数<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;static public function init()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (!self::$firstRun) return;<br/>&nbsp;&nbsp;&nbsp;&nbsp;self::$firstRun = false;<br/>&nbsp;&nbsp;&nbsp;&nbsp;//初始化环境代码，之后添加<br/>&nbsp;&nbsp;&#125; <br/>&#125;<br/>?><br/>[/codes]<br/><br/>是的，一个框架的启动类就是这么简单，当然要实际的运行还需要添加诸多功能，下面我们开发为其添加一些必要的东西。<br/><br/>首先是类的寻找问题，根据我们前面的约定，我们已经可以很轻松的知道类的路径了，但是计算机不知道。在PHP5及其之后的版本，提供了autoload功能，即使你不主动加载类文件，php引擎也会帮助你寻找指定的类文件的，它很方便，只是牺牲了一定的效率，我们建议在任何需要的时候主动加载类，因为某些时候自动寻找类可能是相当费时的，当然你不是必须这样做。为了能够主动加载类，我们需要提供一个方法来主动加载，因为N是整个框架运行的基点，所以我们可以将加载类作为它的一个静态方法来实现，最初版本：<br/>[codes=php]<br/><br/>static public function LoadClass($className)<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (class_exists($className, false) &#124;&#124; interface_exists($className, false))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;//已经加载则直接返回<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;$classPath = './'.str_replace('_', '/', $className).'.php';<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (is_readable($classPath))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;require_once($classPath);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;throw new Exception('Class file not exists!Class Name:'.$className);<br/>&nbsp;&nbsp;&#125;<br/>[/codes]<br/>这样PHP会在./N/Controller/Abstract.php文件中寻找N_Controller_Abstract类，但是问题来了，如果我们N文件夹不是放在根目录下，例如是放在Libs文件夹下，那么PHP就会抛出异常表示该类找不到。<br/><a href="http://www.nd21.com/attachment.php?fid=15" target="_blank"><img src="http://www.nd21.com/attachment.php?fid=15" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><a href="http://www.nd21.com/attachment.php?fid=16" target="_blank"><img src="http://www.nd21.com/attachment.php?fid=16" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>&nbsp;&nbsp;<br/>上面是两种常见的目录安排方式（有些为了安全考虑，甚至将库文件放在站点根目录之外）。第一种N文件夹在根目录下（learning为根目录），第二种在根目录的Libs/文件夹下(schoolPlant为根目录)。我们的N.php是被首页文件（假设为index.php）直接包含了，所以文件包含也是相对index.php的。为了解决这个问题，我们需要导入一些目录作为类目录，下面展示了部分修改后的N类：<br/>[codes=php]<br/><br/>class N<br/>&#123;<br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * 是否首次运行程序<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; * @var boolean<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;static private $firstRun = true;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;static private $_import = array('.');<br/><br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * 包含指定类到程序中，类名称相对根文件夹命名，如：<br/>&nbsp;&nbsp; * $rootDir参数为APP，则该目录下的类Model_Index，应位于Model子文件夹中，<br/>&nbsp;&nbsp; * 且文件名为Index.php<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; * @param string $className<br/>&nbsp;&nbsp; * @param string $rootDir<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;static public function LoadClass($className)<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (class_exists($className, false) &#124;&#124; interface_exists($className, false))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;foreach (self::$_import as $dir)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$classPath = $dir.'/'.str_replace('_', '/', $className).'.php';<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (is_readable($classPath))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;require_once($classPath);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;throw new Exception('Class file not exists!Class Name:'.$className);<br/>&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;public function import($dir)<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;array_push(self::$_import, $dir);<br/>&nbsp;&nbsp;&#125;<br/>[/codes]<br/>这样我们只要在index.php文件中加入如下代码即可寻找到我们的类文件了：<br/>[codes=php]<br/><br/><?php<br/>require('Libs/N/N.php');<br/>define('APP_ROOT', dirname(__FILE__) . DS);<br/>N::import('./Libs');<br/>N::init();<br/>N::runMVC();<br/><br/>[/codes]<br/>另外我们还需要给类添加配置控制功能，对于任何框架都是需要可伸缩的配置功能的。直接看代码吧：（省略重复代码）<br/><br/>[codes=php]<br/><br/>class N<br/>&#123;<br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * 是否首次运行程序<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; * @var boolean<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;static private $firstRun = true;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;static private $_import = array('.');<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;static private $_ini = array();<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * 使用文件导入程序全局配置，可以批量导入配置，避免每次调用setAppIni函数的麻烦<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;static public function loadAppIni()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;$args = func_get_args();<br/>&nbsp;&nbsp;&nbsp;&nbsp;$numOfArgs = sizeof($args);<br/>&nbsp;&nbsp;&nbsp;&nbsp;if ($numOfArgs === 2)<br/>&nbsp;&nbsp;&nbsp;&nbsp;//导入的配置是采用 名称/值 对的形式<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$index = $args[0];<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$value = $args[1];<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (is_array($index) && is_array($value))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$tmpArr = array_combine($index, $value);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this->_ini = array_merge($this->_ini, $tmpArr);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else if (is_string($index) && is_string($value))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this->_ini = array_merge($this->_ini, array($index=>$value));<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;else if ($numOfArgs === 1)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$value = $args[0];<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (is_array($value))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this->_ini = array_merge($this->_ini, $value);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//如果是文件路径 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (file_exists($value) && is_readable($value))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$tmpArr = require_once($value);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this->_ini = array_merge($this->_ini, $tmpArr);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;<br/>&#125;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * 获取某项全局配置值<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; * @param string $iniStr<br/>&nbsp;&nbsp; * @param bool $autoInitClass<br/>&nbsp;&nbsp; * @param string $default<br/>&nbsp;&nbsp; * @return string<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;static public function getAppIni($iniStr, $autoInitClass = false, $default = NULL)<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;$rtn = !empty(self::$_ini[$iniStr]) ? self::$_ini[$iniStr] : $default;<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;//如果自动初始化类<br/>&nbsp;&nbsp;&nbsp;&nbsp;if ($autoInitClass)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self::LoadClass($rtn);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return $rtn;<br/>&nbsp;&nbsp;&#125;<br/>[/codes]<br/>loadAppIni方法有两种传参方式，由于php本身不支持重载，所以我们采用了一些技巧来实现，关键的代码就是func_get_args()。一种是直接传递文件名，文件的内容应该类似下面的格式：<br/>[codes=php]<br/><br/><?php<br/>return array(<br/>&nbsp;&nbsp;&nbsp;&nbsp;//url中controller的键名，如:index.php?con=xxxx，则controllerTrigger为con<br/>&nbsp;&nbsp;&nbsp;&nbsp;'controllerTrigger' => 'con',<br/>&nbsp;&nbsp;&nbsp;&nbsp;//同上<br/>&nbsp;&nbsp;&nbsp;&nbsp;'actionTriggerName' => 'action',<br/>&nbsp;&nbsp;&nbsp;&nbsp;'adminTrigger' => 'cp',<br/>&nbsp;&nbsp;&nbsp;&nbsp;//默认的控制，没有前缀，使用时需要在前连接controllerNamePrefix，首字母大写<br/>&nbsp;&nbsp;&nbsp;&nbsp;'defaultController' => 'Index',<br/>&nbsp;&nbsp;&nbsp;&nbsp;//同上<br/>&nbsp;&nbsp;&nbsp;&nbsp;'defaultAction' => 'actionShow',<br/>[/codes]<br/><br/>这样我们require之后，就直接得到了一个数组，将它合并到N类的$_ini属性中之后就可以方便的通过数组索引来访问配置了。<br/>另一种方式是传递键值对，例如 N::loadAppIni(‘defaultControllerName’, ‘index’);<br/><br/>现在我们就可以在类N的init方法中添加一些其他的初始化代码了：<br/>[codes=php]<br/><br/>/**<br/>&nbsp;&nbsp; * 在程序的开始必须首先调用该函数，用以初始化各种参数<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;static public function init()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (!self::$firstRun) return;<br/>&nbsp;&nbsp;&nbsp;&nbsp;self::$firstRun = false;<br/>&nbsp;&nbsp;&nbsp;&nbsp;//初始化环境：必要文件的包含，基本设置<br/>&nbsp;&nbsp;&nbsp;&nbsp;N::loadAppIni(N_RUNTIME_ROOT.'Config/IniMapping.php');<br/>&nbsp;&nbsp;&nbsp;&nbsp;N::loadAppIni(N_RUNTIME_ROOT.'Config/DataMapping.php');<br/>&nbsp;&nbsp;&nbsp;&nbsp;N::loadAppIni(N_RUNTIME_ROOT.'Config/ClassMapping.php');<br/>&nbsp;&nbsp;&nbsp;&nbsp;N::loadAppIni(N_RUNTIME_ROOT.'Config/TableMapping.php');<br/>&nbsp;&nbsp;&nbsp;&nbsp;//5.1以后版本，设置时区<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (floatval(PHP_VERSION) >= 5.1)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;date_default_timezone_set(N::getAppIni('default_timezone'));<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&#125;<br/>[/codes]<br/><br/>在这里，我尽量少的使用全局变量，而更多的是用类N的成员变量来保存某些全局配置，原因有二：1.我们尽量的希望以面向对象的方法来实现，在这里完全没有必要使用全局变量来保存 2.为了防止直接修改某些重要的全局配置，使用约定方式修改比直接修改往往要安全的多。 另外一个算不上原因的原因是PHP6将取消对全局变量的支持。<br/><br/>里面的几个文件我打包一下，在文章的最后面可以下载。<br/><br/>到这里N类的功能已经可以正常的运行一个框架了，在之后的过程中，我们还会添加一些需要的功能。<br/><br/>下一篇我们开始丰富各个MVC组件的功能。<br/><br/><a href="attachment.php?fid=17">点击这里下载文件</a><br/><br/>Tags - <a href="http://www.nd21.com/go.php/tags/php/" rel="tag">php</a> , <a href="http://www.nd21.com/go.php/tags/framework/" rel="tag">framework</a> , <a href="http://www.nd21.com/go.php/tags/%25E6%2580%25BB%25E4%25BD%2593%25E8%25AE%25BE%25E8%25AE%25A1/" rel="tag">总体设计</a>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/63.htm</link>
<title><![CDATA[PHP页面静态化的两种方式]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[PHP相关]]></category>
<pubDate>Thu, 26 Jun 2008 03:05:10 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/63.htm</guid> 
<description>
<![CDATA[ 
	PHP页面静态化是大多数PHP程序员耳熟能详、随手可写的功能了，在这里不讨论如何生成静态页面的细节，而是考虑：将静态缓存功能作为系统的哪个部分的结构来实现（基于MVC模式，如果对MVC不了解，对于下面的内容的理解可能有困难）。<br/><br/>在我的总结有两种主要的方式，其他的还没有发现，如果你有第三种可行的方案，请给我发一份示意代码，谢谢。（代码使用PHPLIB template示范）<br/><br/>第一种方式：由控制器来调用单独的缓存类。在这个时候缓存类是一个单独的类，与模板引擎相对独立，在一个请求开始的时候，缓存类即被调用，并进行一些相关的缓存操作。这一工作甚至可以直接在调度器中完成（如果存在调度器dispatcher的话）。下面给出一个简单的代码示范（只有框架）：<br/><br/><br/>[codes=php]<br/><?php<br/>class WebController<br/>&#123;<br/>&nbsp;&nbsp;public function actionIndex()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;//实例化静态缓存类，缓存类初始化时要决定是否启用缓存，这里略过<br/>&nbsp;&nbsp;&nbsp;&nbsp;$cache = new HtmlCache();<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (!$cache->enableCache)<br/>&nbsp;&nbsp;&nbsp;&nbsp;//没有启用缓存<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//调用模型层、视图层来完成请求<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;//启动了缓存<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($cache->isCached)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//如果文件已经被缓存<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//重定向到缓存文件,getCacheFile方法根据url生成一个唯一的静态文件名<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;header('Location:'.$cache->getCacheFile($_SERVER['REQUEST_URI']));<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//如果文件还没有被缓存，则我们需要创建该文件并写入内容<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//下面三行代码使用的PHPLIB template的代码<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$tpl->set_file('index', 'index.html');//载入模板文件<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$tpl->set_var('title', 'Hello world');//赋值<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$html = $this->parse('indexHtml', 'index');//解析模板文件并返回解析结构字符串<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//$html变量包含了文件的内容，writeCache方法将其写入到文件<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$cache->writeCache($html);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//重定向<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;header('Location:'.$cache->getCacheFile($_SERVER['REQUEST_URI']));<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&#125;<br/>&#125;<br/>[/codes]<br/><br/><br/>第二种方法：由模板类来控制缓存。对于任何请求，控制器都直接调用模板类来完成工作，由模板类自己完成与缓存相关的工作。下面的代码我只列出框架：<br/><br/>[codes=php]<br/><br/>class N_View_CacheTemplate extends Template_PHPLIB <br/>&#123;<br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * html静态化目录，相对于系统根目录<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; * @var string<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;protected $cacheDir = './cache/';<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * 是否打开静态缓存<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; * @var bool<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;protected $enableCache = false;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * 页面缓存时间<br/>&nbsp;&nbsp; * <br/>&nbsp;&nbsp; * @var int<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;protected $cacheTime = 900;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;protected $htmlFullPathName;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;protected $htmlFileName;<br/><br/>/**<br/>&nbsp;&nbsp; * 如果该选项打开，则在解析模板之后，自动生成对应缓存静态文件<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; * @var unknown_type<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;private $_autoCache = false;<br/><br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;public function __construct($enableCache = false, $root = ".", $unknowns = "remove")<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;parent::__construct($root, $unknowns);&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;$this->enableCache = $enableCache;<br/>&nbsp;&nbsp;&nbsp;&nbsp;$this->_cache();<br/>&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * 返回当前对象实例<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; * @return N_View_CacheTemplate<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;public function getInstance()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return getInstanceOf(__CLASS__);<br/>&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp;* 开始缓存调用<br/>&nbsp;&nbsp;*/<br/>&nbsp;&nbsp;private function _cache()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if ($this->enableCache)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (!$this->isCached)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this->_writeCache();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;header(‘Location:’.$this->cacheDir().$this->htmlFileName);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&#125;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;//检测是否已经缓存了<br/>&nbsp;&nbsp;public function isCached()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;//生成缓存<br/>&nbsp;&nbsp;private function _writeCache()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;<br/>//更新缓存<br/>&nbsp;&nbsp;private function _updateCache()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&#125;<br/><br/>[/codes]<br/><br/>两种方式各有特点，从功能上来说：<br/>第一种方式（独立缓存类）可较大程度的控制缓存，无论是否使用模板引擎、无论使用哪种模板引擎，对其都几乎没有影响。如果模板引擎本身也提供静态缓存功能，则直接关闭模板缓存功能即可； <br/>第二种方式由于缓存功能是嵌入在模板引擎之内的，对于每一步的页面生成都能很好的把握，所以可以更好的定制输出信息。<br/>两种方式在核心处理上是一样的，区别只是他们的在模式中定位的不同，这在框架的编写中是必须要考虑的。<br/><br/><br/>Tags - <a href="http://www.nd21.com/go.php/tags/php/" rel="tag">php</a> , <a href="http://www.nd21.com/go.php/tags/%25E7%25BC%2593%25E5%25AD%2598/" rel="tag">缓存</a> , <a href="http://www.nd21.com/go.php/tags/%25E9%259D%2599%25E6%2580%2581%25E5%258C%2596/" rel="tag">静态化</a> , <a href="http://www.nd21.com/go.php/tags/%25E9%259D%2599%25E6%2580%2581/" rel="tag">静态</a>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/62.htm</link>
<title><![CDATA[[小备忘]接口与实现类]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[PHP相关]]></category>
<pubDate>Tue, 24 Jun 2008 06:53:07 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/62.htm</guid> 
<description>
<![CDATA[ 
	接口用于给类附加特殊的行为信息，可以避免在类中混合一些不属于领域类的方法。<br/><br/>PHP中，接口定义如下：<br/>[codes=php]<br/><?php<br/>interface ITest <br/>&#123;<br/>&nbsp;&nbsp;function test1();<br/>&#125;<br/>[/codes]<br/><br/>如果是一个抽象类实现了某个接口，由于抽象类本身不能实例化，所以不需要抽象类实现所有的接口方法，如下代码可以正常运行：<br/>[codes=php]<br/>interface ITest <br/>&#123;<br/>&nbsp;&nbsp;function test1();<br/>&#125;<br/><br/>abstract class A implements ITest <br/>&#123;<br/>&nbsp;&nbsp;<br/>&#125;<br/><br/>[/codes]<br/><br/>但是如果是一个具体类实现某个接口，则必须实现所有接口的方法。如下代码不能正常运行：<br/>[codes=php]<br/>interface ITest <br/>&#123;<br/>&nbsp;&nbsp;function test1();<br/>&#125;<br/><br/>class C implements ITest <br/>&#123;<br/>&nbsp;&nbsp;<br/>&#125;<br/>[/codes]<br/><br/>一点点基础知识，用来备忘。<br/><br/><br/>Tags - <a href="http://www.nd21.com/go.php/tags/%25E6%258E%25A5%25E5%258F%25A3/" rel="tag">接口</a> , <a href="http://www.nd21.com/go.php/tags/%25E6%258A%25BD%25E8%25B1%25A1%25E7%25B1%25BB/" rel="tag">抽象类</a> , <a href="http://www.nd21.com/go.php/tags/php/" rel="tag">php</a>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/61.htm</link>
<title><![CDATA[[原创] web中的 MVC模式 --- PHP框架编写123]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[PHP相关]]></category>
<pubDate>Sat, 14 Jun 2008 12:22:43 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/61.htm</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;框架, 目的在于提高编程效率(不是提高系统的运行效率, 效率最高的代码方式还是函数)、易于扩展与维护, 所以一个好的设计模式是框架编写之前要决定的最重要的事。<br/>&nbsp;&nbsp;&nbsp;&nbsp;简单的来说， <span style="color: #0000FF;">设计模式是指针对我们周围经常出现的一些问题的通用解决方案。</span><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;在这里我们采用的是被动MVC架构模式（微软的称呼为MVP模式）， 它是MVC模式的一个变种。 如果你还不了解它， 那么这里有两篇文章可以供参考：<br/>&nbsp;&nbsp;&nbsp;&nbsp;1. http://www.phpwact.org/pattern/model_view_controller&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. http://www.microsoft.com/china/msdn/library/architecture/architecture/architecturetopic/MVP.mspx?mfr=true<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MVC是一种概念比较模糊的设计模式， 所以往往带有着比较浓厚的<span style="color: #0000FF;">个人理解色彩</span>，所以我们经常会看到实现不一的MVC框架， 这并不是很重要， 只要是符合它的初衷， 适合当前的环境即可。 在理解MVC时，最好结合代码来理解。 <span style="color: #0000FF;">顺便提一下： 你只需要明白它的运行过程即可，对于为什么用它、有哪些优势可能不是短期内能够体会得到的。</span><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://www.nd21.com/attachment.php?fid=14" target="_blank"><img src="http://www.nd21.com/attachment.php?fid=14" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/>这是被动MVC模式下，一个php请求的执行过程.<br/><br/>简单的代码示范：<br/><br/><br/><br/>[codes=php]<br/><?php<br/>class Dispatcher<br/>&#123;<br/>&nbsp;&nbsp;public function dispatchering()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;$o = new Controller();<br/>&nbsp;&nbsp;&nbsp;&nbsp;$o->actionExample();<br/>&nbsp;&nbsp;&nbsp;&nbsp;//这里应该通过请求来实例化指定的控制器，这里我们简单的以Controller来示范<br/>&nbsp;&nbsp;&nbsp;&nbsp;//你可以自己从Controller派生子类来实现指定请求，形如：<br/>&nbsp;&nbsp;&nbsp;&nbsp;//$controller = $this->getController();<br/>&nbsp;&nbsp;&nbsp;&nbsp;//$action = $this->getAction;<br/>&nbsp;&nbsp;&nbsp;&nbsp;//$o = new $controller();<br/>&nbsp;&nbsp;&nbsp;&nbsp;//$controller->$action();<br/>&nbsp;&nbsp;&#125;<br/>&#125;<br/><br/>class Controller<br/>&#123;<br/>&nbsp;&nbsp;private $_tpl;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;private $_model;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;public function __construct()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;$this->_tpl = new View();<br/>&nbsp;&nbsp;&nbsp;&nbsp;$this->_model = new Model();<br/>&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;public function actionExample()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;$str = $this->_model->get();<br/>&nbsp;&nbsp;&nbsp;&nbsp;$this->_tpl->display($str);&nbsp;&nbsp;<br/>&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;public function actionOthers()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&#125;<br/>&#125;<br/><br/>class View<br/>&#123;<br/>&nbsp;&nbsp;public function display($str)<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;echo $str;<br/>&nbsp;&nbsp;&#125;<br/>&#125;<br/><br/>class Model<br/>&#123;<br/>&nbsp;&nbsp;public function create()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;public function insert()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;public function update()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;public function get()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return "Hello world";//实际当中可能是从数据库、文本等取出数据<br/>&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;public function otherFunctions()<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&#125;<br/>&#125;<br/><br/>$run = new Dispatcher();<br/>$run->dispatchering();<br/>[/codes]<br/><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/60.htm</link>
<title><![CDATA[[原创]  PHP项目开发方式 ---  PHP框架编写123 ]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[PHP相关]]></category>
<pubDate>Sat, 14 Jun 2008 10:08:16 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/60.htm</guid> 
<description>
<![CDATA[ 
	写在前面的话: <span style="color: #0000FF;">感谢李学成师兄.</span><br/><br/>PS: 只是说说我的历程.<br/><br/>随着视野的扩大, 我开发php项目的方式也在不断的改变. 也许还有更多, 只是我没发现. 下面是我的一些改变历程:<br/><br/><br/>1.<span style="color: #FF0000;">最初</span>: 采用的是<span style="color: #0000FF;">php+html混写的方式编码</span>, 那个时候不知道什么是面向对象, 也不知道函数式编程其实就是面向过程. 所有项目都是采用<span style="color: #0000FF;">累积式的函数编写</span>, 稍稍的有一些模块分解的思想. 每一个函数的完成都能让我觉得什么的兴奋. 代码类似:<br/>[codes=php]<br/>if (some codes)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;echo '<tr><td>....</td></tr>';<br/>&#125;<br/>[/codes]<br/><br/>2.<span style="color: #FF0000;">起步</span>: 后来偶然间看到了强大的pw, 试着去阅读他的代码, 突然发现自己之前所学的都是破烂. 在pw身上我知道了<span style="color: #0000FF;">什么是模板, 什么是库, 怎么样去安排代码复用</span>.<br/>[codes=php]<br/><?php<br/>include "table.php";<br/>......<br/>[/codes]<br/><br/><br/>3.<span style="color: #FF0000;">实践</span>: 终于我开始了我一个不算正式的项目, 一个小公司的网站, 我尝试着采用<span style="color: #0000FF;">pw的模板和库</span>方式去做, 呵呵, 很幸运的, 虽然有些困难, 但最终我还是成功了.&nbsp;&nbsp;但是重复了几个类似的项目之后, 我累了, 不是我不够耐心, 而是重复写的代码太多, 即使是采用库的方式, 而且对于界面与功能的整合经常让我焦头烂额.<br/><br/>4.<span style="color: #FF0000;">成长</span>: 终于意识到问题了, gg了很多, 看到了采用 <span style="color: #0000FF;">class + template 的方式</span>, 这个时候才知道什么是面向对象. 因为当初我看的是php4, 几乎没有介绍到面向对象的任何内容. <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;面向对象是个非常庞大的理论体系, 学的越深越发觉他的好, 当然这不是对面向过程的否认, 他们本身并不冲突.&nbsp;&nbsp;在这个阶段我停留的最久.<br/><br/>5. <span style="color: #FF0000;">现在</span>: 人往高处走, 不可否认的, 架构师站得角度的确要比编码人员高, 为了更高的编码效率, 更好的复用, 更好的团队合作, 我开始学习设计模式,架构模式. 这也是我一直到现在还在深入的领域. <span style="color: #0000FF;">设计模式的学习才能更加深刻的理解面向对象, 面向对象不仅仅是类与对象那么的简单</span>, 那些只是它的一小部分. 在这一部分的学习里, 最多的得益来自于<span style="color: #FF0000;">fleaphp (http://www.fleaphp.org). </span>这是一个非常优秀的国产轻量级开发<span style="color: #0000FF;">框架</span>, 可以极大地提高项目的开发速度, 更多的是可以学习多众多优秀的架构思想与编程模式.<br/><br/><br/><a href="http://www.nd21.com/attachment.php?fid=13" target="_blank"><img src="http://www.nd21.com/attachment.php?fid=13" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>今天忽然打算将之前学习的全部整理出来, 所以就有了这篇以及之后的文章.<br/>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/59.htm</link>
<title><![CDATA[[原创] PHP框架编写123 总目录]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[PHP相关]]></category>
<pubDate>Sat, 14 Jun 2008 09:40:26 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/59.htm</guid> 
<description>
<![CDATA[ 
	<span style="color: #FF0000;">这是一项大的工程, 水平所限难免会有错误, 欢迎各位朋友指正.</span><br/><br/>声明: 这个系列的文章包含我学习php的一些经验和总结, 更多的是探讨与深入.<br/><br/>内容：<br/>学习到今天的php，很多东西觉得需要整理一下。这个系列的文章是我自我检验关于设计模式和框架的一些基本想法，很多地方都是分析fleaphp和zf得到的结果，当然也借鉴了其他的一些框架的优秀思想。<br/><br/>这里是汇总目录, 便于查阅:<br/><br/>目录:<br/>1. <a href="http://www.nd21.com/read.php/60.htm" target="_blank"><span style="color: #0000FF;">php项目开发方式</span></a><br/>2.<a href="http://www.nd21.com/read.php/61.htm " target="_blank"><span style="color: #0000FF;">web中的 MVC模式 --- PHP框架编写123 </span></a>[2008-06-27更新]<br/>3.<a href="http://www.nd21.com/read.php/64.htm" target="_blank"> <span style="color: #0000FF;">一些基本设定和框架总体设计---PHP框架编写123 </span></a>[2008-06-28更新]<br/>4.<a href="http://www.nd21.com/read.php/65.htm" target="_blank"><span style="color: #0000FF;">设计分发器（Dispatcher）--- PHP框架编写123</span> </a>[2008-07-03更新]<br/><br/><br/><br/>Tags - <a href="http://www.nd21.com/go.php/tags/php/" rel="tag">php</a> , <a href="http://www.nd21.com/go.php/tags/framework/" rel="tag">framework</a> , <a href="http://www.nd21.com/go.php/tags/mvc/" rel="tag">mvc</a> , <a href="http://www.nd21.com/go.php/tags/%25E6%25A1%2586%25E6%259E%25B6/" rel="tag">框架</a> , <a href="http://www.nd21.com/go.php/tags/%25E6%25A1%2586%25E6%259E%25B6%25E7%25BC%2596%25E5%2586%2599/" rel="tag">框架编写</a> , <a href="http://www.nd21.com/go.php/tags/%25E8%2587%25AA%25E5%25B7%25B1%25E7%25BC%2596%25E5%2586%2599/" rel="tag">自己编写</a> , <a href="http://www.nd21.com/go.php/tags/php%25E6%25A1%2586%25E6%259E%25B6/" rel="tag">php框架</a>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/58.htm</link>
<title><![CDATA[服务器前两天被D,现已恢复]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[站点公告]]></category>
<pubDate>Tue, 10 Jun 2008 05:09:17 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/58.htm</guid> 
<description>
<![CDATA[ 
	服务器前两天被D,现已恢复
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/57.htm</link>
<title><![CDATA[[强推][转帖]CSDN应当减少娱乐化，端正态度，提高水准]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[PHP相关]]></category>
<pubDate>Sun, 08 Jun 2008 04:47:13 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/57.htm</guid> 
<description>
<![CDATA[ 
	原文我也看到了，当时觉得ＣＳＤＮ的编辑是不是思维有问题，只是这样依然不能表达我的愤怒．下面陈浩兄的文章让我心里舒爽了很多，同时也认识到ＣＳＤＮ误导的也只是新手，或者非ＰＨＰ人员．在这里，我再一次的对ＣＳＤＮ编辑不负责任的翻译表示抗议！<br/><br/><br/><br/>帖子内容：<br/><br/><div class="quote"><div class="quote-title">引用</div><div class="quote-content">今天CSDN头条上有篇文章<br/><br/>《国际：身处两难境地，PHP该走向何方？》<br/>http://news.csdn.net/n/20080606/116556.html<br/><br/>文章来源于一个博客，作者因为招不到合格的PHP程序员，发了一通牢骚。<br/><br/>原文标题是：Where did all the PHP programmers go? (PHP程序员都到哪去了)，而CSDN居然翻译成“国际：身处两难境地，PHP 该走向何方？”这加上了“国际”，把“PHP程序员”换成了“PHP”，整个味道全变了，搞得好像什么很正式的国际评论，即没有真实反映原文作者的意图，又误导了国内的读者。<br/><br/>这篇文章反映了CSDN的不少问题：<br/><br/>1。不熟悉国际开源社区，有一定技术偏向；<br/><br/>我不知道CSDN的新闻来源是什么，但感觉CSDN在Linux，PHP这两方面应该说和国际社区太脱节了。大部分信息是Java、.NET相关，Linux/Unix/PHP方面的精品文章很少。这和我在欧洲的感觉完全不同。欧洲各种开源技术的User Group都很活跃，Linux和PHP的信息到处可见。CSDN本身基于Windows/.NET开发，也许这也是一个原因。但我想一个号称“中国最大的IT技术社区”，眼光不应该太狭隘。<br/><br/>CSDN选的这篇文章，来自一个对于PHP根本不怎么了解的公司招聘者，对于我们真正的PHP程序员来说，he is just a nobody，根本是一个无足轻重的小人物，这篇博客更不能代表“PHP 该走向何方”。技术社区的新闻来源要有一定的权威性。　如果真要关注PHP最新的发展，请上php.net或者几个大牛的博客，或者加入内部团队的邮件列表。<br/><br/>2。娱乐化倾向<br/><br/>我相信网络时代，吸引眼球、提高流量对于每个网站都是重要的，但是技术社区娱乐化，绝对不是个好主意。技术社区应该具备一定的严谨性，不可像娱乐八卦那样信口开河。因为娱乐新闻只是大家在茶余饭后的谈资，就算说错了，对于彼此来说不会有太大影响。人家明星如何和我们老百姓有啥关系。　但是技术社区的文章，如果也信口胡说，会严重误导读者，特别是那些新入门的开发者。对他们来说，“哪种语言是最优秀的，哪种语言是不好的”，这些有很重要的意义。也正因为如此，非常容易受到误导。（比如最最常见的说法是“PHP做小网站好用、但开发复杂的网站和大网站得用Java”，一般别人问我这种看法是否正确，我都让他们自己估计一下未来的网站会不会比facebook拥有更多用户，更大流量和更复杂的应用逻辑，因为facebook是用PHP开发的。）<br/><br/>现在PHP一直很流行，甚至上面提到的，号称Google之后最伟大WEB应用的“Facebook”，也是用PHP开发的。而CSDN的这篇文章却说“PHP已经过时”（英文原文是PHP is getting mature，PHP日渐成熟，这里是一个明显的翻译错误），这岂不是让人感到莫名其妙？&nbsp;&nbsp;这到底是编辑的英文水平太低，还是因为对PHP有偏见？　如果是编辑水平太低，请努力，如果是态度问题，真的需要反省一下。<br/><br/>短期的娱乐化运作，可能会带来更多人气，但长此以往，就会使CSDN在技术圈内失去公信力。已经有很多朋友和我说“CSDN编辑水平太低，经常胡扯，这个社区里菜鸟居多”。　这是非常糟糕的问题，CSDN应该像IBM DeveloperWorks那样，成为精品的代名词才行。<br/><br/>PS. 我从04年开始在CSDN写blog，感觉到CSDN越来越好（最直观的是博客系统，然后社区人数，线下活动等）。CSDN对国内技术社区的贡献还是很大的。<br/><br/>我也是CSDN WEB频道和Java频道的“专家”（虽然自认为水平一般），所以觉得应该把自己的想法说出来，供参考，希望CSDN在已有基础上精益求精。<br/><br/></div></div>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/56.htm</link>
<title><![CDATA[来自Adobe的DIV水平、垂直居中代码]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[AJAX/CSS/JS]]></category>
<pubDate>Mon, 02 Jun 2008 23:40:52 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/56.htm</guid> 
<description>
<![CDATA[ 
	呵呵，有创意，有意思的绝对定位：<br/>[codes=html]<br/>div#main &#123;<br/>&nbsp;&nbsp;position: absolute;<br/>&nbsp;&nbsp;left: 50%;<br/>&nbsp;&nbsp;top: 50%;<br/>&nbsp;&nbsp;margin-left: -478px;<br/>&nbsp;&nbsp;margin-top: -325px;<br/>&nbsp;&nbsp;text-align: center;<br/>&nbsp;&nbsp;width: 955px;<br/>&nbsp;&nbsp;height: 650px;<br/>&nbsp;&nbsp;border: 1px #CCCCCC solid;<br/>&#125;<br/>[/codes]<br/><br/>避免了为了兼容FF,IE要设置父子DIV属性的问题。 <span style="color: #0000FF;">当然这段代码也有小小的限制： 如果你的容器的高度超过了浏览器的屏幕高度，则需要在外面再套一层容器。</span><br/>Tags - <a href="http://www.nd21.com/go.php/tags/div/" rel="tag">div</a> , <a href="http://www.nd21.com/go.php/tags/%25E5%25B1%2585%25E4%25B8%25AD/" rel="tag">居中</a> , <a href="http://www.nd21.com/go.php/tags/%25E6%25B0%25B4%25E5%25B9%25B3/" rel="tag">水平</a> , <a href="http://www.nd21.com/go.php/tags/%25E5%259E%2582%25E7%259B%25B4/" rel="tag">垂直</a>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/55.htm</link>
<title><![CDATA[[强推]飞升之后]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[美文欣赏]]></category>
<pubDate>Sun, 01 Jun 2008 02:57:28 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/55.htm</guid> 
<description>
<![CDATA[ 
	玄幻类，绝对的经典，情节、内容、文本都属于上上之选<br/>http://www.qidian.com/Book/144549.aspx
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/54.htm</link>
<title><![CDATA[[强推历史穿越小说]极品家丁]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[美文欣赏]]></category>
<pubDate>Sun, 01 Jun 2008 02:55:53 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/54.htm</guid> 
<description>
<![CDATA[ 
	推荐指数 **********<br/><br/>嘿嘿，YY+智谋<br/><br/>http://www.qidian.com/Book/105199.aspx
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/52.htm</link>
<title><![CDATA[[CSS笔记]块级元素与内联元素]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[AJAX/CSS/JS]]></category>
<pubDate>Thu, 29 May 2008 08:40:12 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/52.htm</guid> 
<description>
<![CDATA[ 
	1.什么是块级元素 Block element<br/>块级元素是指以块的方式显示的元素，特点是单独占据一行，可以设置高宽度，当然设置了一些特殊属性除外，如浮动。块级元素有多个，如div，p，ul等等。<br/>2.什么是内联元素 Inline element<br/>内联元素的特点是以类似文本的方式显示，它不能设置高宽度，它的高宽度是它本身的高宽度（如文字、图片等），如a，span等。<br/><br/>块级元素可以通过display:inline属性来改变为内联显示，内联元素则可以通过display:block属性改变为块级显示。<br/><br/>备忘而已。<br/><br/>Tags - <a href="http://www.nd21.com/go.php/tags/block/" rel="tag">block</a> , <a href="http://www.nd21.com/go.php/tags/element/" rel="tag">element</a> , <a href="http://www.nd21.com/go.php/tags/inline/" rel="tag">inline</a> , <a href="http://www.nd21.com/go.php/tags/%25E5%259D%2597%25E7%25BA%25A7%25E5%2585%2583%25E7%25B4%25A0/" rel="tag">块级元素</a> , <a href="http://www.nd21.com/go.php/tags/%25E5%2586%2585%25E8%2581%2594%25E5%2585%2583%25E7%25B4%25A0/" rel="tag">内联元素</a> , <a href="http://www.nd21.com/go.php/tags/css/" rel="tag">css</a>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/51.htm</link>
<title><![CDATA[请为四川地震中遇难的人们默哀！]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[站点公告]]></category>
<pubDate>Tue, 13 May 2008 08:26:59 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/51.htm</guid> 
<description>
<![CDATA[ 
	请为四川地震中遇难的人们默哀 <br/>平安即是福
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/50.htm</link>
<title><![CDATA[wincachegrind-1.0.0.12下载]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[PHP相关]]></category>
<pubDate>Wed, 16 Apr 2008 14:39:42 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/50.htm</guid> 
<description>
<![CDATA[ 
	xdebug输出文件查看工具wincachegrind 1.0.0.12.<br/><br/>可以方便的查看PHP运行的过程，每个过程中发生的调用以及调用消耗的时间，是检查PHP程序运行效率瓶颈的利器。<br/><br/>示意图：<br/><br/><a href="http://www.nd21.com/attachment.php?fid=18" target="_blank"><img src="http://www.nd21.com/attachment.php?fid=18" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/><br/>打开日志输出对应XDebug配置选项：<br/>xdebug.profiler_enable=on<br/>xdebug.profiler_output_dir="c:/web/var/debuginfo"<br/><br/><br/><a href="attachment.php?fid=9">点击这里下载文件</a><br/><br/>Tags - <a href="http://www.nd21.com/go.php/tags/wincachegrind/" rel="tag">wincachegrind</a> , <a href="http://www.nd21.com/go.php/tags/xdebug/" rel="tag">xdebug</a> , <a href="http://www.nd21.com/go.php/tags/wincachegrind%25E4%25B8%258B%25E8%25BD%25BD/" rel="tag">wincachegrind下载</a>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/48.htm</link>
<title><![CDATA[PHP开发群]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[站点公告]]></category>
<pubDate>Tue, 08 Apr 2008 17:10:26 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/48.htm</guid> 
<description>
<![CDATA[ 
	群号：17588007<br/>暗号：我要php
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/66.htm</link>
<title><![CDATA[新博客启用]]></title> 
<author>Model.King &lt;P.Qingliang@hotmail.com&gt;</author>
<category><![CDATA[站点公告]]></category>
<pubDate>Tue, 08 Apr 2008 16:52:32 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/66.htm</guid> 
<description>
<![CDATA[ 
	使用了几个博客，感觉bo还是挺不错的，功能及支持都挺好。其他话不多说了。<br/>&nbsp;&nbsp; 南斗工作组其实只是我给这个窝起的一个名字而已，希望能在这里记录一些我学习生活中的事情，当然主要还是希望能和大家一起交流交流。当然任何爱好技术的同志我都非常欢迎你加入进来。<br/>&nbsp;&nbsp; 我本人不喜欢QQ群的形式讨论，不过还是建立了一个群：17588007，加入请写上：南斗。由于我个人的爱好，讨论的范围不是很广，主要是php和vc方面的技术，欢迎大家的加入。有什么事情也可以一起商讨一下。<br/><br/><br/><span style="color: #FF0000;">2008-07-08更新：上述信息已经无效。</span>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/47.htm</link>
<title><![CDATA[基于PHP5的上传类]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[PHP相关]]></category>
<pubDate>Sat, 05 Apr 2008 13:33:48 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/47.htm</guid> 
<description>
<![CDATA[ 
	[codes=php]<br/><?php<br/>define('ERROR_FILE_EXISTS', 8);<br/><br/>define('ERROR_EXIST_FILE_CANNOT_REMOVE', 9);<br/><br/>define('ERROR_NOT_UPLOAD_FILE', 10);<br/><br/>define('ERROR_NOT_ALLOW_TYPE', 11);<br/><br/>define('ERROR_CANNOT_MOVE', 12);<br/><br/>class N_Com_Upload<br/>&#123;<br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * 文章保存目录<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; * @var string<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;protected $_uploadDir = '/Upload/';&nbsp;&nbsp; <br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;/**<br/>&nbsp;&nbsp; * 最大文件体积<br/>&nbsp;&nbsp; *<br/>&nbsp;&nbsp; * @var integer<br/>&nbsp;&nbsp; */<br/>&nbsp;&nbsp;protected $_maxFilesize = 4194304;<br/>......<br/>[/codes]<br/>............<br/><br/>Tags - <a href="http://www.nd21.com/go.php/tags/%25E6%2596%2587%25E4%25BB%25B6%25E4%25B8%258A%25E4%25BC%25A0%252Cupload%252Cphp5%252C%25E6%2596%2587%25E4%25BB%25B6%25E4%25B8%258A%25E4%25BC%25A0%25E7%25B1%25BB%252Cphp/" rel="tag">文件上传,upload,php5,文件上传类,php</a>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/46.htm</link>
<title><![CDATA[上传了FreeBSD的手册]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[Linux]]></category>
<pubDate>Thu, 03 Apr 2008 17:58:03 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/46.htm</guid> 
<description>
<![CDATA[ 
	中文版是最新的.<br/>英文版的版本老了点,不过不影响使用. 大部分内容都没有改.<br/>中文版:<a href="http://www.nd21.com/download/online_learning/FreeBSD_Handbook/Chinese_Edition/" target="_blank">http://www.nd21.com/download/online_learning/FreeBSD_Handbook/Chinese_Edition/</a><br/>英文版:<a href="http://www.nd21.com/download/online_learning/FreeBSD_Handbook/English_Edition/" target="_blank">http://www.nd21.com/download/online_learning/FreeBSD_Handbook/English_Edition/</a><br/>Tags - <a href="http://www.nd21.com/go.php/tags/freebsd%252C/" rel="tag">freebsd,</a> , <a href="http://www.nd21.com/go.php/tags/freebsd%25E6%2589%258B%25E5%2586%258C%252Chandbook/" rel="tag">freebsd手册,handbook</a>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/45.htm</link>
<title><![CDATA[php中无限参数函数或方法的一种实现]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[PHP相关]]></category>
<pubDate>Wed, 26 Mar 2008 02:36:24 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/45.htm</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp; 由于需要，经常性的需要函数或方法能够接受任何个数的参数，当然参数的传入顺序是要符合预先指定的契约的。这里提供一种比较简单的方法，见代码<br/>[codes=php]<br/><?php<br/>class NANDOU_Db_TableSel<br/>&#123;<br/>&nbsp;&nbsp;protected $_sql;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;public function where($condition, $param1)<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;$param = func_get_args();<br/>&nbsp;&nbsp;&nbsp;&nbsp;$condition = array_shift($param);<br/>&nbsp;&nbsp;&nbsp;&nbsp;foreach ($param as $value)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$condition = str_replace('?', $value, $condition);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;$this->_sql .= $condition;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return $this;<br/>&nbsp;&nbsp;&#125;<br/>&#125;<br/><br/>$o = new NANDOU_Db_TableSel();<br/>$o->where('date > ? and name = ?', 2006, 'model');<br/>var_dump($o);<br/>?><br/>[/codes]<br/>结果显示<br/><div class="quote"><div class="quote-title">引用</div><div class="quote-content">object(NANDOU_Db_TableSel)#1 (1) &#123; ["_sql:protected"]=> string(27) "date > 2006 and name = 2006" &#125; </div></div><br/>呵呵，想法来源于http://code.google.com/p/qeephp/wiki/QDB_Table_Select ，当时想不出它是怎么实现的。<br/><br/>顺便广告一下：<span style="color: #0000FF;">http://www.fleaphp.org/ 很不错的国产PHP框架，除了文档不如意之外，其他都是非常优秀的，尤其在数据库处理方面，很多有创意的代码。</span><br/>Tags - <a href="http://www.nd21.com/go.php/tags/%25E6%2597%25A0%25E9%2599%2590%25E5%258F%2582%25E6%2595%25B0%252C%25E5%2587%25BD%25E6%2595%25B0%252C%25E6%2596%25B9%25E6%25B3%2595/" rel="tag">无限参数,函数,方法</a>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/44.htm</link>
<title><![CDATA[foreach遍历数组的一点注意]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[PHP相关]]></category>
<pubDate>Sun, 23 Mar 2008 05:38:48 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/44.htm</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp; 使用foreach遍历数组可能是我们php编程中最常见的代码之一，然而也就是这“最常见”的代码让我郁闷了一下。 源代码如下：<br/>[codes=php]<br/>foreach ($rs as $key=>$value)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; $value['title'] = str_repeat('&#124;--', $value['depth']).$value['title'];<br/>&#125;<br/>[/codes]<br/><br/>代码本身希望能够在title列前加上一定数量(depth)的 &#124;-- 标记，实际输出的时候，却什么都没有改变。本来以为是PDOStatement对象本身不能修改的问题，经过测试给排除了。 最后郁闷的发现PHP手册上这样的一句话：<br/><div class="quote"><div class="quote-title">引用</div><div class="quote-content">除非数组是被引用，foreach 所操作的是指定数组的一个拷贝，而不是该数组本身</div></div><br/>汗啊，只好改了下代码使用for循环来操作:<br/>[codes=php]<br/>$size = sizeof($rs);<br/>for ($i=0; $i<$size; $i++)<br/>&#123;<br/>&nbsp;&nbsp;$rs[$i]['title'] = str_repeat('&#124;--', $rs[$i]['depth']).$rs[$i]['title'];<br/>&#125;<br/>[/codes]<br/><br/>如果你的php版本是5.0以上也可以这样写：<br/>[codes=php]<br/>foreach ($rs as $key=>&$value)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $value['title'] = str_repeat('&#124;--', $value['depth']).$value['title'];<br/>&#125;<br/>[/codes]<br/><br/>小小问题，狠狠郁闷<br/>Tags - <a href="http://www.nd21.com/go.php/tags/foreach%252C%25E6%258B%25B7%25E8%25B4%259D%252Cphp5%252Cfor%252C%25E5%25BC%2595%25E7%2594%25A8%252C%25E4%25B8%258D%25E8%2583%25BD%25E4%25BF%25AE%25E6%2594%25B9/" rel="tag">foreach,拷贝,php5,for,引用,不能修改</a>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/43.htm</link>
<title><![CDATA[PHPPDOMysql事务处理的一些总结]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[PHP相关]]></category>
<pubDate>Sun, 16 Mar 2008 02:21:43 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/43.htm</guid> 
<description>
<![CDATA[ 
	一些比较零散的总结：<br/>1.Mysql默认的是自动提交变更的，即默认autocommit模式；可以使用SET AUTOCOMMIT=0;语句来禁用autocommit模式，不过这仅对当前连接有效。<br/><br/>2.当开始一个事务处理过程时，autocommit模式自动被禁用，直至事务结束。<br/><br/>3.如果表支持事务，而在PHP中禁用了autocommit模式，则可能会导致PHP返回成功值，而实际未成功写入数据到Mysql的问题。所以一般情况下，在PHP中请不要禁用连接的autocommit模式。<br/><br/>4.某些操作会导致隐含的结束一个事务过程，见Mysql手册<span style="color: #0000FF;">13.4.3. 会造成隐式提交的语句</span><br/><br/>5.如果使用try catch对来捕捉PDO执行过程中的错误，打开连接后进行如下设置：<br/>[codes=php]$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);[/codes]<br/>表示如何错误都以异常抛出，提高程序健壮性的同时也帮助了改善程序的逻辑。这样在事务处理过程的不能成功执行的语句都以异常抛出，并可以获得这些异常的来源，方便解决。<br/>Tags - <a href="http://www.nd21.com/go.php/tags/mysql%252Cphp%252Cpdo%252C%25E4%25BA%258B%25E5%258A%25A1%25E5%25A4%2584%25E7%2590%2586%252Cautocommit/" rel="tag">mysql,php,pdo,事务处理,autocommit</a>
]]>
</description>
</item><item>
<link>http://www.nd21.com/read.php/42.htm</link>
<title><![CDATA[Form表单action属性设置问题]]></title> 
<author>P.Qingliang &lt;p.qingliang@hotmail.com&gt;</author>
<category><![CDATA[AJAX/CSS/JS]]></category>
<pubDate>Tue, 11 Mar 2008 07:34:05 +0000</pubDate> 
<guid>http://www.nd21.com/read.php/42.htm</guid> 
<description>
<![CDATA[ 
	帖一下代码<br/><br/>[codes=js]<br/>function categoryAction()<br/>&#123;<br/>&nbsp;&nbsp;var url;<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;if ($('#delete').attr('checked'))<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;url = $('#formAction').attr('action') + 'delete';<br/>&nbsp;&nbsp;&nbsp;&nbsp;alert(url);<br/>&nbsp;&nbsp;&nbsp;&nbsp;document.getElementById("formAction").action.value = url; // ......1<br/>&nbsp;&nbsp;&nbsp;&nbsp;$('#formAction').attr('action', url);&nbsp;&nbsp;//......2<br/>&nbsp;&nbsp;&nbsp;&nbsp;alert($('#formAction').attr('action'));<br/>&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;else if ($('#edit').attr('checked'))<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;//$('#formAction').attr('action', actionUrl + 'edit');<br/>&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;alert('请选择动作!');<br/>&nbsp;&nbsp;&#125;<br/>&nbsp;