??xml version="1.0" encoding="utf-8" standalone="yes"?>99久久夜色精品国产网站,伊人久久大香线蕉AV一区二区,久久久久国产精品麻豆AR影院 http://www.shnenglu.com/lmlf001/category/1496.html三悬明镜垂`韵,九撩清泉z尘? zh-cnTue, 20 May 2008 23:40:58 GMTTue, 20 May 2008 23:40:58 GMT60标准输入输出的问?/title><link>http://www.shnenglu.com/lmlf001/archive/2007/10/17/34471.html</link><dc:creator>芥之?/dc:creator><author>芥之?/author><pubDate>Wed, 17 Oct 2007 11:06:00 GMT</pubDate><guid>http://www.shnenglu.com/lmlf001/archive/2007/10/17/34471.html</guid><wfw:comment>http://www.shnenglu.com/lmlf001/comments/34471.html</wfw:comment><comments>http://www.shnenglu.com/lmlf001/archive/2007/10/17/34471.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/lmlf001/comments/commentRss/34471.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/lmlf001/services/trackbacks/34471.html</trackback:ping><description><![CDATA[    先看下面一个小E序Q?br><br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">int</span><span style="color: #000000;"> main(</span><span style="color: #0000ff;">int</span><span style="color: #000000;"> argc, _TCHAR</span><span style="color: #000000;">*</span><span style="color: #000000;"> argv[])<br>{<br>        FILE </span><span style="color: #000000;">*</span><span style="color: #000000;">fp</span><span style="color: #000000;">=</span><span style="color: #000000;">fopen(</span><span style="color: #000000;">"</span><span style="color: #000000;">1.txt</span><span style="color: #000000;">"</span><span style="color: #000000;">,</span><span style="color: #000000;">"</span><span style="color: #000000;">r+</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br></span><span style="color: #000000;"></span><span style="color: #000000;">        fputc(</span><span style="color: #000000;">'</span><span style="color: #000000;">x</span><span style="color: #000000;">'</span><span style="color: #000000;">,fp);<br>        fputc(</span><span style="color: #000000;">'</span><span style="color: #000000;">x</span><span style="color: #000000;">'</span><span style="color: #000000;">,fp);<br>        fputc(</span><span style="color: #000000;">'</span><span style="color: #000000;">x</span><span style="color: #000000;">'</span><span style="color: #000000;">,fp);<br>        </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> </span><span style="color: #000000;">0</span><span style="color: #000000;">;<br>}</span></div>     1.txt文g内容为abcdefgQ调用函C后ؓaxxxefgQ恩Q正?br><br><br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">int</span><span style="color: #000000;"> main(</span><span style="color: #0000ff;">int</span><span style="color: #000000;"> argc, _TCHAR</span><span style="color: #000000;">*</span><span style="color: #000000;"> argv[])<br>{<br>        FILE </span><span style="color: #000000;">*</span><span style="color: #000000;">fp</span><span style="color: #000000;">=</span><span style="color: #000000;">fopen(</span><span style="color: #000000;">"</span><span style="color: #000000;">1.txt</span><span style="color: #000000;">"</span><span style="color: #000000;">,</span><span style="color: #000000;">"</span><span style="color: #000000;">rb+</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br></span><span style="color: #000000;">        </span><span style="color: #0000ff;">char</span><span style="color: #000000;"> c</span><span style="color: #000000;">=</span><span style="color: #000000;">fgetc(fp);<br></span><span style="color: #000000;">        fputc(</span><span style="color: #000000;">'</span><span style="color: #000000;">x</span><span style="color: #000000;">'</span><span style="color: #000000;">,fp);<br>        fputc(</span><span style="color: #000000;">'</span><span style="color: #000000;">x</span><span style="color: #000000;">'</span><span style="color: #000000;">,fp);<br>        fputc(</span><span style="color: #000000;">'</span><span style="color: #000000;">x</span><span style="color: #000000;">'</span><span style="color: #000000;">,fp);<br>    </span><span style="color: #0000ff;">    return</span><span style="color: #000000;"> </span><span style="color: #000000;">0</span><span style="color: #000000;">;<br>}</span></div>     而上面的q个E序只是加了一句fgetcQ调用后却失M作用Q文件内Ҏ有发生变化,仍然为abcdefgQؓ什么呢Q(该问题在Linux下已不存在)<br>    《Unix环境高~程》在使用d方式打开文gӞtype中的+PQ输出的后面不能直接跟输入,输入的后面也不能直接跟输出,否则可能会出错。如果需要输入相q,则中? 需调用fflush,fseek,fsetpos或rewind{操作?br>    既然q样Q那我们试一下,看看能不能解决问题,在上面代码中fgetc和fputc中间加入<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">        fpos_t pos;<br>        fgetpos(fp,</span><span style="color: #000000;">&</span><span style="color: #000000;">pos);<br>        fsetpos(fp,</span><span style="color: #000000;">&</span><span style="color: #000000;">pos);</span></div> 之后Q运行程序,果真可以解决问题?br>    C语言的标准I/O库函数由于用缓存的原因Q在使用时可能出现各U各L问题Q尤其是在那U即时性比较强的I/O中,使用时要慎重。尽量用其他的I/O函数代替之?br><br><br><br><img src ="http://www.shnenglu.com/lmlf001/aggbug/34471.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/lmlf001/" target="_blank">芥之?/a> 2007-10-17 19:06 <a href="http://www.shnenglu.com/lmlf001/archive/2007/10/17/34471.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>scanf的烦?/title><link>http://www.shnenglu.com/lmlf001/archive/2007/10/10/33913.html</link><dc:creator>芥之?/dc:creator><author>芥之?/author><pubDate>Wed, 10 Oct 2007 10:23:00 GMT</pubDate><guid>http://www.shnenglu.com/lmlf001/archive/2007/10/10/33913.html</guid><wfw:comment>http://www.shnenglu.com/lmlf001/comments/33913.html</wfw:comment><comments>http://www.shnenglu.com/lmlf001/archive/2007/10/10/33913.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/lmlf001/comments/commentRss/33913.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/lmlf001/services/trackbacks/33913.html</trackback:ping><description><![CDATA[    今天q着2ơ用错scanf函数Q这大概也是历史上第N+1ơ错误了Q一直用cin来输入数据,q来使用scanf的时候老出错误Q因为它要去参数Z个地址Q而编译器对于整数和地址的处理是cM的,往往不能指出错误。而当它运行时是不发生错误的,但会得到不正的l果。。一步步的检查,q不能发现错误,只好打logQ替换掉相应的块Q然后逐步恢复原来的编码,最后才发现是sscanf的用错误。这U错误实际上是有征兆的,因ؓE序每次q行时后使用的都是一个随机数据,而不是你所输入的数据。但~译的时候ƈ不能发现错误。和往常的错误一P~写一个程序可能只要半时几分钟,而查找一个错误却׃我好几个时的时间。这是一个不的教训Q也提示我在~译的时?Wall选项的必要性。ؓ了我以后不会忘C用这个选项Qalias一下它吧,打开.profile文gQ加入一? <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">alias gcc</span><span style="color: #000000;">=</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">gcc -Wall</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;"><br>alias g</span><span style="color: #000000;">++=</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">g++ -Wall</span><span style="color: #000000; font-weight: bold;">'</span></div> q样以后每次使用gcc/g++的时候它p动启?Wall选项?br><img src ="http://www.shnenglu.com/lmlf001/aggbug/33913.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/lmlf001/" target="_blank">芥之?/a> 2007-10-10 18:23 <a href="http://www.shnenglu.com/lmlf001/archive/2007/10/10/33913.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>cL员函数的默认参数表问?/title><link>http://www.shnenglu.com/lmlf001/archive/2007/09/08/31855.html</link><dc:creator>芥之?/dc:creator><author>芥之?/author><pubDate>Sat, 08 Sep 2007 12:58:00 GMT</pubDate><guid>http://www.shnenglu.com/lmlf001/archive/2007/09/08/31855.html</guid><wfw:comment>http://www.shnenglu.com/lmlf001/comments/31855.html</wfw:comment><comments>http://www.shnenglu.com/lmlf001/archive/2007/09/08/31855.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/lmlf001/comments/commentRss/31855.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/lmlf001/services/trackbacks/31855.html</trackback:ping><description><![CDATA[    今天写程序的时候用C函数的默认参数表Q编译的时候老是无法通过Q后来经q几ơ修Ҏ试才发现是把cȝ函数参数表在函数定义时搞错了?br>    cȝ成员函数的参数表在声明时默认参数位于参数表右部,若int fn(int a,int b=0,int c=5);之类的,但在它定义的时候则不能加默认参敎ͼ只能写int fn(int a,int b,int c);<br><br><a title="http://lmlf001.blog.sohu.com/" >http://lmlf001.blog.sohu.com/</a><br><img src ="http://www.shnenglu.com/lmlf001/aggbug/31855.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/lmlf001/" target="_blank">芥之?/a> 2007-09-08 20:58 <a href="http://www.shnenglu.com/lmlf001/archive/2007/09/08/31855.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多重l承与虚基类http://www.shnenglu.com/lmlf001/archive/2006/04/19/5910.html芥之?/dc:creator>芥之?/author>Wed, 19 Apr 2006 14:19:00 GMThttp://www.shnenglu.com/lmlf001/archive/2006/04/19/5910.htmlhttp://www.shnenglu.com/lmlf001/comments/5910.htmlhttp://www.shnenglu.com/lmlf001/archive/2006/04/19/5910.html#Feedback1http://www.shnenglu.com/lmlf001/comments/commentRss/5910.htmlhttp://www.shnenglu.com/lmlf001/services/trackbacks/5910.html原文地址Qhttp://cpp.ysu.edu.cn/jichu/pslyjc.htm

多重l承
前面我们介绍的派生类只有一个基c,UCؓ单基z或单一l承。在实际q用中,我们l常需要派生类同时h多个基类Q这U方法称为多基派生或多重l承?/span>
2.1 多重l承的声明:
?/span> C++ 中,声明h两个以上基类的派生类与声明单基派生类的Ş式类|只需要l承的多个基cȝ逗号分开卛_?/span>
在多重承中Q公有派生和U有z对于基类成员在派生类的可讉K性与单承的规则相同?/span>
另外Q对基类成员的访问必L无二义的Q若两个基类中具有同名的数据成员或成员函敎ͼ使用成员名限定来消除二义性,若派生类中新增成员或成员函数与基cL员或成员函数同名Q则zcM覆盖外层同名成员Q也M用作用域分LW?/span>
2.2 多重l承的构造函数和析构函数Q?/span>
多重l承的构造函数的定义形式与单l承构造函数的定义形式cMQ只?/span> n 个基cȝ构造函C间用“,”分隔?/span>
多重l承的构造函数的执行序与单l承构造函数的执行序相同Q也是遵循先执行基类的构造函敎ͼ再执行对象成员的构造函敎ͼ最后执行派生类构造函数的原则。在多个基类之间Q则严格按照zcd明是从左到右的顺序来排列先后。而析构函数的执行序与构造函数的执行序相反?/span>
2.3 虚基c?/span> :
如果某个zcȝ部分或全部直接基cL从另一个共同的基类z而来Q在q些基类中,从上一U基cȝ承来的成员就有相同的名称Q则在这个派生类中访问这个共同的基类中的成员Ӟ可能会生二义性,此时Q可定义虚基cR这p求在其直接基cȝ定义中,使用关键?/span> virtual 那个共同的基类定义基类Q其语法形式如下Q?/span>
       class  zcdQ?/span>   virtual z方式 基类
    虚基cȝ初始化与一般的多重l承的初始化在语法上是一L Q但构造函数的调用序不同Q虚基类构造函数的调用序是这栯定的Q?/span>
