﻿<?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++博客-Richard He-文章分类-[转]</title><link>http://www.cppblog.com/richardhe/category/6665.html</link><description>学无止境!永远学下去!</description><language>zh-cn</language><lastBuildDate>Sun, 20 Jul 2008 02:55:46 GMT</lastBuildDate><pubDate>Sun, 20 Jul 2008 02:55:46 GMT</pubDate><ttl>60</ttl><item><title>简介Boost.Regex</title><link>http://www.cppblog.com/richardhe/articles/56662.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Sun, 20 Jul 2008 02:31:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/56662.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/56662.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/56662.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/56662.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/56662.html</trackback:ping><description><![CDATA[<table align="center" bgcolor="#efefef" border="0" cellpadding="4" cellspacing="0" width="99%">
    <tbody>
        <tr>
            <td id="zoom" style="font-size: 10.5pt;" width="89%">
            <p><font size="1"><font style="background-color: #0000ff;"><font color="#000000"><font style="background-color: #ffffff;"><strong>简介<sup>1</sup></strong></font><br></font></font>&nbsp;&nbsp;&nbsp;&nbsp;正
            则表达式（Regular
            expression）是一种在文本处理中经常用到的模式匹配的形式，可能许多用户熟悉Unix下的grep,sed,awk等工具或者perl语言，它
            们都广泛地用到了正则表达式。传统的C++用户还受限于用POSIX C API's（Portable operateing system
            interface standard)来操作正则表达式，而regex++已经提供了这些API's，虽然它不一定是使用POSIX C
            正则表达式库的最好方法。比如regex++能处理宽字符字符串（wide character
            strings），或者搜索、替换操作（在某种意义上类似于sed或perl），这些在传统的C 库中是不能实现的。<br>类boost::reg_expression是regex++库中的关键类，它表示&#8220;机器可读&#8221;的正则表达式，reg_expression 是在string的基础之上构建的，可以认为它是一个具有string的功能，外加这个正则表达式算法所需要的状态机。<br>像std::basic_string一样，它提供了两个针对char和wchar_t的特化版本：<br><br>namespace boost{<br>template &lt;class charT, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class traits = regex_traits&lt;charT&gt;, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class Allocator = std::allocator&lt;charT&gt; &gt;<br>class basic_regex;<br>typedef basic_regex&lt;char&gt; regex;<br>typedef basic_regex&lt;wchar_t&gt; wregex;<br>}</font></p>
            <p><font size="1">&nbsp;&nbsp;&nbsp;&nbsp;要知道regex++库到底有什么用？可以试想我们要写一个信用卡处理程序。信用卡通常有16位数字组成的
            号码，其中每四位一组，用空格或连字号隔开。在将这些信用卡号码存入数据库之前，我们难道不要检验这些数字是否符合正确格式么？为了匹配任何一个数字我们
            可以用正则表达式[0-9]，数字串的宽度可以用[[:digit:]],当然这些是POSIX标准。在regex++和perl中可简化为\d（注意许
            多老的库倾向于硬编码到C-locale，因此这不是什么问题）。下面的正则表达式可以检验信用卡号码的格式。<br>(\d{4}[- ]){3}\d{4}<br>&nbsp;&nbsp;&nbsp;&nbsp;()标记子表达式，{4}表示重复4次。这仅是一个perl,awk,egrep的正则表达式的例子。regex++也支持那些sed,grep用到的比较老的&#8220;基本&#8221;语法，虽然它们很少用到，除非你需要重用一些已有的基本正则表达式。</font></p>
            <p><font size="1">&nbsp;&nbsp;&nbsp;&nbsp;现在让我们把这个表达式置于C++代码中来检验信用卡号码的格式：<br><br>bool validate_card_format(const std::string s)<br>{<br>&nbsp;&nbsp; static const boost::regex e("(</font><a  href="file://%5c%5cd%7b4/"><font size="1">\\d{4</font></a><font size="1">}[- ]){3}\\d{4}");<br>&nbsp;&nbsp; return regex_match(s, e);<br>}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;注意我们以前是如何将某些额外的转义序列（或者翻译成：转义字符）添加到表达式的：要知道，正则表达式引擎处理转义字符前，该转义字符只能被 C++编译器识别一次，因此，在C++代码中嵌入正则表达式的转义字符必须双写（写两次）。<br>&nbsp;&nbsp;&nbsp;&nbsp;还要注意到你的编译器必须支持Koening lookup 2（比如VC6就不支持），否则你需要附加一些boost::prefixes到某些函数引用中。<br>&nbsp;&nbsp;&nbsp;&nbsp;那
            些熟悉信用卡操作的人，可能还会想到上面的那种格式适合于人的阅读，并不表示网上信用卡系统要求的格式（可能是16或15个没有间隔符的数字串）。我们需
            要一种简单的转换方法，我们需要2个字符串，1个是正则表达式，一个是格式字符串（提供一种被匹配的内容的描述）。在regex++中，search和
            replace都能完成regex_merge算法，对于信用卡的例子我们给出了下面2个算法用于格式转换：<br><br>// match any format with the regular expression:<br>const boost::regex e("</font><a  href="file://%5c%5ca%28%5c%5cd%7b3,4/"><font size="1">\\A(\\d{3,4</font></a><font size="1">})[- ]?(</font><a  href="file://%5c%5cd%7b4/"><font size="1">\\d{4</font></a><font size="1">})[- ]?(</font><a  href="file://%5c%5cd%7b4/"><font size="1">\\d{4</font></a><font size="1">})[- ]?(</font><a  href="file://%5c%5cd%7b4%7d%29%5c%5cz/"><font size="1">\\d{4})\\z</font></a><font size="1">");<br>const std::string machine_format("</font><a  href="file://%5c%5c1%5c%5c2%5c%5c3%5c%5c4/"><font size="1">\\1\\2\\3\\4</font></a><font size="1">");<br>const std::string human_format("</font><a  href="file://%5c%5c1-%5c%5c2-%5c%5c3-%5c%5c4/"><font size="1">\\1-\\2-\\3-\\4</font></a><font size="1">");</font></p>
            <p><font size="1">std::string machine_readable_card_number(const std::string s)<br>{<br>&nbsp;&nbsp; return regex_merge(s, e, machine_format, boost::match_default | boost::format_sed);<br>}</font></p>
            <p><font size="1">std::string human_readable_card_number(const std::string s)<br>{<br>&nbsp;&nbsp; return regex_merge(s, e, human_format, boost::match_default | boost::format_sed);<br>}</font></p>
            <p><br><font size="1">&nbsp;&nbsp;&nbsp;&nbsp;这儿，我们用正则表达式中的子式把号码分为4块，format string 用类似sed的语法把被匹配的内容替换为规定格式。<br>&nbsp;&nbsp;&nbsp;&nbsp;上面的例子中，我们还没有直接操作匹配结果，匹配结果包括全体匹配和一些子式的匹配。当需要正则表达式的匹配结果时，就需要用到class match_results的实例，下面是常用类型的特化版本：<br><br>namespace boost{<br>typedef match_results&lt;const char*&gt; cmatch;<br>typedef match_results&lt;const wchar_t*&gt; wcmatch;<br>typedef match_results&lt;std::string::const_iterator&gt; smatch;<br>typedef match_results&lt;std::wstring::const_iterator&gt; wsmatch; <br>}</font></p>
            <p><font size="1">&nbsp;&nbsp;&nbsp;&nbsp;regex_search和regex_grep算法都使用到match_result。<br>&nbsp;&nbsp;&nbsp;&nbsp;注意这些算法并不局限于一般的C-strings,任何双向迭代器（bidirectional iterator）类型都能被搜索，这为无缝搜索任何类型数据提供了可能性。</font></p>
            <p><font size="1">&nbsp;&nbsp;&nbsp;&nbsp;对于那些不喜欢模板（templates）的人还可以使用class RegEx,它是对模板代码的高层次包装，它为那些使用不到库的整个功能的人提供了简单的接口，当然它仅支持窄字符（narrow character）和&#8220;扩展&#8221;的正则表达式语法。<br>&nbsp;&nbsp;&nbsp;&nbsp;对于想兼容POSIX的人可以使用POSIXAPI函数：regcomp,regexec,regfree,regerror,这些对narrow character和Unicode都适用。</font></p>
            <p><font size="1">&nbsp;&nbsp;&nbsp;&nbsp;最后注意，这个库现在支持运行时本地化（run-time localization），它能完全识别POSIX正则表达式语法，包括一些多字符的元素比较和同等类型的高级特性，它还能兼容其它一些正则表达式库包括GNU、BSD4的regex包。</font></p>
            <p><font size="1"><strong>安装和配置</strong></font></p>
            <p><font size="1">&nbsp;&nbsp;&nbsp;&nbsp;首先当你从zip文件解压本库时必须保留它的内部结构，如果你没这样做，那只好删除你解压的文件，重现来一次。<br>&nbsp;&nbsp;&nbsp;&nbsp;由于支持大多数常见的编译器/标准库/平台，这个库不需要作使用前的配置。如果你碰到配置问题，或想测试你的编译器的配置信息，可以参考 配置文档（这和boost的其它所有的库的处理过程都一样）。</font></p>
            <p><font size="1">&nbsp;&nbsp;&nbsp;&nbsp;由于本库混合了模板代码（头文件中）和静态代码数据（cpp文件中），所以在你使用之前，必须将库支持的代码 生成到库内和档案文件中。以下是几个具体平台的操作步骤：<br>Borland C++ Builder<br><font color="#008000">略</font><br>Microsoft Visual C++ 6 and 7<br>如果你使用VC5，你可能要找一下本库的以前版本。<br>打开命令提示符（其MSVC环境变量必须已定义，如果没有可运行Vcvars32.bat，位于&lt;VC6&gt;\bin），进入&lt;boost&gt;\libs\regex\build 目录<br>选择正确的makefile,VC6++的是vc6.mak,支持STLPort的是vc6-stlport.mak<br>如下调用<br>nmake -fvc6.mak<br>如果想在VC6子目录包含所有的lib、dll文件，lib文件拷在&lt;VC6&gt;\lib，dll文件拷在&lt;VC6&gt;\bin，可使用<br>nmake -fvc6.mak install<br>删除生成过程中所有的临时文件，可使用<br>nmake -fvc6.mak clean</font></p>
            <p><font size="1">最后只需添加&lt;boost&gt;根目录到你的工程所包含的目录列表中。没有必要手动将*.lib文件加到工程中，因为在头文件会选择正确的.lib文件。<br>注意：如果想静态地链入regex库，可定义BOOST_REGEX_STATIC_LINK（在release版中生效）。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果想直接使用源文件，可定义BOOST_REGEX_NO_LIB，这样自动选择库将失效。</font></p>
            <p><font size="1">1.简介出处：</font><a  href="http://www.boost.org/libs/regex/doc/introduction.html"><font size="1">http://www.boost.org/libs/regex/doc/introduction.html</font></a><br><font size="1">2.Koening
            lookup：When a function is called, in order to determine if that
            function is visible in the current scope, the namespaces in which the
            functions parameters reside must be taken into account.</font></p>
            </td>
            <td width="5%">&nbsp;</td>
        </tr>
        <tr>
            <td align="right">&nbsp;          </td>
            <td align="right">          <br></td>
        </tr>
    </tbody>
</table><img src ="http://www.cppblog.com/richardhe/aggbug/56662.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-07-20 10:31 <a href="http://www.cppblog.com/richardhe/articles/56662.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>boost::regex</title><link>http://www.cppblog.com/richardhe/articles/56653.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Sun, 20 Jul 2008 01:45:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/56653.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/56653.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/56653.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/56653.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/56653.html</trackback:ping><description><![CDATA[<div id="art" style="margin: 15px;">
<div>
<h4 class="TextColor1" id="subjcns!D831FDBD876F27A2!173" style="margin-bottom: 0px;">boost::regex</h4>
<div id="msgcns!D831FDBD876F27A2!173">
<ul>
    <li>boost::regex的用法</li>
</ul>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bool validate_card_format(const std::string s)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static const boost::regex e("(\\d{4}[- ]){3}\\d{4}");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return regex_match(s, e);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<ul>
    <li>boost::regex的默认正则表达式语法是perl语法</li>
</ul>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;boost::regex支持perl regular表达式、POSIX-Extended
regular表达式和POSIX-Basic
Regular表达式，但默认的表达式语法是perl语法，如果要使用其余两种语法需要在构造表达式的时候明确指定。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;例如，下面两种方法效果相同<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// e1 is a case sensitive Perl regular expression:&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// since Perl is the default option there's no need to explicitly specify the syntax used here:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;boost::regex e1(my_expression);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// e2 a case insensitive Perl regular expression:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;boost::regex e2(my_expression, boost::regex::perl|boost::regex::icase);</p>
<ul>
    <li>perl正则表达式语法</li>
</ul>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perl正则表达式语法可参见《perl语言入门》第7、8、9章或boost的文档。这里列出的语法是不全面的，而且部分说明可能并不清楚。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. 任意字符;使用match_no_dot_null标志时不匹配NULL字符; 使用match_not_dot_newline时不匹配换行字符</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;^ 匹配行的开始<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$ 匹配行的结束<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* 重复零次或则更多,例如a*b可匹配b,ab,aab,aaaaaaab<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ 重复一次以上，例如a+b可匹配ab,aab,aaaaaaaab。但不能匹配b了<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;? 零次或则一次，例如ca?b匹配cb,cab但不匹被caab&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a{n} 匹配字符'a'重复n次<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a{n,}，字符a重复n次以上（含n次）<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a{n,m} a重复n到m次（含）</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*?&nbsp;&nbsp; 匹配前一个原子零次以上<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+?&nbsp;&nbsp; 匹配前一个原子一次以上<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;??&nbsp;&nbsp; 匹配前一个原子零次以上<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{n,}?&nbsp; 匹配前一个原子n次以上(含)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{n,m?&nbsp; 匹配前一个原子n到m次(含)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| 或操作，例如ab(d|ef)匹配abd或则abef<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[] 字符集操作，例如[abc]将匹配任何单个字符'a'，'b'，'c'<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[a-d]，表示a、b、c、d<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;^否操作，例如[^a-c]表示a至c之外的所有字符<br></p>
<ul>
    <li>boost::regex对unicode编码的支持</li>
</ul>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;boost::regex使用ICU来实现对unicode及unicode变种的支持，这需要在编译boost的时候指出是否使
用ICU以及ICU所在的目录。否则编译出来的boost::regex不支持unicode编码。其中boost::wregex支持unicode编
码的搜索，如果要搜索UTF-8、UTF-16、UFT-32编码的字符串，则要用boost::u32regex。注意boost::wregex只能
支持unicode编码，不能支持uft编码。</p>
<ul>
    <li>搜索时如何忽略大小写</li>
</ul>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果要在搜索时忽略大小写（即大小写不敏感），则要用到表达式选项boost::regex::icase，例
如：&nbsp;boost::regex e2(my_expression,
boost::regex::perl|boost::regex::icase);</p>
</div>
</div>
</div><img src ="http://www.cppblog.com/richardhe/aggbug/56653.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-07-20 09:45 <a href="http://www.cppblog.com/richardhe/articles/56653.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C/C++中宏的使用</title><link>http://www.cppblog.com/richardhe/articles/56328.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Wed, 16 Jul 2008 10:10:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/56328.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/56328.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/56328.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/56328.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/56328.html</trackback:ping><description><![CDATA[关于## 和 #及#@的用法<br><br><br>## 是连接符号 连接两个宏,##被称为连接符（concatenator），用来将两个Token连接为一个Token。注意这里连接的对象是Token就行，而不一定是宏的变 <br>量。比如你要做一个菜单项命令名和函数指针组成的结构体的数组，并且希望在函数名和菜单项命令名之间有直观的、名字上的关系。那就可以使用：宏参数## <br>固定部分。当然还可以n个##符号连接 n+1个Token，这个特性也是#符号所不具备的。 <br>#define LINK_MULTIPLE(a,b,c,d) a##_##b##_##c##_##d<br>typedef struct _record_type LINK_MULTIPLE(name,company,position,salary);<br>// 这里这个语句将展开为：<br>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typedef struct _record_type name_company_position_salary;<br><br><br>#@功能是将其后面的宏参数进行字符化。<br>#define makechar(x)&nbsp; <a  href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#35;&#64;&#120;&#97;">#@x<br>a</a> = makechar(b);<br>//a = 'b';<br><br><br>#是把名字代替成字符串,宏体中，#的功能是将其后面的宏参数进行字符串化操作（Stringfication），简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个 <br>双引号。<br>#define WARN_IF(EXP)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; do{ if (EXP)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fprintf(stderr, "Warning: " #EXP "\n"); }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(0)<br>那么实际使用中会出现下面所示的替换过程： <br>WARN_IF (divider == 0);<br>被替换为<br>do {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (divider == 0)<br>fprintf(stderr, "Warning" "divider == 0" "\n");<br>} while(0);<br>这样每次divider（除数）为0的时候便会在标准错误流上输出一个提示信息。 <br><br><br>
<font style="font-size: 12pt;" face="#ce_temp_font#"><dt><strong>!IF </strong><span class="parameter">constantexpression</span>
</dt><dd>
<p>如果 <span class="parameter">constantexpression</span> 计算结果为非零值，则处理 <strong>!IF</strong> 和下一个 <strong>!ELSE</strong> 或 <strong>!ENDIF</strong> 之间的语句。<br><strong>!ENDIF</strong> </p>
</dd>
<dd>
<p>标记 <strong>!IF</strong>、<strong>!IFDEF</strong> 或 <strong>!IFNDEF</strong> 块的结尾。同一行上 <strong>!ENDIF</strong> 后面的所有文本被忽略。</p>
</dd></font><img src ="http://www.cppblog.com/richardhe/aggbug/56328.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-07-16 18:10 <a href="http://www.cppblog.com/richardhe/articles/56328.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>extern "C"</title><link>http://www.cppblog.com/richardhe/articles/55817.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Thu, 10 Jul 2008 09:27:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/55817.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/55817.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/55817.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/55817.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/55817.html</trackback:ping><description><![CDATA[<p>前些天，编程序是用到了很久以前写的C程序，想把里面的函数利用起来，连接发现出现了找不到具体函数的错误：</p>
<p>以下是假设旧的C程序库</p>
<p>C的头文件</p>
<pre><em><font color="#999999">/*-----------c.h--------------*/</font></em><font color="#000099"><br>#ifndef _C_H_<br>#define _C_H_<br></font><font color="#990000">extern</font><font color="#ff6633"> int</font> add<strong><font color="#663300">(</font></strong><font color="#ff6633">int</font> x<strong><font color="#663300">,</font></strong><font color="#ff6633"> int</font> y<strong><font color="#663300">);</font></strong><font color="#000099"><br>#endif</font></pre>
<p>C的源文件</p>
<pre><em><font color="#999999">/*-----------c.c--------------*/</font></em><font color="#ff6633"><br>int</font> add<strong><font color="#663300">(</font></strong><font color="#ff6633">int</font> x<strong><font color="#663300">,</font></strong><font color="#ff6633"> int</font> y<strong><font color="#663300">){</font></strong><font color="#ff0000"><br>	return</font> x<strong><font color="#663300">+</font></strong>y<strong><font color="#663300">;<br>}</font></strong><br></pre>
<p>C++的调用</p>
<pre><em><font color="#999999">/*-----------cpp.cpp--------------*/</font></em><font color="#000099"><br>#include "c.h"<br></font><font color="#ff6633">void</font><font color="#990000"> main</font><strong><font color="#663300">()<br>{</font></strong><br>	add<strong><font color="#663300">(</font></strong><font color="#999900">1</font><strong><font color="#663300">,</font></strong><font color="#999900"> 0</font><strong><font color="#663300">);<br>}</font></strong><br></pre>
<p>这样编译会产生错误cpp.obj : error LNK2001: unresolved external symbol "int __cdecl add(int,int)" (<a  href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#97;&#100;&#100;&#64;&#64;&#89;&#65;&#72;&#72;&#72;&#64;&#90;">?add@@YAHHH@Z</a>)，原因是找不到add的目标模块</p>
<p>这才令我想起C++重载的函数命名方式和C函数的命名方式，让我们回顾一下：C中函数编译后命名会在函数名前加以"_",比如add函数编译成obj文件时的实际命名为_add，而c++命名则不同，为了实现函数重载同样的函数名add因参数的不同会被编译成不同的名字</p>
<p>例如</p>
<p>int add(int , int)==&gt;<font color="#0000ff"><u>add@@YAHHH@Z,</u></font></p>
<p><font color="#0000ff"><font color="#000000">float add(float , float )==&gt;</font></font><font color="#0000ff"><u>add@@YAMMM@Z</u></font><font color="#000000">,</font></p>
<p>以上是VC6的命名方式，不同的编译器会不同，总之不同的参数同样的函数名将编译成不同目标名，以便于函数重载是调用具体的函数。</p>
<p>编译cpp.cpp中编译器在cpp文件中发现add<strong><font color="#663300">(</font></strong><font color="#999900">1</font><strong><font color="#663300">,</font></strong><font color="#999900"> 0</font><strong><font color="#663300">);</font></strong>的调用而函数声明为<font color="#990000">extern</font><font color="#ff6633"> int</font> add<strong><font color="#663300">(</font></strong><font color="#ff6633">int</font> x<strong><font color="#663300">,</font></strong><font color="#ff6633"> int</font> y<font color="#663300"><strong>);</strong></font><font color="#000000">编译器就决定去找</font><font color="#0000ff"><a  href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#97;&#100;&#100;&#64;&#64;&#89;&#65;&#72;&#72;&#72;&#64;&#90;">add@@YAHHH@Z</a></font><font color="#000000">，可惜他找不到，因为C的源文件把<font color="#990000">extern</font><font color="#ff6633"> int</font> add<strong><font color="#663300">(</font></strong><font color="#ff6633">int</font> x<strong><font color="#663300">,</font></strong><font color="#ff6633"> int</font> y<font color="#663300"><strong>);</strong></font></font><font color="#000000">编译成_add了；</font></p>
<p>为了解决这个问题C++采用了extern "C",这就是我们的主题，想要利用以前的C程序库，那么你就要学会它，我们可以看以下标准头文件你会发现，很多头文件都有以下的结构</p>
<pre><font color="#000099">#ifndef __H<br>#define __H<br>#ifdef __cplusplus<br></font><font color="#990000">extern</font><font color="#009900"> "C"</font><strong><font color="#663300"> {</font></strong><font color="#000099"><br>#endif<br></font><font color="#990000"><br>extern</font><font color="#ff6633"> int</font> f1<strong><font color="#663300">(</font></strong><font color="#ff6633">int</font><strong><font color="#663300">,</font></strong><font color="#ff6633"> int</font><strong><font color="#663300">);</font></strong><font color="#990000"><br>extern</font><font color="#ff6633"> int</font> f2<strong><font color="#663300">(</font></strong><font color="#ff6633">int</font><strong><font color="#663300">,</font></strong><font color="#ff6633"> int</font><strong><font color="#663300">);</font></strong><font color="#990000"><br>extern</font><font color="#ff6633"> int</font> f3<strong><font color="#663300">(</font></strong><font color="#ff6633">int</font><strong><font color="#663300">,</font></strong><font color="#ff6633"> int</font><strong><font color="#663300">);</font></strong><font color="#000099"><br><br>	<br>#ifdef __cplusplus<br></font><strong><font color="#663300">}</font></strong><font color="#000099"><br>#endif<br><br>#endif /*__H*/<br></font></pre>
<p>如果我们仿制该头文件可以得到</p>
<pre><font color="#000099">#ifndef _C_H_<br>#define _C_H_<br>#ifdef __cplusplus<br></font><font color="#990000">extern</font><font color="#009900"> "C"</font><strong><font color="#663300"> {</font></strong><font color="#000099"><br>#endif<br></font><font color="#990000"><br>extern</font><font color="#ff6633"> int</font> add<strong><font color="#663300">(</font></strong><font color="#ff6633">int</font><strong><font color="#663300">,</font></strong><font color="#ff6633"> int</font><strong><font color="#663300">);</font></strong><font color="#000099"><br><br>#ifdef __cplusplus<br></font><strong><font color="#663300">}</font></strong><font color="#000099"><br>#endif<br><br>#endif /* _C_H_ */ <br></font></pre>
<p><font color="#000099"><font color="#000000">这样编译</font></font></p>
<p><font color="#000099"><font color="#999999"><em>/*-----------c.c--------------*/</em></font><font color="#ff6633"><br>int</font><font color="#000000"> add</font><strong><font color="#663300">(</font></strong><font color="#ff6633">int</font><font color="#000000"> x</font><strong><font color="#663300">,</font></strong><font color="#ff6633"> int</font><font color="#000000"> y</font><strong><font color="#663300">){</font></strong><font color="#ff0000"><br>return</font><font color="#000000"> x</font><strong><font color="#663300">+</font></strong><font color="#000000">y</font><strong><font color="#663300">;<br>}</font></strong><br></font></p>
<p><font color="#000099"><font color="#000000">这时源文件为*.c，</font><font color="#000099">__cplusplus没有被定义，<font color="#990000">extern</font><font color="#009900"> "C"</font><font color="#663300"><strong> {}</strong></font><font color="#000000">这时没有生效对于C他看到只是<font color="#990000">extern</font><font color="#ff6633"> int</font> add<strong><font color="#663300">(</font></strong><font color="#ff6633">int</font><strong><font color="#663300">,</font></strong><font color="#ff6633"> int</font><strong><font color="#663300">);</font></strong><font color="#000099"><br></font>add函数编译成_add(int, int);</font></font></font></p>
<p><font color="#000099"><font color="#000099"><font color="#000000">而编译c++源文件</font></font></font></p>
<p><font color="#000099"><font color="#000099"><font color="#999999"><em>/*-----------cpp.cpp--------------*/</em></font><font color="#000099"><br>#include "c.h"<br></font><font color="#ff6633">void</font><font color="#990000"> main</font><strong><font color="#663300">()<br>{</font></strong><br><font color="#000000">add</font><strong><font color="#663300">(</font></strong><font color="#999900">1</font><strong><font color="#663300">,</font></strong><font color="#999900"> 0</font><strong><font color="#663300">);<br>}</font></strong><br><font color="#000000">这时源文件为*.cpp,</font><font color="#000099">__cplusplus被定义,对于C++他看到的是<font color="#990000">extern</font><font color="#009900"> "C"</font><font color="#663300"><strong> {</strong><font color="#990000">extern</font><font color="#ff6633"> int</font><font color="#000000"> add</font><font color="#663300"><strong>(</strong></font><font color="#ff6633">int</font><font color="#663300"><strong>,</strong></font><font color="#ff6633"> int</font><strong><font color="#663300">);</font>}</strong></font><font color="#000000">编译器就会知道 add<strong><font color="#663300">(</font></strong><font color="#999900">1</font><strong><font color="#663300">,</font></strong><font color="#999900"> 0</font><font color="#663300"><strong>);调用的C风格的函数，就会知道去c.obj中找_add(int, int)而不是</strong><a  href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#97;&#100;&#100;&#64;&#64;&#89;&#65;&#72;&#72;&#72;&#64;&#90;">add@@YAHHH@Z</a>；</font></font></font></font></font></p>
<font color="#000099"><font color="#000099"><font color="#000099"><font color="#663300">这也就为什么DLL中常看见<font color="#990000">extern</font><font color="#009900"> "C"</font><font color="#663300"><strong> {}，</strong>windows是采用C语言编制他首先要考虑到C可以正确调用这些DLL，而用户可能会使用C++而<font color="#990000">extern</font><font color="#009900"> "C"</font><font color="#663300"><strong> {}就会发生作用</strong></font></font></font></font></font></font><img src ="http://www.cppblog.com/richardhe/aggbug/55817.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-07-10 17:27 <a href="http://www.cppblog.com/richardhe/articles/55817.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>推荐--丰富的游戏开发的站点</title><link>http://www.cppblog.com/richardhe/articles/55714.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Wed, 09 Jul 2008 07:11:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/55714.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/55714.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/55714.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/55714.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/55714.html</trackback:ping><description><![CDATA[按自已认为的站点内容的好坏排了个序的：<br>
<br>
<a  href="http://www.gameres.com/">http://www.gameres.com</a> &nbsp;&nbsp;&nbsp; 属于游戏人的中文网络平台<br>
<a  href="http://www.chinagamedev.net/">http://www.chinagamedev.net</a> &nbsp;&nbsp; 中国游戏开发者<br>
<a  href="http://www.gamedevelop.net/">http://www.gamedevelop.net</a> &nbsp;&nbsp; 中国游戏开发技术资讯网
<a  href="http://www.ogdev.net/">http://www.ogdev.net</a> &nbsp;&nbsp;&nbsp; 中国网游研发中心<br>
<a  href="http://www.chaosstars.com/">http://www.chaosstars.com</a> &nbsp;&nbsp; 中国游戏开发基地<br>
<a  href="http://gamedev.91.com/">http://gamedev.91.com</a>&nbsp;&nbsp;&nbsp; 游戏制作联盟<br>
<a  href="http://www.chinadv.com/">http://www.chinadv.com</a>  &nbsp;&nbsp; 中国数码视频在线<br>
<a  href="http://www.u9u6.com/">http://www.u9u6.com</a> &nbsp;&nbsp;&nbsp; u9u6游戏网<br>
<a  href="http://www.amanpage.com/">http://www.amanpage.com</a> &nbsp;&nbsp; 游戏开发站点<br>
<a  href="http://www.gamecollege.org/">http://www.gamecollege.org</a>  &nbsp;&nbsp; 游戏学院<br>
<br>
手机随便列的：<br>
<a  href="http://soft.yesky.com/SoftChannel/72348977504190464/20031215/1753502.shtml">http://soft.yesky.com/SoftChannel/72348977504190464/20031215/1753502.shtml</a> Java&nbsp;&nbsp; 手机游戏开发专辑<br>
<br>
国外站点：<br>
<a  href="http://www.gdse.com/">http://www.gdse.com</a>&nbsp;&nbsp;&nbsp; Game Development Search Engine<br>
<a  href="http://www.gamedev.net/">http://www.gamedev.net</a><br>
<a  href="http://www.igda.org/">http://www.igda.org</a>&nbsp;&nbsp;&nbsp; International Game Developers Association<br>
<a  href="http://www.gameinstitute.com/">http://www.gameinstitute.com</a>&nbsp;&nbsp; Game Institute<br>
<a  href="http://www.gametutorials.com/">http://www.gametutorials.com</a>&nbsp;&nbsp; Game Tutorials<br>
<a  href="http://www.sagamedev.co.za/">http://www.sagamedev.co.za</a>  &nbsp;&nbsp; South African Game Development<br>
<a  href="http://lgdc.sunsite.dk/">http://lgdc.sunsite.dk</a>&nbsp;&nbsp;&nbsp; Linux Game Development Center<br>
<br>
个人的及专题的：<br>
<a  href="http://gd.91.com/zt/ogre/index.asp">http://gd.91.com/zt/ogre/index.asp</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OGRE引擎研究站<br>
<a  href="http://www.gameres.com/Topics/Technic/OGRE">http://www.gameres.com/Topics/Technic/OGRE</a>  &nbsp;&nbsp;&nbsp;&nbsp; OGRE引擎教程<img src ="http://www.cppblog.com/richardhe/aggbug/55714.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-07-09 15:11 <a href="http://www.cppblog.com/richardhe/articles/55714.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用Boost.Spirit写了一个term下c++词法高亮</title><link>http://www.cppblog.com/richardhe/articles/55612.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Tue, 08 Jul 2008 03:49:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/55612.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/55612.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/55612.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/55612.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/55612.html</trackback:ping><description><![CDATA[出自http://hi.baidu.com/yesbaba/blog/item/79c3eb13215da0d2f7039ec9.html<br>
<p><font size="3">1.1版，命令行下使用如1.0版，</font></p>
<p><font size="3">&nbsp;&nbsp;&nbsp;             增加更易用的方法：点击coco.exe，将文件拖入窗口，高亮文件输出到同名txt文件中</font></p>
<p><font size="3">&nbsp;&nbsp;&nbsp;             转成html的功能以后不懒的时候再写吧<br>
</font></p>
<p><font size="3"><br>
</font></p>
<p><font size="3">1.0版：命令行下使用，输出到stdout，</font></p>
<p><font size="3"> 可以重定向到文件，彩色复制就行了<br>
coco.exe xxx.cpp &gt; whateverfile<br>
记事本打开whateverfile，复制，在bbs上彩色粘贴<br>
编译这个大概需要2百多M内存</font></p>
<p><font size="3">想直接现在用的，可以在这下载，这是水木的附件，不知道能有效到什么时候</font></p>
<p><font size="3">http://www.newsmth.net/att.php?p.335.193566.17417.exe</font></p>
<p><font size="3">论坛可以用它来实现代码高亮显示<br>
以后再改进</font></p>
<p><font size="3">正确的代码coco应该不会分析错，能分析正确的不一定是正确的代码</font></p>
<p><font size="3">读代码可以先看spirit最基础的ch_p,str_p等，还有spirit文档中的utility</font></p>
<p><font size="3">再看如何分析文件</font></p>
<p><font size="3"><a  href="http://hi.baidu.com/yesbaba/blog/item/091ca995d0fe6e49d1135e8b.html">http://hi.baidu.com/yesbaba/blog/item/091ca995d0fe6e49d1135e8b.html</a></font></p>
<p><font size="3">gnu source highlight就可以实现这个功能了，我做这个一来是学spirit练练手，</font></p>
<p><font size="3">二来是要做个课程设计，三来这个很实用，平常在水木帖代码也能用的上<br>
</font></p>
<font size="3" face="fixedsys"><font size="3" face="fixedsys">
<p><font face="fixedsys"> <font color="#0000ff">///////////////////////////////////////////////////////////////////////////////</font><br>
<font color="#0000ff">//</font><br>
<font color="#0000ff">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;             highlight c++ source code in ansi code format</font><br>
<font color="#0000ff">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;             COCO (COlorful COde) version 1.1</font><br>
<font color="#0000ff">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;             ibe@newsmth.net</font><br>
<font color="#0000ff">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;             [ 2007-08-13 ]</font><br>
<font color="#0000ff">//</font><br>
<font color="#0000ff">///////////////////////////////////////////////////////////////////////////////</font><br>
<br>
<font color="#a020f0">#include </font><font color="#ff00ff">&lt;boost/spirit/core.hpp&gt;</font><br>
<font color="#a020f0">#include </font><font color="#ff00ff">&lt;boost/spirit/iterator/file_iterator.hpp&gt;</font><br>
<font color="#a020f0">#include </font><font color="#ff00ff">&lt;boost/spirit/utility/confix.hpp&gt;</font><br>
<font color="#a020f0">#include </font><font color="#ff00ff">&lt;boost/spirit/utility/escape_char.hpp&gt;</font><br>
<font color="#a020f0">#include </font><font color="#ff00ff">&lt;iostream&gt;</font><br>
<font color="#a020f0">#include </font><font color="#ff00ff">&lt;fstream&gt;</font><br>
<font color="#0000ff">///////////////////////////////////////////////////////////////////////////////</font><br>
<font color="#804040"><strong>using</strong></font> <font color="#2e8b57"><strong>namespace</strong></font> boost::spirit;<br>
<font color="#804040"><strong>using</strong></font> <font color="#2e8b57"><strong>namespace</strong></font> std;<br>
<br>
<font color="#0000ff">////////////////////////////////////////////////////////////////////////////</font><br>
<font color="#0000ff">//</font><br>
<font color="#0000ff">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;             Types</font><br>
<font color="#0000ff">//types needed for file parsing</font><br>
<font color="#0000ff">////////////////////////////////////////////////////////////////////////////</font><br>
<font color="#2e8b57"><strong>typedef</strong></font> <font color="#2e8b57"><strong>char</strong></font> char_t;<br>
<font color="#2e8b57"><strong>typedef</strong></font> file_iterator &lt; char_t &gt; iterator_t;<br>
<font color="#2e8b57"><strong>typedef</strong></font> scanner &lt; iterator_t &gt; scanner_t;<br>
<font color="#2e8b57"><strong>typedef</strong></font> rule &lt; scanner_t &gt; rule_t;<br>
<br>
<font color="#0000ff">////////////////////////////////////////////////////////////////////////////</font><br>
<font color="#0000ff">//To ansi，action函数，匹配后输出成ansi代码的彩色控制符，</font><br>
<font color="#0000ff">//可参考各大高校bbs的asciiart版精华区，可以输出成需要的格式，如html</font><br>
<font color="#0000ff">//</font><br>
<font color="#0000ff">////////////////////////////////////////////////////////////////////////////</font><br>
ofstream outfile;<br>
<font color="#2e8b57"><strong>namespace</strong></font> to_ansi<br>
{<br>
&nbsp;&nbsp;<font color="#2e8b57"><strong>void</strong></font><br>
&nbsp;&nbsp;            black (iterator_t first, iterator_t <font color="#2e8b57"><strong>const</strong></font> &amp;last)<br>
&nbsp;&nbsp;            {<br>
&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; <font color="#ff00ff">"</font><font color="#6a5acd">\033</font><font color="#ff00ff">[1;30m"</font>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>while</strong></font> (first != last)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; *first++;<br>
&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; <font color="#ff00ff">"</font><font color="#6a5acd">\033</font><font color="#ff00ff">[m"</font>;<br>
&nbsp;&nbsp;            }<br>
<br>
&nbsp;&nbsp;<font color="#2e8b57"><strong>void</strong></font><br>
&nbsp;&nbsp;            red (iterator_t first, iterator_t <font color="#2e8b57"><strong>const</strong></font> &amp;last)<br>
&nbsp;&nbsp;            {<br>
&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; <font color="#ff00ff">"</font><font color="#6a5acd">\033</font><font color="#ff00ff">[1;31m"</font>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>while</strong></font> (first != last)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; *first++;<br>
&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; <font color="#ff00ff">"</font><font color="#6a5acd">\033</font><font color="#ff00ff">[m"</font>;<br>
&nbsp;&nbsp;            }<br>
<br>
&nbsp;&nbsp;<font color="#2e8b57"><strong>void</strong></font><br>
&nbsp;&nbsp;            green (iterator_t first, iterator_t <font color="#2e8b57"><strong>const</strong></font> &amp;last)<br>
&nbsp;&nbsp;            {<br>
&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; <font color="#ff00ff">"</font><font color="#6a5acd">\033</font><font color="#ff00ff">[1;32m"</font>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>while</strong></font> (first != last)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; *first++;<br>
&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; <font color="#ff00ff">"</font><font color="#6a5acd">\033</font><font color="#ff00ff">[m"</font>;<br>
&nbsp;&nbsp;            }<br>
<br>
&nbsp;&nbsp;<font color="#2e8b57"><strong>void</strong></font><br>
&nbsp;&nbsp;            yellow (iterator_t first, iterator_t <font color="#2e8b57"><strong>const</strong></font> &amp;last)<br>
&nbsp;&nbsp;            {<br>
&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; <font color="#ff00ff">"</font><font color="#6a5acd">\033</font><font color="#ff00ff">[1;33m"</font>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>while</strong></font> (first != last)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; *first++;<br>
&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; <font color="#ff00ff">"</font><font color="#6a5acd">\033</font><font color="#ff00ff">[m"</font>;<br>
&nbsp;&nbsp;            }<br>
<br>
&nbsp;&nbsp;<font color="#2e8b57"><strong>void</strong></font><br>
&nbsp;&nbsp;            blue (iterator_t first, iterator_t <font color="#2e8b57"><strong>const</strong></font> &amp;last)<br>
&nbsp;&nbsp;            {<br>
&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; <font color="#ff00ff">"</font><font color="#6a5acd">\033</font><font color="#ff00ff">[1;34m"</font>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>while</strong></font> (first != last)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; *first++;<br>
&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; <font color="#ff00ff">"</font><font color="#6a5acd">\033</font><font color="#ff00ff">[m"</font>;<br>
&nbsp;&nbsp;            }<br>
<br>
&nbsp;&nbsp;<font color="#2e8b57"><strong>void</strong></font><br>
&nbsp;&nbsp;            magenta (iterator_t first, iterator_t <font color="#2e8b57"><strong>const</strong></font> &amp;last)<br>
&nbsp;&nbsp;            {<br>
&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; <font color="#ff00ff">"</font><font color="#6a5acd">\033</font><font color="#ff00ff">[1;35m"</font>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>while</strong></font> (first != last)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; *first++;<br>
&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; <font color="#ff00ff">"</font><font color="#6a5acd">\033</font><font color="#ff00ff">[m"</font>;<br>
&nbsp;&nbsp;            }<br>
<br>
&nbsp;&nbsp;<font color="#2e8b57"><strong>void</strong></font><br>
&nbsp;&nbsp;            cyan (iterator_t first, iterator_t <font color="#2e8b57"><strong>const</strong></font> &amp;last)<br>
&nbsp;&nbsp;            {<br>
&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; <font color="#ff00ff">"</font><font color="#6a5acd">\033</font><font color="#ff00ff">[1;36m"</font>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>while</strong></font> (first != last)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; *first++;<br>
&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; <font color="#ff00ff">"</font><font color="#6a5acd">\033</font><font color="#ff00ff">[m"</font>;<br>
&nbsp;&nbsp;            }<br>
<br>
&nbsp;&nbsp;<font color="#2e8b57"><strong>void</strong></font><br>
&nbsp;&nbsp;            white (iterator_t first, iterator_t <font color="#2e8b57"><strong>const</strong></font> &amp;last)<br>
&nbsp;&nbsp;            {<br>
&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; <font color="#ff00ff">"</font><font color="#6a5acd">\033</font><font color="#ff00ff">[1;37m"</font>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>while</strong></font> (first != last)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; *first++;<br>
&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; <font color="#ff00ff">"</font><font color="#6a5acd">\033</font><font color="#ff00ff">[m"</font>;<br>
&nbsp;&nbsp;            }<br>
<br>
&nbsp;&nbsp;<font color="#2e8b57"><strong>void</strong></font><br>
&nbsp;&nbsp;            echo (iterator_t first, iterator_t <font color="#2e8b57"><strong>const</strong></font> &amp;last)<br>
&nbsp;&nbsp;            {<br>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>while</strong></font> (first != last)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            outfile &lt;&lt; *first++;<br>
&nbsp;&nbsp;            }<br>
}<br>
<font color="#0000ff">////////////////////////////////////////////////////////////////////////////</font><br>
<font color="#0000ff">//</font><br>
<font color="#0000ff">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;             cpp lex</font><br>
<font color="#0000ff">//c++的词法描述，有了comment_p就方便多了，识别函数名还没实现</font><br>
<font color="#0000ff">////////////////////////////////////////////////////////////////////////////</font><br>
<font color="#2e8b57"><strong>namespace</strong></font> cpp_lex<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;            rule_t comment = comment_p (<font color="#ff00ff">"/*"</font>, <font color="#ff00ff">"*/"</font>) <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | comment_p (<font color="#ff00ff">"//"</font>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            ;<br>
&nbsp;&nbsp;&nbsp;&nbsp;            rule_t whitespace = space_p<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            ;<br>
&nbsp;&nbsp;&nbsp;&nbsp;            rule_t include = str_p (<font color="#ff00ff">"#include"</font>) &gt;&gt; *space_p &gt;&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            (comment_p (<font color="#ff00ff">"&lt;"</font>, <font color="#ff00ff">"&gt;"</font>) | comment_p (<font color="#ff00ff">"</font><font color="#6a5acd">\"</font><font color="#ff00ff">"</font>, <font color="#ff00ff">"</font><font color="#6a5acd">\"</font><font color="#ff00ff">"</font>))<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            ;<br>
&nbsp;&nbsp;&nbsp;&nbsp;            rule_t preprocessor = (include | <font color="#ff00ff">"##"</font> | <font color="#ff00ff">"#define"</font> | <font color="#ff00ff">"#error"</font> | (<font color="#ff00ff">"#if"</font> &gt;&gt; space_p)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | <font color="#ff00ff">"#ifdef"</font> | <font color="#ff00ff">"#ifndef"</font> | <font color="#ff00ff">"#else"</font> | <font color="#ff00ff">"#elif"</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | <font color="#ff00ff">"#endif"</font> | <font color="#ff00ff">"#line"</font> | <font color="#ff00ff">"#pragma"</font> | <font color="#ff00ff">"#undef"</font> | <font color="#ff00ff">"#"</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | <font color="#ff00ff">"__LINE__"</font> | <font color="#ff00ff">"__FILE__"</font> | <font color="#ff00ff">"__DATE__"</font> | <font color="#ff00ff">"__TIME__"</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | <font color="#ff00ff">"_cplusplus"</font> | <font color="#ff00ff">"__STDC__"</font>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            &gt;&gt; space_p<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            ;<br>
&nbsp;&nbsp;&nbsp;&nbsp;            rule_t keyword_ = str_p (<font color="#ff00ff">"asm"</font>) | <font color="#ff00ff">"auto"</font> | <font color="#ff00ff">"bool"</font> | <font color="#ff00ff">"break"</font> | <font color="#ff00ff">"case"</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | <font color="#ff00ff">"catch"</font> | <font color="#ff00ff">"char"</font> | <font color="#ff00ff">"class"</font> | <font color="#ff00ff">"const"</font> | <font color="#ff00ff">"const_cast"</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | <font color="#ff00ff">"continue"</font> | <font color="#ff00ff">"default"</font> | <font color="#ff00ff">"delete"</font> | <font color="#ff00ff">"do"</font> | <font color="#ff00ff">"double"</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | <font color="#ff00ff">"dynamic_cast"</font> | <font color="#ff00ff">"else"</font> | <font color="#ff00ff">"enum"</font> | <font color="#ff00ff">"explicit"</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | <font color="#ff00ff">"extern"</font> | <font color="#ff00ff">"false"</font> | <font color="#ff00ff">"float"</font> | <font color="#ff00ff">"for"</font> | <font color="#ff00ff">"friend"</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | <font color="#ff00ff">"goto"</font> | <font color="#ff00ff">"if"</font> | <font color="#ff00ff">"inline"</font> | <font color="#ff00ff">"int"</font> | <font color="#ff00ff">"long"</font> | <font color="#ff00ff">"mutable"</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | <font color="#ff00ff">"namespace"</font> | <font color="#ff00ff">"new"</font> | <font color="#ff00ff">"operator"</font> | <font color="#ff00ff">"private"</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | <font color="#ff00ff">"protected"</font> | <font color="#ff00ff">"public"</font> | <font color="#ff00ff">"register"</font> | <font color="#ff00ff">"reinterpret_cast"</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | <font color="#ff00ff">"return"</font> | <font color="#ff00ff">"short"</font> | <font color="#ff00ff">"signed"</font> | <font color="#ff00ff">"sizeof"</font> | <font color="#ff00ff">"static"</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | <font color="#ff00ff">"static_cast"</font> | <font color="#ff00ff">"struct"</font> | <font color="#ff00ff">"switch"</font> | <font color="#ff00ff">"template"</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | <font color="#ff00ff">"this"</font> | <font color="#ff00ff">"throw"</font> | <font color="#ff00ff">"true"</font> | <font color="#ff00ff">"try"</font> | <font color="#ff00ff">"typedef"</font> | <font color="#ff00ff">"typeid"</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | <font color="#ff00ff">"typename"</font> | <font color="#ff00ff">"union"</font> | <font color="#ff00ff">"unsighed"</font> | <font color="#ff00ff">"using"</font> | <font color="#ff00ff">"virtual"</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | <font color="#ff00ff">"void"</font> | <font color="#ff00ff">"volatile"</font> | <font color="#ff00ff">"wchar_t"</font> | <font color="#ff00ff">"while"</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            ;<br>
&nbsp;&nbsp;&nbsp;&nbsp;            rule_t keyword = keyword_ &gt;&gt; space_p<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            ;<br>
&nbsp;&nbsp;&nbsp;&nbsp;            rule_t identifer = (alpha_p | <font color="#ff00ff">'_'</font>) &gt;&gt; *(alnum_p | <font color="#ff00ff">'_'</font>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&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;            rule_t operators = punct_p - <font color="#ff00ff">'`'</font> - <font color="#ff00ff">'@'</font> - <font color="#ff00ff">'$'</font> - <font color="#6a5acd">'\\'</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            ;<br>
&nbsp;&nbsp;&nbsp;&nbsp;            rule_t number = real_p<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            ;<br>
&nbsp;&nbsp;&nbsp;&nbsp;            rule_t str = confix_p (<font color="#ff00ff">"</font><font color="#6a5acd">\"</font><font color="#ff00ff">"</font>, *c_escape_ch_p, <font color="#ff00ff">"</font><font color="#6a5acd">\"</font><font color="#ff00ff">"</font>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            ;<br>
&nbsp;&nbsp;&nbsp;&nbsp;            rule_t charcter = confix_p(<font color="#ff00ff">"</font><font color="#6a5acd">\'</font><font color="#ff00ff">"</font>, *c_escape_ch_p, <font color="#ff00ff">"</font><font color="#6a5acd">\'</font><font color="#ff00ff">"</font>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            ;<br>
&nbsp;&nbsp;&nbsp;&nbsp;            rule_t constant = number<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | str<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | charcter<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            ;<br>
<br>
};<br>
<br>
<br>
<br>
<font color="#0000ff">////////////////////////////////////////////////////////////////////////////</font><br>
<font color="#0000ff">//</font><br>
<font color="#0000ff">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;             Main program</font><br>
<font color="#0000ff">//</font><br>
<font color="#0000ff">////////////////////////////////////////////////////////////////////////////</font><br>
<font color="#2e8b57"><strong>int</strong></font><br>
main (<font color="#2e8b57"><strong>int</strong></font> argc, <font color="#2e8b57"><strong>char</strong></font> *argv[])<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            string filepath;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>if</strong></font> (<font color="#ff00ff">2</font> &gt; argc)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            {<font color="#0000ff">//把要处理的文件拖到窗口内</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            cout &lt;&lt; <font color="#ff00ff">"drag file to this windows</font><font color="#6a5acd">\n</font><font color="#ff00ff">"</font>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            string filepath_input;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            getline(cin, filepath_input);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            filepath_input.erase(filepath_input.end()-<font color="#ff00ff">1</font>); <font color="#0000ff">//去掉结尾的'\"'</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            filepath_input.erase(filepath_input.begin());&nbsp;&nbsp;             <font color="#0000ff">//去掉开头"</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>for</strong></font> (<font color="#2e8b57"><strong>int</strong></font> i = <font color="#ff00ff">0</font>; filepath_input[i] != <font color="#ff00ff">0</font>; i++) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            filepath.push_back(filepath_input[i]);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>if</strong></font> (filepath_input[i] == <font color="#6a5acd">'\\'</font>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            filepath.push_back(<font color="#6a5acd">'\\'</font>);<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;            }<font color="#804040"><strong>else</strong></font>{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">// for console usage</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            filepath = argv[<font color="#ff00ff">1</font>];<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            }<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            iterator_t first (filepath);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>if</strong></font> (!first)&nbsp;&nbsp;            {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            std::cerr &lt;&lt; <font color="#ff00ff">"Unable to open file!</font><font color="#6a5acd">\n</font><font color="#ff00ff">"</font>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>return</strong></font> -<font color="#ff00ff">1</font>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            }<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">// Create an EOF iterator</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            iterator_t last = first.make_end ();<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            string filepath_output = filepath+<font color="#ff00ff">".txt"</font>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            outfile.open(filepath_output.c_str());<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">// A simple rule词法对应的颜色在这里改就可以</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            rule_t r = *(<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            cpp_lex::comment[&amp;to_ansi::cyan]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | cpp_lex::constant[&amp;to_ansi::yellow]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | cpp_lex::preprocessor[&amp;to_ansi::red]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | cpp_lex::keyword[&amp;to_ansi::green]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | cpp_lex::whitespace[&amp;to_ansi::echo]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | cpp_lex::operators[&amp;to_ansi::magenta]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            | cpp_lex::identifer[&amp;to_ansi::white]<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;&nbsp;&nbsp;&nbsp;&nbsp;            ;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">//&nbsp;&nbsp;             </font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">// Parse</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">/*</font><font color="#0000ff">The parse_info structure</font><br>
<font color="#0000ff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;             The functions above return a parse_info structure parameterized by the iterator type passed in. </font><br>
<font color="#0000ff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;             The parse_info struct has these members:parse_info</font><br>
<font color="#0000ff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stop&nbsp;&nbsp;&nbsp;&nbsp; Points to the final parse
position (i.e The parser recognized and processed the input up to this
point)</font><br>
<font color="#0000ff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hit&nbsp;&nbsp;&nbsp;&nbsp; True if parsing is successful.
This may be full: the parser consumed all the input, or partial: the
parser consumed only a portion of the input.</font><br>
<font color="#0000ff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;             full&nbsp;&nbsp;&nbsp;&nbsp;            True when we have a full match (i.e The parser consumed all the input).</font><br>
<font color="#0000ff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; length&nbsp;&nbsp;&nbsp;&nbsp; The number of characters
consumed by the parser. This is valid only if we have a successful
match (either partial or full). </font><br>
<font color="#0000ff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#0000ff">*/</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            parse_info &lt; iterator_t &gt; info = parse (first, last, r);<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">// This really shouldn't fail...</font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>if</strong></font> (info.full)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            std::cout &lt;&lt; <font color="#ff00ff">"</font><font color="#6a5acd">\n</font><font color="#ff00ff">Parse succeeded!</font><font color="#6a5acd">\n</font><font color="#ff00ff">"</font>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>else</strong></font><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;            std::cout &lt;&lt; <font color="#ff00ff">"</font><font color="#6a5acd">\n</font><font color="#ff00ff">Parse failed!</font><font color="#6a5acd">\n</font><font color="#ff00ff">"</font>;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
</font><font face="fixedsys"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;         std::cout &lt;&lt; <font color="#ff00ff">"highlight file saved in "</font> &lt;&lt; filepath_output &lt;&lt; endl;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;        string end;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;        getline (cin, end);<font color="#0000ff">//按回车键推出窗口</font><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>return</strong></font> <font color="#ff00ff">0</font>;<br>
}</font></p>
<p> </p>
<div forimg="1"> </div>
<font face="fixedsys"><br>
这只是个词法高亮程序，还不能识别语法，如函数等，用正则也能做，但boost.spirit更简单</font></font></font><br><br><img src ="http://www.cppblog.com/richardhe/aggbug/55612.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-07-08 11:49 <a href="http://www.cppblog.com/richardhe/articles/55612.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>内存分区</title><link>http://www.cppblog.com/richardhe/articles/55395.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Sat, 05 Jul 2008 05:39:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/55395.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/55395.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/55395.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/55395.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/55395.html</trackback:ping><description><![CDATA[来自http://www.cppblog.com/road420/archive/2008/07/05/55388.html<br>
<p><strong>五大内存分区</strong><br>&nbsp;&nbsp;&nbsp; 在C++中，内存分成5个区，他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。<br>&nbsp;&nbsp;&nbsp; 栈，就是那些由编译器在需要的时候分配，在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。<br>&nbsp;&nbsp;&nbsp; 堆，就是那些由new分配的内存块，他们的释放编译器不去管，由我们的应用程序去控制，一般一个new就要对应一个delete。如果程序员没有释放掉，那么在程序结束后，操作系统会自动回收。<br>&nbsp;&nbsp;&nbsp; 自由存储区，就是那些由malloc等分配的内存块，他和堆是十分相似的，不过它是用free来结束自己的生命的。<br>&nbsp;&nbsp;&nbsp; 全局/静态存储区，全局变量和静态变量被分配到同一块内存中，在以前的C语言中，全局变量又分为初始化的和未初始化的，在C++里面没有这个区分了，他们共同占用同一块内存区。<br>&nbsp;&nbsp;&nbsp; 常量存储区，这是一块比较特殊的存储区，他们里面存放的是常量，不允许修改（当然，你要通过非正当手段也可以修改，而且方法很多）<br><strong>明确区分堆与栈<br></strong>&nbsp;&nbsp;&nbsp; 在bbs上，堆与栈的区分问题，似乎是一个永恒的话题，由此可见，初学者对此往往是混淆不清的，所以我决定拿他第一个开刀。<br>&nbsp;&nbsp;&nbsp; 首先，我们举一个例子：<br>&nbsp;&nbsp;&nbsp; void f() { int* p=new int[5]; } <br>&nbsp;&nbsp;&nbsp;
这条短短的一句话就包含了堆与栈，看到new，我们首先就应该想到，我们分配了一块堆内存，那么指针p呢？他分配的是一块栈内存，所以这句话的意思就是：
在栈内存中存放了一个指向一块堆内存的指针p。在程序会先确定在堆中分配内存的大小，然后调用operator
new分配内存，然后返回这块内存的首地址，放入栈中，他在VC6下的汇编代码如下：<br>&nbsp;&nbsp;&nbsp; 00401028&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 14h<br>&nbsp;&nbsp;&nbsp; 0040102A&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; operator new (00401060)<br>&nbsp;&nbsp;&nbsp; 0040102F&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; esp,4<br>&nbsp;&nbsp;&nbsp; 00401032&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-8],eax<br>&nbsp;&nbsp;&nbsp; 00401035&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eax,dword ptr [ebp-8]<br>&nbsp;&nbsp;&nbsp; 00401038&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-4],eax<br>&nbsp;&nbsp;&nbsp; 这里，我们为了简单并没有释放内存，那么该怎么去释放呢？是delete p么？澳，错了，应该是delete []p，这是为了告诉编译器：我删除的是一个数组，VC6就会根据相应的Cookie信息去进行释放内存的工作。<br>&nbsp;&nbsp;&nbsp; 好了，我们回到我们的主题：堆和栈究竟有什么区别？ <br>&nbsp;&nbsp;&nbsp; 主要的区别由以下几点：<br>&nbsp;&nbsp;&nbsp; 1、管理方式不同；<br>&nbsp;&nbsp;&nbsp; 2、空间大小不同；<br>&nbsp;&nbsp;&nbsp; 3、能否产生碎片不同；<br>&nbsp;&nbsp;&nbsp; 4、生长方向不同；<br>&nbsp;&nbsp;&nbsp; 5、分配方式不同；<br>&nbsp;&nbsp;&nbsp; 6、分配效率不同；<br>&nbsp;&nbsp;&nbsp; 管理方式：对于栈来讲，是由编译器自动管理，无需我们手工控制；对于堆来说，释放工作由程序员控制，容易产生memory leak。<br>&nbsp;&nbsp;&nbsp; 空间大小：一般来讲在32位系统下，堆内存可以达到4G的空间，从这个角度来看堆内存几乎是没有什么限制的。但是对于栈来讲，一般都是有一定的空间大小的，例如，在VC6下面，默认的栈空间大小是1M（好像是，记不清楚了）。当然，我们可以修改：&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 打开工程，依次操作菜单如下：Project-&gt;Setting-&gt;Link，在Category 中选中Output，然后在Reserve中设定堆栈的最大值和commit。<br>注意：reserve最小值为4Byte；commit是保留在虚拟内存的页文件里面，它设置的较大会使栈开辟较大的值，可能增加内存的开销和启动时间。<br>&nbsp;&nbsp;&nbsp;
碎片问题：对于堆来讲，频繁的new/delete势必会造成内存空间的不连续，从而造成大量的碎片，使程序效率降低。对于栈来讲，则不会存在这个问题，
因为栈是先进后出的队列，他们是如此的一一对应，以至于永远都不可能有一个内存块从栈中间弹出，在他弹出之前，在他上面的后进的栈内容已经被弹出，详细的
可以参考数据结构，这里我们就不再一一讨论了。<br>&nbsp;&nbsp;&nbsp; 生长方向：对于堆来讲，生长方向是向上的，也就是向着内存地址增加的方向；对于栈来讲，它的生长方向是向下的，是向着内存地址减小的方向增长。<br>&nbsp;&nbsp;&nbsp; 分配方式：堆都是动态分配的，没有静态分配的堆。栈有2种分配方式：静态分配和动态分配。静态分配是编译器完成的，比如局部变量的分配。动态分配由alloca函数进行分配，但是栈的动态分配和堆是不同的，他的动态分配是由编译器进行释放，无需我们手工实现。<br>&nbsp;&nbsp;&nbsp;
分配效率：栈是机器系统提供的数据结构，计算机会在底层对栈提供支持：分配专门的寄存器存放栈的地址，压栈出栈都有专门的指令执行，这就决定了栈的效率比
较高。堆则是C/C++函数库提供的，它的机制是很复杂的，例如为了分配一块内存，库函数会按照一定的算法（具体的算法可以参考数据结构/操作系统）在堆
内存中搜索可用的足够大小的空间，如果没有足够大小的空间（可能是由于内存碎片太多），就有可能调用系统功能去增加程序数据段的内存空间，这样就有机会分
到足够大小的内存，然后进行返回。显然，堆的效率比栈要低得多。<br>&nbsp;&nbsp;&nbsp;
从这里我们可以看到，堆和栈相比，由于大量new/delete的使用，容易造成大量的内存碎片；由于没有专门的系统支持，效率很低；由于可能引发用户态
和核心态的切换，内存的申请，代价变得更加昂贵。所以栈在程序中是应用最广泛的，就算是函数的调用也利用栈去完成，函数调用过程中的参数，返回地
址，EBP和局部变量都采用栈的方式存放。所以，我们推荐大家尽量用栈，而不是用堆。<br>&nbsp;&nbsp;&nbsp; 虽然栈有如此众多的好处，但是由于和堆相比不是那么灵活，有时候分配大量的内存空间，还是用堆好一些。<br>&nbsp;&nbsp;&nbsp;
无论是堆还是栈，都要防止越界现象的发生（除非你是故意使其越界），因为越界的结果要么是程序崩溃，要么是摧毁程序的堆、栈结构，产生以想不到的结果,就
算是在你的程序运行过程中，没有发生上面的问题，你还是要小心，说不定什么时候就崩掉，那时候debug可是相当困难的：）<br>&nbsp;&nbsp;&nbsp; 对了，还有一件事，如果有人把堆栈合起来说，那它的意思是栈，可不是堆，呵呵，清楚了？<br><strong>static用来控制变量的存储方式和可见性<br></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
函数内部定义的变量，在程序执行到它的定义处时，编译器为它在栈上分配空间，函数在栈上分配的空间在此函数执行结束时会释放掉，这样就产生了一个问题:
如果想将函数中此变量的值保存至下一次调用时，如何实现？
最容易想到的方法是定义一个全局的变量，但定义为一个全局变量有许多缺点，最明显的缺点是破坏了此变量的访问范围（使得在此函数中定义的变量，不仅仅受此
函数控制）。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 需要一个数据对象为整个类而非某个对象服务,同时又力求不破坏类的封装性,即要求此成员隐藏在类的内部，对外不可见。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static的内部机制：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 静态数据成员要在程序一开始运行时就必须存在。因为函数在程序运行中被调用，所以静态数据成员不能在任何函数内分配空间和初始化。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这样，它的空间分配有三个可能的地方，一是作为类的外部接口的头文件，那里有类声明；二是类定义的内部实现，那里有类的成员函数定义；三是应用程序的main（）函数前的全局数据声明和定义处。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
静态数据成员要实际地分配空间，故不能在类的声明中定义（只能声明数据成员）。类声明只声明一个类的&#8220;尺寸和规格&#8221;，并不进行实际的内存分配，所以在类声
明中写成定义是错误的。它也不能在头文件中类声明的外部定义，因为那会造成在多个使用该类的源文件中，对其重复定义。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static被引入以告知编译器，将变量存储在程序的静态存储区而非栈上空间，静态<br>数据成员按定义出现的先后顺序依次初始化，注意静态成员嵌套时，要保证所嵌套的成员已经初始化了。消除时的顺序是初始化的反顺序。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static的优势：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
可以节省内存，因为它是所有对象所公有的，因此，对多个对象来说，静态数据成员只存储一处，供所有对象共用。静态数据成员的值对每个对象都是一样，但它的
值是可以更新的。只要对静态数据成员的值更新一次，保证所有对象存取更新后的相同的值，这样可以提高时间效率。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 引用静态数据成员时，采用如下格式：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;类名&gt;::&lt;静态成员名&gt;<br>&nbsp;&nbsp;&nbsp; 如果静态数据成员的访问权限允许的话(即public的成员)，可在程序中，按上述格式<br>来引用静态数据成员。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PS:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (1)类的静态成员函数是属于整个类而非类的对象，所以它没有this指针，这就导致<br>了它仅能访问类的静态数据和静态成员函数。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (2)不能将静态成员函数定义为虚函数。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (3)由于静态成员声明于类中，操作于其外，所以对其取地址操作，就多少有些特殊<br>，变量地址是指向其数据类型的指针 ，函数地址类型是一个&#8220;nonmember函数指针&#8221;。</p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (4)由于静态成员函数没有this指针，所以就差不多等同于nonmember函数，结果就<br>产生了一个意想不到的好处：成为一个callback函数，使得我们得以将C++和C-based X W<br>indow系统结合，同时也成功的应用于线程函数身上。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (5)static并没有增加程序的时空开销，相反她还缩短了子类对父类静态成员的访问<br>时间，节省了子类的内存空间。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (6)静态数据成员在&lt;定义或说明&gt;时前面加关键字static。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (7)静态数据成员是静态存储的，所以必须对它进行初始化。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (8)静态成员初始化与一般数据成员初始化不同:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 初始化在类体外进行，而前面不加static，以免与一般静态变量或对象相混淆；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 初始化时不加该成员的访问权限控制符private，public等；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 初始化时使用作用域运算符来标明它所属类；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所以我们得出静态数据成员初始化的格式：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;数据类型&gt;&lt;类名&gt;::&lt;静态数据成员名&gt;=&lt;值&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
(9)为了防止父类的影响，可以在子类定义一个与父类相同的静态变量，以屏蔽父类的影响。这里有一点需要注意：我们说静态成员为父类和子类共享，但我们有
重复定义了静态成员，这会不会引起错误呢？不会，我们的编译器采用了一种绝妙的手法：name-mangling 用以生成唯一的标志。<br><br><img src ="http://www.cppblog.com/richardhe/aggbug/55395.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-07-05 13:39 <a href="http://www.cppblog.com/richardhe/articles/55395.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>回调函数</title><link>http://www.cppblog.com/richardhe/articles/55396.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Sat, 05 Jul 2008 05:39:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/55396.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/55396.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/55396.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/55396.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/55396.html</trackback:ping><description><![CDATA[来自http://www.cppblog.com/road420/archive/2008/07/05/55390.html<br>
<p><strong>简介<br><br></strong>　　对于很多初学者来说，往往觉得回调函数很神秘，很想知道回调函数的工作原理。本文将要解释什么是回调函数、它们有什么好处、为什么要使用它们等等问题，在开始之前，假设你已经熟知了函数指针。 <br><br>　　<strong>什么是回调函数？</strong><br><br>　　简而言之，回调函数就是一个通过函数指针调用的函数。如果你把函数的指针（地址）作为参数传递给另一个函数，当这个指针被用为调用它所指向的函数时，我们就说这是回调函数。<br><br>　　<strong>为什么要使用回调函数？</strong><br><br>　　因为可以把调用者与被调用者分开。调用者不关心谁是被调用者，所有它需知道的，只是存在一个具有某种特定原型、某些限制条件（如返回值为int）的被调用函数。<br><br>
如果想知道回调函数在实际中有什么作用，先假设有这样一种情况，我们要编写一个库，它提供了某些排序算法的实现，如冒泡排序、快速排序、shell排
序、shake排序等等，但为使库更加通用，不想在函数中嵌入排序逻辑，而让使用者来实现相应的逻辑；或者，想让库可用于多种数据类型（int、
float、string），此时，该怎么办呢？可以使用函数指针，并进行回调。<br><br>　　回调可用于通知机制，例如，有时要在程序中设置一个
计时器，每到一定时间，程序会得到相应的通知，但通知机制的实现者对我们的程序一无所知。而此时，就需有一个特定原型的函数指针，用这个指针来进行回调，
来通知我们的程序事件已经发生。实际上，SetTimer()
API使用了一个回调函数来通知计时器，而且，万一没有提供回调函数，它还会把一个消息发往程序的消息队列。<br><br>　　另一个使用回调机制的
API函数是EnumWindow()，它枚举屏幕上所有的顶层窗口，为每个窗口调用一个程序提供的函数，并传递窗口的处理程序。如果被调用者返回一个
值，就继续进行迭代，否则，退出。EnumWindow()并不关心被调用者在何处，也不关心被调用者用它传递的处理程序做了什么，它只关心返回值，因为
基于返回值，它将继续执行或退出。<br><br>　　不管怎么说，回调函数是继续自C语言的，因而，在C++中，应只在与C代码建立接口，或与已有的回调接口打交道时，才使用回调函数。除了上述情况，在C++中应使用虚拟方法或函数符（functor），而不是回调函数。<br><br>　　<strong>一个简单的回调函数实现</strong><br><br>
下面创建了一个sort.dll的动态链接库，它导出了一个名为CompareFunction的类型--typedef int
(__stdcall *CompareFunction)(const byte*, const
byte*)，它就是回调函数的类型。另外，它也导出了两个方法：Bubblesort()和Quicksort()，这两个方法原型相同，但实现了不同
的排序算法。<br><br>
<table width="90%" align="center" bgcolor="#e7e9e9" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>void DLLDIR __stdcall Bubblesort(byte* array,int size,int elem_size,CompareFunction cmpFunc);<br><br>void DLLDIR __stdcall Quicksort(byte* array,int size,int elem_size,CompareFunction cmpFunc);</td>
        </tr>
    </tbody>
</table>
<br>　　这两个函数接受以下参数：<br><br>　　&#183;byte * array：指向元素数组的指针（任意类型）。<br><br>　　&#183;int size：数组中元素的个数。<br><br>　　&#183;int elem_size：数组中一个元素的大小，以字节为单位。<br><br>　　&#183;CompareFunction cmpFunc：带有上述原型的指向回调函数的指针。<br><br>
这两个函数的会对数组进行某种排序，但每次都需决定两个元素哪个排在前面，而函数中有一个回调函数，其地址是作为一个参数传递进来的。对编写者来说，不
必介意函数在何处实现，或它怎样被实现的，所需在意的只是两个用于比较的元素的地址，并返回以下的某个值（库的编写者和使用者都必须遵守这个约定）：<br><br>　　&#183;-1：如果第一个元素较小，那它在已排序好的数组中，应该排在第二个元素前面。<br><br>　　&#183;0：如果两个元素相等，那么它们的相对位置并不重要，在已排序好的数组中，谁在前面都无所谓。 <br><br>　　&#183;1：如果第一个元素较大，那在已排序好的数组中，它应该排第二个元素后面。<br><br>　　基于以上约定，函数Bubblesort()的实现如下，Quicksort()就稍微复杂一点：<br><br>
<table width="90%" align="center" bgcolor="#e7e9e9" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>void DLLDIR __stdcall Bubblesort(byte* array,int size,int elem_size,CompareFunction cmpFunc)<br>{<br>　for(int i=0; i &lt; size; i++)<br>　{<br>　　for(int j=0; j &lt; size-1; j++)<br>　　{<br>　　　//回调比较函数<br>　　　if(1 == (*cmpFunc)(array+j*elem_size,array+(j+1)*elem_size))<br>　　　{<br>　　　　//两个相比较的元素相交换<br>　　　　byte* temp = new byte[elem_size];<br>　　　　memcpy(temp, array+j*elem_size, elem_size);<br>　　　　memcpy(array+j*elem_size,array+(j+1)*elem_size,elem_size);<br>　　　　memcpy(array+(j+1)*elem_size, temp, elem_size);<br>　　　　delete [] temp;<br>　　　}<br>　　}<br>　}<br>}</td>
        </tr>
    </tbody>
</table>
<br>　　注意：因为实现中使用了memcpy()，所以函数在使用的数据类型方面，会有所局限。<br><br>　　对使用者来说，必须有一个回调函数，其地址要传递给Bubblesort()函数。下面有二个简单的示例，一个比较两个整数，而另一个比较两个字符串：<br><br>
<table width="90%" align="center" bgcolor="#e7e9e9" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>int __stdcall CompareInts(const byte* velem1, const byte* velem2)<br>{<br>　int elem1 = *(int*)velem1;<br>　int elem2 = *(int*)velem2;<br><br>　if(elem1 &lt; elem2)<br>　　return -1;<br>　if(elem1 &gt; elem2)<br>　　return 1;<br><br>　return 0;<br>}<br><br>int __stdcall CompareStrings(const byte* velem1, const byte* velem2)<br>{<br>　const char* elem1 = (char*)velem1;<br>　const char* elem2 = (char*)velem2;<br>　return strcmp(elem1, elem2);<br>}</td>
        </tr>
    </tbody>
</table>
<br>　　下面另有一个程序，用于测试以上所有的代码，它传递了一个有5个元素的数组给Bubblesort()和Quicksort()，同时还传递了一个指向回调函数的指针。<br><br>
<table width="90%" align="center" bgcolor="#e7e9e9" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>int main(int argc, char* argv[])<br>{<br>　int i;<br>　int array[] = {5432, 4321, 3210, 2109, 1098};<br><br>　cout &lt;&lt; "Before sorting ints with Bubblesort\n";<br>　for(i=0; i &lt; 5; i++)<br>　　cout &lt;&lt; array[i] &lt;&lt; '\n';<br><br>　Bubblesort((byte*)array, 5, sizeof(array[0]), &amp;CompareInts);<br><br>　cout &lt;&lt; "After the sorting\n";<br>　for(i=0; i &lt; 5; i++)<br>　　cout &lt;&lt; array[i] &lt;&lt; '\n';<br><br>　const char str[5][10] = {"estella","danielle","crissy","bo","angie"};<br><br>　cout &lt;&lt; "Before sorting strings with Quicksort\n";<br>　for(i=0; i &lt; 5; i++)<br>　　cout &lt;&lt; str[i] &lt;&lt; '\n';<br><br>　Quicksort((byte*)str, 5, 10, &amp;CompareStrings);<br><br>　cout &lt;&lt; "After the sorting\n";<br>　for(i=0; i &lt; 5; i++)<br>　　cout &lt;&lt; str[i] &lt;&lt; '\n';<br><br>　return 0;<br>}</td>
        </tr>
    </tbody>
</table>
<br>　　如果想进行降序排序（大元素在先），就只需修改回调函数的代码，或使用另一个回调函数，这样编程起来灵活性就比较大了。</p>
<p><strong>调用约定<br><br></strong>　　上面的代码中，可在函数原型中找到__stdcall，因为它以双下划线打头，所
以它是一个特定于编译器的扩展，说到底也就是微软的实现。任何支持开发基于Win32的程序都必须支持这个扩展或其等价物。以__stdcall标识的函
数使用了标准调用约定，为什么叫标准约定呢，因为所有的Win32
API（除了个别接受可变参数的除外）都使用它。标准调用约定的函数在它们返回到调用者之前，都会从堆栈中移除掉参数，这也是Pascal的标准约定。但
在C/C++中，调用约定是调用者负责清理堆栈，而不是被调用函数；为强制函数使用C/C++调用约定，可使用__cdecl。另外，可变参数函数也使用
C/C++调用约定。<br><br>　　Windows操作系统采用了标准调用约定（Pascal约定），因为其可减小代码的体积。这点对早期的Windows来说非常重要，因为那时它运行在只有640KB内存的电脑上。<br><br>　　如果你不喜欢__stdcall，还可以使用CALLBACK宏，它定义在windef.h中：<br><br>
<table width="90%" align="center" bgcolor="#e7e9e9" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>#define CALLBACK __stdcallor<br><br>#define CALLBACK PASCAL //而PASCAL在此被#defined成__stdcall</td>
        </tr>
    </tbody>
</table>
<br>　　<strong>作为回调函数的C++方法</strong><br><br>　　因为平时很可能会使用到C++编写代码，也许会想到把回调函数写成类中的一个方法，但先来看看以下的代码：<br><br>
<table width="90%" align="center" bgcolor="#e7e9e9" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>class CCallbackTester<br>{<br>　public:<br>　int CALLBACK CompareInts(const byte* velem1, const byte* velem2);<br>};<br><br>Bubblesort((byte*)array, 5, sizeof(array[0]),<br>&amp;CCallbackTester::CompareInts);</td>
        </tr>
    </tbody>
</table>
<br>　　如果使用微软的编译器，将会得到下面这个编译错误：<br><br>
<table width="90%" align="center" bgcolor="#e7e9e9" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>error
            C2664: 'Bubblesort' : cannot convert parameter 4 from 'int (__stdcall
            CCallbackTester::*)(const unsigned char *,const unsigned char *)' to
            'int (__stdcall *)(const unsigned char *,const unsigned char *)' There
            is no context in which this conversion is possible</td>
        </tr>
    </tbody>
</table>
<br>　　这是因为非静态成员函数有一个额外的参数：this指针，这将迫使你在成员函数前面加上static。当然，还有几种方法可以解决这个问题，但限于篇幅，就不再论述了。</p>
<br><br><img src ="http://www.cppblog.com/richardhe/aggbug/55396.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-07-05 13:39 <a href="http://www.cppblog.com/richardhe/articles/55396.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Boost.Singals 教程</title><link>http://www.cppblog.com/richardhe/articles/55334.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Fri, 04 Jul 2008 05:23:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/55334.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/55334.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/55334.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/55334.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/55334.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 来自http://www.cppblog.com/jinq0123/archive/2008/06/30/boostsignalstutorial.htmlBoost.Singals 教程                                    Home            Libraries            People   ...&nbsp;&nbsp;<a href='http://www.cppblog.com/richardhe/articles/55334.html'>阅读全文</a><img src ="http://www.cppblog.com/richardhe/aggbug/55334.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-07-04 13:23 <a href="http://www.cppblog.com/richardhe/articles/55334.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]回调函数与转移表</title><link>http://www.cppblog.com/richardhe/articles/55333.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Fri, 04 Jul 2008 05:18:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/55333.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/55333.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/55333.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/55333.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/55333.html</trackback:ping><description><![CDATA[出自http://www.cppblog.com/zhaoyg/archive/2008/07/03/55206.html<br>
<p style="font-size: 10pt;">摘录自 《C和指针》<strong><br>1.回调函数</strong><br>这里有一个简单的函数,它用于在一个单链表中查找一个值,它的参数是一个指向链表第一个节点的指针以及那个需要查找的值.<br>Node* search_list(Node* node,int const value)<br>{&nbsp; <br>&nbsp;&nbsp; while(node!=NULL)<br>&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; if(node-&gt;value==value)&nbsp; break;<br>&nbsp;&nbsp;&nbsp; node=node-&gt;link;<br>&nbsp; }<br>&nbsp; return node;<br>}<br>&nbsp;这
个函数看上去相当简单,但它只适用于值为整数的链表,如果你需要在一个字符串链表中查找,你不得不另外编写一个函数,这个函数和上面那个函数的绝大部分代
码相同,只是第二个参数的类型以及节点值的比较方法不同.一种更为通用的方法是查找函数与类型无关,这样它就能用于任何类型的值的链表,我们必须对函数的
两个方面进行修改,使它与类型无关.<br>首先我们必须改变比较的执行方式,这样函数就可以对任何类型的值进行比较.这个目标听上去好象不可能,如果你
编写语句用于比较整型值,它怎么还可能用于其他类型如字符串的比较呢?解决方案就是使用函数指针,调用者编写一个函数,用于比较两个值,然后把一个指向这
个函数的指针作为参数传递给查找函数.然后查找函数调用这个函数来执行值的比较,使用这种方法,任何类型的值都可以进行比较.我们必须修改的第二个方面是
向函数传递一个指向值的指针而不是本身.函数由一个void
*形参,用于接收这个参数,然后指向这个值的指针便传递给比较函数,这个修改使字符串和数组对象也可以被使用,字符串和数组无法作为参数传递给函数,但指
向它们的指针可以.<br>使用这种技巧的函数叫"回调函数"(callback
function);因为用户把一个函数指针作为参数传递给其他函数,后者将"回调"用户的函数.任何时候,如果你所编写的函数必须能够在不同的时刻执行
不同类型的工作或执行只能由函数调用者定义的工作,你都可以使用这个技巧.许多窗口系统使用回调函数连接多个动作,如拖拽鼠标和点击按钮来指定用户程序中
的某个特定函数.我们无法在这个上下文环境中为回调函数编写一个准确的原型,因为我们并不知道进行比较的值的类型.事实上,我们需要查找函数能作用于任何
类型的值,解决这个难题的方法是把参数类型声明为"void *",表示"一个指向未知类型的指针".</p>
<p style="font-size: 10pt;"><br>/***在一个单链表中查找一个指定值的函数,它的参数是一个指向链表第一个节点<br>&nbsp;&nbsp; **的指针,一个指向我们需要查找的值的指针和一个函数指针,它所指向的函数<br>&nbsp;&nbsp; **用于比较存储于此链表中的类型的值.<br>*/<br>#include "node.h"<br>Node* search_list(Node *node,void&nbsp; const *value, int(*compare)(void const*,void const*)) //函数声明;<br>{&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp; while&nbsp;&nbsp; (node!=NULL)<br>&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; if(compare(&amp;node-&gt;value,value)==0)&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp; node=node-&gt;link;<br>&nbsp; }<br>&nbsp; return node;<br>}<br>同时注意虽然函数不会修改参数node所指向的任何节点,但node并未声明为const。如果node被声明为const,函数不得不返回一个const结果，这将限制调用程序，它便无法修改查找函数所找到的节点。<br>&nbsp;在一个特定的链表中进行查找时，用户需要编写一个适当的比较函数，并把指向该函数的指针和指向需要查找的值的指针传递给查找函数。<br>例如，下面是一个比较函数，它用于在一个整数链表中进行查找。<br>int compare_ints(void const* a,void const* b)<br>{<br>&nbsp;&nbsp;&nbsp; if(*(int*)a==*(int*)b)&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>&nbsp;&nbsp;&nbsp; else&nbsp;&nbsp;&nbsp;&nbsp; return 1;<br>}<br>这个函数将像下面这样使用：<br>desired_node=search_list(root,&amp;desired_value,compare_ints);</p>
<p style="font-size: 10pt;"><strong>2.转换表（jump table)</strong><br>&nbsp;转移表最好用个例子来解释。下面的代码段取自一个程序，它用于实现一个袖珍式计算器。程序的其他部分已经读入两个数（op1和op2）和一个操作符（oper)。下面的代码对操作符进行测试，最后决定调用哪个函数。<br>switch(oper)<br>{<br>&nbsp; case ADD:&nbsp;&nbsp; result=add(op1,op2);break;<br>&nbsp; case SUB:&nbsp;&nbsp;&nbsp; result=sub(op1,op2);break;<br>&nbsp; case MUL:&nbsp;&nbsp;&nbsp; result=mul(op1,op2);break;<br>&nbsp; case DIV:&nbsp;&nbsp;&nbsp;&nbsp; result=div(op1,op2);break;<br>&nbsp; ......<br>}</p>
<p style="font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
对于一个新奇的具有上百个操作符的计算器，这条switch语句将会非常之长。为什么要调用函数来执行这些操作呢？把具体操作和选择操作的代码分开是一种
良好的设计方案。更为复杂的操作将肯定以独立的函数来实现，因为它们的长度可能很长。但即使是简单的操作也可能具有副作用，例如保存一个常量值用于以后的
操作。<br>为了使用switch语句，表示操作符的代码必须是整数。如果它们是从零开始连续的整数，我们可以使用转换表来实现相同的任务。转换表就是一个函数指针数组。<br>创建一个转换表需要两个步骤。首先，声明并初始化一个函数指针数组。唯一需要留心之处就是确保这些函数的原型出现在这个数组的声明之前。</p>
<p style="font-size: 10pt;">double add(double,double);<br>double sub(double,double);<br>double mul(double,double);<br>double div(double,double);</p>
<p style="font-size: 10pt;">double (*oper_func[])(double,double)={add,sub,mul,div,...}；</p>
<p style="font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 初始化列表中各个函数名的正确顺序取决于程序中用于表示每个操作符的整型代码。这个例子假定ADD是0，SUB是1，MUL是2，接下去以此类推。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第二个步骤是用下面这条语句替换前面整条switch语句！<br>result=oper_func[oper](op1,op2);<br>oper从数组中选择正确的函数指针，而函数调用操作符将执行这个函数。</p>
<br><br><img src ="http://www.cppblog.com/richardhe/aggbug/55333.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-07-04 13:18 <a href="http://www.cppblog.com/richardhe/articles/55333.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MD5算法的C++实现</title><link>http://www.cppblog.com/richardhe/articles/54567.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Wed, 25 Jun 2008 09:12:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/54567.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/54567.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/54567.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/54567.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/54567.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 来自http://www.cppblog.com/ant/archive/2007/09/11/31886.htmlMD5算法的C++实现1. IntroductionMD5算法是一种消息摘要算法(Message Digest Algorithm)，此算法以任意长度的信息(message)作为输入进行计算，产生一个128-bit(16-byte)的指纹或报文摘要(finge...&nbsp;&nbsp;<a href='http://www.cppblog.com/richardhe/articles/54567.html'>阅读全文</a><img src ="http://www.cppblog.com/richardhe/aggbug/54567.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-06-25 17:12 <a href="http://www.cppblog.com/richardhe/articles/54567.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 基于C++有限状态机的实现技术(调查报告)</title><link>http://www.cppblog.com/richardhe/articles/53134.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Fri, 13 Jun 2008 07:01:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/53134.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/53134.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/53134.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/53134.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/53134.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一.引言言有限状态机是一种用来进行对象行为建模的工具，其作用主要是描述对象在它的生命周期内所经历的状态序列，以及如何响应来自外界的各种事件。在面向对象的软件系统中，一个对象无论多么简单或者多么复杂，都必然会经历一个从开始创建到最终消亡的完整过程，这通常被称为对象的生命周期。一般说来，对象在其生命期内是不可能完全孤立的，它必须通过发送消息来影响其它对象，或者通过接受消息来改变自身。在...&nbsp;&nbsp;<a href='http://www.cppblog.com/richardhe/articles/53134.html'>阅读全文</a><img src ="http://www.cppblog.com/richardhe/aggbug/53134.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-06-13 15:01 <a href="http://www.cppblog.com/richardhe/articles/53134.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>有限状态机的实现</title><link>http://www.cppblog.com/richardhe/articles/53131.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Fri, 13 Jun 2008 06:48:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/53131.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/53131.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/53131.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/53131.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/53131.html</trackback:ping><description><![CDATA[有限状态机（Finite State Machine或者Finite State Automata)是软件领域中一种重要的工具，很多东西的模型实际上就是有限状态机。<br><br>最近看了一些游戏编程AI的材料，感觉游戏中的AI，第一要说的就是有限状态机来实现精灵的AI，然后才是A*寻路，其他学术界讨论比较多的神经网络、模糊控制等问题还不是很热。<br><br>FSM的实现方式：<br>1） switch/case或者if/else<br>这无意是最直观的方式，使用一堆条件判断，会编程的人都可以做到，对简单小巧的状态机来说最合适，但是毫无疑问，这样的方式比较原始，对庞大的状态机难以维护。<br><br>2） 状态表<br>维护一个二维状态表，横坐标表示当前状态，纵坐标表示输入，表中一个元素存储下一个状态和对应的操作。这一招易于维护，但是运行时间和存储空间的代价较大。<br><br>3） 使用State Pattern<br>使
用State Pattern使得代码的维护比switch/case方式稍好，性能上也不会有很多的影响，但是也不是100％完美。不过Robert
C. Martin做了两个自动产生FSM代码的工具，for java和for
C++各一个，在http://www.objectmentor.com/resources/index上有免费下载，这个工具的输入是纯文本的状态
机描述，自动产生符合State
Pattern的代码，这样developer的工作只需要维护状态机的文本描述，每必要冒引入bug的风险去维护code。<br><br>4） 使用宏定义描述状态机<br>一般来说，C++编程中应该避免使用#define，但是这主要是因为如果用宏来定义函数的话，很容易产生这样那样的问题，但是巧妙的使用,还是能够产生奇妙的效果。MFC就是使用宏定义来实现大的架构的。<br>在实现FSM的时候，可以把一些繁琐无比的if/else还有花括号的组合放在宏中，这样，在代码中可以3）中状态机描述文本一样写，通过编译器的预编译处理产生1）一样的效果，我见过产生C代码的宏，如果要产生C++代码，己软MFC可以，那么理论上也是可行的。<img src ="http://www.cppblog.com/richardhe/aggbug/53131.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-06-13 14:48 <a href="http://www.cppblog.com/richardhe/articles/53131.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用C++标准库中文件流对象，如何获得文件的大小</title><link>http://www.cppblog.com/richardhe/articles/52241.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Thu, 05 Jun 2008 06:17:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/52241.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/52241.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/52241.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/52241.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/52241.html</trackback:ping><description><![CDATA[C++标准库中的文件流类提供的各种操作中没有直接获得正在操作的文件的大小的函数。要获得文件大小得转个弯，用如下的方法<br>&nbsp;&nbsp;&nbsp; 假设我们有了一个已经打开的文件对象ifile。<br>&nbsp;&nbsp;&nbsp; 先将文件内的位置指针移到文件尾<br>&nbsp;&nbsp;&nbsp; ifile.seekg( 0, ios::end );<br>&nbsp;&nbsp;&nbsp; 再读取当前位置，这就是文件的大小了。<br>&nbsp;&nbsp;&nbsp; long filelength = ifile.tellg();<br>出自:http://www.cppblog.com/walkspeed/archive/2007/05/02/23336.html<br><img src ="http://www.cppblog.com/richardhe/aggbug/52241.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-06-05 14:17 <a href="http://www.cppblog.com/richardhe/articles/52241.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>接口设计的要点（接口不应被使用者直接销毁）</title><link>http://www.cppblog.com/richardhe/articles/52163.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Wed, 04 Jun 2008 07:39:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/52163.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/52163.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/52163.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/52163.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/52163.html</trackback:ping><description><![CDATA[<div class="postTitle">
<a  href="http://www.cppblog.com/walkspeed/archive/2007/08/07/29457.html" id="viewpost1_TitleUrl" class="postTitle2">接口设计的要点（接口不应被使用者直接销毁）</a>
</div>
接口在使用后，不需要也不允许用户销毁<br><br>接口用来通讯的。虽然在C++中，接口的一般用指针实现，但它代表的是一种通讯方式，而不是资源的<br>位置。请求者在使用完后不应去直接销毁这个指针，而应由接口的提供者去管理。<br><br>接口的提供者要管理接口关联的实体的生命周期，而且还有知道接口的使用情况才能管理接口。<br><br>接口于实体之间有关联，这表明实体要在接口前创建，要在接口后销毁。设计中接口提供者通过接口的<br>计数，来管理接口的状态。有一个请求者就将接口计数增加一，接口每被赋值一次接口计数也增加一次<br>。<br><br>接口的使用者在使用完后，要将接口返回给接口提供者，而不是自己直接销毁。因为接口不是被使用者<br>申请的资源，而是用户要求另一个对象通讯的通道。所以用完后要返还给接口提供者。接口提供者每接<br>到一个接口的返还，就减少这个接口的计数一次。<br><br>在要销毁接口关联的实体时，先要检查这个接口是否还有使用者，如果有，就要通知使用者，要求它们<br>返还接口。在接口没有使用者的情况下常能销毁实体（这样比较安全，当然也可以强行销毁）。<br><br>同一个接口可能对应多个实体，不过用户是感觉不到的。但是接口提供者一定要管理这种接口于不同的<br>实体之间的关联关系，保证对不同的实体销毁时，要收回与这个实体关联的所有接口。<img src ="http://www.cppblog.com/richardhe/aggbug/52163.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-06-04 15:39 <a href="http://www.cppblog.com/richardhe/articles/52163.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在C++中侦测内嵌类型的存在</title><link>http://www.cppblog.com/richardhe/articles/52160.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Wed, 04 Jun 2008 07:23:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/52160.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/52160.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/52160.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/52160.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/52160.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 现在学校里假如不止学生教师，还有工人，警卫等其它人员。如果他们不会在类内部typedef任何东西，则Register需要一种机制以确定T内部是否typedef了某个标识符（例如person_tag）。如果没有，就默认处理。如果有，则再进行更详细的分类。动机(Motivation)假设一所大学的注册系统提供了一个注册函数：&nbsp;template&lt;class T&gt;...&nbsp;&nbsp;<a href='http://www.cppblog.com/richardhe/articles/52160.html'>阅读全文</a><img src ="http://www.cppblog.com/richardhe/aggbug/52160.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-06-04 15:23 <a href="http://www.cppblog.com/richardhe/articles/52160.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>boost源码剖析之：泛型编程精灵type_traits</title><link>http://www.cppblog.com/richardhe/articles/52159.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Wed, 04 Jun 2008 07:22:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/52159.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/52159.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/52159.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/52159.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/52159.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 本文仅介绍一些技术性较强的traits。由于traits的定义往往重复代码较多，所以必要时本文仅剖析其底层机制。所有源码均摘自相应头文件中，为使源码简洁，所有的宏均已展开。由于traits技巧与编译平台息息相关，某些平台可能不支持模板偏特化。动机使用traits的动机一般有三种，分派、效率、使某些代码通过编译。&nbsp;分派下面有一个模板函数，假设一个动物收容组织提供了它，他...&nbsp;&nbsp;<a href='http://www.cppblog.com/richardhe/articles/52159.html'>阅读全文</a><img src ="http://www.cppblog.com/richardhe/aggbug/52159.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-06-04 15:22 <a href="http://www.cppblog.com/richardhe/articles/52159.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>boost源码剖析之：boost::multi_array</title><link>http://www.cppblog.com/richardhe/articles/52157.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Wed, 04 Jun 2008 07:21:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/52157.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/52157.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/52157.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/52157.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/52157.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 本文只是将multi_array最基本的功能代码做了一个扼要的分析，正如文章开始所说，multi_array还有许多很有用的特性，如果读者想充分了解multi_array的运作机制与实现技巧，就请深入完整地分析multi_array的代码吧，相信一定会大有收获的！动机&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; C++是一门自由的语言，允许你自由的表达自己的意图，对...&nbsp;&nbsp;<a href='http://www.cppblog.com/richardhe/articles/52157.html'>阅读全文</a><img src ="http://www.cppblog.com/richardhe/aggbug/52157.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-06-04 15:21 <a href="http://www.cppblog.com/richardhe/articles/52157.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>boost源码剖析之：泛型指针类any之海纳百川</title><link>http://www.cppblog.com/richardhe/articles/52158.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Wed, 04 Jun 2008 07:21:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/52158.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/52158.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/52158.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/52158.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/52158.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 首先，any类里面一定要提供一个模板构造函数和模板operator=操作符。其次，数据的存放之所是个问题，显然你不能将它保存在any类中，那会导致any类成为模板类，后者是明确不被允许的。结论是：为容器准备一个非泛型的基类，而让指针指向该基类。动机C++是强类型语言，所有强类型语言对类型的要求都是苛刻的，类型一有不合编译器就会抱怨说不能将某某类型转换为某某类型，当然如果在类型之间提供了转换...&nbsp;&nbsp;<a href='http://www.cppblog.com/richardhe/articles/52158.html'>阅读全文</a><img src ="http://www.cppblog.com/richardhe/aggbug/52158.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-06-04 15:21 <a href="http://www.cppblog.com/richardhe/articles/52158.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>boost源码剖析之：Tuple Types</title><link>http://www.cppblog.com/richardhe/articles/52156.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Wed, 04 Jun 2008 07:20:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/52156.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/52156.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/52156.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/52156.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/52156.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 了解tuple的设计目标十分重要。下面两个细节设计目标才是真正需要和体现技术的地方，容我向你阐述它们：tuple中的数据成员的个数应该具有某种动态特性；tuple 必须提供某种途径以获取它内部保存的数值。动机[1]假设你有这样一个函数：它接受两个整型数据并返回它们整除的结果，像这样：&nbsp;int DevideInts(int n,int d){&nbsp;&nbs...&nbsp;&nbsp;<a href='http://www.cppblog.com/richardhe/articles/52156.html'>阅读全文</a><img src ="http://www.cppblog.com/richardhe/aggbug/52156.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-06-04 15:20 <a href="http://www.cppblog.com/richardhe/articles/52156.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>刘未鹏之《boost源码剖析》系列多重回调机制signal</title><link>http://www.cppblog.com/richardhe/articles/52155.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Wed, 04 Jun 2008 07:19:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/52155.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/52155.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/52155.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/52155.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/52155.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 上篇：架构篇引入所谓&#8220;事件&#8221;机制，简而言之，就是用户将自己的一个或多个回调函数挂钩到某个&#8220;事件&#8221;上，一旦&#8220;事件&#8221;被触发，所有挂钩的函数都被调用。&nbsp;毫无疑问，事件机制是个十分有用且常用的机制，不然C#也不会将它在语言层面实现了。&nbsp;但是C++语言并无此种机制。 &nbsp;幸运的...&nbsp;&nbsp;<a href='http://www.cppblog.com/richardhe/articles/52155.html'>阅读全文</a><img src ="http://www.cppblog.com/richardhe/aggbug/52155.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-06-04 15:19 <a href="http://www.cppblog.com/richardhe/articles/52155.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Boost.Bind的基础使用</title><link>http://www.cppblog.com/richardhe/articles/52150.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Wed, 04 Jun 2008 07:01:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/52150.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/52150.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/52150.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/52150.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/52150.html</trackback:ping><description><![CDATA[<div class="postTitle">
<a  href="http://www.cppblog.com/walkspeed/archive/2007/07/20/28448.html" id="viewpost1_TitleUrl" class="postTitle2">Boost.Bind的基础使用</a>
</div>
当我们使用函数时习惯于C函数的格式,即如下形式<br>resulttype funname( arglist );<br>返回值类型 函数名( 参数列表 );<br><br>在Boost.Function中，我们可以方便的定义定义函数对象。不过在定义用来表示类成员函数的函数对象时<br>第一个参数是类指针。而且在调用时，要传入一个类实例的指针。这样用起来并不是很方便，因为调用者<br>要知道类实例。这实际上没有实现解耦。而解耦是我们使用回调或委托设计的一个目标。<br><br>为了解决这个问题，我们要使用Boost.Bind库<br><br>Boost.Bind是一个函数对象工厂。他用来产生我们需要的函数对象。好了，有了它，你可以在你设计中大<br>量使用Boost.Function。不用再去定义类成员函数形式的函数对象啦，只用定义普通函数对象。<br><br>一个简单的例子<br><br>class CExample<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; bool printstr( const std::string &amp;str )<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "CExample::printstr" &lt;&lt; str &lt;&lt; std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<br>&nbsp;&nbsp;&nbsp; }<br>};<br><br>//定义一个函数对象<br>boost::function&lt; bool ( const std::string&amp; ) &gt; printstr;<br><br>//用Boost.Bind创建一个函数对象，赋给printstr<br>CExample example;<br>printstr = boost::bind( &amp;CExample::printstr, &amp;example, _1 );<br><br>好了，我们创建了一个函数对象，而且调用时不再需要类实例拉。用Boost.Function和Boost.Bind大大<br>的简化了Command模式的实现。<br><br>在上面的例子中要个古怪的对象"_1"。这个叫做站位符，他代表这个位置有个参数，但现在还不知道参<br>数是什么。_1代表参数列表中的第一个位置上的参数。Boost.Bind一共定义了9个站位符对象。如下<br>_1,_2,_3,_4,_5,_6,_7,_8,_9。分别代表参数列表中位子。<br><br>Boost.Bind产生的函数对象可以直接使用，利用上面的例子。<br><br>bool b = boost::bind( &amp;CExample::printstr, &amp;example, _1 )( "Hello World" );<img src ="http://www.cppblog.com/richardhe/aggbug/52150.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-06-04 15:01 <a href="http://www.cppblog.com/richardhe/articles/52150.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Boost源码剖析：C++泛型函数指针类</title><link>http://www.cppblog.com/richardhe/articles/52148.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Wed, 04 Jun 2008 06:50:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/52148.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/52148.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/52148.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/52148.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/52148.html</trackback:ping><description><![CDATA[<strong>前奏 </strong><br><br>　　如你所知，Boost库是个特性完备，且具备工业强度的库，众多C++权威的参与使其达到了登峰造极的程度。尤其<a  href="http://www.yesky.com/key/171/85171.html" class="bluekey" target="_blank">泛型</a>的强大威力在其中被发挥得淋漓尽致，令人瞠目结舌。<br><br>　　然而弱水三千，我们只取一瓢饮。下面，我试图从最单纯的世界开始，一步一步带领你进入<a  href="http://www.yesky.com/key/747/45747.html" class="bluekey" target="_blank">源码</a>的世界，去探究boost::function(下文简称f