<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title><![CDATA[ufolbb's Blog - PROGRAM/WEB Design]]></title>
<link>http://www.ufolbb.com/</link>
<description><![CDATA[-Don&#39;t grow old, grow up!]]></description>
<language>zh-cn</language>
<copyright><![CDATA[Copyright 2005 PBlog3 v2.8]]></copyright>
<webMaster><![CDATA[admin@ufolbb.com(ufolbb)]]></webMaster>
<generator>PBlog2 v2.4</generator> 
<image>
	<title>ufolbb&#39;s Blog</title>
	<url>http://www.ufolbb.com/images/logos.gif</url>
	<link>http://www.ufolbb.com/</link>
	<description>ufolbb&#39;s Blog</description>
</image>

			<item>
			<link>http://www.ufolbb.com/article.asp?id=286</link>
			<title><![CDATA[看下效果]]></title>
			<author>admin@ufolbb.com(ufolbb)</author>
			<category><![CDATA[PROGRAM/WEB Design]]></category>
			<pubDate>Sat,06 Feb 2010 14:34:20 +0800</pubDate>
			<guid>http://www.ufolbb.com/default.asp?id=286</guid>
		<description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 之前说移植一个皮肤过来，现在整体的效果已经做好了。其实整体布局还是之前那个皮肤的，只是把整体的风格颜色换了下，现在已经换上这个皮肤了！IE7 下已经调好了，但在firefox下还有些问题，IE8还没装。还有些细节慢慢来调，话说调这个CSS还真不是一般的烦，每个浏览器都有些要单独设置 <img src="http://www.ufolbb.com/images/smilies/Face_18.gif" border="0" style="margin:0px 0px -2px 0px" alt=""/>]]></description>
		</item>
		
			<item>
			<link>http://www.ufolbb.com/article.asp?id=278</link>
			<title><![CDATA[【更新】sysu公选刷课程序v2.0发布]]></title>
			<author>admin@ufolbb.com(ufolbb)</author>
			<category><![CDATA[PROGRAM/WEB Design]]></category>
			<pubDate>Sat,04 Jul 2009 01:10:24 +0800</pubDate>
			<guid>http://www.ufolbb.com/default.asp?id=278</guid>
		<description><![CDATA[相关说明：<br/><br/>1.本程序仅适用于中山大学普通本科教务系统的公共选修课选课<br/><br/>2.本程序仅适用于抢选阶段，我不可能改变学校筛选阶段的选课结果。。也就是说只有你们在前两个筛选阶段没选到才能用这个刷课程序刷课<br/><br/>3.本程序的原理是对你事先设置好的想上的课，每间隔一定时间（这个时间可以自己设置，最少为1分钟）尝试去选这门课，一旦有人退选就能在第一时间帮你选上（前提是有人退选，我不保证你用我的程序一定能选上你要上的课，只是免去你每天跑上去看有没有空位的重复性动作）<br/><br/><br/><br/>注意事项：<br/><br/>1、请打开程序后填上自己的学号和密码，当刷课过程中cookies失效程序会自动帮你登录。<br/><br/>2、在开始选课前，请确认自己至少有一个空位可以选课！已经选中了两门课的，将无法刷课。请至少退出一门后再刷。。<br/><br/>3、查找课程时请核对找到课程的ID、课程名称、开课时间和选课校区是否正确，请确保选择课程的开课时间与已选中的课程没有冲突！<br/><br/>4、最多可以同时选3门课来刷，当其中一门选中后，程序将自动停止刷课！选择的课程多于1门时，所有课程的优先级是一样的,开始刷课前请确认所选择的课程都是你想上的,以免不想上的课程被选中影响刷课效果！<br/><br/>5、选课期间尽量不要用浏览器登录“普通本科教务系统”！如需登录,请先停止刷课再登录，以免出现未知错误！<br/><br/><br/><span style="color:Red">暂时只能在IE7下使用！装了IE8将无法正常使用！</span><br/><br/>下载地址：<br/><span id="down_8ebke4lq4p"></span><script language="javascript" type="text/javascript">doAjax('?action=Antidown&id=11&downurl=download%2Easp%3Fid%3D11&main=%E7%82%B9%E5%87%BB%E4%B8%8B%E8%BD%BD%E6%AD%A4%E6%96%87%E4%BB%B6','down_8ebke4lq4p');</script><br/><br/><br/><img src="http://www.ufolbb.com/download.asp?id=12" border="0" alt=""/><br/>]]></description>
		</item>
		
			<item>
			<link>http://www.ufolbb.com/article.asp?id=271</link>
			<title><![CDATA[解决装了IE8后VS2008添加MFC类出现脚本错误的工具]]></title>
			<author>admin@ufolbb.com(ufolbb)</author>
			<category><![CDATA[PROGRAM/WEB Design]]></category>
			<pubDate>Wed,01 Apr 2009 12:37:39 +0800</pubDate>
			<guid>http://www.ufolbb.com/default.asp?id=271</guid>
		<description><![CDATA[装了IE8后，用Visual Studio 2008 添加MFC类时总是提示脚本错误，搞了好久才搞定，找到的这个工具<br/><br/><span id="down_8kwksv7itf"></span><script language="javascript" type="text/javascript">doAjax('?action=Antidown&id=212&downurl=download%2Easp%3Fid%3D212&main=%E7%82%B9%E5%87%BB%E4%B8%8B%E8%BD%BD%E6%AD%A4%E6%96%87%E4%BB%B6','down_8kwksv7itf');</script><br/><br/>使用方法：<br/>解压后里面有个release文件夹，下面有个IE8AddZone.exe<br/>运行后点Cr&#101;ate就可以了。。。]]></description>
		</item>
		
			<item>
			<link>http://www.ufolbb.com/article.asp?id=264</link>
			<title><![CDATA[[VB.NET学习]正则表达式]]></title>
			<author>admin@ufolbb.com(ufolbb)</author>
			<category><![CDATA[PROGRAM/WEB Design]]></category>
			<pubDate>Mon,09 Feb 2009 19:31:22 +0800</pubDate>
			<guid>http://www.ufolbb.com/default.asp?id=264</guid>
		<description><![CDATA[<h2>目录</h2>
<ol>
    <li><u><font color="#0000ff">本文目标</font></u></li>
    <li><u><font color="#0000ff">如何使用本教程</font></u></li>
    <li><u><font color="#0000ff">正则表达式到底是什么？</font></u></li>
    <li><u><font color="#0000ff">入门</font></u></li>
    <li><u><font color="#0000ff">测试正则表达式</font></u></li>
    <li><u><font color="#0000ff">元字符</font></u></li>
    <li><u><font color="#0000ff">字符转义</font></u></li>
    <li><u><font color="#0000ff">重复</font></u></li>
    <li><u><font color="#0000ff">字符类</font></u></li>
    <li><u><font color="#0000ff">反义</font></u></li>
    <li><u><font color="#0000ff">替换</font></u></li>
    <li><u><font color="#0000ff">分组</font></u></li>
    <li><u><font color="#0000ff">后向引用</font></u></li>
    <li><u><font color="#0000ff">零宽断言</font></u></li>
    <li><u><font color="#0000ff">负向零宽断言</font></u></li>
    <li><u><font color="#0000ff">注释</font></u></li>
    <li><u><font color="#0000ff">贪婪与懒惰</font></u></li>
    <li><u><font color="#0000ff">处理选项</font></u></li>
    <li><u><font color="#0000ff">平衡组/递归匹配</font></u></li>
    <li><u><font color="#0000ff">还有些什么东西没提到</font></u></li>
    <li><u><font color="#0000ff">联系作者</font></u></li>
    <li><u><font color="#0000ff">一些我认为你可能已经知道的术语的参考</font></u></li>
    <li><u><font color="#0000ff">网上的资源及本文参考文献</font></u></li>
    <li><u><font color="#0000ff">更新说明</font></u></li>
</ol>
<h2>本文目标</h2>
<p>30分钟内让你明白正则表达式是什么，并对它有一些基本的了解，让你可以在自己的程序或网页里使用它。</p>
<h2>如何使用本教程</h2>
<p>最重要的是&mdash;&mdash;请给我<strong>30分钟</strong>，如果你没有使用正则表达式的经验，请不要试图在30<strong>秒</strong>内入门。当然，如果你是超人，那自然得另当别论。</p>
<p>别被下面那些复杂的表达式吓倒，只要跟着我一步一步来，你会发现正则表达式其实并<span lang="zh-cn">没有</span>你想像中的那么困难。当然，如果你看完了这篇教程之后，发现自己明白了很多，却又几乎什么都记不得，那也是很正常的&mdash;&mdash;我认为，没接触过正则表达式的人在看完这篇教程后，能把提到过的语法记住80%以上的可能性为零。这里只是让你明白基本的原理，以后你还需要多练习，多使用，才能熟练掌握正则表达式。</p>
<p>除了作为入门教程之外，本文还试图成为可以在日常工作中使用的正则表达式语法参考手册。就作者本人的经历来说，这个目标还是完成得不错的&mdash;&mdash;你看，我自己也没能把所有的东西记下来，不是吗？</p>
<p>文本格式约定：<span><strong>专业术语</strong></span>&nbsp;<span><font color="#0000ff">元字符/语法格式</font></span>&nbsp;<span><font color="#ff0000">正则表达式</font></span>&nbsp;<span><font color="#008000">正则表达式中的一部分(用于分析)</font></span>&nbsp;<span><em>用于在其中搜索的字符串</em></span>&nbsp;<span><u>对正则表达式或其中一部分的说明</u></span><font color="#0000ff" style="background-color: #eeeeee">清除格式</font></p>
<h2>正则表达式到底是什么？</h2>
<p>在编写处理字符串的程序或网页时，经常会有查找符合某些复杂规则的字符串的需要。<span><strong>正则表达式</strong></span>就是用于描述这些规则的工具。换句话说，正则表达式就是记录文本规则的代码。</p>
<p>很可能你使用过Windows/Dos下用于文件查找的<span><strong>通配符(wildcard)</strong></span>，也就是<span><font color="#0000ff">*</font></span>和<span><font color="#0000ff">?</font></span>。如果你想查找某个目录下的所有的Word文档的话，你会搜索<span style="color: red">*.doc</span>。在这里，<span><font color="#0000ff">*</font></span>会被解释成任意的<u><font color="#0000ff">字符串</font></u>。和通配符类似，正则表达式也是用来进行<u><font color="#0000ff">文本</font></u><u><font color="#0000ff">匹配</font></u>的工具，只不过比起通配符，它能更精确地描述你的需求&mdash;&mdash;当然，代价就是更复杂&mdash;&mdash;比如你可以编写一个正则表达式，用来查找<span><u>所有以0开头，后面跟着2-3个数字，然后是一个连字号&ldquo;-&rdquo;，最后是7或8位数字的字符串</u></span>(像<span><em>010-12345678</em></span>或<span><em>0376-7654321</em></span>)。</p>
<p>正则表达式是用于进行文本匹配的工具，所以本文里多次提到了在字符串里搜索/查找，这种说法的意思是在给定的字符串中，寻找与给定的正则表达式相匹配的部分。有可能字符串里有不止一个部分满足给定的正则表达式，这时每一个这样的部分被称为一个匹配。<span><strong>匹配</strong></span>在本文里可能会有三种意思：一种是形容词性的，比如说一个字符串匹配一个表达式；一种是动词性的，比如说在字符串里匹配正则表达式；还有一种是名词性的，就是刚刚说到的&ldquo;字符串中满足给定的正则表达式的一部分&rdquo;。</p>
<h2>入门</h2>
<p>学习正则表达式的最好方法是从例子开始，理解例子之后再自己对例子进行修改，实验。下面给出了不少简单的例子，并对它们作了详细的说明。</p>
<p>假设你在一篇英文小说里查找<span><u>hi</u></span>，你可以使用正则表达式<span><font color="#ff0000">hi</font></span>。</p>
<p>这是最简单的正则表达式了，它可以精确匹配这样的字符串：<span><u>由两个字符组成，前一个字符是h,后一个是i</u></span>。通常，处理正则表达式的工具会提供一个忽略大小写的选项，如果选中了这个选项，它可以匹配<span><em>hi</em></span>,<span><em>HI</em></span>,<span><em>Hi</em></span>,<span><em>hI</em></span>这四种情况中的任意一种。</p>
<p>不幸的是，很多单词里包含<span><em>hi</em></span>这两个连续的字符，比如<span><em>him</em></span>,<span><em>history</em></span>,<span><em>high</em></span>等等。用<span><font color="#ff0000">hi</font></span>来查找的话，这里边的<span><em>hi</em></span>也会被找出来。如果要<span><u>精确地查找hi这个单词</u></span>的话，我们应该使用<span><font color="#ff0000">\bhi\b</font></span>。</p>
<p><span><font color="#008000">\b</font></span>是正则表达式规定的一个特殊代码（好吧，某些人叫它<span><strong>元字符，metacharacter</strong></span>），代表着<span><u>单词的开头或结尾，也就是单词的分界处</u></span>。虽然通常英文的单词是由空格或标点符号或换行来分隔的，但是<span><font color="#0000ff">\b</font></span>并不匹配这些单词分隔符中的任何一个，它<strong>只匹配一个位置</strong>。（如果需要更精确的说法，<span><font color="#0000ff">\b</font></span>匹配这样的位置：它的前一个字符和后一个字符不全是(一个是,一个不是或不存在)<span><font color="#0000ff">\w</font></span>）</p>
<p>假如你要找的是<span><u>hi后面不远处跟着一个Lucy</u></span>，你应该用<span><font color="#ff0000">\bhi\b.*\bLucy\b</font></span>。</p>
<p>这里，<span><font color="#008000">.</font></span>是另一个元字符，匹配<span><u>除了换行符以外的任意字符</u></span>。<span><font color="#008000">*</font></span>同样是元字符，不过它代表的不是字符，也不是位置，而是数量&mdash;&mdash;它指定*<span><u>前边的内容可以连续重复出现任意次以使整个表达式得到匹配</u></span>。因此，<span><font color="#008000">.*</font></span>连在一起就意味着<span><u>任意数量的不包含换行的字符</u></span>。现在<span><font color="#ff0000">\bhi\b.*\bLucy\b</font></span>的意思就很明显了：<span><u>先是一个单词hi,然后是任意个任意字符(但不能是换行)，最后是Lucy这个单词</u></span>。</p>
<p>如果同时使用其它的一些元字符，我们就能构造出功能更强大的正则表达式。比如下面这个例子：</p>
<p><span><font color="#ff0000">0\d\d-\d\d\d\d\d\d\d\d</font></span>匹配这样的字符串：<span><u>以0开头，然后是两个数字，然后是一个连字号&ldquo;-&rdquo;，最后是8个数字</u></span>(也就是中国的电话号码。当然，这个例子只能匹配区号为3位的情形)。</p>
<p>这里的<span><font color="#008000">\d</font></span>是一个新的元字符，匹配<span><u>任意的数字(0，或1，或2，或&hellip;&hellip;)</u></span>。<span><font color="#008000">-</font></span>不是元字符，只匹配它本身&mdash;&mdash;连字号。</p>
<p>为了避免那么多烦人的重复，我们也可以这样写这个表达式：<span><font color="#ff0000">0\d{2}-\d{8}</font></span>。 这里<span><font color="#008000">\d</font></span>后面的<span><font color="#008000">{2}</font></span>(<span><font color="#008000">{8}</font></span>)的意思是前面<span><font color="#008000">\d</font></span><span><u>必须连续重复匹配2次(8次)</u></span>。</p>
<h2>测试正则表达式</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>&nbsp;<a target="_blank" href="http://tkfiles.storage.live.com/y1pKq4lmpcJncqsHK6AhSLpTJBBCVdbv1-KMbltwz54iHDst5SenaGyNcmQOo7AvfvqxsAwHKTR1w8"><img height="200" alt="RegexTester" width="216" src="http://tkfiles.storage.live.com/y1pKq4lmpcJncqsHK6AhSLpTJBBCVdbv1-KMbltwz54iHDst5SenaGyNcmQOo7AvfvqxsAwHKTR1w8" /></a></p>
<h2>元字符</h2>
<p>现在你已经知道几个很有用的元字符了，如<span><font color="#0000ff">\b</font></span>,<span><font color="#0000ff">.</font></span>,<span><font color="#0000ff">*</font></span>，还有<span><font color="#0000ff">\d</font></span>.当然还有更多的元字符可用，比如<span><font color="#0000ff">\s</font></span>匹配<span><u>任意的空白符，包括空格，制表符(Tab)，换行符，中文全角空格等</u></span>。<span><font color="#0000ff">\w</font></span>匹配<span><u>字母或数字或下划线或汉字等</u></span>。</p>
<p>下面来试试更多的例子：</p>
<p><span><font color="#ff0000">\ba\w*\b</font></span>匹配<span><u>以字母<span><font color="#008000">a</font></span>开头的单词&mdash;&mdash;先是某个单词开始处(<span><font color="#008000">\b</font></span>)，然后是字母<span><font color="#008000">a</font></span>,然后是任意数量的字母或数字(<span><font color="#008000">\w*</font></span>)，最后是单词结束处(<span><font color="#008000">\b</font></span>)</u></span>（好吧，现在我们说说正则表达式里的单词是什么意思吧：就是几个连续的<span><font color="#0000ff">\w</font></span>。不错，这与学习英文时要背的成千上万个同名的东西的确关系不大）。</p>
<p><span><font color="#ff0000">\d+</font></span>匹配<span><u>1个或更多连续的数字</u></span>。这里的<span><font color="#008000">+</font></span>是和<span><font color="#0000ff">*</font></span>类似的元字符，不同的是<span><font color="#0000ff">*</font></span>匹配<span><u>重复任意次(可能是0次)</u></span>，而<span><font color="#0000ff">+</font></span>则匹配<span><u>重复1次或更多次</u></span>。</p>
<p><span><font color="#ff0000">\b\w{6}\b</font></span> 匹配<span><u>刚好6个字母/数字的单词</u></span>。</p>
<div>
<table cellspacing="0">
    <caption>表1.常用的元字符</caption>
    <tbody>
        <tr>
            <th>代码</th>
            <th>说明</th>
        </tr>
        <tr>
            <td><span><font color="#0000ff">.</font></span></td>
            <td><span><u>匹配除换行符以外的任意字符</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\w</font></span></td>
            <td><span><u>匹配字母或数字或下划线或汉字</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\s</font></span></td>
            <td><span><u>匹配任意的空白符</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\d</font></span></td>
            <td><span><u>匹配数字</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\b</font></span></td>
            <td><span><u>匹配单词的开始或结束</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">^</font></span></td>
            <td><span><u>匹配字符串的开始</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">$</font></span></td>
            <td><span><u>匹配字符串的结束</u></span></td>
        </tr>
    </tbody>
</table>
</div>
<p>元字符<span><font color="#0000ff">^</font></span>（和数字6在同一个键位上的符号）以及<span><font color="#0000ff">$</font></span>和<span><font color="#0000ff">\b</font></span>有点类似，都匹配一个位置。<span><font color="#0000ff">^</font></span>匹配你要用来查找的字符串的开头，<span><font color="#0000ff">$</font></span>匹配结尾。这两个代码在验证输入的内容时非常有用，比如一个网站如果要求你填写的QQ号必须为5位到12位数字时，可以使用：<span><font color="#ff0000">^\d{5,12}$</font></span>。</p>
<p>这里的<span><font color="#008000">{5,12}</font></span>和前面介绍过的<span><font color="#008000">{2}</font></span>是类似的，只不过<span><font color="#008000">{2}</font></span>匹配<span><u>只能不多不少重复2次</u></span>，<span><font color="#008000">{5,12}</font></span>则是<span><u>重复的次数不能少于5次，不能多于12次</u></span>，否则都不匹配。</p>
<p>因为使用了<span><font color="#008000">^</font></span>和<span><font color="#008000">$</font></span>，所以输入的整个字符串都要用来和<span><font color="#008000">\d{5,12}</font></span>来匹配，也就是说整个输入<span><u>必须是5到12个数字</u></span>，因此如果输入的QQ号能匹配这个正则表达式的话，那就符合要求了。</p>
<p>和忽略大小写的选项类似，有些正则表达式处理工具还有一个处理多行的选项。如果选中了这个选项，<span><font color="#0000ff">^</font></span>和<span><font color="#0000ff">$</font></span>的意义就变成了<span><u>匹配行的开始处和结束处</u></span>。</p>
<h2>字符转义</h2>
<p>如果你想查找元字符本身的话，比如你查找<span><u>.</u></span>,或者<span><u>*</u></span>,就出现了问题：你没法指定它们，因为它们会被解释成其它的意思。这时你就必须使用<span><font color="#0000ff">\</font></span>来取消这些字符的特殊意义。因此，你应该使用<span><font color="#ff0000">\.</font></span>和<span><font color="#ff0000">\*</font></span>。当然，要查找<span><u>\</u></span>本身，你也得用<span><font color="#ff0000">\\</font></span>.</p>
<p>例如：<span><font color="#ff0000">www\.unibetter\.com</font></span>匹配<span><u>www.unibetter.com</u></span>，<span><font color="#ff0000">c:\\Windows</font></span>匹配<span><u>c:\Windows</u></span>。</p>
<h2>重复</h2>
<p>你已经看过了前面的<span><font color="#0000ff">*</font></span>,<span><font color="#0000ff">+</font></span>,<span><font color="#0000ff">{2}</font></span>,<span><font color="#0000ff">{5,12}</font></span>这几个匹配重复的方式了。下面是正则表达式中所有的限定符(指定数量的代码，例如*,{5,12}等)：</p>
<div>
<table cellspacing="0">
    <caption>表2.常用的限定符</caption>
    <tbody>
        <tr>
            <th>代码/语法</th>
            <th>说明</th>
        </tr>
        <tr>
            <td><span><font color="#0000ff">*</font></span></td>
            <td><span><u>重复零次或更多次</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">+</font></span></td>
            <td><span><u>重复一次或更多次</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">?</font></span></td>
            <td><span><u>重复零次或一次</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">{n}</font></span></td>
            <td><span><u>重复n次</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">{n,}</font></span></td>
            <td><span><u>重复n次或更多次</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">{n,m}</font></span></td>
            <td><span><u>重复n到m次</u></span></td>
        </tr>
    </tbody>
</table>
</div>
<p>下面是一些使用重复的例子：</p>
<p><span><font color="#ff0000">Windows\d+</font></span>匹配<span><u>Windows后面跟1个或更多数字</u></span></p>
<p><span><font color="#ff0000">13\d{9}</font></span>匹配<span><u>13后面跟9个数字(中国的手机号)</u></span></p>
<p><span><font color="#ff0000">^\w+</font></span>匹配<span><u>一行的第一个单词(或整个字符串的第一个单词，具体匹配哪个意思得看选项设置)</u></span></p>
<h2>字符类</h2>
<p>要想查找数字，字母或数字，空白是很简单的，因为已经有了对应这些字符集合的元字符，但是如果你想匹配没有预定义元字符的字符集合(比如元音字母a,e,i,o,u),应该怎么办？</p>
<p>很简单，你只需要在中括号里列出它们就行了，像<span><font color="#ff0000">[aeiou]</font></span>就匹配<span><u>任何一个英文元音字母</u></span>，<span><font color="#ff0000">[.?!]</font></span>匹配<span><u>标点符号(.或?或!)</u></span>(英文语句通常只以这三个标点结束)。</p>
<p>我们也可以轻松地指定一个字符<span><strong>范围</strong></span>，像<span><font color="#ff0000">[0-9]</font></span>代表的含意与<span><font color="#ff0000">\d</font></span>就是完全一致的：<span><u>一位数字</u></span>，同理<span><font color="#ff0000">[a-z0-9A-Z_]</font></span>也完全等同于<span><font color="#0000ff">\w</font></span>（如果只考虑英文的话）。</p>
<p>下面是一个更复杂的表达式：<span><font color="#ff0000">\(?0\d{2}[) -]?\d{8}</font></span>。</p>
<p>这个表达式可以匹配<span><u>几种格式的电话号码</u></span>，像<span><em>(010)88886666</em></span>，或<span><em>022-22334455</em></span>，或<span><em>02912345678</em></span>等。我们对它进行一些分析吧：首先是一个转义字符<span><font color="#008000">\(</font></span>,它能出现0次或1次(<span><font color="#008000">?</font></span>),然后是一个<span><font color="#008000">0</font></span>，后面跟着2个数字(<span><font color="#008000">\d{2}</font></span>)，然后是<span><font color="#008000">)</font></span>或<span><font color="#008000">-</font></span>或<span><font color="#008000">空格</font></span>中的一个，它出现1次或不出现(<span><font color="#008000">?</font></span>)，最后是8个数字(<span><font color="#008000">\d{8}</font></span>)。不幸的是，它也能匹配<span><em>010)12345678</em></span>或<span><em>(022-87654321</em></span>这样的&ldquo;不正确&rdquo;的格式。要解决这个问题，请在本教程的下面查找答案。</p>
<h2>反义</h2>
<p>有时需要查找不属于某个能简单定义的字符类的字符。比如想查找除了数字以外，其它任意字符都行的情况，这时需要用到<span><strong>反义</strong></span>：</p>
<div>
<table cellspacing="0">
    <caption>表3.常用的反义代码</caption>
    <tbody>
        <tr>
            <th>代码/语法</th>
            <th>说明</th>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\W</font></span></td>
            <td><span><u>匹配任意不是字母，数字，下划线，汉字的字符</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\S</font></span></td>
            <td><span><u>匹配任意不是空白符的字符</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\D</font></span></td>
            <td><span><u>匹配任意非数字的字符</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\B</font></span></td>
            <td><span><u>匹配不是单词开头或结束的位置</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">[^x]</font></span></td>
            <td><span><u>匹配除了x以外的任意字符</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">[^aeiou]</font></span></td>
            <td><span><u>匹配除了aeiou这几个字母以外的任意字符</u></span></td>
        </tr>
    </tbody>
</table>
</div>
<p>例子：<span><font color="#ff0000">\S+</font></span>匹配<span><u>不包含空白符的字符串</u></span>。</p>
<p><span><font color="#ff0000">&lt;a[^&gt;]+&gt;</font></span>匹配<span><u>用尖括号括起来的以a开头的字符串</u></span>。</p>
<h2>替换</h2>
<p>好了，现在终于到了解决3位或4位区号问题的时间了。正则表达式里的<span><strong>替换</strong></span>指的是有几种规则，如果满足其中任意一种规则都应该当成匹配，具体方法是用<span><font color="#0000ff">|</font></span>把不同的规则分隔开。听不明白？没关系，看例子：</p>
<p><span><font color="#ff0000">0\d{2}-\d{8}|0\d{3}-\d{7}</font></span>这个表达式能<span><u>匹配两种以连字号分隔的电话号码：一种是三位区号，8位本地号(如010-12345678)，一种是4位区号，7位本地号(0376-2233445)</u></span>。</p>
<p><span><font color="#ff0000">\(0\d{2}\)[- ]?\d{8}|0\d{2}[- ]?\d{8}</font></span>这个表达式<span><u>匹配3位区号的电话号码，其中区号可以用小括号括起来，也可以不用，区号与本地号间可以用连字号或空格间隔，也可以没有间隔</u></span>。你可以试试用替换|把这个表达式扩展成也支持4位区号的。</p>
<p><span><font color="#ff0000">\d{5}-\d{4}|\d{5}</font></span>这个表达式用于匹配美国的邮政编码。美国邮编的规则是5位数字，或者用连字号间隔的9位数字。之所以要给出这个例子是因为它能说明一个问题：<strong>使用替换时，顺序是很重要的</strong>。如果你把它改成<span><font color="#ff0000">\d{5}|\d{5}-\d{4}</font></span>的话，那么就只会匹配5位的邮编(以及9位邮编的前5位)。原因是匹配替换时，将会从左到右地测试每个分枝条件，如果满足了某个分枝的话，就不会去管其它的替换条件了。</p>
<p><span><font color="#ff0000">Windows98|Windows2000|WindosXP</font></span>这个例子是为了告诉你替换不仅仅能用于两种规则，也能用于更多种规则。</p>
<h2>分组</h2>
<p>我们已经提到了怎么重复单个字符（直接在字符后面加上限定符就行了）；但如果想要重复多个字符又该怎么办？你可以用小括号来指定<span><strong>子表达式</strong></span>(也叫做<span><strong>分组</strong></span>)，然后你就可以指定这个子表达式的重复次数了，你也可以对子表达式进行其它一些操作(后面会有介绍)。</p>
<p><span><font color="#ff0000">(\d{1,3}\.){3}\d{1,3}</font></span>是一个<span><u>简单的IP地址匹配</u></span>表达式。要理解这个表达式，请按下列顺序分析它：<span><font color="#008000">\d{1,3}</font></span>匹配<span><u>1到3位的数字</u></span>，<span><font color="#008000">(\d{1,3}\.){3}</font></span>匹配<span><u>三位数字加上一个英文句号(这个整体也就是这个<span><strong>分组</strong></span>)重复3次</u></span>，最后再加上<span><u>一个一到三位的数字</u></span>(<span><font color="#008000">\d{1,3}</font></span>)。</p>
<p>不幸的是，它也将匹配<span><em>256.300.888.999</em></span>这种不可能存在的IP地址(IP地址中每个数字都不能大于255。题外话，好像反恐24小时第三季的编剧不知道这一点，汗...)。如果能使用算术比较的话，或许能简单地解决这个问题，但是正则表达式中并不提供关于数学的任何功能，所以只能使用冗长的分组，选择，字符类来描述一个正确的IP地址：<span><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><font color="#008000">2[0-4]\d|25[0-5]|[01]?\d\d?</font></span>，这里我就不细说了，你自己应该能分析得出来它的意义。</p>
<h2>后向引用</h2>
<p>使用小括号指定一个子表达式后，<strong>匹配这个子表达式的文本</strong>(也就是此分组捕获的内容)可以在表达式或其它程序中作进一步的处理。默认情况下，每个分组会自动拥有一个<span><strong>组号</strong></span>，规则是：从左向右，以分组的左括号为标志，第一个出现的分组的组号为1，第二个为2，以此类推。</p>
<p><span><strong>后向引用</strong></span>用于重复搜索前面某个分组匹配的文本。例如，<span><font color="#008000">\1</font></span>代表<span><u>分组1匹配的文本</u></span>。难以理解？请看示例：</p>
<p><span><font color="#ff0000">\b(\w+)\b\s+\1\b</font></span>可以用来匹配<span><u>重复的单词</u></span>，像<span><em>go go</em></span>, <span><em>kitty kitty</em></span>。首先是<span><u>一个单词</u></span>，也就是<span><u>单词开始处和结束处之间的多于一个的字母或数字</u></span>(<span><font color="#008000">\b(\w+)\b</font></span>)，然后是<span><u>1个或几个空白符</u></span>(<span><font color="#008000">\s+</font></span>)，最后是<span><u>前面匹配的那个单词</u></span>(<span><font color="#008000">\1</font></span>)。</p>
<p>你也可以自己指定子表达式的<span><strong>组名</strong></span>。要指定一个子表达式的组名，请使用这样的语法：<span><font color="#0000ff">(?&lt;Word&gt;\w+)</font></span>(或者把尖括号换成<span><font color="#0000ff">'</font></span>也行：<span><font color="#0000ff">(?'Word'\w+)</font></span>),这样就把<span><font color="#008000">\w+</font></span>的组名指定为<span><font color="#008000">Word</font></span>了。要反向引用这个分组<span><strong>捕获</strong></span>的内容，你可以使用<span><font color="#0000ff">\k&lt;Word&gt;</font></span>,所以上一个例子也可以写成这样：<span><font color="#ff0000">\b(?&lt;Word&gt;\w+)\b\s+\k&lt;Word&gt;\b</font></span>。</p>
<p>使用小括号的时候，还有很多特定用途的语法。下面列出了最常用的一些：</p>
<div>
<table cellspacing="0">
    <caption>表4.分组语法</caption>
    <tbody>
        <tr>
            <th colspan="2">捕获</th>
        </tr>
        <tr>
            <td><span><font color="#0000ff">(exp)</font></span></td>
            <td><span><u>匹配exp,并捕获文本到自动命名的组里</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">(?&lt;name&gt;exp)</font></span></td>
            <td><span><u>匹配exp,并捕获文本到名称为name的组里，也可以写成(?'name'exp)</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">(?:exp)</font></span></td>
            <td><span><u>匹配exp,不捕获匹配的文本，也不给此分组分配组号</u></span></td>
        </tr>
        <tr>
            <th colspan="2">零宽断言</th>
        </tr>
        <tr>
            <td><span><font color="#0000ff">(?=exp)</font></span></td>
            <td><span><u>匹配exp前面的位置</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">(?&lt;=exp)</font></span></td>
            <td><span><u>匹配exp后面的位置</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">(?!exp)</font></span></td>
            <td><span><u>匹配后面跟的不是exp的位置</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">(?&lt;!exp)</font></span></td>
            <td><span><u>匹配前面不是exp的位置</u></span></td>
        </tr>
        <tr>
            <th colspan="2">注释</th>
        </tr>
        <tr>
            <td><span><font color="#0000ff">(?#comment)</font></span></td>
            <td><span><u>这种类型的组不对正则表达式的处理产生任何影响，用于提供注释让人阅读</u></span></td>
        </tr>
    </tbody>
</table>
</div>
<p>我们已经讨论了前两种语法。第三个<span><font color="#0000ff">(?:exp)</font></span>不会改变正则表达式的处理方式，只是这样的组匹配的内容<span><u>不会像前两种那样被捕获到某个组里面</u></span>。</p>
<h2>零宽断言</h2>
<p>接下来的四个用于查找在某些内容(但并不包括这些内容)之前或之后的东西，也就是说它们像<span><font color="#0000ff">\b</font></span>,<span><font color="#0000ff">^</font></span>,<span><font color="#0000ff">$</font></span>那样用于指定一个位置，这个位置应该满足一定的条件(<u><font color="#0000ff">断言</font></u>)，因此它们也被称为<span><strong>零宽断言</strong></span>。最好还是拿例子来说明吧：</p>
<p><span><font color="#0000ff">(?=exp)</font></span>也叫<span><strong>零宽度正预测先行断言</strong></span>，它<span><u>断言自身出现的位置的后面能匹配表达式exp</u></span>。比如<span><font color="#ff0000">\b\w+(?=ing\b)</font></span>，匹配<span><u>以ing结尾的单词的前面部分(除了ing以外的部分)</u></span>，如查找<span><em>I'm singing while you're dancing.</em></span>时，它会匹配<span><u>sing</u></span>和<span><u>danc</u></span>。</p>
<p><span><font color="#0000ff">(?&lt;=exp)</font></span>也叫<span><strong>零宽度正回顾后发断言</strong></span>，它<span><u>断言自身出现的位置的前面能匹配表达式exp</u></span>。比如<span><font color="#ff0000">(?&lt;=\bre)\w+\b</font></span>会匹配<span><u>以re开头的单词的后半部分(除了re以外的部分)</u></span>，例如在查找<span><em>reading a book</em></span>时，它匹配<span><u>ading</u></span>。</p>
<p>假如你想要给一个很长的数字中每三位间加一个逗号(当然是从右边加起了)，你可以这样查找需要在前面和里面添加逗号的部分：<span><font color="#ff0000">((?&lt;=\d)\d{3})*\b</font></span>，用它对<span><em>1234567890</em></span>进行查找时结果是<span><u>234567890</u></span>。</p>
<p>下面这个例子同时使用了这两种断言：<span><font color="#ff0000">(?&lt;=\s)\d+(?=\s)</font></span>匹配<span><u>以空白符间隔的数字(再次强调，不包括这些空白符)</u></span>。</p>
<h2>负向零宽断言</h2>
<p>前面我们提到过怎么查找<strong>不是某个字符或不在某个字符类里</strong>的字符的方法(反义)。但是如果我们只是想要<strong>确保某个字符没有出现，但并不想去匹配它</strong>时怎么办？例如，如果我们想查找这样的单词--它里面出现了字母q,但是q后面跟的不是字母u,我们可以尝试这样：</p>
<p><span><font color="#ff0000">\b\w*q[^u]\w*\b</font></span>匹配<span><u>包含<strong>后面不是字母u的字母q</strong>的单词</u></span>。但是如果多做测试(或者你思维足够敏锐，直接就观察出来了)，你会发现，如果q出现在单词的结尾的话，像<strong>Iraq</strong>,<strong>Benq</strong>，这个表达式就会出错。这是因为<span><font color="#008000">[^u]</font></span>总要匹配一个字符，所以如果q是单词的最后一个字符的话，后面的<span><font color="#008000">[^u]</font></span>将会匹配q后面的单词分隔符(可能是空格，或者是句号或其它的什么)，后面的<span><font color="#008000">\w*\b</font></span>将会匹配下一个单词，于是<span><font color="#ff0000">\b\w*q[^u]\w*\b</font></span>就能匹配整个<span><em>Iraq fighting</em></span>。<span><strong>负向零宽断言</strong></span>能解决这样的问题，因为它只匹配一个位置，并不<strong>消费</strong>任何字符。现在，我们可以这样来解决这个问题：<span><font color="#ff0000">\b\w*q(?!u)\w*\b</font></span>。</p>
<p><span><strong>零宽度负预测先行断言</strong></span><span><font color="#0000ff">(?!exp)</font></span>，<span><u>断言此位置的后面不能匹配表达式exp</u></span>。例如：<span><font color="#ff0000">\d{3}(?!\d)</font></span>匹配<span><u>三位数字，而且这三位数字的后面不能是数字</u></span>；<span><font color="#ff0000">\b((?!abc)\w)+\b</font></span>匹配<span><u>不包含连续字符串abc的单词</u></span>。</p>
<p>同理，我们可以用<span><font color="#0000ff">(?&lt;!exp)</font></span>,<span><strong>零宽度正回顾后发断言</strong></span>来<span><u>断言此位置的前面不能匹配表达式exp</u></span>：<span><font color="#ff0000">(?&lt;![a-z])\d{7}</font></span>匹配<span><u>前面不是小写字母的七位数字</u></span>。</p>
<p>一个更复杂的例子：<span><font color="#ff0000">(?&lt;=&lt;(\w+)&gt;).*(?=&lt;\/\1&gt;)</font></span>匹配<span><u>不包含属性的简单HTML标签内里的内容</u></span>。<span><font color="#0000ff">(&lt;?(\w+)&gt;)</font></span>指定了这样的<span><strong>前缀</strong></span>：<span><u>被尖括号括起来的单词</u></span>(比如可能是&lt;b&gt;)，然后是<span><font color="#008000">.*</font></span>(任意的字符串),最后是一个<span><strong>后缀</strong></span><span><font color="#008000">(?=&lt;\/\1&gt;)</font></span>。注意后缀里的<span><font color="#008000">\/</font></span>，它用到了前面提过的字符转义；<span><font color="#008000">\1</font></span>则是一个反向引用，引用的正是<span><u>捕获的第一组</u></span>，前面的<span><font color="#008000">(\w+)</font></span>匹配的内容，这样如果前缀实际上是&lt;b&gt;的话，后缀就是&lt;/b&gt;了。整个表达式匹配的是&lt;b&gt;和&lt;/b&gt;之间的内容(再次提醒，不包括前缀和后缀本身)。</p>
<h2>注释</h2>
<p>小括号的另一种用途是能过语法<span><font color="#0000ff">(?#comment)</font></span>来包含注释。例如：<span><font color="#ff0000">2[0-4]\d(?#200-249)|25[0-5](?#250-255)|[01]?\d\d?(?#0-199)</font></span>。</p>
<p>要包含注释的话，最好是启用&ldquo;忽略模式里的空白符&rdquo;选项，这样在编写表达式时能任意的添加空格，Tab，换行，而实际使用时这些都将被忽略。启用这个选项后，在#后面到这一行结束的所有文本都将被当成注释忽略掉。</p>
<p>例如，我们可以前面的一个表达式写成这样：</p>
<pre>
      (?&lt;=    # 断言要匹配的文本的前缀
      &lt;(\w+)&gt; # 查找尖括号括起来的字母或数字(即HTML/XML标签)
      )       # 前缀结束
      .*      # 匹配任意文本
      (?=     # 断言要匹配的文本的后缀
      &lt;\/\1&gt;  # 查找尖括号括起来的内容：前面是一个&quot;/&quot;，后面是先前捕获的标签
      )       # 后缀结束
    </pre>
<h2>贪婪与懒惰</h2>
<p>当正则表达式中包含能接受重复的限定符时，通常的行为是（在使整个表达式能得到匹配的前提下）匹配<strong>尽可能多</strong>的字符。考虑这个表达式：<span><font color="#ff0000">a.*b</font></span>，它将会匹配<span><u>最长的以a开始，以b结束的字符串</u></span>。如果用它来搜索<span><em>aabab</em></span>的话，它会匹配整个字符串<span><u>aabab</u></span>。这被称为<span><strong>贪婪</strong></span>匹配。</p>
<p>有时，我们更需要<span><strong>懒惰</strong></span>匹配，也就是匹配<strong>尽可能少</strong>的字符。前面给出的限定符都可以被转化为懒惰匹配模式，只要在它后面加上一个问号<span><font color="#0000ff">?</font></span>。这样<span><font color="#ff0000">.*?</font></span>就意味着<span><u>匹配任意数量的重复，但是在能使整个匹配成功的前提下使用最少的重复</u></span>。现在看看懒惰版的例子吧：</p>
<p><span><font color="#ff0000">a.*?b</font></span>匹配<span><u>最短的，以a开始，以b结束的字符串</u></span>。如果把它应用于<span><em>aabab</em></span>的话，它会匹配<span><u>aab</u></span>和<span><u>ab</u></span>（为什么第一个匹配是aab而不是ab？简单地说，因为正则表达式有另一条规则，比懒惰／贪婪规则的优先级更高：最先开始的匹配最有最大的优先权&mdash;&mdash;The Match That Begins Earliest Wins）。</p>
<div>
<table cellspacing="0">
    <caption>表5.懒惰限定符</caption>
    <tbody>
        <tr>
            <td><span><font color="#0000ff">*?</font></span></td>
            <td><span><u>重复任意次，但尽可能少重复</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">+?</font></span></td>
            <td><span><u>重复1次或更多次，但尽可能少重复</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">??</font></span></td>
            <td><span><u>重复0次或1次，但尽可能少重复</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">{n,m}?</font></span></td>
            <td><span><u>重复n到m次，但尽可能少重复</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">{n,}?</font></span></td>
            <td><span><u>重复n次以上，但尽可能少重复</u></span></td>
        </tr>
    </tbody>
</table>
</div>
<h2>处理选项</h2>
<p>上面介绍了几个选项如忽略大小写，处理多行等，这些选项能用来改变处理正则表达式的方式。下面是.Net中常用的正则表达式选项：</p>
<div>
<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><font color="#0000ff">^</font></span>和<span><font color="#0000ff">$</font></span>的含义，使它们分别在任意一行的行首和行尾匹配，而不仅仅在整个字符串的开头和结尾匹配。(在此模式下,<span><font color="#0000ff">$</font></span>的精确含意是:匹配\n之前的位置以及字符串结束前的位置.)</td>
        </tr>
        <tr>
            <td>Singleline(单行模式)</td>
            <td>更改<span><font color="#0000ff">.</font></span>的含义，使它与每一个字符匹配（包括换行符\n）。</td>
        </tr>
        <tr>
            <td>IgnorePatternWhitespace(忽略空白)</td>
            <td>忽略表达式中的非转义空白并启用由<span><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>
</div>
<p>一个经常被问到的问题是：是不是只能同时使用多行模式和单行模式中的一种？答案是：不是。这两个选项之间没有任何关系，除了它们的名字比较相似（以至于让人感到疑惑）以外。</p>
<h2>平衡组/递归匹配</h2>
<p>注意：这里介绍的平衡组语法是由.Net Framework支持的；其它语言／库不一定支持这种功能，或者支持此功能但需要使用不同的语法。</p>
<p>有时我们需要匹配像<span><u>( 100 * ( 50 + 15 ) )这样的可嵌套的层次性结构</u></span>，这时简单地使用<span><font color="#0000ff">\(.+\)</font></span>则只会匹配到最左边的左括号和最右边的右括号之间的内容(这里我们讨论的是贪婪模式，懒惰模式也有下面的问题)。假如原来的字符串里的左括号和右括号出现的次数不相等，比如<span><em>( 5 / ( 3 + 2 ) ) )</em></span>，那我们的匹配结果里两者的个数也不会相等。有没有办法在这样的字符串里匹配到最长的，配对的括号之间的内容呢？</p>
<p>为了避免<span><font color="#0000ff">(</font></span>和<span><font color="#0000ff">\(</font></span>把你的大脑彻底搞糊涂，我们还是用尖括号代替圆括号吧。现在我们的问题变成了如何把<span><em>xx &lt;aa &lt;bbb&gt; &lt;bbb&gt; aa&gt; yy</em></span>这样的字符串里，最长的配对的尖括号内的内容捕获出来？</p>
<p>这里需要用到以下的语法构造：</p>
<ul>
    <li><span><font color="#0000ff">(?'group')</font></span> 把捕获的内容命名为group,并压入堆栈</li>
    <li><span><font color="#0000ff">(?'-group')</font></span> 从堆栈上弹出最后压入堆栈的名为group的捕获内容，如果堆栈本来为空，则本分组的匹配失败</li>
    <li><span><font color="#0000ff">(?(group)yes|no)</font></span> 如果堆栈上存在以名为group的捕获内容的话，继续匹配yes部分的表达式，否则继续匹配no部分</li>
    <li><span><font color="#0000ff">(?!)</font></span> 零宽负向先行断言，由于没有后缀表达式，试图匹配总是失败</li>
</ul>
<p>如果你不是一个程序员（或者你是一个对堆栈的概念不熟的程序员），你就这样理解上面的三种语法吧：第一个就是在黑板上写一个 &quot;group&quot;，第二个就是从黑板上擦掉一个&quot;group&quot;，第三个就是看黑板上写的还有没有&quot;group&quot;，如果有就继续匹配yes部分，否则就匹配 no部分。</p>
<p>我们需要做的是每碰到了左括号，就在黑板上写一个&quot;group&quot;，每碰到一个右括号，就擦掉一个，到了最后就看看黑板上还有没有－－如果有那就证明左括号比右括号多，那匹配就应该失败。</p>
<pre>
&lt;                         #最外层的左括号
    [^&lt;&gt;]*                #最外层的左括号后面的不是括号的内容
    (
        (
            (?'Open'&lt;)    #碰到了左括号，在黑板上写一个&quot;Open&quot;
            [^&lt;&gt;]*       #匹配左括号后面的不是括号的内容
        )+
        (
            (?'-Open'&gt;)   #碰到了右括号，擦掉一个&quot;Open&quot;
            [^&lt;&gt;]*        #匹配右括号后面不是括号的内容
        )+
    )*
    (?(Open)(?!))         #在遇到最外层的右括号前面，判断黑板上还有没有没擦掉的&quot;Open&quot;；如果还有，则匹配失败
&gt;                         #最外层的右括号</pre>
<p>平衡组的一个最常见的应用就是匹配HTML,下面这个例子可以匹配<span><u>嵌套的&lt;div&gt;标签</u></span>：<span><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>还有些什么东西没提到</h2>
<p>我已经描述了构造正则表达式的大量元素，还有一些我没有提到的东西。下面是未提到的元素的列表，包含语法和简单的说明。你可以在网上找到更详细的参考资料来学习它们--当你需要用到它们的时候。如果你安装了MSDN Library,你也可以在里面找到关于.net下正则表达式详细的文档。</p>
<div>
<table cellspacing="0">
    <caption>表7.尚未详细讨论的语法</caption>
    <tbody>
        <tr>
            <td><span><font color="#0000ff">\a</font></span></td>
            <td><span><u>报警字符(打印它的效果是电脑嘀一声)</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\b</font></span></td>
            <td><span><u>通常是单词分界位置，但如果在字符类里使用代表退格</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\t</font></span></td>
            <td><span><u>制表符，Tab</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\r</font></span></td>
            <td><span><u>回车</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\v</font></span></td>
            <td><span><u>竖向制表符</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\f</font></span></td>
            <td><span><u>换页符</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\n</font></span></td>
            <td><span><u>换行符</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\e</font></span></td>
            <td><span><u>Escape</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\0nn</font></span></td>
            <td><span><u>ASCII代码中八进制代码为nn的字符</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\xnn</font></span></td>
            <td><span><u>ASCII代码中十六进制代码为nn的字符</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\unnnn</font></span></td>
            <td><span><u>Unicode代码中十六进制代码为nnnn的字符</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\cN</font></span></td>
            <td><span><u>ASCII控制字符。比如\cC代表Ctrl+C</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\A</font></span></td>
            <td><span><u>字符串开头(类似^，但不受处理多行选项的影响)</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\Z</font></span></td>
            <td><span><u>字符串结尾或行尾(不受处理多行选项的影响)</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\z</font></span></td>
            <td><span><u>字符串结尾(类似$，但不受处理多行选项的影响)</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\G</font></span></td>
            <td><span><u>当前搜索的开头</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">\p{name}</font></span></td>
            <td><span><u>Unicode中命名为name的字符类，例如\p{IsGreek}</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">(?&gt;exp)</font></span></td>
            <td><span><u>贪婪子表达式</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">(?&lt;x&gt;-&lt;y&gt;exp)</font></span></td>
            <td><span><u>平衡组</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">(?im-nsx:exp)</font></span></td>
            <td><span><u>在子表达式exp中改变处理选项</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">(?im-nsx)</font></span></td>
            <td><span><u>为表达式后面的部分改变处理选项</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">(?(exp)yes|no)</font></span></td>
            <td><span><u>把exp当作零宽正向先行断言，如果在这个位置能匹配，使用yes作为此组的表达式；否则使用no</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">(?(exp)yes)</font></span></td>
            <td><span><u>同上，只是使用空表达式作为no</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">(?(name)yes|no)</font></span></td>
            <td><span><u>如果命名为name的组捕获到了内容，使用yes作为表达式；否则使用no</u></span></td>
        </tr>
        <tr>
            <td><span><font color="#0000ff">(?(name)yes)</font></span></td>
            <td><span><u>同上，只是使用空表达式作为no</u></span></td>
        </tr>
    </tbody>
</table>
</div>
<h2>联系作者</h2>
<p>好吧,我承认,我骗了你,读到这里你肯定花了不止30分钟.相信我,这是我的错,而不是因为你太笨.我之所以说&quot;30分钟&quot;,是为了让你有信心,有耐心继续下去.既然你看到了这里,那证明我的阴谋成功了.上这种当的滋味还不错吧?</p>
<p>要投诉我,或者觉得我其实可以做得更好,或者有任何其它问题,欢迎来<a href="http://www.cnblogs.com/deerchao/archive/2006/08/24/zhengzhe30fengzhongjiaocheng.html"><u><font color="#0000ff">我的博客</font></u></a>进行讨论.</p>
<h2>一些我认为你可能已经知道的术语的参考</h2>
<dl><dt>字符 </dt><dd>程序处理文字时最基本的单位，可能是字母，数字，标点符号，空格，换行符，汉字等等。 </dd><dt>字符串 </dt><dd>0个或更多个字符的序列。 </dd><dt>文本 </dt><dd>文字，字符串。 </dd><dt>匹配 </dt><dd>符合规则，检验是否符合规则，符合规则的部分。 </dd><dt>断言 </dt><dd>声明一个应该为真的事实。只有当断言为真时才会对正则表达式继续进行匹配。 </dd></dl>
<h2>网上的资源及本文参考文献</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>
    <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>
    <li><a href="http://www.regular-expressions.info/"><u><font color="#0000ff">专业的正则表达式教学网站(英文)</font></u></a></li>
    <li><a href="http://weblogs.asp.net/whaggard/archive/2005/02/20/377025.aspx"><u><font color="#0000ff">关于.Net下的平衡组的详细讨论（英文）</font></u></a></li>
    <li><a href="http://www.oreilly.com/catalog/regex2/"><u><font color="#0000ff">Mastering Regular Expressions (Second Edition)</font></u></a></li>
    <li><a href="http://validator.w3.org/check?uri=referer"><u><font color="#0000ff">Validated XHTML 1.0 Strict</font></u></a></li>
    <li><a href="http://jigsaw.w3.org/css-validator/check/referer"><u><font color="#0000ff">Validated CSS 2.1</font></u></a></li>
    <li><a href="http://www.mozilla.com/"><u><font color="#0000ff">推荐使用Mozilla FireFox浏览</font></u></a></li>
</ul>
<h2>更新说明</h2>
<ol>
    <li>2006-3-27 第一版</li>
    <li>2006-10-12 第二版
    <ul>
        <li>修正了几个细节上的错误和不准确的地方</li>
        <li>增加了对处理中文时的一些说明</li>
        <li>更改了几个术语的翻译（采用了MSDN的翻译方式）</li>
        <li>增加了平衡组的介绍</li>
        <li>放弃了对The Regulator的介绍，改用Regex Tester</li>
    </ul>
    </li>
    <li>2007-3-12 V2.1
    <ul>
        <li>修正了几个小的错误</li>
        <li>增加了对处理选项(RegexOptions)的介绍</li>
    </ul>
    </li>
    <li>2007-5-28 V2.2
    <ul>
        <li>重新组织了对零宽断言的介绍</li>
        <li>删除了几个不太合适的示例，添加了几个实用的示例</li>
        <li>其它一些微小的更改</li>
    </ul>
    </li>
    <li>2007-8-3 V2.21
    <ul>
        <li>修改了几处文字错误</li>
        <li>修改/添加了对$,\b的精确说明</li>
        <li>承认了作者是个骗子</li>
        <li>给RegexTester添加了Singleline选项的相关功能</li>
    </ul>
    </li>
</ol>
<p>Reference webpage:</p>
<p><a href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm"><font color="#4563b9">http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm</font></a></p>
<p>&nbsp;</p>
<p><font color="#ff0000" size="7">一个例子:</font></p>
<p>Public Class ItemIP<br />
&nbsp;&nbsp;&nbsp; Private IPValue As String<br />
&nbsp;&nbsp;&nbsp; Public Property IPString() As String<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Get<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return IPValue<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End Get<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Set(ByVal value As String)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IPValue = value<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End Set<br />
&nbsp;&nbsp;&nbsp; End Property</p>
<p><br />
&nbsp;&nbsp;&nbsp; Public Sub GetFromString(ByVal s As String)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; With System.Text.RegularExpressions.Regex.Matches(s, &quot;\d+\.\d+\.\d+\.\d+&quot;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If .Count = 1 Then<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IPString = .Item(0).Groups(0).Value<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End If<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End With<br />
&nbsp;&nbsp;&nbsp; End Sub<br />
End Class</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim mystring As String<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mystring = LoadFile(&quot;C:\Local Data\IPAddress.txt&quot;)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim ipstring As New ItemIP<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ipstring.GetFromString(mystring)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TextBox5.Text = ipstring.IPString<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'myIPaddress = ipstring.IPString</p>
<p>&nbsp;&nbsp;&nbsp; End Sub</p>]]></description>
		</item>
		
			<item>
			<link>http://www.ufolbb.com/article.asp?id=261</link>
			<title><![CDATA[sysu公选课刷课程序[1.25更新]]]></title>
			<author>admin@ufolbb.com(ufolbb)</author>
			<category><![CDATA[PROGRAM/WEB Design]]></category>
			<pubDate>Sun,18 Jan 2009 20:34:53 +0800</pubDate>
			<guid>http://www.ufolbb.com/default.asp?id=261</guid>
		<description><![CDATA[<span style="color:Orange">如果无法运行，请安装 Microsoft .NET Framework 3.5 SP1 正式版<br/>下载地址:<a href="http://download.microsoft.com/download/0/6/1/061F001C-8752-4600-A198-53214C69B51F/dotnetfx35setup.exe" target="_blank" rel="external">http://download.microsoft.com/download/0/6/1/061F001C-8752-4600-A198-53214C69B51F/dotnetfx35setup.exe</a></span><br/><br/>注意事项：<br/><br/>1、请打开程序后填上自己的学号和密码，当刷课过程中cookies失效程序会自动帮你登录<br/><br/>2、在开始选课前，请确认自己至少有一个空位可以选课！已经选中了两门课的，将无法刷课。请至少退出一门后再刷<br/><br/>3、最多可以同时选3门课来刷，当其中一门选中后，程序将自动停止刷课！选择的课程多于1门时，所有课程的优先级是一样的,开始刷课前请确认所选择的课程都是你想上的,以免不想上的课程被选中影响刷课效果！<br/><br/>4、选课期间尽量不要用浏览器登录“普通本科教务系统”！如需登录,请先停止刷课再登录，以免出现未知错误！<br/><br/><img src="http://www.ufolbb.com/download.asp?id=201" border="0" alt=""/><br/><br/><br/><span style="color:Red">2009/1/25更新<br/><br/>1.增加自动保存上次选课的信息<br/><br/>2.可以选择开机自动启动<br/><br/>3.修复部分Bug</span><br/><br/>下载地址：(如果需要的，请加我QQ:7820235向我要密码！)<br/><a href="http://www.ufolbb.com/article.asp?id=262" target="_blank" rel="external">http://www.ufolbb.com/article.asp?id=262</a>]]></description>
		</item>
		
			<item>
			<link>http://www.ufolbb.com/article.asp?id=253</link>
			<title><![CDATA[vb源码--考勤管理系统]]></title>
			<author>admin@ufolbb.com(ufolbb)</author>
			<category><![CDATA[PROGRAM/WEB Design]]></category>
			<pubDate>Sun,14 Dec 2008 21:55:29 +0800</pubDate>
			<guid>http://www.ufolbb.com/default.asp?id=253</guid>
		<description><![CDATA[上公选课“数据库原理与应用”的期末作业--考勤管理系统<br/><br/>超级管理员账号:admin<br/>密码:admin888<br/>-----------------------------------------------------------------------<br/>普通管理员账号:liaobinbin<br/>密码:123456<br/><br/><img src="http://www.ufolbb.com/images/download.gif" alt="下载文件" style="margin:0px 2px -4px 0px"/> <a href="http://www.ufolbb.com/wbc_showimg.asp?file=attachments/month_0812/52008121421559.rar" target="_blank">考勤管理系统.rar</a><br/>]]></description>
		</item>
		
			<item>
			<link>http://www.ufolbb.com/article.asp?id=243</link>
			<title><![CDATA[CSS在IE与Firefox下不同的解析及解决方案]]></title>
			<author>admin@ufolbb.com(ufolbb)</author>
			<category><![CDATA[PROGRAM/WEB Design]]></category>
			<pubDate>Sat,25 Oct 2008 13:50:18 +0800</pubDate>
			<guid>http://www.ufolbb.com/default.asp?id=243</guid>
		<description><![CDATA[<strong>1、IE与Firefox下对Css解析的区别</strong><br/>对高度的解析<br/>IE：将根据内容的高度变化，包括未定义高度的图片内容，即使定义了高度，当内容超过高度时，将使用实际高度<br/>Firefox：没有定义高度时，如果内容中包括了图片内容，MF的高度解析是根据印刷标准，这样就会造成和实际内容高度不符合的情况；当定义了高度，但是内容超过高度时，内容会超出定义的高度，但是区域使用的样式不会变化，造成样式错位。<br/><br/>结论：大家在可以确定内容高度的情况下最好定义高度，如果真的没有办法定义高度，最好不用使用边框样式，否则样式肯定会出现混乱！<br/><br/>img对象alt和title的解析<br/>alt：当照片不存在或者load错误时的提示；<br/>title：照片的tip说明。<br/>在IE中如果没有定义title，alt也可以作为img的tip使用，但是在MF中，两者完全按照标准中的定义使用<br/><br/>结论：大家在定义img对象时，最后将alt和title对象都写全，保证在各种浏览器中都能正常使用<br/><br/>其他的细节差别<br/>当你在写css的时候，特别是用float: left（或right）排列一窜图片时，会发现在firefox里面正常而IE里面有问题。无论你用margin:0,还是border: 0来约束，都无济于事。<br/><br/>其实这里还有另外一个问题，就是IE对于空格的处理，firefox是忽略的而IE对于块与块之间的空格是处理的。也就是说一个div结束后要紧接着一个div写，中间不要有回车或者空格。不然也许会有问题，比如3px的偏差，而且这个原因很难发现。<br/><br/>非常不走运的是我又碰到了这样的问题，多个img标签连着，然后定义的float: left，希望这些图片可以连起来。但是结果在firefox里面正常而IE里面显示的每个img都相隔了3px。我把标签之间的空格都删除都没有作用。<br/><br/>后来的解决方法是在img外面套li，并且对li定义margin: 0，这样就解决了IE和firefox的显示偏差。IE对于一些模型的解释会产生很多错误问题，只有多多尝试才能发现原因。<br/><br/><strong>2、嵌套DIV:父DIV的高度不能根据子DIV自动变化的解决方案</strong><br/><br/>&lt;div id=&#34;parent&#34;&gt;<br/>&lt;div id=&#34;content&#34;&gt; &lt;/div&gt;<br/>&lt;/div&gt;<br/><br/><br/>当Content内容多时，即使parent设置了高度100%或auto,在不同浏览器下还是不能完好的自动伸展。 解决方案<br/><br/><br/>&lt;div id=&#34;parent&#34;&gt;<br/>&lt;div id=&#34;content&#34;&gt;&lt;/div&gt;<br/>&lt;div style=&#34;font: 0px/0px sans-serif;clear: both;display: block&#34;&gt; &lt;/div&gt;<br/>&lt;/div&gt;<br/><br/><br/>在层的最下方产生一个高度为1的空格，可解除这个问题<br/><br/><strong>3、CSS DIV</strong><br/>一、基本上每个区块的div 都要有自己的id，杜绝不同功能的区块用同一个id/class<br/><br/>二、每个稍大的区块div 后面都跟一个&lt;!-- /id --&gt;标记开始、结束<br/><br/>三、隐藏文字的又一种方法 TEXT-INDENT: -9999px; LINE-HEIGHT: 0<br/><br/>1)<br/>右列为P, width=44.5%, float=left<br/>左列为P.first, border-right: #a7a7a7 1px solid, width=45%<br/>2)<br/>右列#right, margin-left:50%<br/>左列#left, float=left,width=50% border-right:#a7a7a7 1px solid<br/><br/>以上两种方法关键点在于选择其中一个为float=left<br/><br/>五、随机的切换图片：<br/><br/>#random {<br/>BACKGROUND: url(/rotate.ASP);/*这个ASP文件自己写吧，不难*/<br/>}<br/><br/><br/><br/><strong>4、关于div的高度自适应</strong><br/>　　今天小尿让我帮他的页子解决一个问题，就是div的高度自适应，也就是在一个父级div中嵌套一左一右两个子div，右边的子div内容可无限扩展，而可以使得父级div的高度能被无限拉长，用一般的布局方法，在IE中可以正确浏览，在Mozilla中父级div的高度就固定在10px左右，无法自适应高度，height:auto也不行，怎么办呢。网上参考到一篇资料，要实现自适应高度，div层必须具有float属性，于是我开始动手试验，float:left的话，div就跑到页面最左边去了，这好办，我在它的外面再套一层div，把位置定好，那么里面的就算float:left也不会被移动位置了。<br/><br/><br/>xHtml:<br/><br/>&lt;div id=&#34;container_father&#34;&gt;<br/>&nbsp;&nbsp;&lt;div id=&#34;container&#34;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;div id=&#34;panel&#34;&gt; test&lt;br /&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp; test&lt;br /&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp; test&lt;br /&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- id=&#34;panel&#34; --&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;div id=&#34;sidebar&#34;&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp; &lt;ul&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;li class=&#34;current&#34;&gt;预安装检查&lt;/li&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;li&gt;阅读 PFC 授权协议&lt;/li&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;li&gt;初始化数据库&lt;/li&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;li&gt;完成安装&lt;/li&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/ul&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- id=&#34;sidebar&#34; --&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- id=&#34;container&#34; --&gt;<br/>&nbsp;&nbsp;&lt;/div&gt;<br/>&lt;/div&gt;<br/><br/><br/>CSS<br/><br/>#container_father {<br/>margin-left: auto;<br/>margin-right: auto;<br/>padding: 0px;<br/>width: 750px;<br/>}<br/><br/>#container {<br/>&nbsp;&nbsp; width: 750px;<br/>&nbsp;&nbsp; border: 1px solid #cccccc;<br/>&nbsp;&nbsp; padding: 8px;<br/>&nbsp;&nbsp; margin: 0px;<br/>&nbsp;&nbsp; background-color: #F1F3F5;<br/>&nbsp;&nbsp; float: left;<br/>}<br/><br/><br/><br/><strong>5、深入标准&nbsp;&nbsp;~&nbsp;&nbsp;The IE Doubled Float-Margin Bug(IE双倍浮动边界Bug)什么发生故障？</strong><br/><br/>一段无错的代码把一个居左浮动(float:left)的元素放置进一个容器盒(box)，并在浮动元素上使用了左边界(margin-left)来令它和容器的左边产生一段距离。看起来相当的简单，对吗？但直至它被在IE/Win中浏览为止，在浏览器中居左浮动元素的边界长度被神秘地翻了一倍！<br/><br/>情况应该如何？<br/><br/>下面的图释展示了一个简单的div(茶色的盒子)包含着一个居左浮动的div(绿色的盒子)。浮动元素有一个100px的左边界，使容器盒与它的左边缘之间产生了一个100px的间隙。到现在为止，一直都还不错。<br/><br/><br/>.floatbox {<br/>float: left;<br/>width: 150px;<br/>height: 150px;<br/>margin: 5px 0 5px 100px;<br/>/*This last value applies the 100px left margin */<br/>}<br/><br/><br/>陈旧的IE“双倍占据”<br/><br/>原样的相同代码被在IE/Win中浏览时以些微不同的方式显示，下面的图释展示了IE/Win在布局上所做的。<br/><br/>这为什么会发生？别问这种傻问题！这就是IE，记得吗？符合标准只是理想的状况，不指望实现，这个简单的事实正验证了。<br/><br/>重点<br/><br/>这个Bug仅当浮动边界和浮动元素的方向相同时出现在浮动元素和容器盒的内边缘之间，在这之后的任意有着相似边界的浮动元素不会呈现双倍边界。只有特定的浮动行的第一个浮动元素会遭遇这个Bug。像居左的情况一样，双倍边界同样神秘地显示在居右的相同方式。<br/><br/>最后，修复办法！<br/><br/>直到现在(04年1月)这个Bug一直被认为是无法修复的，通常用来替代错误的边界的控制方法如：一个不可视浮动元素的左边距，连同一个内嵌的盒子一起，可视的盒子装在不可视浮动元素里；或者使用技巧仅对IE/Win设定边界的1/2值。这办法生效了，但是是混乱的而且搞糟了干净的源代码。不过现在全部结束了。<br/><br/>Steve Clason发现了一个修复办法，描述在他的Guest Demo里，修复了双倍边界和围绕文字缩进Bug。这是一个经典的IE的Bug修复办法，使用一个属性来修复影响不相关属性的Bug。<br/><br/>现在如何来做？<br/><br/>研究它，简单地将{display: inline;}设置给浮动元素就是全部所需做的！是的，听起来太简单了，不是吗？不过这是真的，仅仅一个display的&#34;inline&#34;声明已经能够胜任了。<br/><br/>熟悉规则的人知道浮动元素自动设置为&#34;block&#34;元素，而不管他们之前是什么。就如Steve从W3C里指出：<br/><br/>9.5.1 Positioning the float: the &#39;float&#39; property<br/><br/>&#34;This property specifies whether a box should float to the left, right, o&#114; not at all. It may be set for elements that generate boxes that are not absolutely positioned. The values of this property have the following meanings:<br/><br/>left<br/>The element generates a block box that is floated to the left. Content flows on the right side of the box, starting at the top (subject to the &#39;clear&#39; property). The &#39;display&#39; is ignored, unless it has the value &#39;none&#39;.<br/><br/>right<br/>Same as &#39;left&#39;, but content flows on the left side of the box, starting at the top.<br/><br/>none<br/>The box is not floated. &#34;<br/><br/>这说明浮动元素上的{display: inline;}会被忽略，事实上所有的浏览器没有呈现任何改变，包括IE。但是，它不知何故让IE停止将浮动元素的边界翻倍。因而，这个修复办法可以被直接应用，而没有任何繁琐的隐藏方法。如果将来的一款浏览器决定对这个修复办法抱恙，只要把这个修复装入IE独用的Tan Hack里，细节如同IE Three Pixel Text-Jog Demo。<br/><br/>下面是两个使用了前面相同代码的生动演示，第一个照常显示了IE的Bug，下一个对浮动元素使用了&#34;inline&#34;修复。<br/><br/>.floatbox {<br/>float: left;<br/>width: 150px;<br/>height: 150px;<br/>margin: 5px 0 5px 100px;<br/>display: inline;}]]></description>
		</item>
		
			<item>
			<link>http://www.ufolbb.com/article.asp?id=231</link>
			<title><![CDATA[C++BUILDER的文件操作]]></title>
			<author>admin@ufolbb.com(ufolbb)</author>
			<category><![CDATA[PROGRAM/WEB Design]]></category>
			<pubDate>Sat,30 Aug 2008 10:36:27 +0800</pubDate>
			<guid>http://www.ufolbb.com/default.asp?id=231</guid>
		<description><![CDATA[　　在ANSI C中，对文件的操作分为两种方式，即流式文件操作和I/O文件操作，下面就分别介绍之。<br/><br/>一、流式文件操作<br/>　　这种方式的文件操作有一个重要的结构FILE，FILE在stdio.h中定义如下：<br/><br/>typedef struct {<br/>int level; /* fill/empty level of buffer */<br/>unsigned flags; /* File status flags */<br/>char fd; /* File descriptor */<br/>unsigned char hold; /* Ungetc char if no buffer */<br/>int bsize; /* Buffer size */<br/>unsigned char _FAR *buffer; /* Data transfer buffer */<br/>unsigned char _FAR *curp; /* Current active pointer */<br/>unsigned istemp; /* Temporary file indicator */<br/>short token; /* Used for validity checking */<br/>} FILE; /* This is the FILE object */<br/><br/>　　FILE这个结构包含了文件操作的基本属性，对文件的操作都要通过这个结构的指针来进行，此种文件操作常用的函数见下表 函数 功能 <br/>fopen() 打开流 <br/>fclose() 关闭流 <br/>fputc() 写一个字符到流中 <br/>fgetc() 从流中读一个字符 <br/>fseek() 在流中定位到指定的字符 <br/>fputs() 写字符串到流 <br/>fgets() 从流中读一行或指定个字符 <br/>fprintf() 按格式输出到流 <br/>fscanf() 从流中按格式读取 <br/>feof() 到达文件尾时返回真值 <br/>ferror() 发生错误时返回其值 <br/>rewind() 复位文件定位器到文件开始处 <br/>remove() 删除文件 <br/>fread() 从流中读指定个数的字符 <br/>fwrite() 向流中写指定个数的字符 <br/>tmpfile() 生成一个临时文件流 <br/>tmpnam() 生成一个唯一的文件名 <br/><br/><br/>　　下面就介绍一下这些函数<br/><br/>1.fopen()<br/>　　fopen的原型是：FILE *fopen(const char *filename,const char *mode)，fopen实现三个功能<br/><br/>为使用而打开一个流 <br/>把一个文件和此流相连接 <br/>给此流返回一个FILR指针<br/>参数filename指向要打开的文件名，mode表示打开状态的字符串，其取值如下表<br/><br/>字符串 含义 <br/>&#34;r&#34; 以只读方式打开文件 <br/>&#34;w&#34; 以只写方式打开文件 <br/>&#34;a&#34; 以追加方式打开文件 <br/>&#34;r+&#34; 以读/写方式打开文件，如无文件出错 <br/>&#34;w+&#34; 以读/写方式打开文件，如无文件生成新文件 <br/><br/>　　一个文件可以以文本模式或二进制模式打开，这两种的区别是：在文本模式中回车被当成一个字符&#39;\n&#39;，而二进制模式认为它是两个字符0x0D,0x0A；如果在文件中读到0x1B，文本模式会认为这是文件结束符，也就是二进制模型不会对文件进行处理，而文本方式会按一定的方式对数据作相应的转换。<br/><br/>　　系统默认的是以文本模式打开，可以修改全部变量_fmode的值来修改这个设置，例如_fmode=O_TEXT；就设置默认打开方式为文本模式；而_fmode=O_BINARY；则设置默认打开方式是二进制模式。<br/><br/>　　我们也可以在模式字符串中指定打开的模式，如&#34;rb&#34;表示以二进制模式打开只读文件，&#34;w+t&#34;或&#34;wt+&#34;表示以文本模式打开读/写文件。<br/><br/>　　此函数返回一个FILE指针，所以申明一个FILE指针后不用初始化，而是用fopen()来返回一个指针并与一个特定的文件相连，如果成败，返回NULL。<br/><br/>例:<br/><br/>　　FILE *fp; <br/>　　if(fp=fopen(&#34;123.456&#34;,&#34;wb&#34;))<br/>　　　　puts(&#34;打开文件成功&#34;);<br/>　　else <br/>　　　　puts(&#34;打开文件成败&#34;); <br/><br/>2.fclose() <br/>　　fclose()的功能就是关闭用fopen()打开的文件，其原型是：int fclose(FILE *fp);如果成功，返回0,失败返回EOF。<br/><br/>　　在程序结束时一定要记得关闭打开的文件，不然可能会造成数据丢失的情况，我以前就经常犯这样的毛病。<br/><br/>例：fclose(fp);<br/><br/>3.fputc()<br/>　　向流写一个字符，原型是int fputc(int c, FILE *stream); 成功返回这个字符,失败返回EOF。<br/><br/>例：fputc(&#39;X&#39;,fp);<br/><br/>4.fgetc()<br/>　　从流中读一个字符，原型是int fputc(FILE *stream); 成功返回这个字符,失败返回EOF。<br/><br/>例：char ch1=fgetc(fp);<br/><br/>5. fseek()<br/>　　此函数一般用于二进制模式打开的文件中，功能是定位到流中指定的位置，原型是int fseek(FILE *stream, long offset, int whence);如果成功返回0，参数offset是移动的字符数，whence是移动的基准，取值是<br/><br/>符号常量 值 基准位置 <br/>SEEK_SET 0 文件开头 <br/>SEEK_CUR 1 当前读写的位置 <br/>SEEK_END 2 文件尾部 <br/><br/>例：fseek(fp,1234L,SEEK_CUR);//把读写位置从当前位置向后移动1234字节(L后缀表示长整数)<br/><br/>　　fseek(fp,0L,2);//把读写位置移动到文件尾<br/><br/>6.fputs()<br/>　　写一个字符串到流中，原型int fputs(const char *s, FILE *stream); <br/><br/>例：fputs(&#34;I Love You&#34;,fp);<br/><br/>7.fgets()<br/>　　从流中读一行或指定个字符，原型是char *fgets(char *s, int n, FILE *stream); 从流中读取n-1个字符，除非读完一行，参数s是来接收字符串，如果成功则返回s的指针，否则返回NULL。<br/><br/>例：如果一个文件的当前位置的文本如下<br/><br/>Love ,I Have<br/><br/>But ……..<br/><br/>如果用<br/><br/>　　fgets(str1,4,file1);<br/><br/>则执行后str1=&#34;Lov&#34;，读取了4-1=3个字符，而如果用<br/><br/>　　fgets(str1,23,file1);<br/><br/>则执行str=&#34;Love ,I Have&#34;，读取了一行(不包括行尾的&#39;\n&#39;)。<br/><br/>8.fprintf()<br/>　　按格式输入到流，其原型是int fprintf(FILE *stream, const char *format[, argument, …]);其用法和printf()相同，不过不是写到控制台，而是写到流罢了<br/><br/>例：fprintf(fp,&#34;%2d%s&#34;,4,&#34;Hahaha&#34;);<br/><br/>9.fscanf()<br/>　　从流中按格式读取，其原型是int fscanf(FILE *stream, const char *format[, address, …]);其用法和scanf()相同，不过不是从控制台读取，而是从流读取罢了。<br/><br/>例：fscanf(fp,&#34;%d%d&#34; ,&amp;x,&amp;y);<br/><br/>10.feof()<br/>　　检测是否已到文件尾，是返回真，否则返回0，其原型是int feof(FILE *stream);<br/><br/>例：if(feof(fp))printf(&#34;已到文件尾&#34;);<br/><br/>11.ferror()<br/>　　原型是int ferror(FILE *stream);返回流最近的错误代码，可用clearerr()来清除它，clearerr()的原型是void clearerr(FILE *stream);<br/><br/>例：printf(&#34;%d&#34;,ferror(fp));<br/><br/>12.rewind()<br/>　　把当前的读写位置回到文件开始，原型是void rewind(FILE *stream);其实本函数相当于fseek(fp,0L,SEEK_SET);<br/><br/>例：rewind(fp);<br/><br/>12.remove()<br/>　　删除文件，原型是int remove(const char *filename); 参数就是要删除的文件名，成功返回0。<br/><br/>例：remove(&#34;c:\\io.sys&#34;);<br/><br/>13.fread()<br/>　　从流中读指定个数的字符，原型是size_t fread(void *ptr, size_t size, size_t n, FILE *stream);参数ptr是保存读取的数据，void*的指针可用任何类型的指针来替换，如char*、int *等等来替换；size是每块的字节数；n是读取的块数，如果成功，返回实际读取的块数(不是字节数)，本函数一般用于二进制模式打开的文件中。<br/><br/>例：<br/><br/>　　char x[4230];<br/>　　FILE *file1=fopen(&#34;c:\\msdos.sys&#34;,&#34;r&#34;);<br/>　　fread(x,200,12 ,file1);//共读取200*12=2400个字节<br/><br/>14.fwrite()<br/>　　与fread对应，向流中写指定的数据，原型是size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream);参数ptr是要写入的数据指针，void*的指针可用任何类型的指针来替换，如char*、int *等等来替换；size是每块的字节数；n是要写的块数，如果成功，返回实际写入的块数(不是字节数)，本函数一般用于二进制模式打开的文件中。<br/><br/>例：<br/><br/>　　char x[]=&#34;I Love You&#34;;<br/>　　fwire(x, 6,12,fp);//写入6*12=72字节<br/><br/>　　将把&#34;I Love&#34;写到流fp中12次，共72字节<br/><br/>15.tmpfile()<br/>　　其原型是FILE *tmpfile(void); 生成一个临时文件，以&#34;w+b&#34;的模式打开，并返回这个临时流的指针，如果失败返回NULL。在程序结束时，这个文件会被自动删除。<br/><br/>例：FILE *fp=tmpfile();<br/><br/>16.tmpnam();<br/>　　其原型为char *tmpnam(char *s); 生成一个唯一的文件名，其实tmpfile()就调用了此函数，参数s用来保存得到的文件名，并返回这个指针，如果失败，返回NULL。<br/><br/>例：tmpnam(str1);<br/><br/><br/>二、直接I/O文件操作<br/>　　这是C提供的另一种文件操作，它是通过直接存/取文件来完成对文件的处理，而上篇所说流式文件操作是通过缓冲区来进行；流式文件操作是围绕一个FILE指针来进行，而此类文件操作是围绕一个文件的“句柄”来进行，什么是句柄呢？它是一个整数，是系统用来标识一个文件(在WINDOWS中，句柄的概念扩展到所有设备资源的标识)的唯一的记号。此类文件操作常用的函数如下表，这些函数及其所用的一些符号在io.h和fcntl.h中定义，在使用时要加入相应的头文件。<br/><br/>函数 说明 <br/>open() 打开一个文件并返回它的句柄 <br/>close() 关闭一个句柄 <br/>lseek() 定位到文件的指定位置 <br/>read() 块读文件 <br/>write() 块写文件 <br/>eof() 测试文件是否结束 <br/>filelength() 取得文件长度 <br/>rename() 重命名文件 <br/>chsize() 改变文件长度 <br/><br/>　　下面就对这些函数一一说明：<br/><br/>1.open()<br/>　　打开一个文件并返回它的句柄，如果失败，将返回一个小于0的值，原型是int open(const char *path, int access [, unsigned mode]); 参数path是要打开的文件名，access是打开的模式，mode是可选项。表示文件的属性，主要用于UNIX系统中，在DOS/WINDOWS这个参数没有意义。其中文件的打开模式如下表。<br/><br/>符号 含义 符号 含义 符号 含义 <br/>O_RDONLY 只读方式 O_WRONLY 只写方式 O_RDWR 读/写方式 <br/>O_NDELAY 用于UNIX系统 O_APPEND 追加方式 O_CREAT 如果文件不存在就创建 <br/>O_TRUNC 把文件长度截为0 O_EXCL 和O_CREAT连用，如果文件存在返回错误 O_BINARY 二进制方式 <br/>O_TEXT 文本方式 <br/><br/>　　对于多个要求，可以用&#34;|&#34;运算符来连接，如O_APPEND|O_TEXT表示以文本模式和追加方式打开文件。<br/><br/>例：int handle=open(&#34;c:\\msdos.sys&#34;,O_BINARY|O_CREAT|O_WRITE)<br/><br/>2.close()<br/>　　关闭一个句柄，原型是int close(int handle);如果成功返回0<br/><br/>例：close(handle)<br/><br/>3.lseek()<br/>　　定位到指定的位置，原型是：long lseek(int handle, long offset, int fromwh&#101;re);参数offset是移动的量，fromwh&#101;re是移动的基准位置，取值和前面讲的fseek()一样，SEEK_SET：文件首部；SEEK_CUR：文件当前位置；SEEK_END：文件尾。此函数返回执行后文件新的存取位置。<br/><br/>例：<br/><br/>　　lseek(handle,-1234L,SEEK_CUR);//把存取位置从当前位置向前移动1234个字节。<br/>　　x=lseek(hnd1,0L,SEEK_END);//把存取位置移动到文件尾，x=文件尾的位置即文件长度<br/><br/>4.read()<br/>　　从文件读取一块，原型是int read(int handle, void *buf, unsigned len);参数buf保存读出的数据，len是读取的字节。函数返回实际读出的字节。<br/><br/>例：char x[200];read(hnd1,x,200);<br/><br/>5.write()<br/>　　写一块数据到文件中，原型是int write(int handle, void *buf, unsigned len);参数的含义同read()，返回实际写入的字节。<br/><br/>例：char x[]=&#34;I Love You&#34;;write(handle,x,strlen(x));<br/><br/>7.eof()<br/>　　类似feof()，测试文件是否结束，是返回1，否则返回0;原型是：int eof(int handle);<br/><br/>例：while(!eof(handle1)){……};<br/><br/>8.filelength()<br/>　　返回文件长度，原型是long filelength(int handle);相当于lseek(handle,0L,SEEK_END)<br/><br/>例：long x=filelength(handle);<br/><br/>9.rename()<br/>　　重命名文件，原型是int rename(const char *oldname, const char *newname); 参数oldname是旧文件名，newname是新文件名。成功返回0<br/><br/>例：rename(&#34;c:\\config.sys&#34;,&#34;c:\\config.w40&#34;);<br/><br/>10.chsize();<br/>　　改变文件长度，原型是int chsize(int handle, long size);参数size表示文件新的长度，成功返回0，否则返回-1，如果指定的长度小于文件长度，则文件被截短；如果指定的长度大于文件长度，则在文件后面补&#39;\0&#39;。<br/><br/>例：chsize(handle,0x12345);<br/><br/><br/>--------------------------------------------------------------------------------<br/><br/>　　如果熟悉汇编可能会发现这种方式和汇编语言的DOS功能调用句柄式文件操作很像，比如open()就像DOS服务的3CH号功能调用，其实这种操作还有两种类型的函数就是直接用DOS功能来完成的，如_open()，_dos_open()等等。有兴趣可自已查询BCB的帮助。<br/><br/>　　同流式文件操作相同，这种也提供了Unicode字符操作的函数，如_wopen()等等，用于9X/NT下的宽字符编程，有兴趣可自已查询BCB的帮助。<br/><br/>　　另外，此种操作还有lock(),unlock(),locking()等用于多用户操作的函数，但在BCB中用得并不多，我就不介绍了，但如果要用C来写CGI，这些就必要的常识了，如果你有这方面的要求，那就得自已好好看帮助了。 <br/><br/>　 <br/><br/>　　在C++中，有一个stream这个类，所有的I/O都以这个“流”类为基础的，包括我们要认识的文件I/O，stream这个类有两个重要的运算符：<br/><br/>1、插入器(&lt;&lt;)<br/>　　向流输出数据。比如说系统有一个默认的标准输出流(cout)，一般情况下就是指的显示器，所以，cout&lt;&lt;&#34;Write Stdout&#34;&lt;&lt;&#39;\n&#39;;就表示把字符串&#34;Write Stdout&#34;和换行字符(&#39;\n&#39;)输出到标准输出流。<br/><br/>2、析取器(&gt;&gt;)<br/>　　从流中输入数据。比如说系统有一个默认的标准输入流(cin)，一般情况下就是指的键盘，所以，cin&gt;&gt;x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。<br/><br/>　　在C++中，对文件的操作是通过stream的子类fstream(file stream)来实现的，所以，要用这种方式操作文件，就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。<br/><br/>一、打开文件<br/>　　在fstream类中，有一个成员函数open()，就是用来打开文件的，其原型是：<br/><br/>void open(const char* filename,int mode,int access);<br/><br/>参数：<br/><br/>filename：　　要打开的文件名 <br/>mode：　　　　要打开文件的方式 <br/>access：　　　打开文件的属性<br/>打开文件的方式在类ios(是所有流式I/O类的基类)中定义，常用的值如下： <br/><br/>ios::app：　　　以追加的方式打开文件 <br/>ios::ate：　　　文件打开后定位到文件尾，ios:app就包含有此属性 <br/>ios::binary： 　以二进制方式打开文件，缺省的方式是文本方式。两种方式的区别见前文 <br/>ios::in：　　　 文件以输入方式打开 <br/>ios::out：　　　文件以输出方式打开 <br/>ios::nocr&#101;ate： 不建立文件，所以文件不存在时打开失败　 <br/>ios::noreplace：不覆盖文件，所以打开文件时如果文件存在失败 <br/>ios::trunc：　　如果文件存在，把文件长度设为0 <br/>　　可以用“或”把以上属性连接起来，如ios::out|ios::binary<br/><br/>　　打开文件的属性取值是：<br/><br/>0：普通文件，打开访问 <br/>1：只读文件 <br/>2：隐含文件 <br/>4：系统文件 <br/>　　可以用“或”或者“+”把以上属性连接起来 ，如3或1|2就是以只读和隐含属性打开文件。<br/><br/>　　例如：以二进制输入方式打开文件c:\config.sys <br/><br/>　　fstream file1;<br/>　　file1.open(&#34;c:\\config.sys&#34;,ios::binary|ios::in,0);<br/><br/>　　如果open函数只有文件名一个参数，则是以读/写普通文件打开，即：<br/><br/>　　file1.open(&#34;c:\\config.sys&#34;);&lt;=&gt;file1.open(&#34;c:\\config.sys&#34;,ios::in|ios::out,0);<br/><br/>　　另外，fstream还有和open()一样的构造函数，对于上例，在定义的时侯就可以打开文件了：<br/><br/>　　fstream file1(&#34;c:\\config.sys&#34;);<br/><br/>　　特别提出的是，fstream有两个子类：ifstream(input file stream)和ofstream(outpu file stream)，ifstream默认以输入方式打开文件，而ofstream默认以输出方式打开文件。<br/><br/>　　ifstream file2(&#34;c:\\pdos.def&#34;);//以输入方式打开文件<br/>　　ofstream file3(&#34;c:\\x.123&#34;);//以输出方式打开文件<br/><br/>　　所以，在实际应用中，根据需要的不同，选择不同的类来定义：如果想以输入方式打开，就用ifstream来定义；如果想以输出方式打开，就用ofstream来定义；如果想以输入/输出方式来打开，就用fstream来定义。<br/><br/>二、关闭文件<br/>　　打开的文件使用完成后一定要关闭，fstream提供了成员函数close()来完成此操作，如：file1.close();就把file1相连的文件关闭。<br/><br/>三、读写文件<br/>　　读写文件分为文本文件和二进制文件的读取，对于文本文件的读取比较简单，用插入器和析取器就可以了；而对于二进制的读取就要复杂些，下要就详细的介绍这两种方式<br/><br/>　　1、文本文件的读写<br/>　　文本文件的读写很简单：用插入器(&lt;&lt;)向文件输出；用析取器(&gt;&gt;)从文件输入。假设file1是以输入方式打开，file2以输出打开。示例如下：<br/><br/>　　file2&lt;&lt;&#34;I Love You&#34;;//向文件写入字符串&#34;I Love You&#34;<br/>　　int I;<br/>　　file1&gt;&gt;I;//从文件输入一个整数值。 <br/><br/>　　这种方式还有一种简单的格式化能力，比如可以指定输出为16进制等等，具体的格式有以下一些<br/><br/>操纵符 功能 输入/输出 <br/>dec 格式化为十进制数值数据 输入和输出 <br/>endl 输出一个换行符并刷新此流 输出 <br/>ends 输出一个空字符 输出 <br/>hex 格式化为十六进制数值数据 输入和输出 <br/>oct 格式化为八进制数值数据 输入和输出 <br/>setpxecision(int p) 设置浮点数的精度位数 输出 <br/><br/>　　比如要把123当作十六进制输出：file1&lt;&lt;hex&lt;&lt;123;要把3.1415926以5位精度输出：file1&lt;&lt;setpxecision(5)&lt;&lt;3.1415926。<br/><br/>　　2、二进制文件的读写<br/>①put()<br/>　　put()函数向流写入一个字符，其原型是ofstream &amp;put(char ch)，使用也比较简单，如file1.put(&#39;c&#39;);就是向流写一个字符&#39;c&#39;。 <br/><br/>②get()<br/>　　get()函数比较灵活，有3种常用的重载形式：<br/><br/>　　一种就是和put()对应的形式：ifstream &amp;get(char &amp;ch);功能是从流中读取一个字符，结果保存在引用ch中，如果到文件尾，返回空字符。如file2.get(x);表示从文件中读取一个字符，并把读取的字符保存在x中。<br/><br/>　　另一种重载形式的原型是： int get();这种形式是从流中返回一个字符，如果到达文件尾，返回EOF，如x=file2.get();和上例功能是一样的。<br/><br/>　　还有一种形式的原型是：ifstream &amp;get(char *buf,int num,char delim=&#39;\n&#39;)；这种形式把字符读入由 buf 指向的数组，直到读入了 num 个字符或遇到了由 delim 指定的字符，如果没使用 delim 这个参数，将使用缺省值换行符&#39;\n&#39;。例如：<br/><br/>　　file2.get(str1,127,&#39;A&#39;);//从文件中读取字符到字符串str1，当遇到字符&#39;A&#39;或读取了127个字符时终止。<br/><br/>③读写数据块<br/>　　要读写二进制数据块，使用成员函数read()和write()成员函数，它们原型如下：<br/><br/>　　　　read(unsigned char *buf,int num);<br/>　　　　write(const unsigned char *buf,int num);<br/><br/>　　read()从文件中读取 num 个字符到 buf 指向的缓存中，如果在还未读入 num 个字符时就到了文件尾，可以用成员函数 int gcount();来取得实际读取的字符数；而 write() 从buf 指向的缓存写 num 个字符到文件中，值得注意的是缓存的类型是 unsigned char *，有时可能需要类型转换。<br/><br/>例：<br/><br/>　　　　unsigned char str1[]=&#34;I Love You&#34;;<br/>　　　　int n[5];<br/>　　　　ifstream in(&#34;xxx.xxx&#34;);<br/>　　　　ofstream out(&#34;yyy.yyy&#34;);<br/>　　　　out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中<br/>　　　　in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数，注意类型转换<br/>　　　　in.close();out.close(); <br/><br/>四、检测EOF<br/>　　成员函数eof()用来检测是否到达文件尾，如果到达文件尾返回非0值，否则返回0。原型是int eof();<br/><br/>例：　　if(in.eof())ShowMessage(&#34;已经到达文件尾！&#34;);<br/><br/>五、文件定位<br/>　　和C的文件操作方式不同的是，C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针，它说明输入操作在文件中的位置；另一个是写指针，它下次写操作的位置。每次执行输入或输出时，相应的指针自动变化。所以，C++的文件定位分为读位置和写位置的定位，对应的成员函数是 seekg()和 seekp()，seekg()是设置读位置，seekp是设置写位置。它们最通用的形式如下：<br/><br/>　　　　istream &amp;seekg(streamoff offset,seek_dir o&#114;igin);<br/>　　　　ostream &amp;seekp(streamoff offset,seek_dir o&#114;igin); <br/><br/>　　streamoff定义于 iostream.h 中，定义有偏移量 offset 所能取得的最大值，seek_dir 表示移动的基准位置，是一个有以下值的枚举： <br/><br/>ios::beg：　　文件开头 <br/>ios::cur：　　文件当前位置 <br/>ios::end：　　文件结尾 <br/>　　这两个函数一般用于二进制文件，因为文本文件会因为系统对字符的解释而可能与预想的值不同。<br/><br/>例：<br/><br/>　　　　 file1.seekg(1234,ios::cur);//把文件的读指针从当前位置向后移1234个字节<br/>　　　　 file2.seekp(1234,ios::beg);//把文件的写指针从文件开头向后移1234个字节 <br/><br/><br/>--------------------------------------------------------------------------------<br/><br/>　　有了这些知识，我们就可以完成对文件的操作了，当然，还有好多的成员函数我没介绍，但有这些我们已经能完成大多数的需要了，这种文件操作方式是我比较喜欢的一种方法，比C的方法灵活，又比BCB函数和WINAPI函数具有通用性。<br/><br/>　　下一次，我将介绍BCB提供的文件操作的库函数。 <br/><br/>　 <br/><br/>　在BCB中也提供了文件操作的函数，这些函数的功能和前面所介绍的大致相同，但这类函数和BCB关系紧密，能使用BCB中的AnsiString等数据类型，在BCB中用这种方式的文件操作是最方便的，下面我就把这种文件操作详细介绍。<br/><br/>　　在BCB提供的这组文件操作函数中，可分为三种类型，就是：1、文件名函数，2、文件管理函数；3、文件I/O函数。<br/><br/>1、文件名函数<br/>　　文件名函数可以对文件的名称、所在子目录、驱动器和扩展名等进行操作。下表列出这些函数及其功能。<br/><br/>函数 说明 <br/>ExpandFileName() 返回文件的全路径(含驱动器、路径) <br/>ExtractFileExt() 从文件名中抽取扩展名 <br/>ExtractFileName() 从文件名中抽取不含路径的文件名 <br/>ExtractFilePath() 从文件名中抽取路径名 <br/>ExtractFileDir() 从文件名中抽取目录名 <br/>ExtractFileDrive() 从文件名中抽取驱动器名 <br/>ChangeFileExt() 改变文件的扩展名 <br/>ExpandUNCFileName() 返回含有网络驱动器的文件全路径 <br/>ExtractRelativePath() 从文件名中抽取相对路径信息 <br/>ExtractShortPathName() 把文件名转化为DOS的8·3格式 <br/>MatchesMask() 检查文件是否与指定的文件名格式匹配 <br/><br/>　　下面就把这些函数作一一介绍：<br/><br/>⑴ExpandFileName() <br/>　　原型：extern PACKAGE AnsiString __fastcall ExpandFileName(const AnsiString FileName);<br/><br/>　　功能：返回文件的全路径(含驱动器、路径)<br/><br/>　　参数：FileName:要处理的文件名<br/><br/>　　例：ShowMessage(ExpandFileName(Application-&gt;ExeName));//显示你的程序文件名，如C:\MyBCB\Sample1.EXE<br/><br/>⑵ExtractFileExt()<br/>　　原型：extern PACKAGE AnsiString __fastcall ExtractFileExt(const AnsiString FileName);<br/><br/>　　功能：从文件名中抽取扩展名<br/><br/>　　参数：FileName:要处理的文件名（全路径）<br/><br/>　　例：ShowMessage(ExtractFileExt(Application-&gt;ExeName));//显示&#34;.exe&#34;<br/><br/>⑶ExtractFileName()<br/>　　原型：extern PACKAGE AnsiString __fastcall ExtractFileName(const AnsiString FileName); <br/><br/>　　功能：从文件名中抽取不含路径的文件名<br/><br/>　　参数：FileName:要处理的文件名<br/><br/>　　例：ShowMessage(ExtractFileExt(&#34;c:\\Winnt\\SOL.EXE&#34;));//显示&#34;SOL.EXE&#34;<br/><br/>⑷ExtractFilePath()<br/>　　原型：extern PACKAGE AnsiString __fastcall ExtractFilePath(const AnsiString FileName); <br/><br/>　　功能：从文件名中抽取路径名<br/><br/>　　参数：FileName:要处理的文件名<br/><br/>　　例：ShowMessage(ExtractFilePath(&#34;Winnt\\SOL.EXE&#34;));//显示&#34;Winnt\&#34;<br/><br/>⑸ExtractFileDir()<br/>　　原型：extern PACKAGE AnsiString __fastcall ExtractFileDir(const AnsiString FileName); <br/><br/>　　功能：从文件名中抽取目录名(和上个函数不同，不包括最后的&#34;\&#34;)<br/><br/>　　参数：FileName:要处理的文件名<br/><br/>　　例：ShowMessage(ExtractFileDir(&#34;Winnt\\SOL.EXE&#34;));//显示&#34;Winnt&#34;,注意和上个函数的区别 <br/><br/>⑹ExtractFileDrive()<br/>　　原型：extern PACKAGE AnsiString __fastcall ExtractFileDrive(const AnsiString FileName); <br/><br/>　　功能：从文件名中抽取驱动器名<br/><br/>　　参数：FileName:要处理的文件名<br/><br/>　　例：ShowMessage(ExtractFileDrive(&#34;c:\\Winnt\\SOL.EXE&#34;));//显示&#34;c:&#34;<br/><br/>⑺ChangeFileExt()<br/>　　原型：extern PACKAGE System::AnsiString __fastcall ChangeFileExt(const System::AnsiString FileName, const System::AnsiString Extension); <br/><br/>　　功能：更改文件名的扩展名，不是对真正的文件进行改名，只是对文件名这个字符串进行处理<br/><br/>　　参数：FileName:要改名的文件名，Extension：新的扩展名<br/><br/>　　例：ShowMessage(ChangeFileExt(&#34;c:\\Winnt\\SOL.EXE&#34;,&#34;.OOO&#34;));//显示&#34;c:\winnt\SOL.OOO&#34;<br/><br/>⑻ExpandUNCFileName()<br/>　　原型：extern PACKAGE AnsiString __fastcall ExpandUNCFileName(const AnsiString FileName);<br/><br/>　　功能：返回含有网络驱动器的文件全路径，格式为：\\机器名\共享名\文件名<br/><br/>　　参数：FileName:要处理的文件名<br/><br/>　　例：ShowMessage(ExpandUNCFileName(&#34;F:\\Winnt\\SOL.EXE&#34;));/*如果F:是映射的网络驱动器\\NT40\WINNT，则显示&#34;\\NT40\WINNT\SOL.EXE&#34;*/<br/><br/>⑼ExtractRelativePath()<br/>　　原型：extern PACKAGE AnsiString __fastcall ExtractRelativePath(const AnsiString BaseName, const AnsiString DestName); <br/><br/>　　功能：从文件名中抽取相对路径信息，如&#34;..\sss\ss.asd&#34;这种形式<br/><br/>　　参数：BaseName：基准文件名；DestName：目标文件名<br/><br/>　　例：ShowMessage(ExtractRelativePath(&#34;D:\\Source\\c\\1.123&#34;,&#34;D:\\Source\\Asm\\dz.asm&#34;));/*显示&#34;..\asm\dz.asm&#34;*/<br/><br/>⑽ExtractShortPathName()<br/>　　原型：extern PACKAGE AnsiString __fastcall ExtractShortPathName(const AnsiString FileName); <br/><br/>　　功能：把文件名转换为DOS的8、3格式<br/><br/>　　参数：FileName:要处理的文件名<br/><br/>　　例：ShowMessage(ExtractShortPathName(&#34;E:\\Program Files\\Dual Wheel Mouse\\4dmain.exe&#34;));/*显示&#34;E:\Progra~1\dualwh~1\4dmain.exe&#34;*/<br/><br/>⑾MatchesMask()<br/>　　原型：extern PACKAGE bool __fastcall MatchesMask(const AnsiString Filename, const AnsiString Mask);<br/><br/>　　功能：检查文件是否与指定的文件名格式匹配<br/><br/>　　参数：FileName:要处理的文件名；Mask:文件名格式，支持通配符<br/><br/>　　例：ShowMessage(MatchesMask(&#34;Lxf.exe&#34;,&#34;*.?x?));//显示&#34;true&#34;<br/><br/><br/>--------------------------------------------------------------------------------<br/><br/>2、文件管理函数<br/>　　这类函数包括设置和读取驱动器、子目录和文件的有关的各种操作，下表列出这类操作常用的函数及其功能。<br/><br/>函数 功能 <br/>Cr&#101;ateDir() 创建新的子目录 <br/>Del&#101;teFile() 删除文件 <br/>DirectoryExists() 判断目录是否存在 <br/>DiskFree() 获取磁盘剩余空间 <br/>DiskSize() 获取磁盘容量 <br/>FileExists() 判断文件是否存在 <br/>FileGetAttr() 获取文件属性 <br/>FileGetDate() 获取文件日期 <br/>GetCurrentDir() 获取当前目录 <br/>RemoveDir() 删除目录 <br/>SetCurrentDir() 设置当前目录 <br/><br/>　　下面就把这些函数作一一介绍：<br/><br/>⑴Cr&#101;ateDir()<br/>　　原型：extern PACKAGE bool __fastcall Cr&#101;ateDir(const System::AnsiString Dir);<br/><br/>　　功能：建立子目录，如果成功返回true，否则返回false<br/><br/>　　参数：Dir:要建立的子目录的名字<br/><br/>　　例：Cr&#101;ate(&#34;ASM&#34;);//在当前目录下建立一个名为ASM的子目录<br/><br/>⑵Del&#101;teFile()<br/>　　原型：extern PACKAGE bool __fastcall Del&#101;teFile(const System::AnsiString FileName);<br/><br/>　　功能：删除文件，如果成功返回true，否则返回false<br/><br/>　　参数：FileName:要删除的文件名<br/><br/>　　例：if(OpenDialog1-&gt;Execute())Del&#101;teFile(OpenDialog1-&gt;FileName);<br/><br/>⑶DirectoryExists()<br/>　　原型：extern PACKAGE bool __fastcall DirectoryExists(const System:: AnsiString Name);<br/><br/>　　功能：检测目录是否存在，如果存在返回true，否则返回false<br/><br/>　　参数：Name:要检测的目录名<br/><br/>　　例：if(!DirectoryExists(&#34;ASM&#34;))Cr&#101;ateDir(&#34;ASM&#34;);//如果ASM这个目录不存在则创建之<br/><br/>⑷DiskFree()<br/>　　原型：extern PACKAGE __int64 __fastcall DiskFree(Byte Drive);<br/><br/>　　功能：检测磁盘剩余空间，返回值以字节为单位，如果指定的磁盘无效，返回-1<br/><br/>　　参数：Drive：磁盘的代号，0表示当前盘, 1=A,2=B,3=C 以此类推<br/><br/>　　例：ShowMessage(DiskFree(0));//显示当前盘的剩余空间<br/><br/>⑸DiskSize()<br/>　　原型：extern PACKAGE __int64 __fastcall DiskSize(Byte Drive);<br/><br/>　　功能：检测磁盘容量，返回值以字节为单位，如果指定的磁盘无效，返回-1<br/><br/>　　参数：Drive：磁盘的代号，0表示当前盘, 1=A,2=B,3=C 以此类推<br/><br/>　　例：ShowMessage(DiskFree(0));//显示当前盘的容量<br/><br/>⑹FileExists()<br/>　　原型：extern PACKAGE bool __fastcall FileExists(const AnsiString FileName);<br/><br/>　　功能：检测文件是否存在，如果存在返回true，否则返回false<br/><br/>　　参数：FileName:要检测的文件名<br/><br/>　　例：if(FileExists(&#34;AAA.ASM&#34;))Del&#101;teFile(&#34;AAA.ASM&#34;);<br/><br/>⑺FileGetAttr()<br/>　　原型：extern PACKAGE int __fastcall FileGetAttr(const AnsiString FileName);<br/><br/>　　功能：取得文件属性，如果出错返回-1<br/><br/>返回值如下表，如果返回$00000006表示是一个具有隐含和系统属性的文件(4+2)<br/><br/>常量 值 含义 <br/>faReadOnly $00000001 只读文件 <br/>faHidden $00000002 隐含文件 <br/>faSysFile $00000004 系统文件 <br/>faVolumeID $00000008 卷标 <br/>faDirectory $00000010 目录 <br/>faArchive $00000020 归档文件 <br/><br/>　　例：if(FileGetAttr(&#34;LLL.TXT&#34;)&amp;0x2)ShowMessage(&#34;这是一个有隐含属性的文件&#34;);<br/><br/>　　与此对应的有FileSetAttr() ，请自已查阅帮助系统<br/><br/><br/>⑻FileGetDate()<br/>　　原型：extern PACKAGE int __fastcall FileGetDate(int Handle);<br/><br/>　　功能：返回文件的建立时间到1970-1-1日0时的秒数<br/><br/>　　参数：Handle:用FileOpen()打开的文件句柄。<br/><br/>　　例：<br/><br/>　　　　int i=FileOpen(&#34;C:\\autoexec.bat&#34;,fmOpenRead);<br/>　　　　ShowMessage(FileGetDate(i));<br/>　　　　FileClose(i);<br/><br/>　　与此对应的有FileSetDate()，请自已查阅帮助系统<br/><br/>⑼GetCurrentDir()<br/>　　原型：extern PACKAGE AnsiString __fastcall GetCurrentDir();<br/><br/>　　功能：取得当前的目录名<br/><br/>　　例：ShowMessage(GetCurrentDir());<br/><br/>⑽RemoveDir()<br/>　　原型：extern PACKAGE bool __fastcall RemoveDir(const AnsiString Dir);<br/><br/>　　功能：删除目录，如果成功返回true，否则返回false<br/><br/>　　参数：Dir:要删除的目录名<br/><br/>　　例：if(DiectoryExists(&#34;ASM&#34;))RemoveDir(&#34;ASM&#34;);<br/><br/>⑾SetCurrentDir()<br/>　　原型：extern PACKAGE bool __fastcall SetCurrentDir(const AnsiString Dir);<br/><br/>　　功能：设置当前目录，如果成功返回true，否则返回false<br/><br/>　　参数：Dir:要切换到的目录名<br/><br/>　　例：SetCurrentDir(&#34;C:\\WINDOWS&#34;);<br/><br/><br/>--------------------------------------------------------------------------------<br/><br/>3、文件I/O函数<br/>　　这类函数完成对文件的读写相关的操作，这种类型的操作和C的基于I/O文件操作类似，下表列出这类操作常用的函数及其功能。<br/><br/>FileOpen() 打开文件 <br/>FileClose() 关闭文件 <br/>FileRead() 读文件 <br/>FileSeek() 文件定位 <br/>FileWrite() 写文件 <br/>FileCr&#101;ate() 创建文件 <br/><br/>　　下面就对这些函数作详细介绍。<br/><br/>⑴FileOpen()<br/>　　原型：extern PACKAGE int __fastcall FileOpen(const AnsiString FileName, int Mode);<br/><br/>　　功能：打开文件，如果成功返回其句柄，否则返回-1<br/><br/>　　参数：FileName:要打开的文件名；Mode：打开的方式，取值如下表，可用&#34;或&#34;(&#34;|&#34;)运算符连接。<br/><br/>常量 值 说明<br/>-------------------------------------------------------------<br/>fmOpenRead 0 以只读属性打开<br/>fmOpenWrite 1 以只写属性打开<br/>fmOpenReadWrite 2 以读/写属性打开<br/>fmShareCompat 0 兼容FCB方式(汇编中有相应的DOS功能调用，感兴趣自已查阅相关资料)<br/>fmShareExclusive 16 共享方式：以独占方式打开，在关闭以前，别人不能访问<br/>fmShareDenyWrite 32 共享方式：拒绝写访问<br/>fmShareDenyRead 48 共享方式：拒绝读访问<br/>fmShareDenyNone 64 共享方式：无限制，允许读写<br/>　　例：int i=FileOpen(&#34;C:\\WINDOWS\\Win.ini&#34;,fmOpenReadWrite|fmShareExclusive);<br/><br/>⑵FileClose()<br/>　　原型：extern PACKAGE void __fastcall FileClose(int Handle);<br/><br/>　　功能：关闭打开的句柄。<br/><br/>　　参数：Handle:要关闭的句柄<br/><br/>　　例：FileClose(i);<br/><br/>⑶FileRead()<br/>　　原型：extern PACKAGE int __fastcall FileRead(int Handle, void *Buffer, int Count);<br/><br/>　　功能：读文件，返回实际读取的字节数，句柄必须首先由FileOpen或FileCr&#101;ate创建。<br/><br/>　　参数：Handle:要读取的句柄；Buffer:存放读取的数据的缓冲区；Count:想读取的字节数<br/><br/>　　例：char str[400];FileRead(hnd1,str,400);<br/><br/>⑷FileSeek()<br/>　　原型：extern PACKAGE int __fastcall FileSeek(int Handle, int Offset, int o&#114;igin);<br/><br/>　　功能：移动文件读取指针，成功返回文件指针的位置，失败返回-1<br/><br/>　　参数：Handle:相关联的句柄；Offset:移动的量；Orgin:移动的基准，0=文件头，1=当前位置，2=文件尾。<br/><br/>　　例：ShowMessage(FileSeek(hnd1,0,2));//取得文件的长度<br/><br/>⑸FileWrite()<br/>　　原型：extern PACKAGE int __fastcall FileWrite(int Handle, const void *Buffer, int Count);<br/><br/>　　功能：写文件，返回实际写入的字节数，句柄必须首先由FileOpen或FileCr&#101;ate创建。<br/><br/>　　参数：Handle:要写入的句柄；Buffer:存放写入数据的缓冲区；Count:想写入的字节数<br/><br/>　　例：char str[]=&#34;I Love You&#34;;FileWrite(hnd1,str,strlen(str));<br/><br/>⑹FileCr&#101;ate()<br/>　　原型：extern PACKAGE int __fastcall FileCr&#101;ate(const AnsiString FileName);<br/><br/>　　功能：创建文件。成功返回其句柄，否则返回-1<br/><br/>　　参数：FileName:要创建的文件名<br/><br/>　　例：if(!FileExists(&#34;KC.C&#34;))hnd1=FileCr&#101;ate(&#34;KC.C&#34;);]]></description>
		</item>
		
			<item>
			<link>http://www.ufolbb.com/article.asp?id=230</link>
			<title><![CDATA[C++Builder中MessageBox的基本用法]]></title>
			<author>admin@ufolbb.com(ufolbb)</author>
			<category><![CDATA[PROGRAM/WEB Design]]></category>
			<pubDate>Thu,28 Aug 2008 09:59:12 +0800</pubDate>
			<guid>http://www.ufolbb.com/default.asp?id=230</guid>
		<description><![CDATA[【函数】 &lt;整型&gt; MessageBox（&lt;字符串&gt; Text, &lt;字符串&gt; Title, &lt;整型&gt; nType）;<br/>【函数说明】 弹出一个消息框。<br/>【语法】<br/>参数：<br/>Text &lt;字符串&gt;，消息框的正文；<br/>Title &lt;字符串&gt;，消息框的标题；<br/>nType &lt;整型&gt;，消息框的类型。<br/>返回值：&lt;整型&gt;，用户在消息框上点击关闭时的选择的按钮。<br/>【说明】<br/>其中nType对应的对话框如下表所示：<br/>0： 确定<br/>1： 确定，取消<br/>2： 终止，重试，忽略<br/>3： 是，否，取消<br/>4： 是，否<br/>5： 重试，取消<br/>6： 取消，再试一次，继续(注：Windows NT下不支持)<br/><br/>返回值对应的值如下：<br/>1： 确定<br/>2： 取消<br/>3： 终止<br/>4： 重试<br/>5： 忽略<br/>6： 是<br/>7： 否<br/>10：再试一次<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;应用程序中的提示信息处理程序是非常出重要的部分，用户要知道他输入的资料到底正不正确<br/><br/>，或者是应用程序有一些提示信息要告诉用户，都必须通过提示信息处理程序来显示适当的信息，<br/><br/>让用户了解下一步该如何配置。提示信息有很多种类，包括警告，错误，提示，确认，重试等。不<br/><br/>同种类的提示信息框适合用在各种不同的情况。<br/><br/>　　在C++Builder中开发提示信息框只须调用MessageBox这个信息提示框函数就行，下面就是这个<br/><br/>函数说明：<br/><br/>int __fastcall MessageBox(const char * Text,//提示信息框的内容<br/><br/>const char * Caption, //提示信息框的标题<br/><br/>int Flags); //提示信息框的类别<br/><br/>　　参数Flags的值是用来标志提示信息框的类别的，下面是一些常用的类别：<br/><br/>参数值 样式 意义<br/>MB_ICONWARNING 含图标、固定按钮 警告信息框<br/>MB_ICONQUESTION 含图标、固定按钮 疑问信息框<br/>MB_ICONERROR 含图标、固定按钮 错误信息框<br/>MB_ICONASTERISK 含图标、固定按钮 提示信息框<br/>MB_HELP 不含图标、可改变按钮 说明信息框<br/>MB_OK 不含图标、可改变按钮 提示信息框<br/>MB_OKCANCEL 不含图标、可改变按钮 确认信息框<br/>MB_RETRYCANCEL 不含图标、可改变按钮 重试信息框<br/>MB_YESNO 不含图标、可改变按钮 是否信息框<br/>MB_YESNOCANCEL 不含图标、可改变按钮 是否取消信息框<br/><br/>　　从上表可以看出来，提示信息框的类别可以分成含图标和不含图标，含图标的意思就是指提示<br/><br/>信息框上会有代表意义的图形，不过这类型的提示信息框的按钮都是固定的，都是【确定】按钮，<br/><br/>不能增加也不能省略；不含图标的提示信息框，虽然没有对应的图形显示在提示信息框上，可是你<br/><br/>却可以在这种类型的提示信息框内，加入各种组合的按钮，用于各种不同的情况。<br/><br/><br/>MessageBox函数会返回一个整数值，这个整数值代表用户刚刚点击提示信息框上的哪个按钮，每个<br/><br/>返回值的代表意义在下表：<br/><br/>返回值 数值 意义<br/>IDOK 1 确定<br/>IDCANCEL 2 取消<br/>IDABORT 3 中断<br/>IDRETRY 4 重试<br/>IDIGNORE 5 忽略<br/>IDYES 6 是<br/>IDNO 7 否<br/><br/><br/>下面是提示信息框的示范程序：<br/><br/>1． 警告信息框<br/><br/>Application-&gt;MessageBox(&#34;警告信息框&#34;,&#34;警告信息框&#34;,MB_ICONWARNING);<br/><br/>2．疑问信息框<br/><br/>Application-&gt;MessageBox(&#34;疑问信息框&#34;,&#34;疑问信息框&#34;,MB_ICONQUESTION);<br/><br/>3．错误提示框<br/><br/>Application-&gt;MessageBox(&#34;错误信息框&#34;,&#34;错误信息框&#34;,MB_IConERROR);<br/><br/>4．提示信息框<br/><br/>Application-&gt;MessageBox(&#34;提示信息框&#34;,&#34;提示信息框&#34;,MB_ICONASTERISK);<br/><br/>5．说明信息框<br/><br/>Application-&gt;MessageBox(&#34;说明信息框&#34;,&#34;说明信息框&#34;,MB_HELP);<br/><br/>6．提示信息框<br/><br/>Application-&gt;MessageBox(&#34;提示信息框&#34;,&#34;提示信息框&#34;,MB_OK);<br/><br/>7．确认信息框<br/><br/>Application-&gt;MessageBox(&#34;确认信息框&#34;,&#34;确认信息框&#34;,MB_OKCANCEL);<br/><br/>8．重试信息框<br/><br/>Application-&gt;MessageBox(&#34;重试信息框&#34;,&#34;重试信息框&#34;,MB_RETRYCANCEL);<br/><br/>9．是否信息框<br/><br/>Application-&gt;MessageBox(&#34;是否信息框&#34;,&#34;是否信息框&#34;,MB_YESNO);<br/><br/>10．是否取消信息框<br/><br/>Application-&gt;MessageBox(&#34;是否取消信息框&#34;,&#34;是否取消信息框&#34;,MB_YESNOCANCEL);<br/><br/>　　在C++Builder中，还提供了一个很简单的信息提示框函数，那就是ShowMessage。这个函数只<br/><br/>有一个字符串参数，你可以把要显示的字符串放到这个字符串参数里面，ShowMessage就回显示出<br/><br/>该信息，但是没有图标，也没有按钮，只有单纯的字符串信息而已。<br/><br/>下面是ShowMessage函数的说明：<br/><br/>extern PACKAGE void __fastcall ShowMessage(const AnsiString Msg);<br/><br/>例子：<br/><br/>ShowMessage(&#34;这个就是ShowMessage函数生成的信息提示框！&#34;);<br/><br/><br/>Application-&gt;MessageBox(&#34;AA&#34;, &#34;BB&#34;, MB_OK | MB_ICONSTOP);<br/>或<br/>MessageBox(Application-&gt;Handle,&#34;AA&#34;, &#34;BB&#34;, MB_OK | MB_ICONSTOP);<br/>这种写法“级别”最高：如果弹出这样的对话框，不点掉，Application下所有的Form都<br/>不能“动”的。<br/><br/>MessageBox(Form1-&gt;Handle,&#34;AA&#34;, &#34;BB&#34;, MB_OK | MB_ICONSTOP);<br/>这种写法“级别”其次：如果弹出这样的对话框，不点掉，只有From1不能“动”，其他<br/>Show()的From还可以点。<br/><br/>MessageBox(NULL,&#34;AA&#34;, &#34;BB&#34;, MB_OK | MB_ICONSTOP);<br/>这种写法“级别”最低：如果弹出这样的对话框，不点掉，From1也能“动”，其他<br/>Show()的From也可以点。 <br/>]]></description>
		</item>
		
			<item>
			<link>http://www.ufolbb.com/article.asp?id=229</link>
			<title><![CDATA[最近开始学习C++ Builder ]]></title>
			<author>admin@ufolbb.com(ufolbb)</author>
			<category><![CDATA[PROGRAM/WEB Design]]></category>
			<pubDate>Thu,28 Aug 2008 09:58:19 +0800</pubDate>
			<guid>http://www.ufolbb.com/default.asp?id=229</guid>
		<description><![CDATA[开个C++分类，收集一些C++/C++ Builder的东西 <img src="http://www.ufolbb.com/images/smilies/Face_12.gif" border="0" style="margin:0px 0px -2px 0px" alt=""/><br/><br/>不知有没有什么书是介绍C++ Builder的各种组件的属性及其使用方法的？不是很会用 <img src="http://www.ufolbb.com/images/smilies/Face_01.gif" border="0" style="margin:0px 0px -2px 0px" alt=""/>]]></description>
		</item>
		
</channel>
</rss>