1) 在同一层次中,先调用虚基类的构造函敎ͼ接下来依ơ是非虚基类的构造函敎ͼ对象成员的构造函敎ͼzcȝ构造函数?/span>
2) 若同一层次中包含多个虚基类Q这些虚基类的构造函数按对他们说明的先后ơ序调用
3) 若虚基类由非虚基cL生而来Q则仍然先调用基cL造函敎ͼ再调用派生类构造函数?br />



]]>
volatile关键?/title><link>http://www.shnenglu.com/lmlf001/archive/2006/04/19/5908.html</link><dc:creator>芥之?/dc:creator><author>芥之?/author><pubDate>Wed, 19 Apr 2006 14:05:00 GMT</pubDate><guid>http://www.shnenglu.com/lmlf001/archive/2006/04/19/5908.html</guid><wfw:comment>http://www.shnenglu.com/lmlf001/comments/5908.html</wfw:comment><comments>http://www.shnenglu.com/lmlf001/archive/2006/04/19/5908.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/lmlf001/comments/commentRss/5908.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/lmlf001/services/trackbacks/5908.html</trackback:ping><description><![CDATA[ <p> <font face="宋体" size="2">volatile关键?/font> </p> <p> <font face="宋体" size="2">volatile是c/c++中一个鲜Zh知的关键?该关键字告诉~译器不要持有变量的临时拯,它可以适用于基cd<br />如:int,char,long......也适用于C的结构和C++的类。当对结构或者类对象使用volatile修饰的时候,l构或?br />cȝ所有成员都会被视ؓvolatile.</font> </p> <p> <font face="宋体" size="2">使用volatileq不会否定对CRITICAL_SECTION,Mutex,Event{同步对象的需?br />例如Q?br />int i;<br />i = i + 3;<br />无论如何QL会有一段旉Qi会被攑֜一个寄存器中,因ؓ术q算只能在寄存器中进行。一般来_volatitle<br />关键字适用于行与行之间Q而不是放在行内?/font> </p> <p> <font face="宋体" size="2">我们先来实现一个简单的函数Q来观察一下由~译器生出来的汇编代码中的不之处Qƈ观察volatile关键字如何修?br />q个不之处。在q个函数体内存在一个busy loop(所谓busy loop也叫做busy waits,是一U高度浪费CPU旉的@环方?</font> </p> <p> <font face="宋体" size="2">void getKey(char* pch)<br />{<br /> while (*pch == 0)<br />  ;<br />}</font> </p> <p> <font face="宋体" size="2">当你在VC开发环境中最优化选项都关闭之后,~译q个E序Q将获得以下l果(汇编代码)<br />;       while (*pch == 0)<br />$L27<br /> ; Load the address stored in pch<br /> mov eax, DWORD PTR _pch$[ebp]<br /> ; Load the character into the EAX register<br /> movsx eax, BYTE PTR [eax]<br /> ; Compare the value to zero<br /> test eax, eax<br /> ; If not zero, exit loop<br /> jne $L28<br /> ;<br /> jmp $L27<br />$L28<br />;}</font> </p> <p> <font face="宋体" size="2">q段没有优化的代码不断的载入适当的地址Q蝲入地址中的内容Q测试结果。效率相当的低,但是l果非常准确</font> </p> <p> <font face="宋体" size="2">现在我们再来看看编译器的所有最优化选项开关都打开以后Q重新编译程序,生成的汇~代码,和上面的代码<br />比较一下有什么不?br />;{ <br /> ; Load the address stored in pch<br /> mov eax, DWORD PTR _pch$[esp-4]<br /> ; Load the character into the AL register<br /> movsx al, BYTE PTR [eax]<br />; while (*pch == 0)<br /> ; Compare the value in the AL register to zero<br /> test al, al<br /> ; If still zero, try again<br /> je SHORT $L84<br /> ;<br />;}</font> </p> <p> <font face="宋体" size="2">从代码的长度可以看出来Q比没有优化的情况要短的多。需要注意的是编译器把MOV指o攑ֈ了@环之外。这?br />单线E中是一个非常好的优化,但是Q在多线E应用程序中Q如果另一个线E改变了变量的|则@环永q不?br />l束。被试的值永q被攑֜寄存器中Q所以该D代码在多线E的情况下,存在一个巨大的BUG。解x法是重新<br />写一ơgetKey函数Qƈ把参数pch声明为volatile,代码如下Q?/font> </p> <p> <font face="宋体" size="2">void getKey(volatile char* pch)<br />{<br /> while (*pch == 0)<br />  ;<br />}</font> </p> <p> <font face="宋体" size="2">q次的修改对于非最优化的版本没有Q何媄响,下面L最优化后的l果Q?/font> </p> <p> <font face="宋体" size="2">;{<br /> ; Load the address stored in pch<br /> mov eax, DWORD PTR _pch$[esp-4]<br />;       while (*pch == 0)<br />$L84:<br /> ; Directly compare the value to zero<br /> cmp BYTE PTR [eax], 0<br /> ; If still zero, try again<br /> je SHORT $L84<br /> ;<br />;}</font> </p> <p> <font face="宋体" size="2">q次的修改结果比较完,地址不会改变Q所以地址声明被移动到循环之外。地址内容是volatile,所以每ơ@?br />之中它不断的被重新检查?/font> </p> <p> <font face="宋体" size="2">把一个const volatile变量作ؓ参数传递给函数是合法的。如此的声明意味着函数不能改变变量的|但是变量?br />值却可以被另一个线E在M旉改变掉?/font> </p> <p> <font size="2"> <font face="宋体">另:</font> </font> </p> <p>如果在一个多U程E序中想在两个函C׃n一个局部变量,需把变量声明ؓvolatilecd</p>例如Q?p></p><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> f1(</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> x)<br />{    <br />    </span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">)x==0</span><span style="color: rgb(0, 0, 0);"></span><span style="color: rgb(0, 0, 0);"></span><span style="color: rgb(0, 0, 0);">);<br />    cout</span><span style="color: rgb(0, 0, 0);"><<</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">helo</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">;<br />    _endthread();<br />}<br /><br /></span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> f2(</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">i)<br />{<br />    </span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> j</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;j</span><span style="color: rgb(0, 0, 0);"><</span><span style="color: rgb(0, 0, 0);">111</span><span style="color: rgb(0, 0, 0);">;j</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">);<br />    (</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">((</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">)i))</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">;<br />    _endthread();<br />}<br /><br /></span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> main()<br />{<br /></span><span style="color: rgb(0, 0, 255);">    int</span><span style="color: rgb(0, 0, 0);"> i</span><span style="color: rgb(0, 0, 0);">=0</span><span style="color: rgb(0, 0, 0);">;<br />    _beginthread((</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">)(</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">))f1,</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">&</span><span style="color: rgb(0, 0, 0);">i);    <br />    _beginthread((</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">)(</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">))f2,</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">&</span><span style="color: rgb(0, 0, 0);">i);<br />    </span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">(getch()</span><span style="color: rgb(0, 0, 0);">!=</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">q</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">;<br />    </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br />}</span></div><p>上例中,函数f1()中的循环控制条g永远为真Q字W串"helo"得不到打印?/p><p>如果把f1()的参数类型改为volatitle void *x,则打印命令被实现?br /></p><img src ="http://www.shnenglu.com/lmlf001/aggbug/5908.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/lmlf001/" target="_blank">芥之?/a> 2006-04-19 22:05 <a href="http://www.shnenglu.com/lmlf001/archive/2006/04/19/5908.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>mutable关键字的用法http://www.shnenglu.com/lmlf001/archive/2006/04/19/5905.html芥之?/dc:creator>芥之?/author>Wed, 19 Apr 2006 13:26:00 GMThttp://www.shnenglu.com/lmlf001/archive/2006/04/19/5905.htmlhttp://www.shnenglu.com/lmlf001/comments/5905.htmlhttp://www.shnenglu.com/lmlf001/archive/2006/04/19/5905.html#Feedback0http://www.shnenglu.com/lmlf001/comments/commentRss/5905.htmlhttp://www.shnenglu.com/lmlf001/services/trackbacks/5905.html关键?span class="hilite1">mutable是C++中一个不常用的关键字,他只能用于类的非静态和非常量数据成?br />我们知道一个对象的状态由该对象的非静态数据成员决?所以随着数据成员的改?
对像的状态也会随之发生变?

如果一个类的成员函数被声明为constcd,表示该函C会改变对象的状?也就?br />该函C会修改类的非静态数据成?但是有些时候需要在该类函数中对cȝ数据成员
q行赋?q个时候就需要用?span class="hilite1">mutable关键字了

mutable关键字提C编译器该变量可以被cȝconst函数修改




]]>
explicit关键字用?/title><link>http://www.shnenglu.com/lmlf001/archive/2006/04/19/5904.html</link><dc:creator>芥之?/dc:creator><author>芥之?/author><pubDate>Wed, 19 Apr 2006 13:11:00 GMT</pubDate><guid>http://www.shnenglu.com/lmlf001/archive/2006/04/19/5904.html</guid><wfw:comment>http://www.shnenglu.com/lmlf001/comments/5904.html</wfw:comment><comments>http://www.shnenglu.com/lmlf001/archive/2006/04/19/5904.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/lmlf001/comments/commentRss/5904.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/lmlf001/services/trackbacks/5904.html</trackback:ping><description><![CDATA[explicit关键字用于取消构造函数的隐式转换Q对有多个参数的构造函C用explicit是个语法错误?br /><p><br /></p><p>In C++ it is possible to declare constructors for a class, taking a single parameter, and use those constructors for doing type conversion. For example: <br /></p><pre><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);"></span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> A {<br /></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">:<br />        A(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">);<br />};<br /><br /></span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> f(A) {}<br /></span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> g()<br />{<br />         A a1 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">37</span><span style="color: rgb(0, 0, 0);">;<br />         A a2 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> A(</span><span style="color: rgb(0, 0, 0);">47</span><span style="color: rgb(0, 0, 0);">);<br />         A a3(</span><span style="color: rgb(0, 0, 0);">57</span><span style="color: rgb(0, 0, 0);">);<br />         a1 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">67</span><span style="color: rgb(0, 0, 0);">;<br />         f(</span><span style="color: rgb(0, 0, 0);">77</span><span style="color: rgb(0, 0, 0);">);<br />}<br /></span></div><br />A declaration like:<br />  A a1 = 37;<br />says to call the A(int) constructor to create an A object from the integer value. Such a constructor is called a "converting constructor". <br /></pre><p>However, this type of implicit conversion can be confusing, and there is a way of disabling it, using a new keyword "explicit" in the constructor declaration: <br /></p><pre><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);"></span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> A {<br /></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">:<br />        </span><span style="color: rgb(0, 0, 255);">explicit</span><span style="color: rgb(0, 0, 0);"> A(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">);<br />};<br /><br /></span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> f(A) {}<br /></span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> g()<br />{<br />          A a1 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">37</span><span style="color: rgb(0, 0, 0);">;      </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> illegal</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">          A a2 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> A(</span><span style="color: rgb(0, 0, 0);">47</span><span style="color: rgb(0, 0, 0);">);   </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> OK</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">          A a3(</span><span style="color: rgb(0, 0, 0);">57</span><span style="color: rgb(0, 0, 0);">);       </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> OK</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">          a1 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">67</span><span style="color: rgb(0, 0, 0);">;        </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> illegal</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">          f(</span><span style="color: rgb(0, 0, 0);">77</span><span style="color: rgb(0, 0, 0);">);          </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> illegal</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">}<br /><br /></span></div><br /></pre>Using the explicit keyword, a constructor is declared to be<br />"nonconverting", and explicit constructor syntax is required:<br /><br /><pre><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> A {<br /></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">:<br />        </span><span style="color: rgb(0, 0, 255);">explicit</span><span style="color: rgb(0, 0, 0);"> A(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">);<br />        };<br /><br /></span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> f(A) {}<br /><br /></span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> g()<br />{<br />        A a1 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> A(</span><span style="color: rgb(0, 0, 0);">37</span><span style="color: rgb(0, 0, 0);">);<br />        A a2 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> A(</span><span style="color: rgb(0, 0, 0);">47</span><span style="color: rgb(0, 0, 0);">);<br />        A a3(</span><span style="color: rgb(0, 0, 0);">57</span><span style="color: rgb(0, 0, 0);">);<br />        a1 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> A(</span><span style="color: rgb(0, 0, 0);">67</span><span style="color: rgb(0, 0, 0);">);<br />        f(A(</span><span style="color: rgb(0, 0, 0);">77</span><span style="color: rgb(0, 0, 0);">));<br />}<br /><br /></span></div><br /></pre><p>Note that an expression such as: <br /></p><pre> A(47)<br /></pre><p>is closely related to function-style casts supported by C++. For example: <br /></p><pre> double d = 12.34;<br /><br /> int i = int(d);<br /></pre><br /><img src ="http://www.shnenglu.com/lmlf001/aggbug/5904.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/lmlf001/" target="_blank">芥之?/a> 2006-04-19 21:11 <a href="http://www.shnenglu.com/lmlf001/archive/2006/04/19/5904.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++风格的类型{换的用法(ZZ)http://www.shnenglu.com/lmlf001/archive/2006/04/19/5903.html芥之?/dc:creator>芥之?/author>Wed, 19 Apr 2006 12:52:00 GMThttp://www.shnenglu.com/lmlf001/archive/2006/04/19/5903.htmlhttp://www.shnenglu.com/lmlf001/comments/5903.htmlhttp://www.shnenglu.com/lmlf001/archive/2006/04/19/5903.html#Feedback0http://www.shnenglu.com/lmlf001/comments/commentRss/5903.htmlhttp://www.shnenglu.com/lmlf001/services/trackbacks/5903.html C++风格的类型{换的用法

