﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-oyjpArt ACM/ICPC算法程序设计空间-随笔分类-程序设计</title><link>http://www.cppblog.com/sicheng/category/6000.html</link><description>// I am new in programming, welcome to my blog &lt;br&gt;
I am oyjpart(alpc12, 四城)
</description><language>zh-cn</language><lastBuildDate>Fri, 26 Feb 2010 21:41:44 GMT</lastBuildDate><pubDate>Fri, 26 Feb 2010 21:41:44 GMT</pubDate><ttl>60</ttl><item><title>[zz]当你输入一个网址的时候，实际会发生什么?</title><link>http://www.cppblog.com/sicheng/archive/2010/02/26/108499.html</link><dc:creator>oyjpart</dc:creator><author>oyjpart</author><pubDate>Fri, 26 Feb 2010 08:22:00 GMT</pubDate><guid>http://www.cppblog.com/sicheng/archive/2010/02/26/108499.html</guid><wfw:comment>http://www.cppblog.com/sicheng/comments/108499.html</wfw:comment><comments>http://www.cppblog.com/sicheng/archive/2010/02/26/108499.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/sicheng/comments/commentRss/108499.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/sicheng/services/trackbacks/108499.html</trackback:ping><description><![CDATA[<span class=Apple-style-span style="FONT-SIZE: 13px; FONT-FAMILY: arial, sans-serif; BORDER-COLLAPSE: collapse" sizset="13" sizcache="2">&nbsp;
<p>作为一个软件开发者，你一定会对网络应用如何工作有一个完整的层次化的认知，同样这里也包括这些应用所用到的技术：像浏览器，HTTP，HTML，网络服务器，需求处理等等。</p>
<p>本文将更深入的研究当你输入一个网址的时候，后台到底发生了一件件什么样的事～</p>
<h3>1. 首先嘛，你得在浏览器里输入要网址:</h3>
<p sizset="13" sizcache="2"><img title=image height=103 alt=image src="http://top.oa.com/apis/imgcache.php/http://igoro.com/wordpress/wp-content/uploads/2010/02/image4.png" width=591 border=0></p>
<p>&#160;</p>
<h3>2. 浏览器查找域名的IP地址</h3>
<p sizset="14" sizcache="2"><img title=image height=96 alt=image src="http://top.oa.com/apis/imgcache.php/http://igoro.com/wordpress/wp-content/uploads/2010/02/image13.png" width=228 border=0></p>
<p>导航的第一步是通过访问的域名找出其IP地址。DNS查找过程如下：</p>
<div style="MARGIN: 0px">
<ul>
    <li><strong>浏览器缓存 &#8211;&nbsp;</strong>浏览器会缓存DNS记录一段时间。 有趣的是，操作系统没有告诉浏览器储存DNS记录的时间，这样不同浏览器会储存个自固定的一个时间（2分钟到30分钟不等）。
    <li><strong>系统缓存</strong>&nbsp;&#8211; 如果在浏览器缓存里没有找到需要的记录，浏览器会做一个系统调用（windows里是gethostbyname）。这样便可获得系统缓存中的记录。
    <li><strong>路由器缓存</strong>&nbsp;&#8211; 接着，前面的查询请求发向路由器，它一般会有自己的DNS缓存。
    <li><strong>ISP DNS 缓存</strong>&nbsp;&#8211; 接下来要check的就是ISP缓存DNS的服务器。在这一般都能找到相应的缓存记录。
    <li><strong>递归搜索</strong>&nbsp;&#8211; 你的ISP的DNS服务器从跟域名服务器开始进行递归搜索，从.com顶级域名服务器到Facebook的域名服务器。一般DNS服务器的缓存中会有.com域名服务器中的域名，所以到顶级服务器的匹配过程不是那么必要了。</li>
</ul>
</div>
<p>DNS递归查找如下图所示：</p>
<p sizset="15" sizcache="2"><img title=500px-An_example_of_theoretical_DNS_recursion_svg height=178 alt=500px-An_example_of_theoretical_DNS_recursion_svg src="http://top.oa.com/apis/imgcache.php/http://igoro.com/wordpress/wp-content/uploads/2010/02/500pxAn_example_of_theoretical_DNS_recursion_svg.png" width=500 border=0></p>
<div style="MARGIN: 0px">
<p>DNS有一点令人担忧，这就是像wikipedia.org 或者 facebook.com这样的整个域名看上去只是对应一个单独的IP地址。还好，有几种方法可以消除这个瓶颈：</p>
<ul>
    <li><a style="COLOR: rgb(34,68,187)" href="http://baike.baidu.com/view/1527368.html" target=_blank><strong><u>循环 DNS</u></strong></a>&nbsp;是DNS查找时返回多个IP时的解决方案。举例来说，Facebook.com实际上就对应了四个IP地址。
    <li><a style="COLOR: rgb(34,68,187)" href="http://baike.baidu.com/view/486970.htm" target=_blank><strong><u>负载平衡器</u></strong></a>&nbsp;是以一个特定IP地址进行侦听并将网络请求转发到集群服务器上的硬件设备。 一些大型的站点一般都会使用这种昂贵的高性能负载平衡器。
    <li><strong>地理 DNS&nbsp;</strong>根据用户所处的地理位置，通过把域名映射到多个不同的IP地址提高可扩展性。这样不同的服务器不能够更新同步状态，但映射静态内容的话非常好。
    <li><a style="COLOR: rgb(34,68,187)" href="http://baike.baidu.com/view/1398775.htm" target=_blank><u><strong>Anycast</strong>&nbsp;</u></a>是一个IP地址映射多个物理主机的路由技术。 美中不足，Anycast与TCP协议适应的不是很好，所以很少应用在那些方案中。</li>
</ul>
</div>
<div style="MARGIN: 0px">
<p>大多数DNS服务器使用Anycast来获得高效低延迟的DNS查找。</p>
<p>&#160;</p>
</div>
<h3>3. 浏览器给web服务器发送一个HTTP请求</h3>
<p sizset="16" sizcache="2"><img title=image height=95 alt=image src="http://top.oa.com/apis/imgcache.php/http://igoro.com/wordpress/wp-content/uploads/2010/02/image22.png" width=216 border=0></p>
<p>因为像Facebook主页这样的动态页面，打开后在浏览器缓存中很快甚至马上就会过期，毫无疑问他们不能从中读取。</p>
<p>所以，浏览器将把一下请求发送到Facebook所在的服务器：</p>
<pre style="FONT-SIZE: 12px">GET http://facebook.com/ HTTP/1.1<br> Accept: application/x-ms-application, image/jpeg, application/xaml+xml, <font size=+0>[...]</font><br> User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; <font size=+0>[...]</font><br> Accept-Encoding: gzip, deflate<br> Connection: Keep-Alive<br> Host: facebook.com<br> Cookie: datr=1265876274-<font size=+0>[...]</font>; locale=en_US; lsd=WW<font size=+0>[...]</font>; c_user=2101<font size=+0>[...]</font></pre>
<p>GET 这个请求定义了要读取的<strong>URL</strong>： &#8220;http://facebook.com/&#8221;。 浏览器自身定义 (<strong>User-Agent</strong>&nbsp;头)， 和它希望接受什么类型的相应 (<strong>Accept</strong>&nbsp;and&nbsp;<strong>Accept-Encoding</strong>&nbsp;头).&nbsp;<strong>Connection</strong>头要求服务器为了后边的请求不要关闭TCP连接。</p>
<p>请求中也包含浏览器存储的该域名的<strong>cookies</strong>。可能你已经知道，在不同页面请求当中，cookies是与跟踪一个网站状态相匹配的键值。这样cookies会存储登录用户名，服务器分配的密码和一些用户设置等。Cookies会以文本文档形式存储在客户机里，每次请求时发送给服务器。</p>
<div style="MARGIN: 0px">
<p>用来看原始HTTP请求及其相应的工具很多。作者比较喜欢使用fiddler，当然也有像FireBug这样其他的工具。这些软件在网站优化时会帮上很大忙。</p>
</div>
除了获取请求，还有一种是发送请求，它常在提交表单用到。发送请求通过URL传递其参数(e.g.: http://robozzle.com/puzzle.aspx?id=85)。发送请求在请求正文头之后发送其参数。<br><br>像&#8220;http://facebook.com/&#8221;中的斜杠是至关重要的。这种情况下，浏览器能安全的添加斜杠。而像&#8220;http://example.com/folderOrFile&#8221;这样的地址，因为浏览器不清楚folderOrFile到底是文件夹还是文件，所以不能自动添加斜杠。这时，浏览器就不加斜杠直接访问地址，服务器会响应一个重定向，结果造成一次不必要的握手。<br><br>
<h3>4. facebook服务的永久重定向响应</h3>
<p sizset="17" sizcache="2"><img title=image height=87 alt=image src="http://top.oa.com/apis/imgcache.php/http://igoro.com/wordpress/wp-content/uploads/2010/02/image8.png" width=214 border=0></p>
<p>图中所示为Facebook服务器发回给浏览器的响应：</p>
<pre style="FONT-SIZE: 12px">HTTP/1.1 301 Moved Permanently<br> Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0,<br> pre-check=0<br> Expires: Sat, 01 Jan 2000 00:00:00 GMT<br> Location: http://www.facebook.com/<br> P3P: CP="DSP LAW"<br> Pragma: no-cache<br> Set-Cookie: made_write_conn=deleted; expires=Thu, 12-Feb-2009 05:09:50 GMT;<br> path=/; domain=.facebook.com; httponly<br> Content-Type: text/html; charset=utf-8<br> X-Cnection: close<br> Date: Fri, 12 Feb 2010 05:09:51 GMT<br> Content-Length: 0</pre>
<p>服务器给浏览器响应一个301永久重定向响应，这样浏览器就会访问&#8220;http://www.facebook.com/&#8221; 而非&#8220;http://facebook.com/&#8221;。</p>
<div style="MARGIN: 0px">
<p>为什么服务器一定要重定向而不是直接发会用户想看的网页内容呢？这个问题有好多有意思的答案。</p>
<p>其中一个原因跟<strong>搜索引擎排名</strong>有关。你看，如果一个页面有两个地址，就像http://www.igoro.com/ 和http://igoro.com/，搜索引擎会认为它们是两个网站，结果造成每一个的搜索链接都减少从而降低排名。而搜索引擎知道301永久重定向是什么意思，这样就会把访问带www的和不带www的地址归到同一个网站排名下。</p>
<p>还有一个是用不同的地址会造成<strong>缓存友好性</strong>变差。当一个页面有好几个名字时，它可能会在缓存里出现好几次。</p>
</div>
<h3>5. 浏览器跟踪重定向地址</h3>
<p sizset="18" sizcache="2"><img title=image height=95 alt=image src="http://top.oa.com/apis/imgcache.php/http://igoro.com/wordpress/wp-content/uploads/2010/02/image23.png" width=216 border=0></p>
<p>现在，浏览器知道了&#8220;http://www.facebook.com/&#8221;才是要访问的正确地址，所以它会发送另一个获取请求：</p>
<pre style="FONT-SIZE: 12px">GET http://www.facebook.com/ HTTP/1.1<br> Accept: application/x-ms-application, image/jpeg, application/xaml+xml, <font size=+0>[...]</font><br> Accept-Language: en-US<br> User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; <font size=+0>[...]</font><br> Accept-Encoding: gzip, deflate<br> Connection: Keep-Alive<br> Cookie: lsd=XW<font size=+0>[...]</font>; c_user=21<font size=+0>[...]</font>; x-referer=<font size=+0>[...]</font><br> Host: www.facebook.com</pre>
<p>头信息以之前请求中的意义相同。</p>
<h3>6. 服务器&#8220;处理&#8221;请求</h3>
<p sizset="19" sizcache="2"><img title=image height=78 alt=image src="http://top.oa.com/apis/imgcache.php/http://igoro.com/wordpress/wp-content/uploads/2010/02/image9.png" width=93 border=0></p>
<p>服务器接收到获取请求，然后处理并返回一个响应。</p>
<p>这表面上看起来是一个顺向的任务，但其实这中间发生了很多有意思的东西- 就像作者博客这样简单的网站，何况像facebook那样访问量大的网站呢！</p>
<ul>
    <li><strong>Web 服务器软件<br></strong>web服务器软件（像IIS和阿帕奇）接收到HTTP请求，然后确定执行什么请求处理来处理它。请求处理就是一个能够读懂请求并且能生成HTML来进行响应的程序（像ASP.NET,PHP,RUBY...）。
    <p>举个最简单的例子，需求处理可以以映射网站地址结构的文件层次存储。像http://example.com/folder1/page1.aspx这个地址会映射/httpdocs/folder1/page1.aspx这个文件。web服务器软件可以设置成为地址人工的对应请求处理，这样page1.aspx的发布地址就可以是http://example.com/folder1/page1。</p>
    <li><strong>请求处理<br></strong>请求处理阅读请求及它的参数和cookies。它会读取也可能更新一些数据，并讲数据存储在服务器上。然后，需求处理会生成一个HTML响应。</li>
</ul>
<div style="MARGIN: 0px">
<p>所有动态网站都面临一个有意思的难点 -如何存储数据。小网站一半都会有一个SQL数据库来存储数据，存储大量数据和/或访问量大的网站不得不找一些办法把数据库分配到多台机器上。解决方案有：sharding （基于主键值讲数据表分散到多个数据库中），复制，利用弱语义一致性的简化数据库。</p>
</div>
<div style="MARGIN: 0px">
<p>委托工作给批处理是一个廉价保持数据更新的技术。举例来讲，Fackbook得及时更新新闻feed，但数据支持下的&#8220;你可能认识的人&#8221;功能只需要每晚更新（作者猜测是这样的，改功能如何完善不得而知）。批处理作业更新会导致一些不太重要的数据陈旧，但能使数据更新耕作更快更简洁。</p>
</div>
<h3>7. 服务器发回一个HTML响应</h3>
<p sizset="20" sizcache="2"><img title=image height=87 alt=image src="http://top.oa.com/apis/imgcache.php/http://igoro.com/wordpress/wp-content/uploads/2010/02/image10.png" width=214 border=0></p>
<p>图中为服务器生成并返回的响应：</p>
<pre style="FONT-SIZE: 12px">HTTP/1.1 200 OK<br> Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0,<br> pre-check=0<br> Expires: Sat, 01 Jan 2000 00:00:00 GMT<br> P3P: CP="DSP LAW"<br> Pragma: no-cache<br> Content-Encoding: gzip<br> Content-Type: text/html; charset=utf-8<br> X-Cnection: close<br> Transfer-Encoding: chunked<br> Date: Fri, 12 Feb 2010 09:05:55 GMT<br> <br> 2b3��������T�n�@����<font size=+0>[...]</font></pre>
<p>整个响应大小为35kB，其中大部分在整理后以blob类型传输。</p>
<p><strong>内容编码</strong>头告诉浏览器整个响应体用gzip算法进行压缩。解压blob块后，你可以看到如下期望的HTML：</p>
<pre style="FONT-SIZE: 12px">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"&nbsp;&nbsp;&nbsp; <br> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;<br> &lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"<br> lang="en" id="facebook" class=" no_js"&gt;<br> &lt;head&gt;<br> &lt;meta http-equiv="Content-type" content="text/html; charset=utf-8" /&gt;<br> &lt;meta http-equiv="Content-language" content="en" /&gt;<br> ...</pre>
<p>关于压缩，头信息说明了是否缓存这个页面，如果缓存的话如何去做，有什么cookies要去设置（前面这个响应里没有这点）和隐私信息等等。</p>
<div style="MARGIN: 0px">
<p>请注意报头中把<strong>Content-type</strong>设置为&#8220;<strong>text/html</strong>&#8221;。报头让浏览器将该响应内容以HTML形式呈现，而不是以文件形式下载它。浏览器会根据报头信息决定如何解释该响应，不过同时也会考虑像URL扩展内容等其他因素。</p>
</div>
<h3>8. 浏览器开始显示HTML</h3>
<p>在浏览器没有完整接受全部HTML文档时，它就已经开始显示这个页面了：</p>
<p sizset="21" sizcache="2"><img title=image height=137 alt=image src="http://top.oa.com/apis/imgcache.php/http://igoro.com/wordpress/wp-content/uploads/2010/02/image6.png" width=244 border=0></p>
<h3>9. 浏览器发送获取嵌入在HTML中的对象</h3>
<p sizset="22" sizcache="2"><img title=image height=126 alt=image src="http://top.oa.com/apis/imgcache.php/http://igoro.com/wordpress/wp-content/uploads/2010/02/image11.png" width=214 border=0></p>
<p>在浏览器显示HTML时，它会注意到需要获取其他地址内容的标签。这时，浏览器会发送一个获取请求来重新获得这些文件。</p>
<p>下面是几个我们访问facebook.com时需要重获取的几个URL：</p>
<ul>
    <li><strong>图片<br></strong>http://static.ak.fbcdn.net/rsrc.php/z12E0/hash/8q2anwu7.gif<br>http://static.ak.fbcdn.net/rsrc.php/zBS5C/hash/7hwy7at6.gif<br>&#8230;
    <li><strong>CSS 式样表<br></strong>http://static.ak.fbcdn.net/rsrc.php/z448Z/hash/2plh8s4n.css<br>http://static.ak.fbcdn.net/rsrc.php/zANE1/hash/cvtutcee.css<br>&#8230;
    <li><strong>JavaScript 文件</strong><br>http://static.ak.fbcdn.net/rsrc.php/zEMOA/hash/c8yzb6ub.js<br>http://static.ak.fbcdn.net/rsrc.php/z6R9L/hash/cq2lgbs8.js<br>&#8230;</li>
</ul>
<p>这些地址都要经历一个和HTML读取类似的过程。所以浏览器会在DNS中查找这些域名，发送请求，重定向等等...</p>
<p>但不像动态页面那样，静态文件会允许浏览器对其进行缓存。有的文件可能会不需要与服务器通讯，而从缓存中直接读取。服务器的响应中包含了静态文件保存的期限信息，所以浏览器知道要把它们缓存多长时间。还有，每个响应都可能包含像版本号一样工作的ETag头（被请求变量的实体值），如果浏览器观察到文件的版本ETag信息已经存在，就马上停止这个文件的传输。</p>
<div style="MARGIN: 0px">
<p>试着猜猜看&#8220;<strong>fbcdn.net</strong>&#8221;在地址中代表什么？聪明的答案是"Facebook内容分发网络"。Facebook利用内容分发网络（CDN）分发像图片，CSS表和JavaScript文件这些静态文件。所以，这些文件会在全球很多CDN的数据中心中留下备份。</p>
<p>静态内容往往代表站点的带宽大小，也能通过CDN轻松的复制。通常网站会使用第三方的CDN。例如，Facebook的静态文件由最大的CDN提供商Akamai来托管。</p>
<p>举例来讲，当你试着ping static.ak.fbcdn.net的时候，可能会从某个akamai.net服务器上获得响应。有意思的是，当你同样再ping一次的时候，响应的服务器可能就不一样，这说明幕后的负载平衡开始起作用了。</p>
</div>
<h3>10. 浏览器发送异步（AJAX）请求</h3>
<p sizset="23" sizcache="2"><img title=image height=120 alt=image src="http://top.oa.com/apis/imgcache.php/http://igoro.com/wordpress/wp-content/uploads/2010/02/image12.png" width=214 border=0></p>
<p>在Web 2.0伟大精神的指引下，页面显示完成后客户端仍与服务器端保持着联系。</p>
<p>以Facebook聊天功能为例，它会持续与服务器保持联系来及时更新你那些亮亮灰灰的好友状态。为了更新这些头像亮着的好友状态，在浏览器中执行的JavaScript代码会给服务器发送异步请求。这个异步请求发送给特定的地址，它是一个按照程式构造的获取或发送请求。还是在Facebook这个例子中，客户端发送给http://www.facebook.com/ajax/chat/buddy_list.php一个发布请求来获取你好友里哪个在线的状态信息。</p>
<p>提起这个模式，就必须要讲讲"AJAX"-- &#8220;异步JavaScript 和 XML&#8221;，虽然服务器为什么用XML格式来进行响应也没有个一清二白的原因。再举个例子吧，对于异步请求，Facebook会返回一些JavaScript的代码片段。</p>
<div style="MARGIN: 0px">
<p>除了其他，fiddler这个工具能够让你看到浏览器发送的异步请求。事实上，你不仅可以被动的做为这些请求的看客，还能主动出击修改和重新发送它们。AJAX请求这么容易被蒙，可着实让那些计分的在线游戏开发者们郁闷的了。（当然，可别那样骗人家~）</p>
</div>
<div style="MARGIN: 0px">
<p>Facebook聊天功能提供了关于AJAX一个有意思的问题案例：把数据从服务器端推送到客户端。因为HTTP是一个请求-响应协议，所以聊天服务器不能把新消息发给客户。取而代之的是客户端不得不隔几秒就轮询下服务器端看自己有没有新消息。</p>
<p>这些情况发生时长轮询是个减轻服务器负载挺有趣的技术。如果当被轮询时服务器没有新消息，它就不理这个客户端。而当尚未超时的情况下收到了该客户的新消息，服务器就会找到未完成的请求，把新消息做为响应返回给客户端。</p>
</div>
<h3>总结一下</h3>
<p>希望看了本文，你能明白不同的网络模块是如何协同工作的</p>
</span>
<img src ="http://www.cppblog.com/sicheng/aggbug/108499.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/sicheng/" target="_blank">oyjpart</a> 2010-02-26 16:22 <a href="http://www.cppblog.com/sicheng/archive/2010/02/26/108499.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>记录一个bug</title><link>http://www.cppblog.com/sicheng/archive/2009/10/24/99336.html</link><dc:creator>oyjpart</dc:creator><author>oyjpart</author><pubDate>Fri, 23 Oct 2009 18:05:00 GMT</pubDate><guid>http://www.cppblog.com/sicheng/archive/2009/10/24/99336.html</guid><wfw:comment>http://www.cppblog.com/sicheng/comments/99336.html</wfw:comment><comments>http://www.cppblog.com/sicheng/archive/2009/10/24/99336.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/sicheng/comments/commentRss/99336.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/sicheng/services/trackbacks/99336.html</trackback:ping><description><![CDATA[<p>&nbsp;vector&lt;SyllState&gt; StateQueue;</p>
<p>&nbsp;StateQueue.reserve(m_psz.GetLength());<br>&nbsp;StateQueue.push_back(SyllState(_T(""), iEndCharIdx));<br>&nbsp;BOOL bExit = FALSE;<br>&nbsp;INT iBegin = 0;<br>&nbsp;while(iBegin &lt; (INT)StateQueue.size() &amp;&amp; !bExit)<br>&nbsp;{<br><span style="COLOR: red">&nbsp;&nbsp;INT&amp; iIndex = StateQueue[iBegin].iIndex;<br>&nbsp;&nbsp;CString&amp; strSyll = StateQueue[iBegin].strSyll;</span><br>&nbsp;&nbsp;iBegin++;</p>
<p>&nbsp;&nbsp;INT&amp; nNumOfPres = m_pNumOfPre[iIndex];<br>&nbsp;&nbsp;for(INT i = 0; i &lt; nNumOfPres; ++i)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;INT&amp; nPre = m_pPre[iIndex][i];<br>&nbsp;&nbsp;&nbsp;if(nPre &lt; iBegCharIdx) continue;</p>
<p>&nbsp;&nbsp;&nbsp;if(nPre == iBegCharIdx)<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;CString strSyllFound = m_psz.Mid(nPre, iIndex - nPre) + _T("\'") + strSyll;<br>&nbsp;&nbsp;&nbsp;&nbsp;vecSubSyllable.Add(strSyllFound.Left(strSyllFound.GetLength()-1));<br>&nbsp;&nbsp;&nbsp;&nbsp;if(vecSubSyllable.GetCount() &gt;= MAX_SYLLABLE_NUM)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bExit = TRUE;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;else<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;StateQueue.push_back(SyllState(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_psz.Mid(nPre, iIndex - nPre) + _T("\'") + strSyll, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nPre));<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;}<br>&nbsp;}</p>
<br>上述代码有问题吗？<br>有。拿的是vector的引用，但是vector自动扩容去了，结果导致引用位置内存被重写，引起错误。
<img src ="http://www.cppblog.com/sicheng/aggbug/99336.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/sicheng/" target="_blank">oyjpart</a> 2009-10-24 02:05 <a href="http://www.cppblog.com/sicheng/archive/2009/10/24/99336.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转】简介vc中的release和debug版本的区别</title><link>http://www.cppblog.com/sicheng/archive/2009/03/16/76698.html</link><dc:creator>oyjpart</dc:creator><author>oyjpart</author><pubDate>Sun, 15 Mar 2009 16:25:00 GMT</pubDate><guid>http://www.cppblog.com/sicheng/archive/2009/03/16/76698.html</guid><wfw:comment>http://www.cppblog.com/sicheng/comments/76698.html</wfw:comment><comments>http://www.cppblog.com/sicheng/archive/2009/03/16/76698.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/sicheng/comments/commentRss/76698.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/sicheng/services/trackbacks/76698.html</trackback:ping><description><![CDATA[<p>原文地址http://www.cinrad.com/Get/Program/VC/VC/223112980.htm
<br></p>
<p>Debug通常称为调试版本，它包含调试信息，并且不作任何优化，便于程序员调试程序。Release称为发布版本，它往往是进行了各种优化，使得程序在代码大小和运行速度上都是最优的，以便用户很好地使用。</p>
<p>Debug 和 Release 的真正秘密，在于一组编译选项。下面列出了分别针对二者的选项（当然除此之外还有其他一些，如/Fd /Fo，但区别并不重要，通常他们也不会引起 Release 版错误，在此不讨论）</p>
<p>Debug 版本</p>
<p><br>参数 含义 <br>/MDd /MLd 或 /MTd 使用 Debug runtime library (调试版本的运行时刻函数库) <br>/Od 关闭优化开关 <br>/D "_DEBUG" 相当于 #define _DEBUG,打开编译调试代码开关 (主要针对assert函数) <br>/ZI 创建 Edit and continue(编辑继续)数据库，这样在调试过程中如果修改了源代码不需重新编译 <br>/GZ 可以帮助捕获内存错误 <br>/Gm 打开最小化重链接开关， 减少链接时间 </p>
<p>&nbsp;</p>
<p>Release 版本 </p>
<p><br>参数 含义 <br>/MD /ML 或 /MT 使用发布版本的运行时刻函数库 <br>/O1 或 /O2 优化开关，使程序最小或最快 <br>/D "NDEBUG" 关闭条件编译调试代码开关 (即不编译assert函数) <br>/GF 合并重复的字符串， 并将字符串常量放到只读内存， 防止被修改 </p>
<p>&nbsp;</p>
<p>实际上，Debug 和 Release 并没有本质的界限，他们只是一组编译选项的集合，编译器只是按照预定的选项行动。事实上，我们甚至可以修改这些选项，从而得到优化过的调试版本或是带跟踪语句的发布版本。 </p>
<p>哪些情况下 Release 版会出错 </p>
<p>有了上面的介绍，我们再来逐个对照这些选项看看 Release 版错误是怎样产生的 </p>
<p>1、Runtime Library：链接哪种运行时刻函数库通常只对程序的性能产生影响。调试版本的 Runtime Library
包含了调试信息，并采用了一些保护机制以帮助发现错误，因此性能不如发布版本。编译器提供的 Runtime Library 通常很稳定，不会造成
Release 版错误；倒是由于 Debug 的 Runtime Library 加强了对错误的检测，如堆内存分配，有时会出现 Debug
有错但 Release 正常的现象。应当指出的是，如果 Debug 有错，即使 Release 正常，程序肯定是有 Bug 的，只不过可能是
Release 版的某次运行没有表现出来而已。 </p>
<p>2、优化：这是造成错误的主要原因，因为关闭优化时源程序基本上是直接翻译的，而打开优化后编译器会作出一系列假设。这类错误主要有以下几种： </p>
<p>1. 帧指针(Frame
Pointer)省略（简称FPO）：在函数调用过程中，所有调用信息（返回地址、参数）以及自动变量都是放在栈中的。若函数的声明与实现不同（参数、返
回值、调用方式），就会产生错误，但 Debug 方式下，栈的访问通过 EBP
寄存器保存的地址实现，如果没有发生数组越界之类的错误（或是越界&#8220;不多&#8221;），函数通常能正常执行；Release 方式下，优化会省略 EBP
栈基址指针，这样通过一个全局指针访问栈就会造成返回地址错误是程序崩溃。 </p>
<p>C++ 的强类型特性能检查出大多数这样的错误，但如果用了强制类型转换，就不行了。你可以在 Release 版本中强制加入/Oy-编译选项来关掉帧指针省略，以确定是否此类错误。此类错误通常有：MFC 消息响应函数书写错误。正确的应为： </p>
<p><br>afx_msg LRESULT OnMessageOwn<br>(WPARAM wparam, LPARAM lparam);<br>&nbsp;<br>ON_MESSAGE 宏包含强制类型转换。防止这种错误的方法之一是重定义 ON_MESSAGE 宏，把下列代码加到 stdafx.h 中（在#include "afxwin.h"之后）,函数原形错误时编译会报错。 </p>
<p><br>#undef ON_MESSAGE<br>#define ON_MESSAGE(message, memberFxn) \<br>{<br>message, 0, 0, 0, AfxSig_lwl, \<br>(AFX_PMSG)(AFX_PMSGW)<br>(static_cast&lt; LRESULT (AFX_MSG_CALL \<br>CWnd::*)(WPARAM, LPARAM) &gt; (&amp;memberFxn)<br>},</p>
<p><br>2. volatile 型变量：volatile
告诉编译器该变量可能被程序之外的未知方式修改（如系统、其他进程和线程）。优化程序为了使程序性能提高，常把一些变量放在寄存器中（类似于
register 关键字），而其他进程只能对该变量所在的内存进行修改，而寄存器中的值没变。 </p>
<p>如果你的程序是多线程的，或者你发现某个变量的值与预期的不符而你确信已正确的设置了，则很可能遇到这样的问题。这种错误有时会表现为程序在最快优化出错而最小优化正常。把你认为可疑的变量加上 volatile 试试。</p>
<p>3. 变量优化：优化程序会根据变量的使用情况优化变量。例如，函数中有一个未被使用的变量，在 Debug
版中它有可能掩盖一个数组越界，而在 Release
版中，这个变量很可能被优化调，此时数组越界会破坏栈中有用的数据。当然，实际的情况会比这复杂得多。与此有关的错误有非法访问，包括数组越界、指针错误
等。例如：</p>
<p><br>void fn(void)<br>{<br>&nbsp; int i;<br>&nbsp; i = 1;<br>&nbsp; int a[4];<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp; int j;<br>&nbsp;&nbsp;&nbsp; j = 1;<br>&nbsp; }<br>&nbsp; a[-1] = 1;<br>&nbsp; //当然错误不会这么明显，例如下标是变量<br>&nbsp; a[4] = 1;<br>}<br>&nbsp;</p>
<p>&nbsp;</p>
<p>j 虽然在数组越界时已出了作用域，但其空间并未收回，因而 i 和 j 就会掩盖越界。而 Release 版由于 i、j 并未其很大作用可能会被优化掉，从而使栈被破坏。 </p>
<p>3. DEBUG 与 NDEBUG ：当定义了 _DEBUG 时，assert() 函数会被编译，而 NDEBUG 时不被编译。此外，TRACE() 宏的编译也受 _DEBUG 控制。 </p>
<p>所有这些断言都只在 Debug版中才被编译，而在 Release 版中被忽略。唯一的例外是
VERIFY()。事实上，这些宏都是调用了assert()函数，只不过附加了一些与库有关的调试代码。如果你在这些宏中加入了任何程序代码，而不只是
布尔表达式（例如赋值、能改变变量值的函数调用等），那么Release版都不会执行这些操作，从而造成错误。初学者很容易犯这类错误，查找的方法也很简
单，因为这些宏都已在上面列出，只要利用 VC++ 的 Find in Files
功能在工程所有文件中找到用这些宏的地方再一一检查即可。另外，有些高手可能还会加入 #ifdef _DEBUG 之类的条件编译，也要注意一下。 </p>
<p>顺便值得一提的是VERIFY()宏，这个宏允许你将程序代码放在布尔表达式里。这个宏通常用来检查 Windows
API的返回值。有些人可能为这个原因而滥用VERIFY()，事实上这是危险的，因为VERIFY()违反了断言的思想，不能使程序代码和调试代码完全
分离，最终可能会带来很多麻烦。因此，专家们建议尽量少用这个宏。 </p>
<p>4. /GZ 选项：这个选项会做以下这些事： </p>
<p>1. 初始化内存和变量。包括用 0xCC 初始化所有自动变量，0xCD ( Cleared Data )
初始化堆中分配的内存（即动态分配的内存，例如 new ），0xDD ( Dead Data ) 填充已被释放的堆内存（例如 delete
），0xFD( deFencde Data ) 初始化受保护的内存（debug
版在动态分配内存的前后加入保护内存以防止越界访问），其中括号中的词是微软建议的助记词。这样做的好处是这些值都很大，作为指针是不可能的（而且
32 位系统中指针很少是奇数值，在有些系统中奇数的指针会产生运行时错误），作为数值也很少遇到，而且这些值也很容易辨认，因此这很有利于在
Debug 版中发现 Release
版才会遇到的错误。要特别注意的是，很多人认为编译器会用0来初始化变量，这是错误的（而且这样很不利于查找错误）。 </p>
<p>2. 通过函数指针调用函数时，会通过检查栈指针验证函数调用的匹配性。（防止原形不匹配） </p>
<p>3. 函数返回前检查栈指针，确认未被修改。（防止越界访问和原形不匹配，与第二项合在一起可大致模拟帧指针省略 FPO ）通常 /GZ
选项会造成 Debug 版出错而 Release 版正常的现象，因为 Release
版中未初始化的变量是随机的，这有可能使指针指向一个有效地址而掩盖了非法访问。除此之外，/Gm/GF等选项造成错误的情况比较少，而且他们的效果显而
易见，比较容易发现。 </p>
<p>怎样&#8220;调试&#8221; Release 版的程序 </p>
<p>遇到Debug成功但Release失败，显然是一件很沮丧的事，而且往往无从下手。如果你看了以上的分析，结合错误的具体表现，很快找出了错误，固然很好。但如果一时找不出，以下给出了一些在这种情况下的策略。 </p>
<p>1.
前面已经提过，Debug和Release只是一组编译选项的差别，实际上并没有什么定义能区分二者。我们可以修改Release版的编译选项来缩小错误
范围。如上所述，可以把Release
的选项逐个改为与之相对的Debug选项，如/MD改为/MDd、/O1改为/Od，或运行时间优化改为程序大小优化。注意，一次只改一个选项，看改哪个
选项时错误消失，再对应该选项相关的错误，针对性地查找。这些选项在Project\Settings...中都可以直接通过列表选取，通常不要手动修
改。由于以上的分析已相当全面，这个方法是最有效的。 </p>
<p>2. 在编程过程中就要时常注意测试 Release 版本，以免最后代码太多，时间又很紧。 </p>
<p>3. 在 Debug 版中使用 /W4 警告级别，这样可以从编译器获得最大限度的错误信息，比如 if( i =0 )就会引起 /W4
警告。不要忽略这些警告，通常这是你程序中的 Bug 引起的。但有时 /W4 会带来很多冗余信息，如 未使用的函数参数
警告，而很多消息处理函数都会忽略某些参数。我们可以用: </p>
<p><br>#progma warning(disable: 4702)<br>//禁止<br>//...<br>#progma warning(default: 4702)<br>//重新允许来暂时禁止某个警告，或使用<br>#progma warning(push, 3) <br>//设置警告级别为 /W3<br>//...<br>#progma warning(pop)<br>//重设为 /W4<br>&nbsp;</p>
<p>&nbsp;</p>
<p>来暂时改变警告级别，有时你可以只在认为可疑的那一部分代码使用 /W4。 </p>
<p>4. 你也可以像Debug一样调试你的Release版，只要加入调试符号。在Project/Settings... 中，选中
Settings for "Win32 Release"，选中 C/C++ 标签，Category 选 General，Debug Info
选 Program Database。再在 Link 标签 Project options 最后加上 "/OPT:REF"
(引号不要输)。这样调试器就能使用 pdb 文件中的调试符号。 </p>
<p>但调试时你会发现断点很难设置，变量也很难找到??这些都被优化过了。不过令人庆幸的是，Call Stack窗口仍然工作正常，即使帧指针被优化，栈信息（特别是返回地址）仍然能找到。这对定位错误很有帮助。 </p><img src ="http://www.cppblog.com/sicheng/aggbug/76698.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/sicheng/" target="_blank">oyjpart</a> 2009-03-16 00:25 <a href="http://www.cppblog.com/sicheng/archive/2009/03/16/76698.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SRM406 PTS500 FoldThePaper</title><link>http://www.cppblog.com/sicheng/archive/2008/06/18/53831.html</link><dc:creator>oyjpart</dc:creator><author>oyjpart</author><pubDate>Wed, 18 Jun 2008 03:29:00 GMT</pubDate><guid>http://www.cppblog.com/sicheng/archive/2008/06/18/53831.html</guid><wfw:comment>http://www.cppblog.com/sicheng/comments/53831.html</wfw:comment><comments>http://www.cppblog.com/sicheng/archive/2008/06/18/53831.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/sicheng/comments/commentRss/53831.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/sicheng/services/trackbacks/53831.html</trackback:ping><description><![CDATA[<table>
    <tbody>
        <tr>
            <td colspan="2">
            <h3>Problem Statement</h3>
            </td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
            <td>You
            have a rectangular piece of paper that's divided into 1x1 cells, each
            of which has an integer value. The paper will be described by a vector
            &lt;string&gt; <strong>paper</strong>.  The <em>i</em>th element of <strong>paper</strong> will be a space delimited list of integers, where the <em>j</em>th integer of the <em>i</em>th element of <strong>paper</strong> represents the value of the <em>j</em>th cell of the <em>i</em>th row of the paper.<br><br><br><br>
            You want to perform a sequence of folds on the paper, where you may
            fold anywhere along an axis that is in between two rows or columns of
            the paper. After performing a fold, we wish to model the folded paper
            as a new, flat piece of paper. We will do this by considering two
            overlapping cells as a single cell, with a value that is the sum of the
            individual cells.<br><br><br><br>
            You wish to perform a sequence of folds such that the value of some
            single cell in the resulting piece of paper is as large as possible.
            Return this value.</td>
        </tr>
        <tr>
            <td colspan="2">
            <h3>Definition</h3>
            </td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
            <td>
            <table>
                <tbody>
                    <tr>
                        <td>Class:</td>
                        <td>FoldThePaper</td>
                    </tr>
                    <tr>
                        <td>Method:</td>
                        <td>getValue</td>
                    </tr>
                    <tr>
                        <td>Parameters:</td>
                        <td>vector &lt;string&gt;</td>
                    </tr>
                    <tr>
                        <td>Returns:</td>
                        <td>int</td>
                    </tr>
                    <tr>
                        <td>Method signature:</td>
                        <td>int getValue(vector &lt;string&gt; paper)</td>
                    </tr>
                    <tr>
                        <td colspan="2">(be sure your method is public)</td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
        </tr>
        <tr>
            <td><br></td>
        </tr>
        <tr>
            <td colspan="2">
            <h3>Constraints</h3>
            </td>
        </tr>
        <tr>
            <td align="center" valign="top">-</td>
            <td><strong>paper</strong> will contain between 1 and 12 elements, inclusive.</td>
        </tr>
        <tr>
            <td align="center" valign="top">-</td>
            <td>Each element of <strong>paper</strong> will be a single-space delimited list of integers with no leading or trailing spaces.</td>
        </tr>
        <tr>
            <td align="center" valign="top">-</td>
            <td>Each element of <strong>paper</strong> will contain between 1 and 12 integers, inclusive.</td>
        </tr>
        <tr>
            <td align="center" valign="top">-</td>
            <td>Each element of <strong>paper</strong> will contain the same number of integers.</td>
        </tr>
        <tr>
            <td align="center" valign="top">-</td>
            <td>Each element of <strong>paper</strong> will contain between 1 and 50 characters, inclusive.</td>
        </tr>
        <tr>
            <td align="center" valign="top">-</td>
            <td>Each integer in <strong>paper</strong> will be between -100 and 100, inclusive.</td>
        </tr>
        <tr>
            <td align="center" valign="top">-</td>
            <td>Each integer in <strong>paper</strong> will have no leading zeros.</td>
        </tr>
        <tr>
            <td align="center" valign="top">-</td>
            <td>An integer in <strong>paper</strong> equal to zero will not have a preceding negative sign.</td>
        </tr>
        <tr>
            <td colspan="2">
            <h3>Examples</h3>
            </td>
        </tr>
        <tr>
            <td align="center" nowrap="true">0)</td>
            <td><br></td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
            <td>
            <table>
                <tbody>
                    <tr>
                        <td>
                        <table>
                            <tbody>
                                <tr>
                                    <td>
                                    <pre>{<br>"1 1 1",<br>"1 1 1"<br>}</pre>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                    <tr>
                        <td>
                        <pre>Returns: 6</pre>
                        </td>
                    </tr>
                    <tr>
                        <td>
                        <table>
                            <tbody>
                                <tr>
                                    <td colspan="2">We can collapse every cell onto the upper-left cell.</td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
        <tr>
            <td align="center" nowrap="true">1)</td>
            <td><br></td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
            <td>
            <table>
                <tbody>
                    <tr>
                        <td>
                        <table>
                            <tbody>
                                <tr>
                                    <td>
                                    <pre>{<br>"1 -1",<br>"1 -1"<br>}</pre>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                    <tr>
                        <td>
                        <pre>Returns: 2</pre>
                        </td>
                    </tr>
                    <tr>
                        <td>
                        <table>
                            <tbody>
                                <tr>
                                    <td colspan="2">We should perform only the fold between the two rows, and take the resulting left column.</td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
        <tr>
            <td align="center" nowrap="true">2)</td>
            <td><br></td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
            <td>
            <table>
                <tbody>
                    <tr>
                        <td>
                        <table>
                            <tbody>
                                <tr>
                                    <td>
                                    <pre>{<br>"1 -1 -1 1",<br>"-1 -1 -1 -1",<br>"-1 -1 -1 -1",<br>"1 -1 -1 1"<br>}</pre>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                    <tr>
                        <td>
                        <pre>Returns: 4</pre>
                        </td>
                    </tr>
                    <tr>
                        <td>
                        <table>
                            <tbody>
                                <tr>
                                    <td colspan="2">Folding between the middle rows then the middle columns allows us to combine the four corner cells.</td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
        <tr>
            <td align="center" nowrap="true">3)</td>
            <td><br></td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
            <td>
            <table>
                <tbody>
                    <tr>
                        <td>
                        <table>
                            <tbody>
                                <tr>
                                    <td>
                                    <pre>{<br>"20 13 -2 100",<br>"-12 0 4 -3",<br>"4 1 -36 21"<br>}</pre>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                    <tr>
                        <td>
                        <pre>Returns: 131</pre>
                        </td>
                    </tr>
                    <tr>
                        <td>
                        <table>
                            <tbody>
                                <tr>
                                    <td colspan="2"><br></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
        <tr>
            <td align="center" nowrap="true">4)</td>
            <td><br></td>
        </tr>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
            <td>
            <table>
                <tbody>
                    <tr>
                        <td>
                        <table>
                            <tbody>
                                <tr>
                                    <td>
                                    <pre>{<br>"0"<br>}</pre>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                    <tr>
                        <td>
                        <pre>Returns: 0</pre>
                        </td>
                    </tr>
                    <tr>
                        <td>
                        <table>
                            <tbody>
                                <tr>
                                    <td colspan="2"><br></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<p>This