q是More Effecitve C++里的W二条对cd转换讲的很好Q也很基好懂?br />Item M2Q尽量用C++风格的类型{?br />仔细xC卑贱的类型{换功能(castQ,其在E序设计中的Cpgoto语句一样o人鄙视。但是它q不是无法o人忍受,因ؓ当在某些紧要的关_cd转换q是必需的,q时它是一个必需品?br />不过C风格的类型{换ƈ不代表所有的cd转换功能?br />一 来它们过于粗鲁,能允怽在Q何类型之间进行{换。不q如果要q行更精的cd转换Q这会是一个优炏V在q些cd转换中存在着巨大的不同,例如把一个指? const对象的指针(pointer-to-const-objectQ{换成指向非const对象的指针(pointer-to-non-const -objectQ?即一个仅仅去除const的类型{?Q把一个指向基cȝ指针转换成指向子cȝ指针Q即完全改变对象cdQ。传l的C风格的类型{换不 对上qCU{换进行区分。(q一点也不o人惊Ӟ因ؓC风格的类型{换是为C语言设计的,而不是ؓC++语言设计的)?br />二来C风格的类型{换在E? 序语句中难以识别。在语法上,cd转换由圆括号和标识符l成Q而这些可以用在CQ+中的M地方。这使得回答象这样一个最基本的有关类型{换的问题变得? 困难Q“在q个E序中是否用了cd转换Q”。这是因Zh工阅d可能忽略了类型{换的语句Q而利用象grep的工L序也不能从语句构成上区分出它? 来?br />C++通过引进四个新的cd转换操作W克服了C风格cd转换的缺点,q四个操作符? static_cast, const_cast, dynamic_cast, 和reinterpret_cast。在大多数情况下Q对于这些操作符你只需要知道原来你习惯于这样写Q?br />(type) expression
而现在你d该这样写Q?br />static_cast<type>(expression)
例如Q假设你x一个int转换成doubleQ以便让包含intcd变量的表辑ּ产生出QҎ值的l果。如果用C风格的类型{换,你能q样写:
int firstNumber, secondNumber;
...
double result = ((double)firstNumber)/secondNumberQ?br />如果用上q新的类型{换方法,你应该这样写Q?br />double result = static_cast<double>(firstNumber)/secondNumber;
q样的类型{换不论是对h工还是对E序都很Ҏ识别?br />static_cast 在功能上基本上与C风格的类型{换一样强大,含义也一栗它也有功能上限制。例如,你不能用static_cast象用C风格的类型{换一h struct转换成intcd或者把doublecd转换成指针类型,另外Qstatic_cast不能从表辑ּ中去除const属性,因ؓ另一个新的类 型{换操作符const_cast有这L功能?br />其它新的C++cd转换操作W被用在需要更多限制的地方。const_cast用于cd转换掉表 辑ּ的const或volatileness属性。通过使用const_castQ你向h们和~译器强调你通过cd转换惛_的只是改变一些东西的 constness或者volatileness属性。这个含义被~译器所U束。如果你试图使用const_cast来完成修改constness 或者volatileness属性之外的事情Q你的类型{换将被拒l。下面是一些例子:
class Widget { ... };
class SpecialWidget: public Widget { ... };
void update(SpecialWidget *psw);
SpecialWidget sw; // sw 是一个非const 对象?br />const SpecialWidget& csw = sw; // csw 是sw的一个引?br />// 它是一个const 对象
update(&csw); // 错误!不能传递一个const SpecialWidget* 变量
// l一个处理SpecialWidget*cd变量的函?br />update(const_cast<SpecialWidget*>(&csw));
// 正确Qcsw的const被显C地转换掉(
// csw和sw两个变量值在update
//函数中能被更斎ͼ
update((SpecialWidget*)&csw);
// 同上Q但用了一个更难识?br />//的C风格的类型{?br />Widget *pw = new SpecialWidget;
update(pw); // 错误Qpw的类型是Widget*Q但?br />// update函数处理的是SpecialWidget*cd
update(const_cast<SpecialWidget*>(pw));
// 错误Qconst_cast仅能被用在媄?br />// constness or volatileness的地方上?
// 不能用在向承子c进行类型{换?br />到目前ؓ止,const_cast最普通的用途就是{换掉对象的const属性?br />W? 二种Ҏ的类型{换符是dynamic_castQ它被用于安全地沿着cȝl承关系向下q行cd转换。这是_你能用dynamic_cast把指向基 cȝ指针或引用{换成指向其派生类或其兄弟cȝ指针或引用,而且你能知道转换是否成功。失败的转换返回空指针Q当Ҏ针进行类型{换时Q或者抛出异? Q当对引用进行类型{换时Q:
Widget *pw;
...
update(dynamic_cast<SpecialWidget*>(pw));
// 正确Q传递给update函数一个指?br />// 是指向变量类型ؓSpecialWidget的pw的指?br />// 如果pw实指向一个对?
// 否则传递过ȝɽI指针?br />void updateViaRef(SpecialWidget& rsw);
updateViaRef(dynamic_cast<SpecialWidget&>(*pw));
//正确。传递给updateViaRef函数
// SpecialWidget pw 指针Q如果pw
// 实指向了某个对?br />// 否则抛出异?br />dynamic_casts在帮助你览l承层次上是有限制的。它不能被用于缺乏虚函数的类型上Q参见条ƾM24Q,也不能用它来转换掉constnessQ?br />int firstNumber, secondNumber;
...
double result = dynamic_cast<double>(firstNumber)/secondNumber;
// 错误Q没有承关p?br />const SpecialWidget sw;
...
update(dynamic_cast<SpecialWidget*>(&sw));
// 错误! dynamic_cast不能转换
// 掉const?br />如你惛_没有l承关系的类型中q行转换Q你可能惛_static_cast。如果是Z去除constQ你d用const_cast?br />q四个类型{换符中的最后一个是reinterpret_cast。用这个操作符的类型{换,其的转换l果几乎都是执行期定义(implementation-definedQ。因此,使用reinterpret_casts的代码很隄植?br />reinterpret_casts的最普通的用途就是在函数指针cd之间q行转换。例如,假设你有一个函数指针数l:
typedef void (*FuncPtr)(); // FuncPtr is 一个指向函?br />// 的指针,该函数没有参?br />// q回值类型ؓvoid
FuncPtr funcPtrArray[10]; // funcPtrArray 是一个能容纳
// 10个FuncPtrs指针的数l?br />让我们假设你希望Q因为某些莫名其妙的原因Q把一个指向下面函数的指针存入funcPtrArray数组Q?br />int doSomething();
你不能不l过cd转换而直接去做,因ؓdoSomething函数对于funcPtrArray数组来说有一个错误的cd。在FuncPtrArray数组里的函数q回值是voidcdQ而doSomething函数q回值是intcd?br />funcPtrArray[0] = &doSomething; // 错误Q类型不匚w
reinterpret_cast可以让你qɾ~译器以你的Ҏȝ待它们:
funcPtrArray[0] = // this compiles
reinterpret_cast<FuncPtr>(&doSomething);
转换函数指针的代码是不可UL的(C++不保证所有的函数指针都被用一LҎ表示Q,在一些情况下q样的{换会产生不正的l果Q参见条ƾM31Q,所以你应该避免转换函数指针cdQ除非你处于着背水一战和刀架喉的危急时刅R一把锋利的刀。一把非帔R利的刀?br />如果你用的~译器缺乏对新的cd转换方式的支持,你可以用传统的类型{换方法代替static_cast, const_cast, 以及reinterpret_cast。也可以用下面的宏替换来模拟新的cd转换语法Q?br />#define static_cast(TYPE,EXPR) ((TYPE)(EXPR))
#define const_cast(TYPE,EXPR) ((TYPE)(EXPR))
#define reinterpret_cast(TYPE,EXPR) ((TYPE)(EXPR))
你可以象q样使用使用Q?br />double result = static_cast(double, firstNumber)/secondNumber;
update(const_cast(SpecialWidget*, &sw));
funcPtrArray[0] = reinterpret_cast(FuncPtr, &doSomething);
q些模拟不会象真实的操作W一样安全,但是当你的编译器可以支持新的的类型{换时Q它们可以简化你把代码升U的q程?br />? 有一个容易的Ҏ来模拟dynamic_cast的操作,但是很多函数库提供了函数Q安全地在派生类与基cM间进行类型{换。如果你没有q些函数而你有必 进行这Lcd转换Q你也可以回到C风格的类型{换方法上Q但是这L话你不能获知类型{换是否失败。当Ӟ你也可以定义一个宏来模? dynamic_cast的功能,p模拟其它的类型{换一P
#define dynamic_cast(TYPE,EXPR) (TYPE)(EXPR)
误住,q个模拟q不能完全实现dynamic_cast的功能,它没有办法知道{换是否失败?br />? 知道Q是的,我知道,新的cd转换操作W不是很观而且用键盘键入也很麻烦。如果你发现它们看上d在o厌,C风格的类型{换还可以l箋使用q且? 法。然而,正是因ؓ新的cd转换W缺乏美感才能它I补了在含义精性和可L认性上的缺炏Vƈ且,使用新类型{换符的程序更Ҏ被解析(不论是对人工q是 对于工具E序Q,它们允许~译器检出原来不能发现的错误。这些都是放弃C风格cd转换Ҏ的强有力的理由。还有第三个理由Q也许让cd转换W不观和键 入麻烦是一件好事?/font>



]]>
C++stringcd用函?/title><link>http://www.shnenglu.com/lmlf001/archive/2006/04/19/5883.html</link><dc:creator>芥之?/dc:creator><author>芥之?/author><pubDate>Wed, 19 Apr 2006 08:00:00 GMT</pubDate><guid>http://www.shnenglu.com/lmlf001/archive/2006/04/19/5883.html</guid><wfw:comment>http://www.shnenglu.com/lmlf001/comments/5883.html</wfw:comment><comments>http://www.shnenglu.com/lmlf001/archive/2006/04/19/5883.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.shnenglu.com/lmlf001/comments/commentRss/5883.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/lmlf001/services/trackbacks/5883.html</trackback:ping><description><![CDATA[ <p> <font size="3">stringcȝ构造函敎ͼ<br /> string(const char *s);    //用c字符串s初始?br /> string(int n,char c);     //用n个字Wc初始?br /> 此外Qstringc还支持默认构造函数和复制构造函敎ͼ如string s1Qstring s2="hello"Q都是正的写法。当构造的string太长而无法表达时会抛出length_error异常</font> </p> <p> <font size="3">stringcȝ字符操作Q?br /> const char &operator[](int n)const;<br /> const char &at(int n)const;<br /> char &operator[](int n);<br /> char &at(int n);<br /> operator[]和at()均返回当前字W串中第n个字W的位置Q但at函数提供范围查,当越界时会抛出out_of_range异常Q下标运符[]不提供检查访问?br /> const char *data()const;//q回一个非nulll止的c字符数组<br /> const char *c_str()const;//q回一个以nulll止的c字符?br /> int copy(char *s, int n, int pos = 0) const;//把当前串中以pos开始的n个字W拷贝到以sv始位|的字符数组中,q回实际拯的数?/font> </p> <p> <font size="3">string的特性描q?<br /> int capacity()const;    //q回当前定wQ即string中不必增加内存即可存攄元素个数Q?br /> int max_size()const;    //q回string对象中可存放的最大字W串的长?br /> int size()const;        //q回当前字符串的大小<br /> int length()const;       //q回当前字符串的长度<br /> bool empty()const;        //当前字符串是否ؓI?br /> void resize(int len,char c);//把字W串当前大小|ؓlenQƈ用字Wc填充不的部?/font> </p> <p> <font size="3">stringcȝ输入输出操作:<br /> stringc重载运符operator>>用于输入Q同样重载运符operator<<用于输出操作?br /> 函数getline(istream &in,string &s);用于从输入流in中读取字W串到s中,以换行符'\n'分开?br />  </font> </p> <p> <font size="3">string的赋|<br /> string &operator=(const string &s);//把字W串s赋给当前字符?br /> string &assign(const char *s);//用ccd字符串s赋?br /> string &assign(const char *s,int n);//用c字符串s开始的n个字W赋?br /> string &assign(const string &s);//把字W串s赋给当前字符?br /> string &assign(int n,char c);//用n个字Wc赋值给当前字符?br /> string &assign(const string &s,int start,int n);//把字W串s中从start开始的n个字W赋l当前字W串<br /> string &assign(const_iterator first,const_itertor last);//把first和lastq代器之间的部分赋给字符?br />  </font> </p> <p> <font size="3">string的连接:<br /><code> string &operator+=(const string &s);//把字W串sq接到当前字W串的结? </code></font> <font size="3"> <br /> string &append(const char *s);            //把ccd字符串sq接到当前字W串l尾<br /><code> string &append(const char *s,int n);//把ccd字符串s的前n个字W连接到当前字符串结?br /> string &append(const string &s);    //同operator+=()<br /> string &append(const string &s,int pos,int n);//把字W串s中从pos开始的n个字W连接到当前字符串的l尾<br /> string &append(int n,char c);        //在当前字W串l尾dn个字Wc<br /> string &append(const_iterator first,const_iterator last);//把P代器first和last之间的部分连接到当前字符串的l尾 </code></font> <font size="3"> <br />  </font> </p> <p> <font size="3"> <code> string的比较:<br /> bool operator==(const string &s1,const string &s2)const;//比较两个字符串是否相{?br /> q算W?>","<",">=","<=","!="均被重蝲用于字符串的比较Q?br /> int compare(const string &s) const;//比较当前字符串和s的大?br /> int compare(int pos, int n,const string &s)const;//比较当前字符串从pos开始的n个字W组成的字符串与s的大?br /> int compare(int pos, int n,const string &s,int pos2,int n2)const;//比较当前字符串从pos开始的n个字W组成的字符串与s中pos2开始的n2个字W组成的字符串的大小<br /> int compare(const char *s) const;<br /> int compare(int pos, int n,const char *s) const;<br /> int compare(int pos, int n,const char *s, int pos2) const;<br /> compare函数?gt;时返?Q?lt;时返?1Q?=时返? </code> </font> <font size="3"> </font> </p> <p> <font size="3"> <code> string的子Ԍ<br /> string substr(int pos = 0,int n = npos) const;//q回pos开始的n个字W组成的字符? </code> </font> </p> <p> <font size="3"> <br /> string的交换:<br /> void swap(string &s2);    //交换当前字符串与s2的?/font> </p> <p> <font size="3"> </font> </p> <p> <font size="3">stringcȝ查找函数Q?/font> </p> <p> <font size="3"> <code> int find(char c, int pos = 0) const;//从pos开始查扑֭Wc在当前字W串的位|?br /> int find(const char *s, int pos = 0) const;//从pos开始查扑֭W串s在当前串中的位置<br /> int find(const char *s, int pos, int n) const;//从pos开始查扑֭W串s中前n个字W在当前串中的位|?br /> int find(const string &s, int pos = 0) const;//从pos开始查扑֭W串s在当前串中的位置<br /> //查找成功时返回所在位|,p|q回string::npos的? </code> </font> </p> <p> <font size="3"> <code> int rfind(char c, int pos = npos) const;//从pos开始从后向前查扑֭Wc在当前串中的位置<br /> int rfind(const char *s, int pos = npos) const;<br /> int rfind(const char *s, int pos, int n = npos) const;<br /> int rfind(const string &s,int pos = npos) const;<br /> //从pos开始从后向前查扑֭W串s中前n个字W组成的字符串在当前串中的位|,成功q回所在位|,p|时返回string::npos的? </code> </font> </p> <p> <font size="3"> <code> int find_first_of(char c, int pos = 0) const;//从pos开始查扑֭WcW一ơ出现的位置<br /> int find_first_of(const char *s, int pos = 0) const;<br /> int find_first_of(const char *s, int pos, int n) const;<br /> int find_first_of(const string &s,int pos = 0) const;<br /> //从pos开始查扑ֽ前串中第一个在s的前n个字W组成的数组里的字符的位|。查扑֤败返回string::npos </code> </font> </p> <p> <font size="3"> <code> int find_first_not_of(char c, int pos = 0) const;<br /> int find_first_not_of(const char *s, int pos = 0) const;<br /> int find_first_not_of(const char *s, int pos,int n) const;<br /> int find_first_not_of(const string &s,int pos = 0) const;<br /> //从当前串中查扄一个不在串s中的字符出现的位|,p|q回string::npos </code> </font> </p> <p> <font size="3"> <code> int find_last_of(char c, int pos = npos) const;<br /> int find_last_of(const char *s, int pos = npos) const;<br /> int find_last_of(const char *s, int pos, int n = npos) const;<br /> int find_last_of(const string &s,int pos = npos) const; </code> </font> </p> <p> <font size="3"> <code> int find_last_not_of(char c, int pos = npos) const;<br /> int find_last_not_of(const char *s, int pos = npos) const;<br /> int find_last_not_of(const char *s, int pos,  int n) const;<br /> int find_last_not_of(const string &s,int pos = npos) const;<br /> //find_last_of和find_last_not_of与find_first_of和find_first_not_of怼Q只不过是从后向前查? </code> </font> </p> <p> <font size="3"> </font> </p> <p> <font size="3">stringcȝ替换函数Q?/font> </p> <p> <font size="3"> <code> string &replace(int p0, int n0,const char *s);//删除从p0开始的n0个字W,然后在p0处插入串s<br /> string &replace(int p0, int n0,const char *s, int n);//删除p0开始的n0个字W,然后在p0处插入字W串s的前n个字W?br /> string &replace(int p0, int n0,const string &s);//删除从p0开始的n0个字W,然后在p0处插入串s<br /> string &replace(int p0, int n0,const string &s, int pos, int n);//删除p0开始的n0个字W,然后在p0处插入串s中从pos开始的n个字W?br /> string &replace(int p0, int n0,int n, char c);//删除p0开始的n0个字W,然后在p0处插入n个字Wc<br /> string &replace(iterator first0, iterator last0,const char *s);//把[first0Qlast0Q之间的部分替换为字W串s<br /> string &replace(iterator first0, iterator last0,const char *s, int n);//把[first0Qlast0Q之间的部分替换为s的前n个字W?br /> string &replace(iterator first0, iterator last0,const string &s);//把[first0Qlast0Q之间的部分替换Zs<br /> string &replace(iterator first0, iterator last0,int n, char c);//把[first0Qlast0Q之间的部分替换为n个字Wc<br /> string &replace(iterator first0, iterator last0,const_iterator first, const_iterator last);//把[first0Qlast0Q之间的部分替换成[firstQlastQ之间的字符? </code> </font> </p> <p> <font size="3">stringcȝ插入函数Q?/font> </p> <p> <font size="3"> <code> string &insert(int p0, const char *s);<br /> string &insert(int p0, const char *s, int n);<br /> string &insert(int p0,const string &s);<br /> string &insert(int p0,const string &s, int pos, int n);<br /> //?个函数在p0位置插入字符串s中pos开始的前n个字W?br /> string &insert(int p0, int n, char c);//此函数在p0处插入n个字Wc<br /> iterator insert(iterator it, char c);//在it处插入字WcQ返回插入后q代器的位置<br /> void insert(iterator it, const_iterator first, const_iterator last);//在it处插入[firstQlastQ之间的字符<br /> void insert(iterator it, int n, char c);//在it处插入n个字Wc<br />   </code> </font> </p> <p> <font size="3">stringcȝ删除函数</font> </p> <p> <font size="3">iterator erase(iterator first, iterator last);//删除[firstQlastQ之间的所有字W,q回删除后P代器的位|?br /> iterator erase(iterator it);//删除it指向的字W,q回删除后P代器的位|?br /> string &erase(int pos = 0, int n = npos);//删除pos开始的n个字W,q回修改后的字符?/font> </p> <p> <font size="3"> </font> </p> <p> <font size="3">stringcȝq代器处理:</font> </p> <p> <font size="3">stringcL供了向前和向后遍历的q代器iteratorQP代器提供了访问各个字W的语法Q类g指针操作QP代器不检查范围?br /> 用string::iterator或string::const_iterator声明q代器变量,const_iterator不允许改变P代的内容。常用P代器函数有:<br /> const_iterator begin()const;<br /> iterator begin();                //q回string的v始位|?br /> const_iterator end()const;<br /> iterator end();                    //q回string的最后一个字W后面的位置<br /> const_iterator rbegin()const;<br /> iterator rbegin();                //q回string的最后一个字W的位置<br /> const_iterator rend()const;<br /> iterator rend();                    //q回stringW一个字W位|的前面<br /> rbegin和rend用于从后向前的P代访问,通过讄q代器string::reverse_iterator,string::const_reverse_iterator实现</font> </p> <p> <font size="3"> </font> </p> <p> <font size="3">字符串流处理Q?/font> </p> <p> <font size="3">通过定义ostringstream和istringstream变量实现Q?lt;sstream>头文件中<br /> 例如Q?br />     string input("hello,this is a test");<br />     istringstream is(input);<br />     string s1,s2,s3,s4;<br />     is>>s1>>s2>>s3>>s4;//s1="hello,this",s2="is",s3="a",s4="test"<br />     ostringstream os;<br />     os<<s1<<s2<<s3<<s4;<br />     cout<<os.str();</font> </p> <p> <font size="3"> </font> </p> <img src ="http://www.shnenglu.com/lmlf001/aggbug/5883.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/lmlf001/" target="_blank">芥之?/a> 2006-04-19 16:00 <a href="http://www.shnenglu.com/lmlf001/archive/2006/04/19/5883.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> q度使用C++模板(overdoing C++ templates)QZZQ?/title><link>http://www.shnenglu.com/lmlf001/archive/2006/04/19/5880.html</link><dc:creator>芥之?/dc:creator><author>芥之?/author><pubDate>Wed, 19 Apr 2006 06:30:00 GMT</pubDate><guid>http://www.shnenglu.com/lmlf001/archive/2006/04/19/5880.html</guid><wfw:comment>http://www.shnenglu.com/lmlf001/comments/5880.html</wfw:comment><comments>http://www.shnenglu.com/lmlf001/archive/2006/04/19/5880.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/lmlf001/comments/commentRss/5880.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/lmlf001/services/trackbacks/5880.html</trackback:ping><description><![CDATA[ <h2> q度使用C++模板(overdoing C++ templates) </h2> 作者:Steve Donovan. <br /> 译: <a target="_top">Winter</a><br /> 原文: <a target="_top">Overdoing C++ Templates</a><hr /> 大约每隔十年Q都会出C个编E新概念Q宣布自己是以往概念的承者。我们也再一ơ相信,从今往后Y件比以前更可靠,更容易buildQ或者更有意?? 有h怿它会比以前更或者更?。在70q代Q有l构~程Q在80q代Q开始了面向对象~程Q从90q代中期Q出C范型~程(generic programming)。范型编E得名于其用模板而代码重用的高效技?范型cd范型函数)? <p>模板cd模板函数都是非常有用的工兗例如sqr()函数可以计算qx敎ͼM定义了乘法运的数据cdQ数字,矩阵Q都适用。标准容器类(? list)都是模板Q这样对于每个新cd无需重写了,q正是用旧版的C++时真正头疼的事情Q因此我认ؓISO的标准是个伟大的q步。然而,在这个过E? 中有些东西用得过头了? </p><p>例如Q标准库中得string 和iostream 都是使用"character traits"cd作ؓ参数。这意味着同一个basic_string<>cd以用于ASCII字符Ԍ也可用于UnicodeQ甚至用于火 星h的三字节字符Ԍ原则虽然如此Q但许多版本都只是实CASCII字符Ԍ看v来有ҎE)。标准要求这些常用类必须实现成模板Ş式,而这些类几乎? 及到所有C++应用? </p><p>但是q对性能和调试会带来许多ȝ。下面几个试验解释了q个问题Q本试验使用的编译器为VC++6.0)。编译器同时支持新风格的 iostreamQ用模板)和经兔R格的iostream, 因此我们能比较他们二者的版本实现。第一个测试程序当然是使用"Hello, Word"了,新风格的~译旉是经兔R格的2倍。另一个更正规的例子大U有200行,每行输出10个变量用于计数。这个测试程序最显著的结论是~译? 度:新风格版本花?0U编译完成,而旧版本只用了1.5U?0U时间可q不,可以完成很多事情。另外,新风格版本的可执行文件的大小?15KQ? 而旧版本只有70K。你的测试数据可能有些出入,但是整体l论是一LQ当使用新版本时Q会有更慢的~译速度和更大的可执行文件。这q不是因为微软公司编 译器的问题,使用GCC试也会得到同样的结论? </p><p>当然Q和q去不一P可执行文件的大小q不是那么重要,现在Q可~程讑֤U类正快速增长,包括许多信息应用Q如遥控、手机、智能冰、基 于蓝牙技术的咖啡机等{,在这些应用中内存q几q都会是十分宝贵的资源。用标准iostream 而生的额外的二q制文gQ来源于内联了整个模板类的代码,要是没有code bload工具Q你很难优化那些重要的操作。对我来_~译旉问题更严重一些,因ؓq样意味着更长的等待,从而失M开发中非常重要原则Q互动原则? </p><p> 现在我们来考虑调试的问题。标准库中string cȝ模板实现非常聪明Q但q不适合于调试。你会面临用超长名字的~译器和调试器的信息Q? </p><div id="d7r7vjh" class="fragment"><pre><font color="brown">class</font> std::basic_string<<font color="brown">char</font>,<font color="brown">struct</font> std::char_traits<<font color="brown">char</font>>,<font color="brown">class</font> std::allocator<<font color="brown">char</font>>></pre></div>? 样对于非常有用的容器 map < string,string > , 你可以去惌其复杂性。这些名字太长了Q以至于产生数十个内部名字被截断的警告。对于初学者来_std::string 应该设计得尽可能透明Q而不应该让他们面临许多语a内置得一些特性。当输出了编译错误信息后Q在技术上Ԍ应该是可以查扑ֈ所有的 typedef 。我?UnderC 目中就试图q么做。Verity Stob ~写一个后|的处理器来译q些错误信息Q我倒希望这是她q么做只是开个玩W。如果不使用q么复杂的类型,q个问题׃Ҏ处理的多。我在C++开? 上的U诀是Q我首次坦诚的公开q个U密): 在稍微大一点的工程中用一个兼容的string cL替换std::string 的头文g. 有时我会重新build q些标准的头文gQ用来检是否我的库q能正常使用Q但让其他h为如何提高其性能而努力? <p>当然Q在许多应用中我们都需要这Ustd::string提供的灵zL,例如Q需要同时处理ASCII 和Unicode字符Ԍ或者需要定制自qallocator {等。但qƈ不是普遍需?通常E序员要么只处理ASCIIQ要么只处理Unicode ), 看v来对于程序员承担q种范型机制有些不公q뀂这U机制确实让标准库的设计者觉得很有意思,但增加了应用开发程序员使用的复杂度。这g颠倒了q个原则Q? 良好的标准库设计应该隐藏其实现的复杂度,而让用户直接使用。但std::string 对其实现的复杂度隐藏得ƈ不够Q导致在用户使用q程中不断的遇到设计中的问题。我们不能要求标准库的用户都是专家。标准坚持要求这U特定的实现方式Q和? 准库的设计初Lq背Q其初衷是只提供公共的接口和包含一些特定功能的cd。自Ӟq种范型模板对于那些真正去要他们的h是一直有效的? </p><p>q些l节考虑同样应用于标准容器,例如list<>容器Qlist 有一些额外的默认模板参数Q用于定义了默认的allocator。当然自己定义allocator 十分有用Q但l大多数Z需要自己去实现。这些泛化的版本完全可以作ؓ单独的模板提供。我承认q样做会让标准库的设计在技术上变得没有以前有意思,但这? 库在设计之初应该考虑到最l用戗篡改一下C++的颂歌:用户不应该ؓ他们不需要的东西买单? </p><p> 当我们不需要模板的时候,我们不得不用模ѝ除此之外,在CQ+中用范型~程q会遇到另一个的问题。大多数人都同意Q标准的algorithm 十分有用。如果你有一个整型的vector, 你可以直接用下面的语句来排序: </p><div id="7pdhb99" class="fragment"><pre>sort(v.begin(),v.end());</pre></div> 因ؓint型数据的比较函数时内联的Q而且q种范型法比旧版本的qsort()函数速度q快Q也更容易用,特别是用用戯定义cd的vector. copy()函数也可以在M时候高效率地拷贝Q何数据? <p> 但有些应用理解v来十分晦涩: </p><div id="l1tvzn1" class="fragment"><pre>copy_if(v.begin(),v.end(),ostream_iterator<<font color="brown">int</font>>(cout) bind2nd(greater<<font color="brown">int</font>>(),7));</pre></div> 如果要写得严g点,每个名字都应该加上std::前缀Q这里假定所有变量都是用全局命名I间Q或单独使用命o或用其他Ҏ。用Stroustrup (C++的创始h)的例子更Ҏ说明问题Q这个例子把所有的整型数输出到l端Q? <div id="p779v9x" class="fragment"><pre>vector<<font color="brown">int</font>>::iterator li;<br /><font color="brown">for</font> (li = v.begin(); li != v.end(); ++li)<br /><font color="brown">if</font> (*li > 7) cout << *li;</pre></div>Stroustrup 告诉我们如果使用昄的@环是"ȝ而又Ҏ产生错误", 但我看不Z用第一个版本有什么优ѝ显ӞZ能习惯这U方式,人类的适应性很强,作ؓ专业人士Q我们也不得不学习这个新概念。但是,q样做ƈ没有减少 多少ȝQ而且我们可以证明q样做可L更差,更不灉|。同Ӟ它还会限制你的设计。例如,假设我们有一个Shape * 的指针list, 我们可以通过下面的调用方式来d他们自己的ŞӞ <div id="9zpl919" class="fragment"><pre>for_each(ls.begin(),ls.end(),<br />bind2nd(mem_fun(&Shape::draw),canvas));</pre></div> 也可以选择q种方式Q? <div id="jhv7tv9" class="fragment"><pre>ShapeList::iterator li;<br /><font color="brown">for</font> (li = ls.begin(); li != ls.end(); ++li)<br />(*li)->draw(canvas);</pre></div>? 在假设我需要修Ҏ的设计,我只想画那些满某种要求的图形(而且不希望把q些需求包在shapec里?, 那么我只需要在昑ּ的@环中增加一条if条g语句。如果要使用范型概念Q我唯一能想到的方式定义一个函敎ͼ然后使用for_each()法。用设计模 式一书中的术语,W一个例子是一个内部P代器(internal iterator)Q第二个例子式一个外部跌倒器(external iterator). 作者认为C++ q不擅长使用内部q代器,我想我们q是应该考虑语言的局限性。其实问题在于在C++中过度应用范型概?-从而导致不必要的难度。C++ 完全不支持一般的匿名函数(anonymous functions)如LIST, SmallTalk, Ruby{。C++中的匿名函数或许看v来和下面一P可能某天有h会实现它Q? <div id="t99r777" class="fragment"><pre>for_each(ls.begin(),ls.end(),<br /><font color="brown">void</font> lambda(Shape *p) { p->draw(canvas); }); </pre></div><p>C++ 是一U不可思议的编E语aQ小到手机,大到跨国际网l,都有其应用。它非常灉|Q能够支持多U编E风|但这U灵zd样也是其问题所在。编E的艺术在于? 特定的问题选择合适编E风|像老师L醒写作文是要选择好的风格一栗我q不惌?C++ 标准库,q里面包含了许多人的辛勤力_Qƈ为大家提供了一个公共^台。我对于q个标准的态度是,它和范型~程联系q于紧密Q从而变成了在说明什么风格是? 的编E风?例如Q算法中明显們֐于不要用显式@?, 同时它也让程序员们不得不介入一些实现细?如basic_string<>)Q这样做让h们更加觉得C++ 是只是内核工E师们的~程语言? </p><img src ="http://www.shnenglu.com/lmlf001/aggbug/5880.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/lmlf001/" target="_blank">芥之?/a> 2006-04-19 14:30 <a href="http://www.shnenglu.com/lmlf001/archive/2006/04/19/5880.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C可变长参数表问题http://www.shnenglu.com/lmlf001/archive/2006/04/19/5874.html芥之?/dc:creator>芥之?/author>Wed, 19 Apr 2006 05:28:00 GMThttp://www.shnenglu.com/lmlf001/archive/2006/04/19/5874.htmlhttp://www.shnenglu.com/lmlf001/comments/5874.htmlhttp://www.shnenglu.com/lmlf001/archive/2006/04/19/5874.html#Feedback0http://www.shnenglu.com/lmlf001/comments/commentRss/5874.htmlhttp://www.shnenglu.com/lmlf001/services/trackbacks/5874.html
一、什么是可变参数
我们在C语言~程中有时会遇到一些参C数可变的函数,例如printf()函数,其函数原型ؓ:
int printf( const char* format, ...);
它除了有一个参数format固定以外,后面跟的参数的个数和cd是可变的Q用三个点“…”做参数占位W),实际调用时可以有以下的Ş? printf("%d",i);
printf("%s",s);
printf("the number is %d ,string is:%s", i, s);    
以上q些东西已ؓ大家所熟悉。但是究竟如何写可变参数的C函数以及q些可变参数的函数编译器是如何实玎ͼq个问题却一直困C我好久。本文就q个饨幸恍┨?希望能对大家有些帮助.
long sum(int i,...)
{
  int *p,j;
  long s = 0;
  p = &i+1;
  for (j=0;j<i;j++)
    s += p[j];
   return s;
}
long Sum = sum(3,1,2,3);
printf("%ld",Sum);
Sum == 6
二、写一个简单的可变参数的C函数
先看例子E序。该函数臛_有一个整数参?其后占位W…,表示后面参数的个C? 在这个例子里Q所有的输入参数必须都是整数Q函数的功能只是打印所有参数的?
函数代码如下Q?br /> //CZ代码1Q可变参数函数的使用
#include "stdio.h"
#include "stdarg.h"
void simple_va_fun(int start, ...)
{
    va_list arg_ptr;
    int nArgValue =start;
    int nArgCout=0;     //可变参数的数?br />     va_start(arg_ptr,start); //以固定参数的地址v点确定变参的内存起始地址?br />     do
    {
        ++nArgCout;
        printf("the %d th arg: %d",nArgCout,nArgValue);     //输出各参数的?br />         nArgValue = va_arg(arg_ptr,int);                      //得到下一个可变参数的?br />     } while(nArgValue != -1);                
    return;
}
int main(int argc, char* argv[])
{
    simple_va_fun(100,-1);
    simple_va_fun(100,200,-1);
       return 0;
}
下面解释一下这些代?br /> 从这个函数的实现可以看到,我们使用可变参数应该有以下步?
⑴由于在E序中将用到以下q些?
void va_start( va_list arg_ptr, prev_param );
type va_arg( va_list arg_ptr, type );
void va_end( va_list arg_ptr );
va在这里是variable-argument(可变参数)的意?
q些宏定义在stdarg.h?所以用到可变参数的E序应该包含q个头文?
⑵函数里首先定义一个va_list型的变量,q里是arg_ptr,q个?
量是存储参数地址的指?因ؓ得到参数的地址之后Q再l合参数的类型,才能得到参数的倹{?br /> ⑶然后用va_start宏初始化⑵中定义的变量arg_ptr,q个宏的W二个参数是可变参数列表的前一个参?x后一个固定参?
L后依ơ用va_arg宏arg_ptrq回可变参数的地址,得到q个地址之后Q结合参数的cdQ就可以得到参数的倹{?br /> ⑸设定结束条Ӟq里的条件就是判断参数值是否ؓ-1。注意被调的函数在调用时是不知道可变参数的正数目的Q程序员必须自己在代码中指明l束条g。至于ؓ什么它不会知道参数的数目,读者在看完q几个宏的内部实现机制后Q自然就会明白?br />



--------------------------------------------------------------------------------


(?可变参数在编译器中的处理
我们知道va_start,va_arg,va_end是在stdarg.h中被定义成宏? ׃1)gq_的不? 2)~译器的不同,所以定义的宏也有所不同,下面看一下VC++6.0中stdarg.h里的代码Q文件的路径为VC安装目录下的\vc98\ include\stdarg.hQ?br /> typedef char *  va_list;
#define _INTSIZEOF(n) ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define va_start(ap,v)  ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap)      ( ap = (va_list)0 )
下面我们解释q些代码的含义:
1、首先把va_list被定义成char*Q这是因为在我们目前所用的PCZQ字W指针类型可以用来存储内存单元地址。而在有的机器上va_list是被定义成void*?br /> 2、定义_INTSIZEOF(n)主要是ؓ了某些需要内存的寚w的系l?q个宏的目的是ؓ了得到最后一个固定参数的实际内存?gt;>Q谖业幕魃现苯佑胹izeofq朔创妫猿l虻脑诵薪峁挂裁挥杏跋臁Qê笪慕吹易约旱氖q郑?
3、va_start的定义ؓ &v+_INTSIZEOF(v) ,q里&v是最后一个固定参数的起始地址Q再加上其实际占用大后Q就得到了第一个可变参数的起始内存地址。所以我们运行va_start (ap, v)以后,ap指向W一个可变参数在的内存地址,有了q个地址Q以后的事情q单了?
q里要知道两个事情:
    ⑴在intel+windows的机器上Q函数栈的方向是向下的,栈顶指针的内存地址低于栈底指针Q所以先q栈的数据是存放在内存的高地址处?br />     (2)在VC{绝大多数C~译器中Q默认情况下Q参数进栈的序是由叛_左的Q因此,参数q栈以后的内存模型如下图所C:最后一个固定参数的地址位于W一个可变参C下,q且是连l存储的?br /> |——————————————————————————|
|  最后一个可变参敊W            |   ->高内存地址?br /> |——————————————————————————|
   ...................
|——————————————————————————|
|  WN个可变参敊W             |     ->va_arg(arg_ptr,int)后arg_ptr所指的地方,
|                               |     即第N个可变参数的地址?br /> |——————————————?|     
   ………………………?
|——————————————————————————|
|  W一个可变参敊W              |     ->va_start(arg_ptr,start)后arg_ptr所指的地方
|                               |     即第一个可变参数的地址
|——————————————?|     
|———————————————————————?——|
|                               |
|  最后一个固定参敊W            |    -> start的v始地址
|—————————————?—|       .................
|—————————————————————————?|
|                               |  
|——————————————?|  -> 低内存地址?br />
(4) va_arg():有了va_start的良好基Q我们取得了W一个可变参数的地址Q在va_arg()里的d是Ҏ指定的参数类型取得本参数的|q且把指针调到u桓霾问钠鹗嫉刂?
因此Q现在再来看va_arg()的实现就应该心中有数了:
#define va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
q个宏做了两个事情,
       ①用用户输入的类型名对参数地址q行强制cd转换Q得到用h需要的?br />    ②计出本参数的实际大小Q将指针调到本参数的l尾Q也是下一个参数的首地址Q以便后l处理?br /> (5)va_end宏的解释Qx86q_定义为ap=(char*)0;使ap不再 指向堆栈,而是跟NULL一?有些直接定义?(void*)0),q样~译器不会ؓva_end产生代码,例如gcc在linux的x86q_是q? 样定义的. 在这里大家要注意一个问?׃参数的地址用于va_start?所以参C能声明ؓ寄存器变量或作ؓ函数或数l类? 关于va_start, va_arg, va_end的描q就是这些了,我们要注意的 是不同的操作pȝ和硬件^台的定义有些不同,但原理却是相似的.

(?可变参数在编E中要注意的问题
因ؓva_start, va_arg, va_end{定义成?所以它昑־很愚? 可变参数的类型和个数完全在该函数中由E序代码控制,它ƈ不能 地识别不同参数的个数和类? 有h会问:那么printf中不是实C识别参数?那是因ؓ函数 printf是从固定参数format字符串来分析出参数的cd,再调用va_arg 的来获取可变参数?也就是说,你想实现识别可变参数的话是要通过在自qE序里作判断来实现的. 例如Q在C的经典教材《the c programming language》的7.3节中qZ一个printf的可能实现方式,׃幅原因q里不再叙述?br /> Q四Q小l?
1、标准C库的中的三个宏的作用只是用来定可变参数列表中每个参数的内存地址Q编译器是不知道参数的实际数目的?br /> 2、在实际应用的代码中Q程序员必须自己考虑定参数数目的办法,?br /> ⑴在固定参数中设标志—?printf函数是用这个办法。后面也有例子?br /> ⑵在预先讑֮一个特D的l束标记Q就是说多输入一个可变参敎ͼ调用时要最后一个可变参数的D|成q个Ҏ的|在函C中根据这个值判断是否达到参数的l尾。本文前面的代码是采用q个办法.
无论采用哪种办法Q程序员都应该在文档中告诉调用者自qU定?br /> 3、实现可变参数的要点是惛_法取得每个参数的地址Q取得地址的办法由以下几个因素军_Q?br /> ①函数栈的生长方?br /> ②参数的入栈序
③CPU的对齐方?br /> ④内存地址的表达方?br /> l合源代码,我们可以看出va_list的实现是由④军_的,_INTSIZEOF(n)的引入则是由③决定的Q他和①②又一起决定了va_start的实玎ͼ最后va_end的存在则是良好编E风格的体现Q将不再使用的指针设为NULL,q样可以防止以后的误操作?br /> 4、取得地址后,再结合参数的cdQ程序员可以正的处理参数了。理解了以上要点Q相信稍有经验的读者就可以写出适合于自己机器的实现来。下面臼且桓隉A?
Q五Q扩展——自己实现简单的可变参数的函数?br /> 下面是一个简单的printf函数的实玎ͼ参考了<The C Programming Language>中的156늚例子Q读者可以结合书上的代码与本文参照?br /> #include "stdio.h"
#include "stdlib.h"
void myprintf(char* fmt, ...)        //一个简单的cM于printf的实玎ͼ//参数必须都是int cd
{
    char* pArg=NULL;               //{h于原来的va_list
    char c;
    
    pArg = (char*) &fmt;          //注意不要写成p = fmt !!因ؓq里要对//参数取址Q而不是取?br />     pArg += sizeof(fmt);         //{h于原来的va_start          

    do
    {
        c =*fmt;
        if (c != '%')
        {
            putchar(c);            //照原栯出字W?br />         }
        else
{
//按格式字W输出数?br />             switch(*++fmt)
{
            case 'd':
                printf("%d",*((int*)pArg));           
                break;
            case 'x':
                printf("%#x",*((int*)pArg));
                break;
            default:
                break;
            }
            pArg += sizeof(int);               //{h于原来的va_arg
        }
        ++fmt;
    }while (*fmt != '\0');
    pArg = NULL;                               //{h于va_end
    return;
}
int main(int argc, char* argv[])
{
    int i = 1234;
    int j = 5678;
    
    myprintf("the first test:i=%d",i,j);
    myprintf("the secend test:i=%d; %x;j=%d;",i,0xabcd,j);
    system("pause");
    return 0;
}
在intel+win2k+vc6的机器执行结果如下:
the first test:i=1234
the secend test:i=1234; 0xabcd;j=5678;
#include <stdarg.h>//不定数目参数需要的?br /> int max(int n,int num,...)
{
va_list x;//说明变量x
va_start(x,num);//x被初始化为指向num后的W一个参?br /> int m=num;
for(int i=1;i<n;i++)
{
//变量x所指向的intcd的Dly,同时使x指向下一个参?br /> int y=va_arg(x,int);
if(y>m)m=y;
}
va_end(x);//清除变量x
return m;
}
main()
{
    printf("%d,%d",max(3,5,56),max(6,0,4,32,45,533));
}



]]>
C预处理指?/title><link>http://www.shnenglu.com/lmlf001/archive/2006/04/19/5873.html</link><dc:creator>芥之?/dc:creator><author>芥之?/author><pubDate>Wed, 19 Apr 2006 05:14:00 GMT</pubDate><guid>http://www.shnenglu.com/lmlf001/archive/2006/04/19/5873.html</guid><wfw:comment>http://www.shnenglu.com/lmlf001/comments/5873.html</wfw:comment><comments>http://www.shnenglu.com/lmlf001/archive/2006/04/19/5873.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.shnenglu.com/lmlf001/comments/commentRss/5873.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/lmlf001/services/trackbacks/5873.html</trackback:ping><description><![CDATA[ <span id="tvhx9dl" class="top11">原文地址Qhttp://www.51cto.com/html/2005/0927/3844.htm<br /><br />一、预处理的由来:<br />在C++的历史发展中Q有很多的语a特征Q特别是语言的晦涩之处)来自于C语言Q预处理是其中的一个。C++从C语言那里把C语言预处理器l承q来QC语言预处理器Q被Bjarne博士UCؓCppQ不知道是不是C Program Preprocessor的简Uͼ?br /><br />二、常见的预处理功能:<br />预处理器的主要作用就是把通过预处理的内徏功能对一个资源进行等h换,最常见的预处理有:文g包含Q条件编译、布局控制和宏替换4U?br />文g包含Q?include 是一U最为常见的预处理,主要是做为文件的引用l合源程序正文?br />条g~译Q?if,#ifndef,#ifdef,#endif,#undef{也是比较常见的预处理,主要是进行编译时q行有选择的挑选,注释掉一些指定的代码Q以辑ֈ版本控制、防止对文g重复包含的功能?br />布局控制Q?progmaQ这也是我们应用预处理的一个重要方面,主要功能是ؓ~译E序提供非常规的控制信息?br />宏替换: #defineQ这是最常见的用法,它可以定义符号常量、函数功能、重新命名、字W串的拼接等各种功能?br /><br />三、预处理指oQ?br />预处理指令的格式如下Q?br /># directive tokens<br />#W号应该是这一行的W一个非I字W,一般我们把它放在v始位|。如果指令一行放不下Q可以通过\q行控制Q例如:<br />#define Error if(error) exit(1) {h?br />#define Error \<br />if(error) exit(1)<br />不过我们Z化赯Q一般都不怎么q么用,更常见的方式如下Q?br /># ifdef __BORLANDC__<br />if_true<(is_convertible<Value,named_template_param_base>::value)>::<br />template then<make_named_arg, make_key_value>::type Make;<br /># else<br />enum { is_named = is_named_parameter<Value>::value };<br />typedef typename if_true<(is_named)>::template<br />then<make_named_arg, make_key_value>::type Make;<br /># endif<br />下面我们看一下常见的预处理指令:<br />#define 宏定?br />#undef 未定义宏<br />#include 文本包含<br />#ifdef 如果宏被定义p行编?br />#ifndef 如果宏未被定义就q行~译<br />#endif l束~译块的控制<br />#if 表达式非零就对代码进行编?br />#else 作ؓ其他预处理的剩余选项q行~译<br />#elif q是一U?else?if的组合选项 <img style="vertical-align: middle;" alt="tongue.gif" src="http://www.s8s8.net/forums/html/emoticons/tongue.gif" border="0" /><br />#line 改变当前的行数和文g名称<br />#error 输出一个错误信?br />#pragma 为编译程序提供非常规的控制流信息<br />下面我们对这些预处理q行一一的说明,考虑到宏的重要性和J琐性,我们把它攑ֈ最后讲?br /><br />四、文件包含指令:<br />q种预处理用方式是最为常见的Q^时我们编写程序都会用刎ͼ最常见的用法是Q?br />#include <iostream>         //标准库头文g<br />#include <iostream.h>         //旧式的标准库头文?br />#include "IO.h"             //用户自定义的头文?br />#include "../file.h"         //UNIX下的父目录下的头文g<br />#include "/usr/local/file.h" //UNIX下的完整路径<br />#include "..\file.h"         //Dos下的父目录下的头文g<br />#include "\usr\local\file.h" //Dos下的完整路径<br />q里面有2个地方要注意Q?br />1、我们用<iostream>q是<iostream.h>?<br />我们d使用<iostream>Q而不?lt;iostream.h>,Z么呢Q我想你可能q记得我曄l出q几点理由,q里我大致的说一下:首先Q?h格式的头文g早在98q?月䆾p标准委员会抛弃了Q我们应该紧跟标准,以适合时代的发展。其ơ,iostream.h只支持窄字符集,iostream则支持窄/宽字W集?br />q有Q标准对iostream作了很多的改动,接口和实现都有了变化。最后,iostreamlg全部攑օnamespace std中,防止了名字污染?br />2?lt;io.h>?io.h"的区别?<br />其实他们唯一的区别就是搜索\径不同:<br />对于#include <io.h> Q编译器从标准库路径开始搜?br />对于#include "io.h" Q编译器从用L工作路径开始搜?br />五、编译控制指令:<br />q些指o的主要目的是q行~译时进行有选择的挑选,注释掉一些指定的代码Q以辑ֈ版本控制、防止对文g重复包含的功能?br />使用格式Q如下:<br />1?br />#ifdef identifier<br />your code<br />#endif<br />如果identifierZ个定义了的符Pyour code׃被编译,否则剔除<br />2?br />#ifndef identifier<br />your code<br />#endif<br />如果identifierZ个未定义的符Pyour code׃被编译,否则剔除<br />3?br />#if expression<br />your code<br />#endif<br />如果expression非零Qyour code׃被编译,否则剔除<br />4?br />#ifdef identifier<br />your code1<br />#else<br />your code2<br />#endif<br />如果identifierZ个定义了的符Pyour code1׃被编译,否则yourcode2׃被编?br />5?br />#if expressin1<br />your code1<br />#elif expression2 //呵呵Qelif<br />your code2<br />#else<br />your code3<br />#enif<br />如果epression1非零Q就~译your code1Q否则,如果expression2非零Q就~译your code2Q否则,q译your code3<br /><br />其他预编译指?br />除了上面我们说的集中常用的编译指令,q有3U不太常见的~译指oQ?line?error?pragmaQ我们接下来q单的谈一下?br />#line的语法如下:<br />#line number filename<br />例如Q?line 30 a.h 其中Q文件名a.h可以省略不写?br />q条指o可以改变当前的行号和文g名,例如上面的这条预处理指o可以改变当前的行号?0Q文件名是a.h。初看v来似乎没有什么用Q不q,他还是有点用的,那就是用在编译器的编写中Q我们知道编译器对C++源码~译q程中会产生一些中间文Ӟ通过q条指oQ可以保证文件名是固定的Q不会被q些中间文g代替Q有利于q行分析?br />#error语法如下Q?br />#error info<br />例如Q?ifndef UNIX<br />#error This software requires the UNIX OS.<br />#endif<br />q条指o主要是给出错误信息,上面的这个例子就是,如果没有在UNIX环境下,׃输出This software requires the UNIX OS.然后诱发~译器终止。所以ȝ来说Q这条指令的目的是在程序崩溃之前能够给Z定的信息?br />#pragma是非l一的,他要依靠各个~译器生产者,例如Q在SUN C++~译器中Q?br />// 把name和val的v始地址调整?个字节的倍数<br />#progma align 8 (name, val)<br />char name[9];<br />double val;<br />//在程序执行开始,调用函数MyFunction<br />#progma init (MyFunction)<br />预定义标识符<br />Z处理一些有用的信息Q预处理定义了一些预处理标识W,虽然各种~译器的预处理标识符不尽相同Q但是他们都会处理下面的4U:<br />__FILE__ 正在~译的文件的名字<br />__LINE__ 正在~译的文件的行号<br />__DATE__ ~译时刻的日期字W串Q例如: "25 Dec 2000"<br />__TIME__ ~译时刻的时间字W串Q例如: "12:30:55"<br />例如Qcout<<"The file is :"<<__FILE__"<<"! The lines is:"<<__LINE__<<endl;<br /><br />预处理何M?br />如何取代#include预处理指令,我们在这里就不再一一讨论了?br />C++q没有ؓ#include提供替代形式Q但是namespace提供了一U作用域机制Q它能以某种方式支持l合Q利用它可以改善#include的行为方式,但是我们q是无法取代#include?br />#progma应该是一个可有可无的预处理指令,按照C++之父Bjarne的话_是Q?#progma被过分的l常的用于将语言语义的变形隐藏到~译pȝ里,或者被用于提供带有Ҏ语义和笨拙语法的语言扩充。?br />对于#ifdefQ我们仍然束手无{,q是我们利用if语句和常量表辑ּQ仍然不以替代她,因ؓ一个if语句的正文必d语法上正,满cL查,即他处在一个绝不会被执行的分支里面?</span> <img src ="http://www.shnenglu.com/lmlf001/aggbug/5873.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/lmlf001/" target="_blank">芥之?/a> 2006-04-19 13:14 <a href="http://www.shnenglu.com/lmlf001/archive/2006/04/19/5873.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>字符串处理库中的内存函数http://www.shnenglu.com/lmlf001/archive/2006/04/19/5872.html芥之?/dc:creator>芥之?/author>Wed, 19 Apr 2006 05:00:00 GMThttp://www.shnenglu.com/lmlf001/archive/2006/04/19/5872.htmlhttp://www.shnenglu.com/lmlf001/comments/5872.htmlhttp://www.shnenglu.com/lmlf001/archive/2006/04/19/5872.html#Feedback0http://www.shnenglu.com/lmlf001/comments/commentRss/5872.htmlhttp://www.shnenglu.com/lmlf001/services/trackbacks/5872.html
函数原型函数描述
void *memcpy(void *s1,const void *s2, size_t n)?/span>s2所指的对象中的n个字W复制到s1所指的对象中。返?/span>s1l果指针
void *memmove(void *s1,const void *s2,size_t n)?/span>memcpy,q且多考虑了重叠情况(Overlapping BuffersQ?/span>
int memcmp(const void *s1,const void *s2,size_t n)

s1?/span>s2指向对象的前n个字W。如?/span>s1所指向对象的字W等于、小于或大于s2所指向对象中的字符Q返回值分别等?/span>0?/span><0 ?/span>>0

void *memchr(const char *s,int c,size_t n)定位s的前n个字W首ơ出?/span>c的位|。找到就q回指向它的指针Q否则返?/span>0
void *memset(void *s, int c,size_t n)?/span>c复制?/span>s所指的对象的前n个字W中。返回指向结果指?/span>


]]>
字符串处理库中的查找函数http://www.shnenglu.com/lmlf001/archive/2006/04/19/5871.html芥之?/dc:creator>芥之?/author>Wed, 19 Apr 2006 04:57:00 GMThttp://www.shnenglu.com/lmlf001/archive/2006/04/19/5871.htmlhttp://www.shnenglu.com/lmlf001/comments/5871.htmlhttp://www.shnenglu.com/lmlf001/archive/2006/04/19/5871.html#Feedback0http://www.shnenglu.com/lmlf001/comments/commentRss/5871.htmlhttp://www.shnenglu.com/lmlf001/services/trackbacks/5871.html
函数原型函数描述
char *strchr(const char *s,int c)查找c?/span>s中首ơ出现的位置Q成功将q回该位|的指针Q否则返?/span>NULL
size_t strcspn(const char *s1,const char *s2)计算q返?/span>s1中不包含s2中Q何字W的起始D늚长度。即?/span>s1中查找是否有s2的字W,若碰到有该字W则q回从开始(数数1开始)到该字符之前的字W串长度?/span>

size_t strspn(const char *s1,const char *s2)

计算q返?/span>s1中只包含s2中字W的起始D长度。即当在s1中没遇到?/span>s2中的字符Ӟq回从开始到该字W之前的字符串的长度?/span>
char *strpbrk(const char *s1,const char *s2)定位字符?/span>s1首次出现在字W串s2中字W的位置。若扑ֈ了字W串s2中的字符Q返回一个指向字W串s1中该字符的指针,否则q回NULL
char *strrchr(const char *s,int c)q回c?/span>s中最后一ơ出现的位置指针Q否则返?/span>NULL

char *strstr(const char *s1, const char *s2)

q回s2?/span>s1中首ơ出玎ͼ整个字符串匹配)的位|指针,否则q回NULL


]]>
字符串与数字之间的{换函?/title><link>http://www.shnenglu.com/lmlf001/archive/2006/04/19/5870.html</link><dc:creator>芥之?/dc:creator><author>芥之?/author><pubDate>Wed, 19 Apr 2006 04:50:00 GMT</pubDate><guid>http://www.shnenglu.com/lmlf001/archive/2006/04/19/5870.html</guid><wfw:comment>http://www.shnenglu.com/lmlf001/comments/5870.html</wfw:comment><comments>http://www.shnenglu.com/lmlf001/archive/2006/04/19/5870.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/lmlf001/comments/commentRss/5870.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/lmlf001/services/trackbacks/5870.html</trackback:ping><description><![CDATA[#include<stdlib.h><br /><br /><div align="center"><table id="table1" border="1" height="138" width="100%"><tbody><tr><td><font size="2">函数原型</font></td><td>函数描述</td></tr><tr><td><font size="2"><span lang="EN-US">double atof(const char *nPtr)<span style=""> </span></span></font></td><td>把字W串<span lang="EN-US">nPtr</span>转换?span lang="EN-US">double</span>cd</td></tr><tr><td><font size="2"><span lang="EN-US">int atoi(const char* nPtr)<span style=""> </span></span></font></td><td>把字W串<span lang="EN-US">nPtr</span>转换?span lang="EN-US">int</span>cd</td></tr><tr><td><font size="2">long atol(const char *nPtr)</font></td><td><p class="MsoNormal">把字W串<span lang="EN-US">nPtr</span>转换?span lang="EN-US">long</span></p></td></tr><tr><td><font size="2"><span lang="EN-US">double strtod(const char* nPtr,char **endPtr)</span></font></td><td>把字W串<span lang="EN-US">nPtr</span>转换?span lang="EN-US">double</span>cdQ?span lang="EN-US">endPtr指向nPtr中第一个不是数字的字符的位|?/span></td></tr><tr><td><font size="2"><span lang="EN-US">long strtol(const char *nPtr,char** endPtr, int base)</span></font></td><td>把字W串<span lang="EN-US">nPtr</span>转换?span lang="EN-US">long</span>cdQ?span lang="EN-US">eendPtr指向nPtr中第一个不是数字的字符的位|?/span>Q?span lang="EN-US">base</span>是待转换字符串中数值的q制cdQ?span lang="EN-US">0</span>表示可以是(<span lang="EN-US">8</span>?span lang="EN-US">10</span>?span lang="EN-US">16</span>Q。也可是<span lang="EN-US">2</span>?span lang="EN-US">36</span>中Q何倹{?/td></tr><tr><td><p class="MsoNormal"><font size="2"><span lang="EN-US">unsigned long strtoul(const char* nPtr,char **endPtr, int base)</span></font></p><br /></td><td>把字W串<span lang="EN-US">nPtr</span>转换?span lang="EN-US">unsigned long</span>cdQ?span lang="EN-US">endPtr指向nPtr中第一个不是数字的字符的位|?/span>Q?span lang="EN-US">base</span>是待转换字符串中数值的q制cdQ?span lang="EN-US">0</span>表示可以是(<span lang="EN-US">8</span>?span lang="EN-US">10</span>?span lang="EN-US">16</span>Q。也可是<span lang="EN-US">2</span>?span lang="EN-US">36</span>中Q何倹{?/td></tr></tbody></table></div><br /><img src ="http://www.shnenglu.com/lmlf001/aggbug/5870.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/lmlf001/" target="_blank">芥之?/a> 2006-04-19 12:50 <a href="http://www.shnenglu.com/lmlf001/archive/2006/04/19/5870.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C字符处理函数?/title><link>http://www.shnenglu.com/lmlf001/archive/2006/04/19/5868.html</link><dc:creator>芥之?/dc:creator><author>芥之?/author><pubDate>Wed, 19 Apr 2006 04:28:00 GMT</pubDate><guid>http://www.shnenglu.com/lmlf001/archive/2006/04/19/5868.html</guid><wfw:comment>http://www.shnenglu.com/lmlf001/comments/5868.html</wfw:comment><comments>http://www.shnenglu.com/lmlf001/archive/2006/04/19/5868.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/lmlf001/comments/commentRss/5868.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/lmlf001/services/trackbacks/5868.html</trackback:ping><description><![CDATA[ <p class="MsoNormal"> <span style="font-family: Verdana;" lang="EN-US">#include<ctype.h><br /></span> </p> <br /> <table style="width: 558px; height: 506px;" id="table1" border="1"> <tbody> <tr> <td width="152">函数原型</td> <td> <font face="Book Antiqua">函数描述</font> </td> </tr> <tr> <td width="152"> <span lang="EN-US">int isdigit(int c)</span> </td> <td> <span style="font-family: Book Antiqua;">如果</span> <span style="font-family: Book Antiqua;" lang="EN-US">c</span> <span style="font-family: Book Antiqua;">是一个数字,q回</span> <span style="font-family: Book Antiqua;" lang="EN-US">true</span> <span style="font-family: Book Antiqua;">Q否则返?/span> <span style="font-family: Book Antiqua;" lang="EN-US">false</span> </td> </tr> <tr> <td width="152"> <span lang="EN-US">int isalpha(int c)</span> </td> <td> <span style="font-family: Book Antiqua;">如果</span> <span style="font-family: Book Antiqua;" lang="EN-US">c</span> <span style="font-family: Book Antiqua;">是一个字母,q回</span> <span style="font-family: Book Antiqua;" lang="EN-US">true</span> <span style="font-family: Book Antiqua;">Q否则返?/span> <span style="font-family: Book Antiqua;" lang="EN-US">false</span> </td> </tr> <tr> <td width="152"> <span lang="EN-US">int isalnum(int c)</span> </td> <td> <span style="font-family: Book Antiqua;">如果</span> <span style="font-family: Book Antiqua;" lang="EN-US">c</span> <span style="font-family: Book Antiqua;">是一个字母或数字Q返?/span> <span style="font-family: Book Antiqua;" lang="EN-US">true</span> <span style="font-family: Book Antiqua;">Q否则返?/span> <span style="font-family: Book Antiqua;" lang="EN-US">false</span> </td> </tr> <tr> <td width="152"> <span lang="EN-US">int isxdigit(int c)</span> </td> <td> <p class="MsoNormal"> <span style="font-family: Book Antiqua;">如果</span> <span style="font-family: Book Antiqua;" lang="EN-US">c</span> <span style="font-family: Book Antiqua;">是一个十六进制字W,q回</span> <span style="font-family: Book Antiqua;" lang="EN-US">true</span> <span style="font-family: Book Antiqua;">Q否则返?/span> <span style="font-family: Book Antiqua;" lang="EN-US">false</span> </p> </td> </tr> <tr> <td width="152"> <span lang="EN-US">int islower(int c)</span> </td> <td> <span style="font-family: Book Antiqua;">如果</span> <span style="font-family: Book Antiqua;" lang="EN-US">c</span> <span style="font-family: Book Antiqua;">是一个小写字母,q回</span> <span style="font-family: Book Antiqua;" lang="EN-US">true</span> <span style="font-family: Book Antiqua;">Q否则返?/span> <span style="font-family: Book Antiqua;" lang="EN-US">false</span> </td> </tr> <tr> <td width="152"> <span lang="EN-US">int isupper(int c) </span> </td> <td> <p class="MsoNormal"> <span style="font-family: Book Antiqua;">如果</span> <span style="font-family: Book Antiqua;" lang="EN-US">c</span> <span style="font-family: Book Antiqua;">是一个大写字母,q回</span> <span style="font-family: Book Antiqua;" lang="EN-US">true</span> <span style="font-family: Book Antiqua;">Q否则返?/span> <span style="font-family: Book Antiqua;" lang="EN-US">false</span> </p> </td> </tr> <tr> <td width="152"> <span lang="EN-US">int tolower(int c)</span> </td> <td> <p class="MsoNormal"> <span style="font-family: Book Antiqua;"> 如果c为大写字母,q回其小写字母,否则q回原参?/span> </p> </td> </tr> <tr> <td width="152"> <p class="MsoNormal"> <span lang="EN-US">int toupper(int c)</span> </p> </td> <td> <p class="MsoNormal"> <span style="font-family: Book Antiqua;" lang="EN-US">如果c为小写字母,</span> <span style="font-family: Book Antiqua;">q回其大写字母,否则q回原参?/span> </p> </td> </tr> <tr> <td width="152"> <span lang="EN-US">int isspace(int c) </span> </td> <td> <span style="font-family: Book Antiqua;">如果</span> <span style="font-family: Book Antiqua;" lang="EN-US">c</span> <span style="font-family: Book Antiqua;">是一个空白符Q返?/span> <span style="font-family: Book Antiqua;" lang="EN-US">true</span> <span style="font-family: Book Antiqua;">Q否则返?/span> <span style="font-family: Book Antiqua;" lang="EN-US">false</span> <span style="font-family: Book Antiqua;">。空白符包括Q?/span> <span style="font-family: Book Antiqua;" lang="EN-US">’\n? </span> <span style="font-family: Book Antiqua;">I格Q?/span> <span style="font-family: Book Antiqua;" lang="EN-US">’\t? , ‘\r?,</span> <span style="font-family: Book Antiqua;">q纸W(</span> <span style="font-family: Book Antiqua;" lang="EN-US">’\f?/span> <span style="font-family: Book Antiqua;">Q?/span> <span style="font-family: Book Antiqua;" lang="EN-US">,</span> <span style="font-family: Book Antiqua;">垂直制表W?/span> <span style="font-family: Book Antiqua;" lang="EN-US">(‘\v?</span> </td> </tr> <tr> <td width="152"> <span lang="EN-US">int iscntrl(int c)</span> </td> <td> <span style="font-family: Book Antiqua;" lang="EN-US"> </span> <span style="font-family: Book Antiqua;">如果</span> <span style="font-family: Book Antiqua;" lang="EN-US">c</span> <span style="font-family: Book Antiqua;">是一个控制符Q返?/span> <span style="font-family: Book Antiqua;" lang="EN-US">true</span> <span style="font-family: Book Antiqua;">Q否则返?/span> <span style="font-family: Book Antiqua;" lang="EN-US">false</span> </td> </tr> <tr> <td width="152"> <span lang="EN-US">int ispunct(int c)</span> </td> <td> <p class="MsoNormal"> <span style="font-family: Book Antiqua;" lang="EN-US"> </span> <span style="font-family: Book Antiqua;">如果</span> <span style="font-family: Book Antiqua;" lang="EN-US">c</span> <span style="font-family: Book Antiqua;">是一个除I格、数字和字母外的可打印字W,q回</span> <span style="font-family: Book Antiqua;" lang="EN-US">true</span>,<span style="font-family: Book Antiqua;">否则q回</span><span style="font-family: Book Antiqua;" lang="EN-US">false</span></p> </td> </tr> <tr> <td width="152"> <span lang="EN-US">int isprint(int c) </span> </td> <td> <p class="MsoNormal"> <span style="font-family: Book Antiqua;">如果</span> <span style="font-family: Book Antiqua;" lang="EN-US">c</span> <span style="font-family: Book Antiqua;">是一个可打印W(包括I格Q,q回</span> <span style="font-family: Book Antiqua;" lang="EN-US">true</span> <span style="font-family: Book Antiqua;">Q否则返?/span> <span style="font-family: Book Antiqua;" lang="EN-US">false</span> </p> </td> </tr> <tr> <td width="152"> <span lang="EN-US">int isgraph(int c)</span> </td> <td> <p class="MsoNormal"> <span style="font-family: Book Antiqua;" lang="EN-US"> </span> <span style="font-family: Book Antiqua;">如果</span> <span style="font-family: Book Antiqua;" lang="EN-US">c</span> <span style="font-family: Book Antiqua;">是除I格之外的可打印字符Q返?/span> <span style="font-family: Book Antiqua;" lang="EN-US">true</span> <span style="font-family: Book Antiqua;">Q否则返?/span> <span style="font-family: Book Antiqua;" lang="EN-US">false</span> </p> </td> </tr> </tbody> </table> <img src ="http://www.shnenglu.com/lmlf001/aggbug/5868.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/lmlf001/" target="_blank">芥之?/a> 2006-04-19 12:28 <a href="http://www.shnenglu.com/lmlf001/archive/2006/04/19/5868.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++文g操作http://www.shnenglu.com/lmlf001/archive/2006/04/18/5815.html芥之?/dc:creator>芥之?/author>Tue, 18 Apr 2006 05:03:00 GMThttp://www.shnenglu.com/lmlf001/archive/2006/04/18/5815.htmlhttp://www.shnenglu.com/lmlf001/comments/5815.htmlhttp://www.shnenglu.com/lmlf001/archive/2006/04/18/5815.html#Feedback5http://www.shnenglu.com/lmlf001/comments/commentRss/5815.htmlhttp://www.shnenglu.com/lmlf001/services/trackbacks/5815.html 在C++中,有一个streamq个c,所有的I/O都以q个“流”类为基的,包括我们要认识的文gI/OQstreamq个cL两个重要的运符Q?

1、插入器(<<)
   向流输出数据。比如说pȝ有一个默认的标准输出?cout)Q一般情况下是指的昄器,所以,cout<<"Write Stdout"<<'\n';pC把字符?Write Stdout"和换行字W?'\n')输出到标准输出流?

2、析取器(>>)
  从流中输入数据。比如说pȝ有一个默认的标准输入?cin)Q一般情况下是指的键盘Q所以,cin>>x;pCZ标准输入中d一个指定类?卛_量x的类?的数据?

  在C++中,Ҏ件的操作是通过stream的子cfstream(file stream)来实现的Q所以,要用q种方式操作文gQ就必须加入头文件fstream.h。下面就把此cȝ文g操作q程一一道来?

一、打开文g
  在fstreamcMQ有一个成员函数open()Q就是用来打开文g的,其原型是Q?

void open(const char* filename,int mode,int access);

参数Q?

filenameQ  要打开的文件名
modeQ    要打开文g的方?
accessQ   打开文g的属?
打开文g的方式在cios(是所有流式I/Ocȝ基类)中定义,常用的值如下:

ios::appQ   以追加的方式打开文g
ios::ateQ   文g打开后定位到文g,ios:app包含有此属?
ios::binaryQ? 以二q制方式打开文gQ缺省的方式是文本方式。两U方式的区别见前?
ios::inQ    文g以输入方式打开
ios::outQ   文g以输出方式打开
ios::nocreateQ?不徏立文Ӟ所以文件不存在时打开p| 
ios::noreplaceQ不覆盖文gQ所以打开文g时如果文件存在失?
ios::truncQ  如果文g存在Q把文g长度设ؓ0
  可以用“或”把以上属性连接v来,如ios::out|ios::binary

  打开文g的属性取值是Q?

0Q普通文Ӟ打开讉K
1Q只L?
2Q隐含文?
4Q系l文?
  可以用“或”或者?”把以上属性连接v?Q如3?|2是以只d隐含属性打开文g?

  例如Q以二进制输入方式打开文gc:\config.sys

  fstream file1;
  file1.open("c:\\config.sys",ios::binary|ios::in,0);

  如果open函数只有文g名一个参敎ͼ则是以读/写普通文件打开Q即Q?

  file1.open("c:\\config.sys");<=>file1.open("c:\\config.sys",ios::in|ios::out,0);

  另外Qfstreamq有和open()一L构造函敎ͼ对于上例Q在定义的时侯就可以打开文g了:

  fstream file1("c:\\config.sys");

  特别提出的是Qfstream有两个子c:ifstream(input file stream)和ofstream(outpu file stream)Qifstream默认以输入方式打开文gQ而ofstream默认以输出方式打开文g?

  ifstream file2("c:\\pdos.def");//以输入方式打开文g
  ofstream file3("c:\\x.123");//以输出方式打开文g

  所以,在实际应用中Q根据需要的不同Q选择不同的类来定义:如果想以输入方式打开Q就用ifstream来定义;如果想以输出方式打开Q就用ofstream来定义;如果想以输入/输出方式来打开Q就用fstream来定义?

二、关闭文?
  打开的文件用完成后一定要关闭Qfstream提供了成员函数close()来完成此操作Q如Qfile1.close();把file1相连的文件关闭?

三、读写文?
  d文g分ؓ文本文g和二q制文g的读取,对于文本文g的读取比较简单,用插入器和析取器可以了Q而对于二q制的读取就要复杂些Q下要就详细的介l这两种方式

  1、文本文件的d
  文本文g的读写很单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开Qfile2以输出打开。示例如下:

  file2<<"I Love You";//向文件写入字W串"I Love You"
  int i;
  file1>>i;//从文件输入一个整数倹{?

  q种方式q有一U简单的格式化能力,比如可以指定输出?6q制{等Q具体的格式有以下一?

操纵W?功能 输入/输出
dec 格式化ؓ十进制数值数?输入和输?
endl 输出一个换行符q刷新此?输出
ends 输出一个空字符 输出
hex 格式化ؓ十六q制数值数?输入和输?
oct 格式化ؓ八进制数值数?输入和输?
setpxecision(int p) 讄点数的_ֺ位数 输出

  比如要把123当作十六q制输出Qfile1<<<123;要把3.1415926?位精度输出:FILE1<<<3.1415926?

  2、二q制文g的读?
①put()
  put()函数向流写入一个字W,其原型是ofstream &put(char ch)Q用也比较单,如file1.put('c');是向流写一个字W?c'?

②get()
  get()函数比较灉|Q有3U常用的重蝲形式Q?

  一U就是和put()对应的Ş式:ifstream &get(char &ch);功能是从中d一个字W,l果保存在引用ch中,如果到文件尾Q返回空字符。如file2.get(x);表示从文件中d一个字W,q把d的字W保存在x中?

  另一U重载Ş式的原型是: int get();q种形式是从中q回一个字W,如果到达文g,q回EOFQ如x=file2.get();和上例功能是一L?

   q有一UŞ式的原型是:ifstream &get(char *buf,int num,char delim='\n')Q这UŞ式把字符d?buf 指向的数l,直到d?num 个字W或遇到了由 delim 指定的字W,如果没? delim q个参数Q将使用~省值换行符'\n'。例如:

  file2.get(str1,127,'A');//从文件中d字符到字W串str1Q当遇到字符'A'或读取了127个字W时l止?

③读写数据块
  要读写二q制数据块,使用成员函数read()和write()成员函数Q它们原型如下:

    read(unsigned char *buf,int num);
    write(const unsigned char *buf,int num);

   read()从文件中d num 个字W到 buf 指向的缓存中Q如果在q未d num 个字W时到了文件尾Q可以用成员函数 int gcount();来取得实际读取的字符敎ͼ?write() 从buf 指向的缓存写 num 个字W到文g中,值得注意的是~存的类型是 unsigned char *Q有时可能需要类型{换?

例:

    unsigned char str1[]="I Love You";
    int n[5];
    ifstream in("xxx.xxx");
    ofstream out("yyy.yyy");
    out.write(str1,strlen(str1));//把字W串str1全部写到yyy.yyy?
    in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数Q注意类型{?
    in.close();out.close();

四、检EOF
  成员函数eof()用来是否到达文件尾Q如果到达文件尾q回?|否则q回0。原型是int eof();

例:  if(in.eof())ShowMessage("已经到达文g!");

五、文件定?
   和C的文件操作方式不同的是,C++ I/Opȝ理两个与一个文件相联系的指针。一个是L针,它说明输入操作在文g中的位置Q另一个是写指针,它下ơ写操作的位|。每ơ执行输入或输出Ӟ 相应的指针自动变化。所以,C++的文件定位分位置和写位置的定位,对应的成员函数是 seekg()? seekp()Qseekg()是设|读位置Qseekp是设|写位置。它们最通用的Ş式如下:

    istream &seekg(streamoff offset,seek_dir origin);
    ostream &seekp(streamoff offset,seek_dir origin);

  streamoff定义?iostream.h 中,定义有偏U量 offset 所能取得的最大|seek_dir 表示Ud的基准位|,是一个有以下值的枚DQ?

ios::begQ  文g开?
ios::curQ  文g当前位置
ios::endQ  文gl尾
  q两个函C般用于二q制文gQ因为文本文件会因ؓpȝ对字W的解释而可能与预想的g同?

例:

     file1.seekg(1234,ios::cur);//把文件的L针从当前位置向后U?234个字?
     file2.seekp(1234,ios::beg);//把文件的写指针从文g开头向后移1234个字?br />



]]>
C++I/O操作http://www.shnenglu.com/lmlf001/archive/2006/04/17/5761.html芥之?/dc:creator>芥之?/author>Mon, 17 Apr 2006 08:15:00 GMThttp://www.shnenglu.com/lmlf001/archive/2006/04/17/5761.htmlhttp://www.shnenglu.com/lmlf001/comments/5761.htmlhttp://www.shnenglu.com/lmlf001/archive/2006/04/17/5761.html#Feedback0http://www.shnenglu.com/lmlf001/comments/commentRss/5761.htmlhttp://www.shnenglu.com/lmlf001/services/trackbacks/5761.html 原文地址:http://wonderow.cnblogs.com/archive/2005/06/21/178719.html

格式控制

    在前面,输入Q输出的数据没有指定格式Q它们都按缺省的格式输入Q输出。然而,有时需要对数据 格式q行控制。这旉利用ioscM定义的格式控制成员函敎ͼ通过调用它们来完成格式的讄。ioscȝ格式控制函数如下所C:

long flags( ) const q回当前的格式标志?/font>
long flays(long newflag) 讄格式标志为newflagQ返回旧的格式标志?/font>
long setf(long bits)   讄指定的格式标志位Q返回旧的格式标志?/font>
long setf(long bits,long field) field指定的格式标志位|ؓbitsQ返回旧的格式标志?/font>
long unsetf(long bits) 清除bits指定的格式标志位Q返回旧的格式标志?/font>
long fill(char c)  讄填充字符Q缺省条件下是空根{?/font>
char fill( )   q回当前填充字符?/font>
int precision(int val)  讄_度ؓvalQ控制输出QҎ的有效位Q返回旧倹{?/font>
int precision( ) q回旧的_度倹{?/font>
int width(int val)      讄昄数据的宽?域宽),q回旧的域宽?/font>
int width( )  只返回当前域宽,~省宽度?。这时插入操作能按表C数 据的最宽度显C数据。?/font>

预定义的操纵子
    使用成员函数控制格式化输入输出时Q每个函数调用需要写一条语句,其是它不能用在插入或提取运符的表辑ּ中,而用操U늮子,则可以在插入和提取运符的表辑ּ中控制格式化?/font> 入和输出。在E序中用操U늮字必d入头文g
iomanip.h

dec 十进制的输入输出
hex 十六q制的输入输?/font>
oct   八进制的输入输出
ws   提取I白字符
ends   输出一个nul字符
endl   输出一个换行字W,同时h?/font>
flush h?/font>
resetiosflags(long) 请除特定的格式标志位
setiosflags(long) 讄特定的格式标志位
setfill(char) 讄填充字符
setprecision(int) 讄输出点数的_?/font>
setw(int) 讄域宽格式变量

其它函?/font>

错误处理
    在对一个流对象q行I/O操作Ӟ可能会生错误。当错误发生Ӟ错误的性质被记录在ioscȝ一个数据成员中?/font>
ioscM定义的描q错误状态的帔R:

goodbit   没有错误Q正常状态  eofbit 到达的l尾  
failbit I/O操作p|Q清除状态字后,可以Ҏl箋q行操作?/font>
badbit 试图q行非法操作Q清除状态字后,可能还可以使用?/font>
hardfail 致命错误Q不可恢复的错误?/font>

ostreamcȝ成员函数
的其它成员函数可以从流中读取字W或字符ԌҎq行无格式化的输?输出操作Q以及直接控制对的I/O操作?/font>

q回cd ioscȝ成员 描      q?/font>
ostream* tie(ostream*)    当前流与指定的输出连接v来。每当需?d当前时Q连接的会自动h。C++库已用cin.tie(cout)输入流与输出流q接 h。要取消与输出流的连接可采用is.tie(0)
ostream* tie( ) q回指向q接的指针


q回cd ostreamcȝ成员 描      q?/font>
ostream& put(char ch) 向流中输Z个字WchQ不q行M转换
ostream& write(char*,int) 向流中输出指定长度的字符Ԍ不进行{?/font>
ostream&  flush( ) h,输出所有缓冲的但还未输出的数据
ostream& seekp(streampos) Ud的当前指针到给定的l对位置
ostream& seekp(sereamoff,seek_dir) 的当前指针cM与文件的当前指针
streampos teelp( ) q回的当前指针的绝对位|?/font>

istreamcȝ成员函数

q回cd istreamcȝ成员 描        q?/font>
int get( ) dq返回一个字W?/font>
istream& get(char&c) d字符q存入c?/font>
istream& get(char*ptr,int len,char delim='') d指定的字W到~冲ZQ直到遇到指定的分界Wؓ止,分界W不填入~冲区?/font>
istream& getline(char*ptr,int len,char delim='') 与get(char*ptr,int len,chardelim =''Q?cMQ但分界符?/font> 入缓冲区?/font>
istream& putback( ) 最q读取的字符攑֛中
istream& read(char*,int)
d规定长度的字W串到缓冲区?br />函数gcount()q回d的字节数
int peek( )  q回中下一个字W,但不Ud?/font> 件指?/font>
istream& seekg(streampos) Ud当前指针Cl对地址
istream&  seekg(streampos,seek_dir) Ud当前指针C相对地址
streampos tellg( ) q回当前指针
istream& ignore(int n=1,delim=EOF) 跌中几个字符Q或直到遇到指定的分界符为止

getch()函数用于从键盘输入一个字W,不回显,包含头文?lt;conio.h>?br />

]]>
字符串处理函?/title><link>http://www.shnenglu.com/lmlf001/archive/2006/04/17/5756.html</link><dc:creator>芥之?/dc:creator><author>芥之?/author><pubDate>Mon, 17 Apr 2006 08:05:00 GMT</pubDate><guid>http://www.shnenglu.com/lmlf001/archive/2006/04/17/5756.html</guid><wfw:comment>http://www.shnenglu.com/lmlf001/comments/5756.html</wfw:comment><comments>http://www.shnenglu.com/lmlf001/archive/2006/04/17/5756.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/lmlf001/comments/commentRss/5756.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/lmlf001/services/trackbacks/5756.html</trackback:ping><description><![CDATA[char *strcpy(char *s1, const char *s2)<br />字W串s2复制到字W串数组s1中,q回s1的?br /><br />char *strncpy(char *s1, const char *s2, size_t n)  <br />字W串s2中最多n个字W复制到字符串数ls1中,q回s1的?br />//当n <strlen(s2)Ӟpȝ不自动在s1l尾dnull字符<br /><br />char *strcat(char *s1, const char *s2)<br />字W串s2d到字W串s1的后面。s2的第一个字W重定义s1的nulll止W。返回s1的?br /><br />char *strncat(char *s1, const char *s2, size_t n)<br />字W串s2中最多n个字W添加到字符串s1的后面。s2的第一个字W重定义s1的nulll止W。返回s1的?br />//函数在s1l尾自动dnull字符<br /><br />int strcmp(const char *s1, const char *s2)<br />比较字符串s1和字W串s2。函数在s1{于、小于或大于s2时分别返?、小?或者大?的?br /><br />int strncmp(const char *s1, const char *s2, size_t n)<br />比较字符串s1中的n个字W和字符串s2。函数在s1{于、小于或大于s2时分别返?、小?或者大?的?br /><br />char * strtok(char *s1,const char *s2)<br />? 一pdstrtok调用s1字符串标记化(字W串分成各个逻辑lgQ如同一行文本中的每个单?Q用字符串s2所包含的字W分隔。首ơ调用时包含s1 为第一个参敎ͼ后面调用时l标记化同一字符Ԍ包含NULL为第一个参数。每ơ调用时q回当前标记指针。如果函数调用时不再有更多标讎ͼ则返回NULL<br /><br />size_t strlen(const char *s)<br />定字符串长?q回nulll止W之前的字符敊W?img src ="http://www.shnenglu.com/lmlf001/aggbug/5756.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/lmlf001/" target="_blank">芥之?/a> 2006-04-17 16:05 <a href="http://www.shnenglu.com/lmlf001/archive/2006/04/17/5756.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.tzcn86.cn" target="_blank">þ99Ʒһ</a>| <a href="http://www.panxl.cn" target="_blank">þҹ³Ƭ</a>| <a href="http://www.fzdhqp.cn" target="_blank">ĻþþƷ </a>| <a href="http://www.6wx.com.cn" target="_blank">˾ƷѾþþþ</a>| <a href="http://www.fd-tex.cn" target="_blank">˾þۺ</a>| <a href="http://www.52wysq.cn" target="_blank">Ʒþþþa</a>| <a href="http://www.0r2kd.cn" target="_blank">Ʒξþþþ99վ</a>| <a href="http://www.nic-xie.cn" target="_blank">þþɫۺϾɫ99</a>| <a href="http://www.5uatm.cn" target="_blank">þwwƷw˳</a>| <a href="http://www.ivgh.cn" target="_blank">ٸƷþ</a>| <a href="http://www.yangrendong.com.cn" target="_blank">ھƷþþžŹƷ</a>| <a href="http://www.whruide.cn" target="_blank">þþþav</a>| <a href="http://www.pi04.cn" target="_blank">69Ʒþþþ9999</a>| <a href="http://www.gdhaojulai.cn" target="_blank">ھƷþ</a>| <a href="http://www.eufonius.cn" target="_blank">ŷþۺ㽶</a>| <a href="http://www.9bexgq.cn" target="_blank">þ㽶߿ۿ</a>| <a href="http://www.qzshinetex.cn" target="_blank">þþwww˳ɾƷ</a>| <a href="http://www.0532ks.cn" target="_blank">þþþþྫƷֱ</a>| <a href="http://www.vcexpress.cn" target="_blank">ɫۺϾþþþۺһ</a>| <a href="http://www.ihxc.cn" target="_blank">?VþþƷ </a>| <a href="http://www.shangxinju.cn" target="_blank">޾þһ</a>| <a href="http://www.life-notes.cn" target="_blank">þþƷŷպ</a>| <a href="http://www.vhxz.cn" target="_blank">޹Ʒþ66</a>| <a href="http://www.gm53.cn" target="_blank">91ƷۺϾþþþþ</a>| <a href="http://www.818pkmu.cn" target="_blank">þþþþ˸߳ӰԺ</a>| <a href="http://www.kexuncms.cn" target="_blank">þ</a>| <a href="http://www.y3d9.cn" target="_blank">þþƷһ</a>| <a href="http://www.fengdingjun.cn" target="_blank">þۺۺϾþ97ɫ</a>| <a href="http://www.glhu.cn" target="_blank">97þþƷ</a>| <a href="http://www.hnzzwl.cn" target="_blank">˾þô߽AVۺӰԺ</a>| <a href="http://www.grandfreshop.cn" target="_blank">޾ƷŮþþþ99С˵</a>| <a href="http://www.yz10.cn" target="_blank">þþþAVȥ</a>| <a href="http://www.34lz.cn" target="_blank">ۺϾƷþ</a>| <a href="http://www.watchesmade.cn" target="_blank">Ʒ׾þAAAƬ69 </a>| <a href="http://www.z5621.cn" target="_blank">Ʒ˾þþþҹӰ </a>| <a href="http://www.i231.cn" target="_blank">һһþaaۺϾƷ</a>| <a href="http://www.p8595.cn" target="_blank">ݺɫþþۺƵպ</a>| <a href="http://www.clwc.net.cn" target="_blank">þۺɫݺ</a>| <a href="http://www.x3077.cn" target="_blank">ŷ˾þۺ </a>| <a href="http://www.jtoushou.cn" target="_blank">2020þþƷ</a>| <a href="http://www.feimatuan.cn" target="_blank">Ʒþþø</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>