problem statement is the exclusive and proprietary property of
TopCoder, Inc. Any unauthorized use or reproduction of this information
without the prior written consent of TopCoder, Inc. is strictly
prohibited. (c)2003, TopCoder, Inc. All rights reserved.</p>
<br>题目大意是有一个12*12的矩阵，现在可以对这个矩阵横向或纵向折叠，出在重叠位置的数相加。<br>求折叠过程中任意位置产生的最大数。<br>
<p>很多大牛fail了，我一个DFS+剪枝也超时了，一共32人pass sys test，1000pts无人ac，此套题难度还是很大的。</p>
<p>基本思路是状态压缩DP，横向(1&lt;&lt;12)*纵向(1&lt;&lt;12)*加和。</p>
<p>但是这样会超时。关键是没有利用到折叠的信息。</p>
<p>预先生成某个位置的状态（由那些位置叠加而来），就可以减少检查量，就可以ac了。</p>
如何生成这些状态呢？没错，又是一个DP. 呵呵。<br>
<p><br></p><img src ="http://www.cppblog.com/sicheng/aggbug/53831.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/sicheng/" target="_blank">oyjpart</a> 2008-06-18 11:29 <a href="http://www.cppblog.com/sicheng/archive/2008/06/18/53831.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat JSP Web 开发中的乱码问题小结</title><link>http://www.cppblog.com/sicheng/archive/2008/05/22/50739.html</link><dc:creator>oyjpart</dc:creator><author>oyjpart</author><pubDate>Thu, 22 May 2008 03:26:00 GMT</pubDate><guid>http://www.cppblog.com/sicheng/archive/2008/05/22/50739.html</guid><wfw:comment>http://www.cppblog.com/sicheng/comments/50739.html</wfw:comment><comments>http://www.cppblog.com/sicheng/archive/2008/05/22/50739.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/sicheng/comments/commentRss/50739.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/sicheng/services/trackbacks/50739.html</trackback:ping><description><![CDATA[Tomcat JSP Web 开发中的乱码问题小结<br>1. 静态页面的乱码问题<br>文件的编码和浏览器要显示的编码不一致。<br>1) 检查文件原始的编码, 可以用记事本打开, 然后选择另存为来看;<br>2) 给当前页面加入一个指令来建议浏览器用指定的编码来显示文件字符内容.<br>&lt;meta http-equiv="content-type" content="text/html; charset=GBK"&gt;<br>3) 如果系统是英文XP,没装东亚字符集支持, 也会显示乱码.<br>2. JSP 页面的乱码问题<br>1) page 指令有个 pageEncoding="GBK" 这个会指定当前页面保存的编码, 如果写成<br>ISO8859-1 就不能保存汉字;<br>2) page 指令的 contentType="text/html; charset=ISO8859-1" 也会像静态页面一样让<br>浏览器来优先选择一种编码.<br>如果JSP 乱码的话,一般就显示成?，而且不管你给浏览器选什么样的编码，它都不能正<br>确显示<br>3. 表单提交的乱码问题(Tomcat 特有)<br>1). POST 的乱码<br>MyEclipse 6 Java 开发中文教程<br>157 刘长炯著<br>a. 首先浏览器提交表单的编码是根据表单所在页面来决定的, 而不是根据提交后的<br>JSP 页面的编码来决定的. 把所有的页面的编码都设置成一样的,例如 GBK.<br>b. 处理方式就是在获取参数之前设置编码:<br>request.setCharacterEncoding("GBK");<br>c. 可以用过滤器的方式来解决, Tomcat 已经带了一个现成的:<br>apache-tomcat-5.5.23\webapps\jsp-examples\WEB-INF\classes\filters\SetCharacter<br>EncodingFilter.java<br>web.xml<br>&lt;filter&gt;<br>&lt;filter-name&gt;Set Character Encoding&lt;/filter-name&gt;<br>&lt;filter-class&gt;filters.SetCharacterEncodingFilter&lt;/filter-class&gt;<br>&lt;init-param&gt;<br>&lt;param-name&gt;encoding&lt;/param-name&gt;<br>&lt;param-value&gt;GBK&lt;/param-value&gt;<br>&lt;/init-param&gt;<br>&lt;/filter&gt;<br>&lt;filter-mapping&gt;<br>&lt;filter-name&gt;Set Character Encoding&lt;/filter-name&gt;<br>&lt;url-pattern&gt;/*&lt;/url-pattern&gt;<br>&lt;/filter-mapping&gt;<br>2) GET 方式的乱码<br>用 setCharacterEncoding() 不能解决. TOMCAT 的一个BUG, GET 方式传送的表单参<br>数总是用的 ISO8859-1 编码. 我们要把它转成 GBK 方式.<br>String username = request.getParameter("username");<br>System.out.println(username);<br>// 转码, 先取得原始的二进制字节数组<br>byte[] data = username.getBytes("ISO8859-1");<br>// 根据新的字符集再构造新的字符串<br>username = new String(data, "GBK");<br>小结:<br>所有的页面(除了最后的 GET 的乱码问题)都用统一的编码(GBK 或者UTF-8), 就不会出现<br>乱码问题
<br><br>以上内容为【转】<br><br>下面是一个完整的过滤器例子：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">package</span><span style="color: #000000;">&nbsp;filters;<br><br></span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.io.IOException;<br></span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax.servlet.Filter;<br></span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax.servlet.FilterChain;<br></span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax.servlet.FilterConfig;<br></span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax.servlet.ServletException;<br></span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax.servlet.ServletRequest;<br></span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax.servlet.ServletResponse;<br></span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax.servlet.http.HttpServletRequest;<br></span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax.servlet.http.HttpServletRequestWrapper;<br><br></span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;TomcatFormFilter&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;Filter&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Request.java&nbsp;对&nbsp;HttpServletRequestWrapper&nbsp;进行扩充,&nbsp;不影响原来的功能并能提供所&nbsp;有的<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;HttpServletRequest&nbsp;接口中的功能.&nbsp;它可以统一的对&nbsp;Tomcat&nbsp;默认设置下的中文问题进行解决而只&nbsp;需要用新的&nbsp;Request<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;对象替换页面中的&nbsp;request&nbsp;对象即可.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Request&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;HttpServletRequestWrapper&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Request(HttpServletRequest&nbsp;request)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">super</span><span style="color: #000000;">(request);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;转换由表单读取的数据的内码.&nbsp;从&nbsp;ISO&nbsp;字符转到&nbsp;GBK.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;String&nbsp;toChi(String&nbsp;input)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">byte</span><span style="color: #000000;">[]&nbsp;bytes&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;input.getBytes(</span><span style="color: #000000;">"</span><span style="color: #000000;">ISO8859-1</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;String(bytes,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">utf-8</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(Exception&nbsp;ex)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Return&nbsp;the&nbsp;HttpServletRequest&nbsp;holded&nbsp;by&nbsp;this&nbsp;object.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;HttpServletRequest&nbsp;getHttpServletRequest()&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;(HttpServletRequest)&nbsp;</span><span style="color: #0000ff;">super</span><span style="color: #000000;">.getRequest();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;读取参数&nbsp;--&nbsp;修正了中文问题.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;String&nbsp;getParameter(String&nbsp;name)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;toChi(getHttpServletRequest().getParameter(name));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;读取参数列表&nbsp;-&nbsp;修正了中文问题.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;String[]&nbsp;getParameterValues(String&nbsp;name)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;values[]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;getHttpServletRequest().getParameterValues(name);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(values&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;i&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;values.length;&nbsp;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;values[i]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;toChi(values[i]);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;values;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;destroy()&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;doFilter(ServletRequest&nbsp;request,&nbsp;ServletResponse&nbsp;response,&nbsp;FilterChain&nbsp;chain)&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;IOException,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServletException&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletRequest&nbsp;httpreq&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(HttpServletRequest)&nbsp;request;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(httpreq.getMethod().equals(</span><span style="color: #000000;">"</span><span style="color: #000000;">POST</span><span style="color: #000000;">"</span><span style="color: #000000;">))&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;request.setCharacterEncoding(</span><span style="color: #000000;">"</span><span style="color: #000000;">utf-8</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;request&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Request(httpreq);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response.setCharacterEncoding(</span><span style="color: #000000;">"</span><span style="color: #000000;">utf-8</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chain.doFilter(request,&nbsp;response);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;init(FilterConfig&nbsp;filterConfig)&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;ServletException&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}</span></div>
<br>web.xml中加入如下配置信息<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">filter</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">filter-name</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">TomcatFormFilter</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">filter-name</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">filter-class</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">filters.TomcatFormFilter</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">filter-class</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">filter</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">filter-mapping</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">filter-name</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">TomcatFormFilter</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">filter-name</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">url-pattern</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">/*</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">url-pattern</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">filter-mapping</span><span style="color: #0000ff;">&gt;</span></div>
<br><br>上述都是使用统一的GBK编码，如果想用utf-8编码的话，稍作修改就可以了。<br>在解决了JSP乱码问题之后，还有一个问题，就是数据库乱码问题。 <br>我使用的数据库是mysql<br>在hibernate的配置文件中加入<br>&nbsp;&nbsp; &nbsp;&lt;property name="connection.useUnicode"&gt;true&lt;/property&gt;<br>&nbsp;&nbsp; &nbsp;&lt;property name="connection.characterEncoding"&gt;UTF-8&lt;/property&gt;
<br>就算是一整套的中文解决方案了。<br><br> <img src ="http://www.cppblog.com/sicheng/aggbug/50739.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/sicheng/" target="_blank">oyjpart</a> 2008-05-22 11:26 <a href="http://www.cppblog.com/sicheng/archive/2008/05/22/50739.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>有信息的搜索--传教士与食人魔的故事</title><link>http://www.cppblog.com/sicheng/archive/2008/04/04/46267.html</link><dc:creator>oyjpart</dc:creator><author>oyjpart</author><pubDate>Fri, 04 Apr 2008 10:15:00 GMT</pubDate><guid>http://www.cppblog.com/sicheng/archive/2008/04/04/46267.html</guid><wfw:comment>http://www.cppblog.com/sicheng/comments/46267.html</wfw:comment><comments>http://www.cppblog.com/sicheng/archive/2008/04/04/46267.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/sicheng/comments/commentRss/46267.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/sicheng/services/trackbacks/46267.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;有信息的搜索作者 欧阳君沛200506050044简介搜索1.广度优先搜索每次将集合中的元素经过一些改动，分层生成当前状态的子状态（通常还删除父情况），添加到集合（队列）中，以实现遍历或搜索等目的的算法。Pseudocode (用队列)1 procedure(state)2&nbsp; &nbsp;for each possible next state fro...&nbsp;&nbsp;<a href='http://www.cppblog.com/sicheng/archive/2008/04/04/46267.html'>阅读全文</a><img src ="http://www.cppblog.com/sicheng/aggbug/46267.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/sicheng/" target="_blank">oyjpart</a> 2008-04-04 18:15 <a href="http://www.cppblog.com/sicheng/archive/2008/04/04/46267.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转】正则表达式30分钟入门教程</title><link>http://www.cppblog.com/sicheng/archive/2008/03/20/44944.html</link><dc:creator>oyjpart</dc:creator><author>oyjpart</author><pubDate>Thu, 20 Mar 2008 06:15:00 GMT</pubDate><guid>http://www.cppblog.com/sicheng/archive/2008/03/20/44944.html</guid><wfw:comment>http://www.cppblog.com/sicheng/comments/44944.html</wfw:comment><comments>http://www.cppblog.com/sicheng/archive/2008/03/20/44944.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/sicheng/comments/commentRss/44944.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/sicheng/services/trackbacks/44944.html</trackback:ping><description><![CDATA[<h1>正则表达式30分钟入门教程</h1>
<p>匹配Email地址的正则表达式：\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)* <br>匹配网址URL的正则表达式：http:<font face="Courier New"><span style="COLOR: #008000">//([\w-]+\.)+[\w-]+(/[\w-&nbsp;./?%&amp;=]*)? </span></font></p>
<p id=meta>版本：v2.21 (2007-8-3) 作者：<a href="http://www.unibetter.com/members/deerchao.aspx"><u><font color=#0000ff>deerchao</font></u></a> 来源:<a href="http://www.unibetter.com/"><u><font color=#0000ff>unibetter大学生社区</font></u></a> 转载请注明来源</p>
<h2 id=contents>目录</h2>
<ol>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#mission"><u><font color=#800080>本文目标</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#howtouse"><u><font color=#800080>如何使用本教程</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#introduction"><u><font color=#800080>正则表达式到底是什么？</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#getstarted"><u><font color=#800080>入门</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#testing"><u><font color=#800080>测试正则表达式</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#metacode"><u><font color=#800080>元字符</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#escape"><u><font color=#800080>字符转义</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#repeat"><u><font color=#800080>重复</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#charclass"><u><font color=#800080>字符类</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#negation"><u><font color=#800080>反义</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#alternative"><u><font color=#800080>替换</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#grouping"><u><font color=#800080>分组</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#backreference"><u><font color=#800080>后向引用</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#lookaround"><u><font color=#800080>零宽断言</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#negativelookaround"><u><font color=#800080>负向零宽断言</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#commenting"><u><font color=#800080>注释</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#greedyandlazy"><u><font color=#800080>贪婪与懒惰</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#regexoptions"><u><font color=#800080>处理选项</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#balancedgroup"><u><font color=#800080>平衡组/递归匹配</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#more"><u><font color=#800080>还有些什么东西没提到</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#contact"><u><font color=#800080>联系作者</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#ad"><u><font color=#800080>最后,来点广告...</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#reference"><u><font color=#800080>一些我认为你可能已经知道的术语的参考</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#resources"><u><font color=#800080>网上的资源及本文参考文献</font></u></a>
    <li><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#updatelog"><u><font color=#800080>更新说明</font></u></a> </li>
</ol>
<h2 id=mission>本文目标</h2>
<p>30分钟内让你明白正则表达式是什么，并对它有一些基本的了解，让你可以在自己的程序或网页里使用它。</p>
<h2 id=howtouse>如何使用本教程</h2>
<p class=important>最重要的是——请给我<strong>30分钟</strong>，如果你没有使用正则表达式的经验，请不要试图在30<strong>秒</strong>内入门。当然，如果你是超人，那自然得另当别论。</p>
<p>别被下面那些复杂的表达式吓倒，只要跟着我一步一步来，你会发现正则表达式其实并<span lang=zh-cn>没有</span>你想像中的那么困难。当然，如果你看完了这篇教程之后，发现自己明白了很多，却又几乎什么都记不得，那也是很正常的——我认为，没接触过正则表达式的人在看完这篇教程后，能把提到过的语法记住80%以上的可能性为零。这里只是让你明白基本的原理，以后你还需要多练习，多使用，才能熟练掌握正则表达式。</p>
<p>除了作为入门教程之外，本文还试图成为可以在日常工作中使用的正则表达式语法参考手册。就作者本人的经历来说，这个目标还是完成得不错的——你看，我自己也没能把所有的东西记下来，不是吗？</p>
<p>文本格式约定：<span class=name><strong>专业术语</strong></span>&nbsp;<span class=code><font color=#0000ff>元字符/语法格式</font></span>&nbsp;<span class=regex><font color=#ff0000>正则表达式</font></span>&nbsp;<span class=part><font color=#008000>正则表达式中的一部分(用于分析)</font></span>&nbsp;<span class=string><em>用于在其中搜索的字符串</em></span>&nbsp;<span class=desc><u>对正则表达式或其中一部分的说明</u></span><a id=clearButton accessKey=c onclick="return clearFormats();" href="http://www.unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm"><font style="BACKGROUND-COLOR: #eeeeee" color=#0000ff>清除格式</font></a></p>
<h2 id=introduction>正则表达式到底是什么？</h2>
<p>在编写处理字符串的程序或网页时，经常会有查找符合某些复杂规则的字符串的需要。<span class=name><strong>正则表达式</strong></span>就是用于描述这些规则的工具。换句话说，正则表达式就是记录文本规则的代码。</p>
<p>很可能你使用过Windows/Dos下用于文件查找的<span class=name><strong>通配符(wildcard)</strong></span>，也就是<span class=code><font color=#0000ff>*</font></span>和<span class=code><font color=#0000ff>?</font></span>。如果你想查找某个目录下的所有的Word文档的话，你会搜索<span style="COLOR: red">*.doc</span>。在这里，<span class=code><font color=#0000ff>*</font></span>会被解释成任意的<a title=参考 href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#reference"><u><font color=#800080>字符串</font></u></a>。和通配符类似，正则表达式也是用来进行<a title=参考 href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#reference"><u><font color=#800080>文本</font></u></a><a title=参考 href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#reference"><u><font color=#800080>匹配</font></u></a>的工具，只不过比起通配符，它能更精确地描述你的需求——当然，代价就是更复杂——比如你可以编写一个正则表达式，用来查找<span class=desc><u>所有以0开头，后面跟着2-3个数字，然后是一个连字号&#8220;-&#8221;，最后是7或8位数字的字符串</u></span>(像<span class=string><em>010-12345678</em></span>或<span class=string><em>0376-7654321</em></span>)。</p>
<p id=match>正则表达式是用于进行文本匹配的工具，所以本文里多次提到了在字符串里搜索/查找，这种说法的意思是在给定的字符串中，寻找与给定的正则表达式相匹配的部分。有可能字符串里有不止一个部分满足给定的正则表达式，这时每一个这样的部分被称为一个匹配。<span class=name><strong>匹配</strong></span>在本文里可能会有三种意思：一种是形容词性的，比如说一个字符串匹配一个表达式；一种是动词性的，比如说在字符串里匹配正则表达式；还有一种是名词性的，就是刚刚说到的&#8220;字符串中满足给定的正则表达式的一部分&#8221;。</p>
<h2 id=getstarted>入门</h2>
<p>学习正则表达式的最好方法是从例子开始，理解例子之后再自己对例子进行修改，实验。下面给出了不少简单的例子，并对它们作了详细的说明。</p>
<p>假设你在一篇英文小说里查找<span class=desc><u>hi</u></span>，你可以使用正则表达式<span class=regex><font color=#ff0000>hi</font></span>。</p>
<p>这是最简单的正则表达式了，它可以精确匹配这样的字符串：<span class=desc><u>由两个字符组成，前一个字符是h,后一个是i</u></span>。通常，处理正则表达式的工具会提供一个忽略大小写的选项，如果选中了这个选项，它可以匹配<span class=string><em>hi</em></span>,<span class=string><em>HI</em></span>,<span class=string><em>Hi</em></span>,<span class=string><em>hI</em></span>这四种情况中的任意一种。</p>
<p>不幸的是，很多单词里包含<span class=string><em>hi</em></span>这两个连续的字符，比如<span class=string><em>him</em></span>,<span class=string><em>history</em></span>,<span class=string><em>high</em></span>等等。用<span class=regex><font color=#ff0000>hi</font></span>来查找的话，这里边的<span class=string><em>hi</em></span>也会被找出来。如果要<span class=desc><u>精确地查找hi这个单词</u></span>的话，我们应该使用<span class=regex><font color=#ff0000>\bhi\b</font></span>。</p>
<p><span class=part><font color=#008000>\b</font></span>是正则表达式规定的一个特殊代码（好吧，某些人叫它<span class=name><strong>元字符，metacharacter</strong></span>），代表着<span class=desc><u>单词的开头或结尾，也就是单词的分界处</u></span>。虽然通常英文的单词是由空格或标点符号或换行来分隔的，但是<span class=code><font color=#0000ff>\b</font></span>并不匹配这些单词分隔符中的任何一个，它<strong>只匹配一个位置</strong>。（如果需要更精确的说法，<span class=code><font color=#0000ff>\b</font></span>匹配这样的位置：它的前一个字符和后一个字符不全是(一个是,一个不是或不存在)<span class=code><font color=#0000ff>\w</font></span>）</p>
<p>假如你要找的是<span class=desc><u>hi后面不远处跟着一个Lucy</u></span>，你应该用<span class=regex><font color=#ff0000>\bhi\b.*\bLucy\b</font></span>。</p>
<p>这里，<span class=part><font color=#008000>.</font></span>是另一个元字符，匹配<span class=desc><u>除了换行符以外的任意字符</u></span>。<span class=part><font color=#008000>*</font></span>同样是元字符，不过它代表的不是字符，也不是位置，而是数量——它指定*<span class=desc><u>前边的内容可以连续重复出现任意次以使整个表达式得到匹配</u></span>。因此，<span class=part><font color=#008000>.*</font></span>连在一起就意味着<span class=desc><u>任意数量的不包含换行的字符</u></span>。现在<span class=regex><font color=#ff0000>\bhi\b.*\bLucy\b</font></span>的意思就很明显了：<span class=desc><u>先是一个单词hi,然后是任意个任意字符(但不能是换行)，最后是Lucy这个单词</u></span>。</p>
<p>如果同时使用其它的一些元字符，我们就能构造出功能更强大的正则表达式。比如下面这个例子：</p>
<p><span class=regex><font color=#ff0000>0\d\d-\d\d\d\d\d\d\d\d</font></span>匹配这样的字符串：<span class=desc><u>以0开头，然后是两个数字，然后是一个连字号&#8220;-&#8221;，最后是8个数字</u></span>(也就是中国的电话号码。当然，这个例子只能匹配区号为3位的情形)。</p>
<p>这里的<span class=part><font color=#008000>\d</font></span>是一个新的元字符，匹配<span class=desc><u>任意的数字(0，或1，或2，或&#8230;&#8230;)</u></span>。<span class=part><font color=#008000>-</font></span>不是元字符，只匹配它本身——连字号。</p>
<p>为了避免那么多烦人的重复，我们也可以这样写这个表达式：<span class=regex><font color=#ff0000>0\d{2}-\d{8}</font></span>。 这里<span class=part><font color=#008000>\d</font></span>后面的<span class=part><font color=#008000>{2}</font></span>(<span class=part><font color=#008000>{8}</font></span>)的意思是前面<span class=part><font color=#008000>\d</font></span><span class=desc><u>必须连续重复匹配2次(8次)</u></span>。</p>
<h2 id=testing>测试正则表达式</h2>
<p>如果你不觉得正则表达式很难读写的话，要么你是一个天才，要么，你不是地球人。正则表达式的语法很令人头疼，即使对经常使用它的人来说也是如此。由于难于读写，容易出错，所以很有必要创建一种工具来测试正则表达式。</p>
<p>由于在不同的环境下正则表达式的一些细节是不相同的，本教程介绍的是Microsoft .Net 2.0下正则表达式的行为，所以，我向你介绍一个.Net下的工具<a title=转到RegexTester的官方网站（英文） href="http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,13bce26d-7755-441e-92b3-1eb5f9e859f9.aspx"><u><font color=#0000ff>Regex Tester</font></u></a>。首先你确保已经安装了<a title="转到下载.Net Framework 2.0的页面" href="http://www.microsoft.com/downloads/details.aspx?displaylang=zh-cn&amp;FamilyID=0856eacb-4362-4b0d-8edd-aab15c5e04f5"><u><font color=#0000ff>.Net Framework 2.0</font></u></a>，然后<a title="从www.unibetter.com下载Regex Tester, 75KB" href="http://www.unibetter.com/deerchao/downloads/RegexTester.zip"><u><font color=#0000ff>下载Regex Tester</font></u></a>。这是个绿色软件，下载完后打开压缩包,直接运行RegexTester.exe就可以了。</p>
<p>下面是Regex Tester运行时的截图：</p>
<p><img alt="Regex Tester运行时的截图" src="http://unibetter.com/deerchao/images/RegexTester.jpg"></p>
<h2 id=metacode>元字符</h2>
<p>现在你已经知道几个很有用的元字符了，如<span class=code><font color=#0000ff>\b</font></span>,<span class=code><font color=#0000ff>.</font></span>,<span class=code><font color=#0000ff>*</font></span>，还有<span class=code><font color=#0000ff>\d</font></span>.当然还有更多的元字符可用，比如<span class=code><font color=#0000ff>\s</font></span>匹配<span class=desc><u>任意的空白符，包括空格，制表符(Tab)，换行符，中文全角空格等</u></span>。<span class=code><font color=#0000ff>\w</font></span>匹配<span class=desc><u>字母或数字或下划线或汉字等</u></span>。</p>
<p>下面来试试更多的例子：</p>
<p><span class=regex><font color=#ff0000>\ba\w*\b</font></span>匹配<span class=desc><u>以字母<span class=part><font color=#008000>a</font></span>开头的单词——先是某个单词开始处(<span class=part><font color=#008000>\b</font></span>)，然后是字母<span class=part><font color=#008000>a</font></span>,然后是任意数量的字母或数字(<span class=part><font color=#008000>\w*</font></span>)，最后是单词结束处(<span class=part><font color=#008000>\b</font></span>)</u></span>（好吧，现在我们说说正则表达式里的单词是什么意思吧：就是几个连续的<span class=code><font color=#0000ff>\w</font></span>。不错，这与学习英文时要背的成千上万个同名的东西的确关系不大）。</p>
<p><span class=regex><font color=#ff0000>\d+</font></span>匹配<span class=desc><u>1个或更多连续的数字</u></span>。这里的<span class=part><font color=#008000>+</font></span>是和<span class=code><font color=#0000ff>*</font></span>类似的元字符，不同的是<span class=code><font color=#0000ff>*</font></span>匹配<span class=desc><u>重复任意次(可能是0次)</u></span>，而<span class=code><font color=#0000ff>+</font></span>则匹配<span class=desc><u>重复1次或更多次</u></span>。</p>
<p><span class=regex><font color=#ff0000>\b\w{6}\b</font></span> 匹配<span class=desc><u>刚好6个字母/数字的单词</u></span>。</p>
<table cellSpacing=0>
    <caption>表1.常用的元字符</caption>
    <tbody>
        <tr>
            <th>代码</th>
            <th>说明</th>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>.</font></span></td>
            <td><span class=desc><u>匹配除换行符以外的任意字符</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\w</font></span></td>
            <td><span class=desc><u>匹配字母或数字或下划线或汉字</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\s</font></span></td>
            <td><span class=desc><u>匹配任意的空白符</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\d</font></span></td>
            <td><span class=desc><u>匹配数字</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\b</font></span></td>
            <td><span class=desc><u>匹配单词的开始或结束</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>^</font></span></td>
            <td><span class=desc><u>匹配字符串的开始</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>$</font></span></td>
            <td><span class=desc><u>匹配字符串的结束</u></span></td>
        </tr>
    </tbody>
</table>
<p>元字符<span class=code><font color=#0000ff>^</font></span>（和数字6在同一个键位上的符号）以及<span class=code><font color=#0000ff>$</font></span>和<span class=code><font color=#0000ff>\b</font></span>有点类似，都匹配一个位置。<span class=code><font color=#0000ff>^</font></span>匹配你要用来查找的字符串的开头，<span class=code><font color=#0000ff>$</font></span>匹配结尾。这两个代码在验证输入的内容时非常有用，比如一个网站如果要求你填写的QQ号必须为5位到12位数字时，可以使用：<span class=regex><font color=#ff0000>^\d{5,12}$</font></span>。</p>
<p>这里的<span class=part><font color=#008000>{5,12}</font></span>和前面介绍过的<span class=part><font color=#008000>{2}</font></span>是类似的，只不过<span class=part><font color=#008000>{2}</font></span>匹配<span class=desc><u>只能不多不少重复2次</u></span>，<span class=part><font color=#008000>{5,12}</font></span>则是<span class=desc><u>重复的次数不能少于5次，不能多于12次</u></span>，否则都不匹配。</p>
<p>因为使用了<span class=part><font color=#008000>^</font></span>和<span class=part><font color=#008000>$</font></span>，所以输入的整个字符串都要用来和<span class=part><font color=#008000>\d{5,12}</font></span>来匹配，也就是说整个输入<span class=desc><u>必须是5到12个数字</u></span>，因此如果输入的QQ号能匹配这个正则表达式的话，那就符合要求了。</p>
<p>和忽略大小写的选项类似，有些正则表达式处理工具还有一个处理多行的选项。如果选中了这个选项，<span class=code><font color=#0000ff>^</font></span>和<span class=code><font color=#0000ff>$</font></span>的意义就变成了<span class=desc><u>匹配行的开始处和结束处</u></span>。</p>
<h2 id=escape>字符转义</h2>
<p>如果你想查找元字符本身的话，比如你查找<span class=desc><u>.</u></span>,或者<span class=desc><u>*</u></span>,就出现了问题：你没法指定它们，因为它们会被解释成其它的意思。这时你就必须使用<span class=code><font color=#0000ff>\</font></span>来取消这些字符的特殊意义。因此，你应该使用<span class=regex><font color=#ff0000>\.</font></span>和<span class=regex><font color=#ff0000>\*</font></span>。当然，要查找<span class=desc><u>\</u></span>本身，你也得用<span class=regex><font color=#ff0000>\\</font></span>.</p>
<p>例如：<span class=regex><font color=#ff0000>www\.unibetter\.com</font></span>匹配<span class=desc><u>www.unibetter.com</u></span>，<span class=regex><font color=#ff0000>c:\\Windows</font></span>匹配<span class=desc><u>c:\Windows</u></span>。</p>
<h2 id=repeat>重复</h2>
<p>你已经看过了前面的<span class=code><font color=#0000ff>*</font></span>,<span class=code><font color=#0000ff>+</font></span>,<span class=code><font color=#0000ff>{2}</font></span>,<span class=code><font color=#0000ff>{5,12}</font></span>这几个匹配重复的方式了。下面是正则表达式中所有的限定符(指定数量的代码，例如*,{5,12}等)：</p>
<table cellSpacing=0>
    <caption>表2.常用的限定符</caption>
    <tbody>
        <tr>
            <th>代码/语法</th>
            <th>说明</th>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>*</font></span></td>
            <td><span class=desc><u>重复零次或更多次</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>+</font></span></td>
            <td><span class=desc><u>重复一次或更多次</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>?</font></span></td>
            <td><span class=desc><u>重复零次或一次</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>{n}</font></span></td>
            <td><span class=desc><u>重复n次</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>{n,}</font></span></td>
            <td><span class=desc><u>重复n次或更多次</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>{n,m}</font></span></td>
            <td><span class=desc><u>重复n到m次</u></span></td>
        </tr>
    </tbody>
</table>
<p>下面是一些使用重复的例子：</p>
<p><span class=regex><font color=#ff0000>Windows\d+</font></span>匹配<span class=desc><u>Windows后面跟1个或更多数字</u></span></p>
<p><span class=regex><font color=#ff0000>13\d{9}</font></span>匹配<span class=desc><u>13后面跟9个数字(中国的手机号)</u></span></p>
<p><span class=regex><font color=#ff0000>^\w+</font></span>匹配<span class=desc><u>一行的第一个单词(或整个字符串的第一个单词，具体匹配哪个意思得看选项设置)</u></span></p>
<h2 id=charclass>字符类</h2>
<p>要想查找数字，字母或数字，空白是很简单的，因为已经有了对应这些字符集合的元字符，但是如果你想匹配没有预定义元字符的字符集合(比如元音字母a,e,i,o,u),应该怎么办？</p>
<p>很简单，你只需要在中括号里列出它们就行了，像<span class=regex><font color=#ff0000>[aeiou]</font></span>就匹配<span class=desc><u>任何一个英文元音字母</u></span>，<span class=regex><font color=#ff0000>[.?!]</font></span>匹配<span class=desc><u>标点符号(.或?或!)</u></span>(英文语句通常只以这三个标点结束)。</p>
<p>我们也可以轻松地指定一个字符<span class=name><strong>范围</strong></span>，像<span class=regex><font color=#ff0000>[0-9]</font></span>代表的含意与<span class=regex><font color=#ff0000>\d</font></span>就是完全一致的：<span class=desc><u>一位数字</u></span>，同理<span class=regex><font color=#ff0000>[a-z0-9A-Z_]</font></span>也完全等同于<span class=code><font color=#0000ff>\w</font></span>（如果只考虑英文的话）。</p>
<p>下面是一个更复杂的表达式：<span class=regex><font color=#ff0000>\(?0\d{2}[) -]?\d{8}</font></span>。</p>
<p>这个表达式可以匹配<span class=desc><u>几种格式的电话号码</u></span>，像<span class=string><em>(010)88886666</em></span>，或<span class=string><em>022-22334455</em></span>，或<span class=string><em>02912345678</em></span>等。我们对它进行一些分析吧：首先是一个转义字符<span class=part><font color=#008000>\(</font></span>,它能出现0次或1次(<span class=part><font color=#008000>?</font></span>),然后是一个<span class=part><font color=#008000>0</font></span>，后面跟着2个数字(<span class=part><font color=#008000>\d{2}</font></span>)，然后是<span class=part><font color=#008000>)</font></span>或<span class=part><font color=#008000>-</font></span>或<span class=part><font color=#008000>空格</font></span>中的一个，它出现1次或不出现(<span class=part><font color=#008000>?</font></span>)，最后是8个数字(<span class=part><font color=#008000>\d{8}</font></span>)。不幸的是，它也能匹配<span class=string><em>010)12345678</em></span>或<span class=string><em>(022-87654321</em></span>这样的&#8220;不正确&#8221;的格式。要解决这个问题，请在本教程的下面查找答案。</p>
<h2 id=negation>反义</h2>
<p>有时需要查找不属于某个能简单定义的字符类的字符。比如想查找除了数字以外，其它任意字符都行的情况，这时需要用到<span class=name><strong>反义</strong></span>：</p>
<table cellSpacing=0>
    <caption>表3.常用的反义代码</caption>
    <tbody>
        <tr>
            <th>代码/语法</th>
            <th>说明</th>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\W</font></span></td>
            <td><span class=desc><u>匹配任意不是字母，数字，下划线，汉字的字符</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\S</font></span></td>
            <td><span class=desc><u>匹配任意不是空白符的字符</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\D</font></span></td>
            <td><span class=desc><u>匹配任意非数字的字符</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\B</font></span></td>
            <td><span class=desc><u>匹配不是单词开头或结束的位置</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>[^x]</font></span></td>
            <td><span class=desc><u>匹配除了x以外的任意字符</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>[^aeiou]</font></span></td>
            <td><span class=desc><u>匹配除了aeiou这几个字母以外的任意字符</u></span></td>
        </tr>
    </tbody>
</table>
<p>例子：<span class=regex><font color=#ff0000>\S+</font></span>匹配<span class=desc><u>不包含空白符的字符串</u></span>。</p>
<p><span class=regex><font color=#ff0000>&lt;a[^&gt;]+&gt;</font></span>匹配<span class=desc><u>用尖括号括起来的以a开头的字符串</u></span>。</p>
<h2 id=alternative>替换</h2>
<p>好了，现在终于到了解决3位或4位区号问题的时间了。正则表达式里的<span class=name><strong>替换</strong></span>指的是有几种规则，如果满足其中任意一种规则都应该当成匹配，具体方法是用<span class=code><font color=#0000ff>|</font></span>把不同的规则分隔开。听不明白？没关系，看例子：</p>
<p><span class=regex><font color=#ff0000>0\d{2}-\d{8}|0\d{3}-\d{7}</font></span>这个表达式能<span class=desc><u>匹配两种以连字号分隔的电话号码：一种是三位区号，8位本地号(如010-12345678)，一种是4位区号，7位本地号(0376-2233445)</u></span>。</p>
<p><span class=regex><font color=#ff0000>\(0\d{2}\)[- ]?\d{8}|0\d{2}[- ]?\d{8}</font></span>这个表达式<span class=desc><u>匹配3位区号的电话号码，其中区号可以用小括号括起来，也可以不用，区号与本地号间可以用连字号或空格间隔，也可以没有间隔</u></span>。你可以试试用替换|把这个表达式扩展成也支持4位区号的。</p>
<p><span class=regex><font color=#ff0000>\d{5}-\d{4}|\d{5}</font></span>这个表达式用于匹配美国的邮政编码。美国邮编的规则是5位数字，或者用连字号间隔的9位数字。之所以要给出这个例子是因为它能说明一个问题：<strong>使用替换时，顺序是很重要的</strong>。如果你把它改成<span class=regex><font color=#ff0000>\d{5}|\d{5}-\d{4}</font></span>的话，那么就只会匹配5位的邮编(以及9位邮编的前5位)。原因是匹配替换时，将会从左到右地测试每个分枝条件，如果满足了某个分枝的话，就不会去管其它的替换条件了。</p>
<p><span class=regex><font color=#ff0000>Windows98|Windows2000|WindosXP</font></span>这个例子是为了告诉你替换不仅仅能用于两种规则，也能用于更多种规则。</p>
<h2 id=grouping>分组</h2>
<p>我们已经提到了怎么重复单个字符（直接在字符后面加上限定符就行了）；但如果想要重复多个字符又该怎么办？你可以用小括号来指定<span class=name><strong>子表达式</strong></span>(也叫做<span class=name><strong>分组</strong></span>)，然后你就可以指定这个子表达式的重复次数了，你也可以对子表达式进行其它一些操作(后面会有介绍)。</p>
<p><span class=regex><font color=#ff0000>(\d{1,3}\.){3}\d{1,3}</font></span>是一个<span class=desc><u>简单的IP地址匹配</u></span>表达式。要理解这个表达式，请按下列顺序分析它：<span class=part><font color=#008000>\d{1,3}</font></span>匹配<span class=desc><u>1到3位的数字</u></span>，<span class=part><font color=#008000>(\d{1,3}\.){3}</font></span>匹配<span class=desc><u>三位数字加上一个英文句号(这个整体也就是这个<span class=name><strong>分组</strong></span>)重复3次</u></span>，最后再加上<span class=desc><u>一个一到三位的数字</u></span>(<span class=part><font color=#008000>\d{1,3}</font></span>)。</p>
<p>不幸的是，它也将匹配<span class=string><em>256.300.888.999</em></span>这种不可能存在的IP地址(IP地址中每个数字都不能大于255。题外话，好像反恐24小时第三季的编剧不知道这一点，汗...)。如果能使用算术比较的话，或许能简单地解决这个问题，但是正则表达式中并不提供关于数学的任何功能，所以只能使用冗长的分组，选择，字符类来描述一个正确的IP地址：<span class=regex><font color=#ff0000>((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)</font></span>。</p>
<p>理解这个表达式的关键是理解<span class=part><font color=#008000>2[0-4]\d|25[0-5]|[01]?\d\d?</font></span>，这里我就不细说了，你自己应该能分析得出来它的意义。</p>
<h2 id=backreference>后向引用</h2>
<p>使用小括号指定一个子表达式后，<strong>匹配这个子表达式的文本</strong>(也就是此分组捕获的内容)可以在表达式或其它程序中作进一步的处理。默认情况下，每个分组会自动拥有一个<span class=name><strong>组号</strong></span>，规则是：从左向右，以分组的左括号为标志，第一个出现的分组的组号为1，第二个为2，以此类推。</p>
<p><span class=name><strong>后向引用</strong></span>用于重复搜索前面某个分组匹配的文本。例如，<span class=part><font color=#008000>\1</font></span>代表<span class=desc><u>分组1匹配的文本</u></span>。难以理解？请看示例：</p>
<p><span class=regex><font color=#ff0000>\b(\w+)\b\s+\1\b</font></span>可以用来匹配<span class=desc><u>重复的单词</u></span>，像<span class=string><em>go go</em></span>, <span class=string><em>kitty kitty</em></span>。首先是<span class=desc><u>一个单词</u></span>，也就是<span class=desc><u>单词开始处和结束处之间的多于一个的字母或数字</u></span>(<span class=part><font color=#008000>\b(\w+)\b</font></span>)，然后是<span class=desc><u>1个或几个空白符</u></span>(<span class=part><font color=#008000>\s+</font></span>)，最后是<span class=desc><u>前面匹配的那个单词</u></span>(<span class=part><font color=#008000>\1</font></span>)。</p>
<p>你也可以自己指定子表达式的<span class=name><strong>组名</strong></span>。要指定一个子表达式的组名，请使用这样的语法：<span class=code><font color=#0000ff>(?&lt;Word&gt;\w+)</font></span>(或者把尖括号换成<span class=code><font color=#0000ff>'</font></span>也行：<span class=code><font color=#0000ff>(?'Word'\w+)</font></span>),这样就把<span class=part><font color=#008000>\w+</font></span>的组名指定为<span class=part><font color=#008000>Word</font></span>了。要反向引用这个分组<span class=name><strong>捕获</strong></span>的内容，你可以使用<span class=code><font color=#0000ff>\k&lt;Word&gt;</font></span>,所以上一个例子也可以写成这样：<span class=regex><font color=#ff0000>\b(?&lt;Word&gt;\w+)\b\s+\k&lt;Word&gt;\b</font></span>。</p>
<p>使用小括号的时候，还有很多特定用途的语法。下面列出了最常用的一些：</p>
<table cellSpacing=0>
    <caption>表4.分组语法</caption>
    <tbody>
        <tr>
            <th colSpan=2>捕获</th>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>(exp)</font></span></td>
            <td><span class=desc><u>匹配exp,并捕获文本到自动命名的组里</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>(?&lt;name&gt;exp)</font></span></td>
            <td><span class=desc><u>匹配exp,并捕获文本到名称为name的组里，也可以写成(?'name'exp)</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>(?:exp)</font></span></td>
            <td><span class=desc><u>匹配exp,不捕获匹配的文本，也不给此分组分配组号</u></span></td>
        </tr>
        <tr>
            <th colSpan=2>零宽断言</th>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>(?=exp)</font></span></td>
            <td><span class=desc><u>匹配exp前面的位置</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>(?&lt;=exp)</font></span></td>
            <td><span class=desc><u>匹配exp后面的位置</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>(?!exp)</font></span></td>
            <td><span class=desc><u>匹配后面跟的不是exp的位置</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>(?&lt;!exp)</font></span></td>
            <td><span class=desc><u>匹配前面不是exp的位置</u></span></td>
        </tr>
        <tr>
            <th colSpan=2>注释</th>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>(?#comment)</font></span></td>
            <td><span class=desc><u>这种类型的组不对正则表达式的处理产生任何影响，用于提供注释让人阅读</u></span></td>
        </tr>
    </tbody>
</table>
<p>我们已经讨论了前两种语法。第三个<span class=code><font color=#0000ff>(?:exp)</font></span>不会改变正则表达式的处理方式，只是这样的组匹配的内容<span class=desc><u>不会像前两种那样被捕获到某个组里面</u></span>。</p>
<h2 id=lookaround>零宽断言</h2>
<p>接下来的四个用于查找在某些内容(但并不包括这些内容)之前或之后的东西，也就是说它们像<span class=code><font color=#0000ff>\b</font></span>,<span class=code><font color=#0000ff>^</font></span>,<span class=code><font color=#0000ff>$</font></span>那样用于指定一个位置，这个位置应该满足一定的条件(<a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#reference"><u><font color=#800080>断言</font></u></a>)，因此它们也被称为<span class=name><strong>零宽断言</strong></span>。最好还是拿例子来说明吧：</p>
<p><span class=code><font color=#0000ff>(?=exp)</font></span>也叫<span class=name><strong>零宽度正预测先行断言</strong></span>，它<span class=desc><u>断言自身出现的位置的后面能匹配表达式exp</u></span>。比如<span class=regex><font color=#ff0000>\b\w+(?=ing\b)</font></span>，匹配<span class=desc><u>以ing结尾的单词的前面部分(除了ing以外的部分)</u></span>，如查找<span class=string><em>I'm singing while you're dancing.</em></span>时，它会匹配<span class=desc><u>sing</u></span>和<span class=desc><u>danc</u></span>。</p>
<p><span class=code><font color=#0000ff>(?&lt;=exp)</font></span>也叫<span class=name><strong>零宽度正回顾后发断言</strong></span>，它<span class=desc><u>断言自身出现的位置的前面能匹配表达式exp</u></span>。比如<span class=regex><font color=#ff0000>(?&lt;=\bre)\w+\b</font></span>会匹配<span class=desc><u>以re开头的单词的后半部分(除了re以外的部分)</u></span>，例如在查找<span class=string><em>reading a book</em></span>时，它匹配<span class=desc><u>ading</u></span>。</p>
<p>假如你想要给一个很长的数字中每三位间加一个逗号(当然是从右边加起了)，你可以这样查找需要在前面和里面添加逗号的部分：<span class=regex><font color=#ff0000>((?&lt;=\d)\d{3})*\b</font></span>，用它对<span class=string><em>1234567890</em></span>进行查找时结果是<span class=desc><u>234567890</u></span>。</p>
<p>下面这个例子同时使用了这两种断言：<span class=regex><font color=#ff0000>(?&lt;=\s)\d+(?=\s)</font></span>匹配<span class=desc><u>以空白符间隔的数字(再次强调，不包括这些空白符)</u></span>。</p>
<h2 id=negativelookaround>负向零宽断言</h2>
<p>前面我们提到过怎么查找<strong>不是某个字符或不在某个字符类里</strong>的字符的方法(反义)。但是如果我们只是想要<strong>确保某个字符没有出现，但并不想去匹配它</strong>时怎么办？例如，如果我们想查找这样的单词--它里面出现了字母q,但是q后面跟的不是字母u,我们可以尝试这样：</p>
<p><span class=regex><font color=#ff0000>\b\w*q[^u]\w*\b</font></span>匹配<span class=desc><u>包含<strong>后面不是字母u的字母q</strong>的单词</u></span>。但是如果多做测试(或者你思维足够敏锐，直接就观察出来了)，你会发现，如果q出现在单词的结尾的话，像<strong>Iraq</strong>,<strong>Benq</strong>，这个表达式就会出错。这是因为<span class=part><font color=#008000>[^u]</font></span>总要匹配一个字符，所以如果q是单词的最后一个字符的话，后面的<span class=part><font color=#008000>[^u]</font></span>将会匹配q后面的单词分隔符(可能是空格，或者是句号或其它的什么)，后面的<span class=part><font color=#008000>\w*\b</font></span>将会匹配下一个单词，于是<span class=regex><font color=#ff0000>\b\w*q[^u]\w*\b</font></span>就能匹配整个<span class=string><em>Iraq fighting</em></span>。<span class=name><strong>负向零宽断言</strong></span>能解决这样的问题，因为它只匹配一个位置，并不<strong>消费</strong>任何字符。现在，我们可以这样来解决这个问题：<span class=regex><font color=#ff0000>\b\w*q(?!u)\w*\b</font></span>。</p>
<p><span class=name><strong>零宽度负预测先行断言</strong></span><span class=code><font color=#0000ff>(?!exp)</font></span>，<span class=desc><u>断言此位置的后面不能匹配表达式exp</u></span>。例如：<span class=regex><font color=#ff0000>\d{3}(?!\d)</font></span>匹配<span class=desc><u>三位数字，而且这三位数字的后面不能是数字</u></span>；<span class=regex><font color=#ff0000>\b((?!abc)\w)+\b</font></span>匹配<span class=desc><u>不包含连续字符串abc的单词</u></span>。</p>
<p>同理，我们可以用<span class=code><font color=#0000ff>(?&lt;!exp)</font></span>,<span class=name><strong>零宽度正回顾后发断言</strong></span>来<span class=desc><u>断言此位置的前面不能匹配表达式exp</u></span>：<span class=regex><font color=#ff0000>(?&lt;![a-z])\d{7}</font></span>匹配<span class=desc><u>前面不是小写字母的七位数字</u></span>。</p>
<p>一个更复杂的例子：<span class=regex><font color=#ff0000>(?&lt;=&lt;(\w+)&gt;).*(?=&lt;\/\1&gt;)</font></span>匹配<span class=desc><u>不包含属性的简单HTML标签内里的内容</u></span>。<span class=code><font color=#0000ff>(&lt;?(\w+)&gt;)</font></span>指定了这样的<span class=name><strong>前缀</strong></span>：<span class=desc><u>被尖括号括起来的单词</u></span>(比如可能是&lt;b&gt;)，然后是<span class=part><font color=#008000>.*</font></span>(任意的字符串),最后是一个<span class=name><strong>后缀</strong></span><span class=part><font color=#008000>(?=&lt;\/\1&gt;)</font></span>。注意后缀里的<span class=part><font color=#008000>\/</font></span>，它用到了前面提过的字符转义；<span class=part><font color=#008000>\1</font></span>则是一个反向引用，引用的正是<span class=desc><u>捕获的第一组</u></span>，前面的<span class=part><font color=#008000>(\w+)</font></span>匹配的内容，这样如果前缀实际上是&lt;b&gt;的话，后缀就是&lt;/b&gt;了。整个表达式匹配的是&lt;b&gt;和&lt;/b&gt;之间的内容(再次提醒，不包括前缀和后缀本身)。</p>
<h2 id=commenting>注释</h2>
<p>小括号的另一种用途是能过语法<span class=code><font color=#0000ff>(?#comment)</font></span>来包含注释。例如：<span class=regex><font color=#ff0000>2[0-4]\d(?#200-249)|25[0-5](?#250-255)|[01]?\d\d?(?#0-199)</font></span>。</p>
<p>要包含注释的话，最好是启用&#8220;忽略模式里的空白符&#8221;选项，这样在编写表达式时能任意的添加空格，Tab，换行，而实际使用时这些都将被忽略。启用这个选项后，在#后面到这一行结束的所有文本都将被当成注释忽略掉。</p>
<p>例如，我们可以前面的一个表达式写成这样：</p>
<pre class=regex>      (?&lt;=    # 断言要匹配的文本的前缀
&lt;(\w+)&gt; # 查找尖括号括起来的字母或数字(即HTML/XML标签)
)       # 前缀结束
.*      # 匹配任意文本
(?=     # 断言要匹配的文本的后缀
&lt;\/\1&gt;  # 查找尖括号括起来的内容：前面是一个"/"，后面是先前捕获的标签
)       # 后缀结束
</pre>
<h2 id=greedyandlazy>贪婪与懒惰</h2>
<p>当正则表达式中包含能接受重复的限定符时，通常的行为是（在使整个表达式能得到匹配的前提下）匹配<strong>尽可能多</strong>的字符。考虑这个表达式：<span class=regex><font color=#ff0000>a.*b</font></span>，它将会匹配<span class=desc><u>最长的以a开始，以b结束的字符串</u></span>。如果用它来搜索<span class=string><em>aabab</em></span>的话，它会匹配整个字符串<span class=desc><u>aabab</u></span>。这被称为<span class=name><strong>贪婪</strong></span>匹配。</p>
<p>有时，我们更需要<span class=name><strong>懒惰</strong></span>匹配，也就是匹配<strong>尽可能少</strong>的字符。前面给出的限定符都可以被转化为懒惰匹配模式，只要在它后面加上一个问号<span class=code><font color=#0000ff>?</font></span>。这样<span class=regex><font color=#ff0000>.*?</font></span>就意味着<span class=desc><u>匹配任意数量的重复，但是在能使整个匹配成功的前提下使用最少的重复</u></span>。现在看看懒惰版的例子吧：</p>
<p><span class=regex><font color=#ff0000>a.*?b</font></span>匹配<span class=desc><u>最短的，以a开始，以b结束的字符串</u></span>。如果把它应用于<span class=string><em>aabab</em></span>的话，它会匹配<span class=desc><u>aab</u></span>和<span class=desc><u>ab</u></span>（为什么第一个匹配是aab而不是ab？简单地说，因为正则表达式有另一条规则，比懒惰／贪婪规则的优先级更高：最先开始的匹配拥有最高的优先权——The Match That Begins Earliest Wins）。</p>
<table cellSpacing=0>
    <caption>表5.懒惰限定符</caption>
    <tbody>
        <tr>
            <td><span class=code><font color=#0000ff>*?</font></span></td>
            <td><span class=desc><u>重复任意次，但尽可能少重复</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>+?</font></span></td>
            <td><span class=desc><u>重复1次或更多次，但尽可能少重复</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>??</font></span></td>
            <td><span class=desc><u>重复0次或1次，但尽可能少重复</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>{n,m}?</font></span></td>
            <td><span class=desc><u>重复n到m次，但尽可能少重复</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>{n,}?</font></span></td>
            <td><span class=desc><u>重复n次以上，但尽可能少重复</u></span></td>
        </tr>
    </tbody>
</table>
<h2 id=regexoptions>处理选项</h2>
<p>上面介绍了几个选项如忽略大小写，处理多行等，这些选项能用来改变处理正则表达式的方式。下面是.Net中常用的正则表达式选项：</p>
<table cellSpacing=0>
    <caption>表6.常用的处理选项</caption>
    <thead>
        <tr>
            <th>名称</th>
            <th>说明</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>IgnoreCase(忽略大小写)</td>
            <td>匹配时不区分大小写。</td>
        </tr>
        <tr>
            <td>Multiline(多行模式)</td>
            <td>更改<span class=code><font color=#0000ff>^</font></span>和<span class=code><font color=#0000ff>$</font></span>的含义，使它们分别在任意一行的行首和行尾匹配，而不仅仅在整个字符串的开头和结尾匹配。(在此模式下,<span class=code><font color=#0000ff>$</font></span>的精确含意是:匹配\n之前的位置以及字符串结束前的位置.) </td>
        </tr>
        <tr>
            <td>Singleline(单行模式)</td>
            <td>更改<span class=code><font color=#0000ff>.</font></span>的含义，使它与每一个字符匹配（包括换行符\n）。 </td>
        </tr>
        <tr>
            <td>IgnorePatternWhitespace(忽略空白)</td>
            <td>忽略表达式中的非转义空白并启用由<span class=code><font color=#0000ff>#</font></span>标记的注释。</td>
        </tr>
        <tr>
            <td>RightToLeft(从右向左查找)</td>
            <td>匹配从右向左而不是从左向右进行。</td>
        </tr>
        <tr>
            <td>ExplicitCapture(显式捕获)</td>
            <td>仅捕获已被显式命名的组。</td>
        </tr>
        <tr>
            <td>ECMAScript(JavaScript兼容模式)</td>
            <td>使表达式的行为与它在JavaScript里的行为一致。</td>
        </tr>
    </tbody>
</table>
<p>一个经常被问到的问题是：是不是只能同时使用多行模式和单行模式中的一种？答案是：不是。这两个选项之间没有任何关系，除了它们的名字比较相似（以至于让人感到疑惑）以外。</p>
<h2 id=balancedgroup>平衡组/递归匹配</h2>
<p class=important>注意：这里介绍的平衡组语法是由.Net Framework支持的；其它语言／库不一定支持这种功能，或者支持此功能但需要使用不同的语法。 </p>
<p>有时我们需要匹配像<span class=desc><u>( 100 * ( 50 + 15 ) )这样的可嵌套的层次性结构</u></span>，这时简单地使用<span class=code><font color=#0000ff>\(.+\)</font></span>则只会匹配到最左边的左括号和最右边的右括号之间的内容(这里我们讨论的是贪婪模式，懒惰模式也有下面的问题)。假如原来的字符串里的左括号和右括号出现的次数不相等，比如<span class=string><em>( 5 / ( 3 + 2 ) ) )</em></span>，那我们的匹配结果里两者的个数也不会相等。有没有办法在这样的字符串里匹配到最长的，配对的括号之间的内容呢？ </p>
<p>为了避免<span class=code><font color=#0000ff>(</font></span>和<span class=code><font color=#0000ff>\(</font></span>把你的大脑彻底搞糊涂，我们还是用尖括号代替圆括号吧。现在我们的问题变成了如何把<span class=string><em>xx &lt;aa &lt;bbb&gt; &lt;bbb&gt; aa&gt; yy</em></span>这样的字符串里，最长的配对的尖括号内的内容捕获出来？ </p>
<p>这里需要用到以下的语法构造：</p>
<ul>
    <li><span class=code><font color=#0000ff>(?'group')</font></span> 把捕获的内容命名为group,并压入堆栈
    <li><span class=code><font color=#0000ff>(?'-group')</font></span> 从堆栈上弹出最后压入堆栈的名为group的捕获内容，如果堆栈本来为空，则本分组的匹配失败
    <li><span class=code><font color=#0000ff>(?(group)yes|no)</font></span> 如果堆栈上存在以名为group的捕获内容的话，继续匹配yes部分的表达式，否则继续匹配no部分
    <li><span class=code><font color=#0000ff>(?!)</font></span> 零宽负向先行断言，由于没有后缀表达式，试图匹配总是失败 </li>
</ul>
<p>如果你不是一个程序员（或者你是一个对堆栈的概念不熟的程序员），你就这样理解上面的三种语法吧：第一个就是在黑板上写一个 "group"，第二个就是从黑板上擦掉一个"group"，第三个就是看黑板上写的还有没有"group"，如果有就继续匹配yes部分，否则就匹配 no部分。</p>
<p>我们需要做的是每碰到了左括号，就在黑板上写一个"group"，每碰到一个右括号，就擦掉一个，到了最后就看看黑板上还有没有－－如果有那就证明左括号比右括号多，那匹配就应该失败。 </p>
<pre class=regex>&lt;                         #最外层的左括号
[^&lt;&gt;]*                #最外层的左括号后面的不是括号的内容
(
(
(?'Open'&lt;)    #碰到了左括号，在黑板上写一个"Open"
[^&lt;&gt;]*       #匹配左括号后面的不是括号的内容
)+
(
(?'-Open'&gt;)   #碰到了右括号，擦掉一个"Open"
[^&lt;&gt;]*        #匹配右括号后面不是括号的内容
)+
)*
(?(Open)(?!))         #在遇到最外层的右括号前面，判断黑板上还有没有没擦掉的"Open"；如果还有，则匹配失败
&gt;                         #最外层的右括号</pre>
<p>平衡组的一个最常见的应用就是匹配HTML,下面这个例子可以匹配<span class=desc><u>嵌套的&lt;div&gt;标签</u></span>：<span class=regex><font color=#ff0000>&lt;div[^&gt;]*&gt;[^&lt;&gt;]*(((?'Open'&lt;div[^&gt;]*&gt;)[^&lt;&gt;]*)+((?'-Open'&lt;/div&gt;)[^&lt;&gt;]*)+)*(?(Open)(?!))&lt;/div&gt;</font></span>.</p>
<h2 id=more>还有些什么东西没提到</h2>
<p>我已经描述了构造正则表达式的大量元素，还有一些我没有提到的东西。下面是未提到的元素的列表，包含语法和简单的说明。你可以在网上找到更详细的参考资料来学习它们--当你需要用到它们的时候。如果你安装了MSDN Library,你也可以在里面找到关于.net下正则表达式详细的文档。</p>
<table cellSpacing=0>
    <caption>表7.尚未详细讨论的语法</caption>
    <tbody>
        <tr>
            <td><span class=code><font color=#0000ff>\a</font></span></td>
            <td><span class=desc><u>报警字符(打印它的效果是电脑嘀一声)</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\b</font></span></td>
            <td><span class=desc><u>通常是单词分界位置，但如果在字符类里使用代表退格</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\t</font></span></td>
            <td><span class=desc><u>制表符，Tab</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\r</font></span></td>
            <td><span class=desc><u>回车</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\v</font></span></td>
            <td><span class=desc><u>竖向制表符</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\f</font></span></td>
            <td><span class=desc><u>换页符</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\n</font></span></td>
            <td><span class=desc><u>换行符</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\e</font></span></td>
            <td><span class=desc><u>Escape</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\0nn</font></span></td>
            <td><span class=desc><u>ASCII代码中八进制代码为nn的字符</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\xnn</font></span></td>
            <td><span class=desc><u>ASCII代码中十六进制代码为nn的字符</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\unnnn</font></span></td>
            <td><span class=desc><u>Unicode代码中十六进制代码为nnnn的字符</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\cN</font></span></td>
            <td><span class=desc><u>ASCII控制字符。比如\cC代表Ctrl+C</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\A</font></span></td>
            <td><span class=desc><u>字符串开头(类似^，但不受处理多行选项的影响)</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\Z</font></span></td>
            <td><span class=desc><u>字符串结尾或行尾(不受处理多行选项的影响)</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\z</font></span></td>
            <td><span class=desc><u>字符串结尾(类似$，但不受处理多行选项的影响)</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\G</font></span></td>
            <td><span class=desc><u>当前搜索的开头</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>\p{name}</font></span></td>
            <td><span class=desc><u>Unicode中命名为name的字符类，例如\p{IsGreek}</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>(?&gt;exp)</font></span></td>
            <td><span class=desc><u>贪婪子表达式</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>(?&lt;x&gt;-&lt;y&gt;exp)</font></span></td>
            <td><span class=desc><u>平衡组</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>(?im-nsx:exp)</font></span></td>
            <td><span class=desc><u>在子表达式exp中改变处理选项</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>(?im-nsx)</font></span></td>
            <td><span class=desc><u>为表达式后面的部分改变处理选项</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>(?(exp)yes|no)</font></span></td>
            <td><span class=desc><u>把exp当作零宽正向先行断言，如果在这个位置能匹配，使用yes作为此组的表达式；否则使用no</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>(?(exp)yes)</font></span></td>
            <td><span class=desc><u>同上，只是使用空表达式作为no</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>(?(name)yes|no)</font></span></td>
            <td><span class=desc><u>如果命名为name的组捕获到了内容，使用yes作为表达式；否则使用no</u></span></td>
        </tr>
        <tr>
            <td><span class=code><font color=#0000ff>(?(name)yes)</font></span></td>
            <td><span class=desc><u>同上，只是使用空表达式作为no</u></span></td>
        </tr>
    </tbody>
</table>
<h2 id=contact>联系作者</h2>
<p>好吧,我承认,我骗了你,读到这里你肯定花了不止30分钟.相信我,这是我的错,而不是因为你太笨.我之所以说"30分钟",是为了让你有信心,有耐心继续下去.既然你看到了这里,那证明我的阴谋成功了.上这种当的滋味还不错吧?</p>
<p>要投诉我,或者觉得我其实可以做得更好,或者有任何其它问题,欢迎来<a href="http://www.cnblogs.com/deerchao/archive/2006/08/24/zhengzhe30fengzhongjiaocheng.html"><u><font color=#0000ff>我的博客</font></u></a>进行讨论.</p>
<h2 id=reference>一些我认为你可能已经知道的术语的参考</h2>
<dl>
<dt>字符
<dd>程序处理文字时最基本的单位，可能是字母，数字，标点符号，空格，换行符，汉字等等。
<dt>字符串
<dd>0个或更多个字符的序列。
<dt>文本
<dd>文字，字符串。
<dt>匹配
<dd>符合规则，检验是否符合规则，符合规则的部分。
<dt>断言
<dd>声明一个应该为真的事实。只有当断言为真时才会对正则表达式继续进行匹配。 </dd></dl>
<h2 id=resources>网上的资源及本文参考文献</h2>
<ul>
    <li><a href="http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/jscript7/html/jsreconintroductiontoregularexpressions.asp"><u><font color=#0000ff>微软的正则表达式教程</font></u></a>
    <li><a href="http://msdn2.microsoft.com/zh-cn/library/system.text.regularexpressions.regex.aspx"><u><font color=#0000ff>System.Text.RegularExpressions.Regex类(MSDN)</font></u></a>
    <li><a href="http://www.regular-expressions.info/"><u><font color=#0000ff>专业的正则表达式教学网站(英文)</font></u></a>
    <li><a href="http://weblogs.asp.net/whaggard/archive/2005/02/20/377025.aspx"><u><font color=#0000ff>关于.Net下的平衡组的详细讨论（英文）</font></u></a>
    <li><a href="http://www.oreilly.com/catalog/regex2/"><u><font color=#0000ff>Mastering Regular Expressions (Second Edition)</font></u></a> </li>
</ul>
<h2 id=updatelog>&nbsp;</h2>
<ul>
    <li></li>
</ul>
<img src ="http://www.cppblog.com/sicheng/aggbug/44944.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/sicheng/" target="_blank">oyjpart</a> 2008-03-20 14:15 <a href="http://www.cppblog.com/sicheng/archive/2008/03/20/44944.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA常用设计模式2 MVC [ Model-View-Controller ]</title><link>http://www.cppblog.com/sicheng/archive/2008/01/16/41274.html</link><dc:creator>oyjpart</dc:creator><author>oyjpart</author><pubDate>Wed, 16 Jan 2008 06:01:00 GMT</pubDate><guid>http://www.cppblog.com/sicheng/archive/2008/01/16/41274.html</guid><wfw:comment>http://www.cppblog.com/sicheng/comments/41274.html</wfw:comment><comments>http://www.cppblog.com/sicheng/archive/2008/01/16/41274.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/sicheng/comments/commentRss/41274.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/sicheng/services/trackbacks/41274.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Model-View-Controller, MVC模式的目的是将自己的用户界面逻辑从业务逻辑中分离。通过这种实现，他可以重用业务逻辑，并且阻止界面中的修改对业务逻辑造成影响。下面这个实例正好体现了这一点。WorkPanel中的CommandButton被控制器LoginAction监听，控制器控制model工作，Model工作得到结果，同时JWorkPanel监听Model的工作，在试图上做出相...&nbsp;&nbsp;<a href='http://www.cppblog.com/sicheng/archive/2008/01/16/41274.html'>阅读全文</a><img src ="http://www.cppblog.com/sicheng/aggbug/41274.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/sicheng/" target="_blank">oyjpart</a> 2008-01-16 14:01 <a href="http://www.cppblog.com/sicheng/archive/2008/01/16/41274.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA常用设计模式1 Adapter</title><link>http://www.cppblog.com/sicheng/archive/2008/01/15/41233.html</link><dc:creator>oyjpart</dc:creator><author>oyjpart</author><pubDate>Tue, 15 Jan 2008 14:45:00 GMT</pubDate><guid>http://www.cppblog.com/sicheng/archive/2008/01/15/41233.html</guid><wfw:comment>http://www.cppblog.com/sicheng/comments/41233.html</wfw:comment><comments>http://www.cppblog.com/sicheng/archive/2008/01/15/41233.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/sicheng/comments/commentRss/41233.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/sicheng/services/trackbacks/41233.html</trackback:ping><description><![CDATA[<p>一个适配器允许不带有兼容接口的组件之间进行通信。<br>适配器模式是使用面向对象设计概念的优秀示例，其中一个原因就是因为他非常简单。<br>同时，它也是有关三个重要设计原则的优秀示例：委托，继承和抽象。<br><br>概念UML类图<br><img height=235 alt="" src="http://www.cppblog.com/images/cppblog_com/sicheng/asd.JPG" width=539 border=0><br>实例类图<br><img height=354 alt="" src="http://www.cppblog.com/images/cppblog_com/sicheng/asd2.jpg" width=686 border=0><br><br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Triks.java</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">package</span><span style="COLOR: #000000">&nbsp;oyjpart.designpattern;<br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img id=Codehighlighter1_71_145_Open_Image onclick="this.style.display='none'; Codehighlighter1_71_145_Open_Text.style.display='none'; Codehighlighter1_71_145_Closed_Image.style.display='inline'; Codehighlighter1_71_145_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_71_145_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_71_145_Closed_Text.style.display='none'; Codehighlighter1_71_145_Open_Image.style.display='inline'; Codehighlighter1_71_145_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">interface</span><span style="COLOR: #000000">&nbsp;Tricks&nbsp;</span><span id=Codehighlighter1_71_145_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_71_145_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;walk();<br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;run();<br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;fetch();<br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p><br>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;DogShow.java</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">package</span><span style="COLOR: #000000">&nbsp;oyjpart.designpattern;<br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img id=Codehighlighter1_70_423_Open_Image onclick="this.style.display='none'; Codehighlighter1_70_423_Open_Text.style.display='none'; Codehighlighter1_70_423_Closed_Image.style.display='inline'; Codehighlighter1_70_423_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_70_423_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_70_423_Closed_Text.style.display='none'; Codehighlighter1_70_423_Open_Image.style.display='inline'; Codehighlighter1_70_423_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;DogShow&nbsp;</span><span id=Codehighlighter1_70_423_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_70_423_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img id=Codehighlighter1_111_186_Open_Image onclick="this.style.display='none'; Codehighlighter1_111_186_Open_Text.style.display='none'; Codehighlighter1_111_186_Closed_Image.style.display='inline'; Codehighlighter1_111_186_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_111_186_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_111_186_Closed_Text.style.display='none'; Codehighlighter1_111_186_Open_Image.style.display='inline'; Codehighlighter1_111_186_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;compete(Tricks&nbsp;target)&nbsp;</span><span id=Codehighlighter1_111_186_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_111_186_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target.run();<br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target.walk();<br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target.fetch();<br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img id=Codehighlighter1_236_421_Open_Image onclick="this.style.display='none'; Codehighlighter1_236_421_Open_Text.style.display='none'; Codehighlighter1_236_421_Closed_Image.style.display='inline'; Codehighlighter1_236_421_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_236_421_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_236_421_Closed_Text.style.display='none'; Codehighlighter1_236_421_Open_Image.style.display='inline'; Codehighlighter1_236_421_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;</span><span id=Codehighlighter1_236_421_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_236_421_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OldDog&nbsp;oldDog&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;OldDog(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Tim</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OldDogTricksAdapter&nbsp;oldDogTricksAdapter&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;OldDogTricksAdapter(oldDog);&nbsp;<br></span><span style="COLOR: #008080">15</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;DogShow().compete(oldDogTricksAdapter);<br></span><span style="COLOR: #008080">16</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">17</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">18</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">19</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;OldDog.java</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">package</span><span style="COLOR: #000000">&nbsp;oyjpart.designpattern;<br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img id=Codehighlighter1_68_368_Open_Image onclick="this.style.display='none'; Codehighlighter1_68_368_Open_Text.style.display='none'; Codehighlighter1_68_368_Closed_Image.style.display='inline'; Codehighlighter1_68_368_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_68_368_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_68_368_Closed_Text.style.display='none'; Codehighlighter1_68_368_Open_Image.style.display='inline'; Codehighlighter1_68_368_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;OldDog&nbsp;</span><span id=Codehighlighter1_68_368_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_68_368_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;name;<br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img id=Codehighlighter1_123_155_Open_Image onclick="this.style.display='none'; Codehighlighter1_123_155_Open_Text.style.display='none'; Codehighlighter1_123_155_Closed_Image.style.display='inline'; Codehighlighter1_123_155_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_123_155_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_123_155_Closed_Text.style.display='none'; Codehighlighter1_123_155_Open_Image.style.display='inline'; Codehighlighter1_123_155_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;OldDog(String&nbsp;name)&nbsp;</span><span id=Codehighlighter1_123_155_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_123_155_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.name&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;name;<br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img id=Codehighlighter1_185_257_Open_Image onclick="this.style.display='none'; Codehighlighter1_185_257_Open_Text.style.display='none'; Codehighlighter1_185_257_Closed_Image.style.display='inline'; Codehighlighter1_185_257_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_185_257_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_185_257_Closed_Text.style.display='none'; Codehighlighter1_185_257_Open_Image.style.display='inline'; Codehighlighter1_185_257_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;walk()&nbsp;</span><span id=Codehighlighter1_185_257_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_185_257_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Old&nbsp;Dog&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;name&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;is&nbsp;walking<img src="http://www.cppblog.com/Images/dot.gif"></span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">15</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">16</span><span style="COLOR: #000000"><img id=Codehighlighter1_288_361_Open_Image onclick="this.style.display='none'; Codehighlighter1_288_361_Open_Text.style.display='none'; Codehighlighter1_288_361_Closed_Image.style.display='inline'; Codehighlighter1_288_361_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_288_361_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_288_361_Closed_Text.style.display='none'; Codehighlighter1_288_361_Open_Image.style.display='inline'; Codehighlighter1_288_361_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;sleep()&nbsp;</span><span id=Codehighlighter1_288_361_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_288_361_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">17</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Old&nbsp;Dog&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;name&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;is&nbsp;sleeping<img src="http://www.cppblog.com/Images/dot.gif"></span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">18</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">19</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">20</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">21</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">22</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;OldDogTricksAdapter.java</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">package</span><span style="COLOR: #000000">&nbsp;oyjpart.designpattern;<br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img id=Codehighlighter1_113_486_Open_Image onclick="this.style.display='none'; Codehighlighter1_113_486_Open_Text.style.display='none'; Codehighlighter1_113_486_Closed_Image.style.display='inline'; Codehighlighter1_113_486_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_113_486_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_113_486_Closed_Text.style.display='none'; Codehighlighter1_113_486_Open_Image.style.display='inline'; Codehighlighter1_113_486_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;OldDogTricksAdapter&nbsp;</span><span style="COLOR: #0000ff">implements</span><span style="COLOR: #000000">&nbsp;Tricks&nbsp;</span><span id=Codehighlighter1_113_486_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_113_486_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;OldDog&nbsp;adaptee;<br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img id=Codehighlighter1_194_231_Open_Image onclick="this.style.display='none'; Codehighlighter1_194_231_Open_Text.style.display='none'; Codehighlighter1_194_231_Closed_Image.style.display='inline'; Codehighlighter1_194_231_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_194_231_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_194_231_Closed_Text.style.display='none'; Codehighlighter1_194_231_Open_Image.style.display='inline'; Codehighlighter1_194_231_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;OldDogTricksAdapter(OldDog&nbsp;oldDog)&nbsp;</span><span id=Codehighlighter1_194_231_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_194_231_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.adaptee&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;oldDog;<br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img id=Codehighlighter1_257_312_Open_Image onclick="this.style.display='none'; Codehighlighter1_257_312_Open_Text.style.display='none'; Codehighlighter1_257_312_Closed_Image.style.display='inline'; Codehighlighter1_257_312_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_257_312_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_257_312_Closed_Text.style.display='none'; Codehighlighter1_257_312_Open_Image.style.display='inline'; Codehighlighter1_257_312_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;walk()&nbsp;</span><span id=Codehighlighter1_257_312_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_257_312_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">This&nbsp;dog&nbsp;can&nbsp;walk</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">15</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">16</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">17</span><span style="COLOR: #000000"><img id=Codehighlighter1_339_398_Open_Image onclick="this.style.display='none'; Codehighlighter1_339_398_Open_Text.style.display='none'; Codehighlighter1_339_398_Closed_Image.style.display='inline'; Codehighlighter1_339_398_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_339_398_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_339_398_Closed_Text.style.display='none'; Codehighlighter1_339_398_Open_Image.style.display='inline'; Codehighlighter1_339_398_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;fetch()&nbsp;</span><span id=Codehighlighter1_339_398_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_339_398_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">18</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">This&nbsp;dog&nbsp;cannot&nbsp;fetch</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">19</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">20</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">21</span><span style="COLOR: #000000"><img id=Codehighlighter1_427_484_Open_Image onclick="this.style.display='none'; Codehighlighter1_427_484_Open_Text.style.display='none'; Codehighlighter1_427_484_Closed_Image.style.display='inline'; Codehighlighter1_427_484_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_427_484_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_427_484_Closed_Text.style.display='none'; Codehighlighter1_427_484_Open_Image.style.display='inline'; Codehighlighter1_427_484_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;run()&nbsp;</span><span id=Codehighlighter1_427_484_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_427_484_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">22</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">This&nbsp;dog&nbsp;cannot&nbsp;run</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">23</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">24</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">25</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">26</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<img src ="http://www.cppblog.com/sicheng/aggbug/41233.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/sicheng/" target="_blank">oyjpart</a> 2008-01-15 22:45 <a href="http://www.cppblog.com/sicheng/archive/2008/01/15/41233.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>