﻿<?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++博客-鹰击长空</title><link>http://www.cppblog.com/ylfeng/</link><description /><language>zh-cn</language><lastBuildDate>Mon, 09 Mar 2026 02:46:53 GMT</lastBuildDate><pubDate>Mon, 09 Mar 2026 02:46:53 GMT</pubDate><ttl>60</ttl><item><title>.NET and COM</title><link>http://www.cppblog.com/ylfeng/archive/2013/06/27/201328.html</link><dc:creator>鹰击长空</dc:creator><author>鹰击长空</author><pubDate>Wed, 26 Jun 2013 19:32:00 GMT</pubDate><guid>http://www.cppblog.com/ylfeng/archive/2013/06/27/201328.html</guid><wfw:comment>http://www.cppblog.com/ylfeng/comments/201328.html</wfw:comment><comments>http://www.cppblog.com/ylfeng/archive/2013/06/27/201328.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/ylfeng/comments/commentRss/201328.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ylfeng/services/trackbacks/201328.html</trackback:ping><description><![CDATA[<br /><span style="font-family: Arial; font-size: 12pt;">This note is about book<em> .NET and COM</em>.</span><br /><br /><span style="font-family: Arial; font-size: 12pt; line-height: normal; background-color: #ffffff;">Think of XML Web services simply as components or Application Programming Interfaces (APIs) exposed on a Web site rather than a DLL residing on your own computer.<br /><br /></span><p class="docText" style="margin: 16px 0px 12px; padding: 0px; font-size: 19px; line-height: normal; font-family: verdana, sans-serif; background-color: #ffffff;"><span style="font-family: Arial; font-size: 12pt;">An assembly is a self-describing logical component. Assemblies are units of deployment, units of security, units of versioning, and units of scope for the types contained within. Although an assembly is typically one executable or one DLL, it could be made up of multiple files.&nbsp;</span></p><span style="font-family: Arial; font-size: 12pt; line-height: normal; background-color: #ffffff;">Any assemblies with type definitions contain corresponding type information describing them. This information is called&nbsp;</span><em style="font-family: verdana, sans-serif; font-size: 19px; line-height: normal; background-color: #ffffff;"><a data-book="1" href="http://ezproxy.stevens.edu:2155/9780672333583/app06#gloss53" style="text-decoration: none; outline: none; color: #003399; font-weight: bold;"><span style="font-family: Arial; font-size: 12pt;">metadata</span></a></em><a name="All " style="font-family: verdana, sans-serif; font-size: 19px; line-height: normal; background-color: rgb(255, 255, 255);"></a><span style="font-family: Arial; font-size: 12pt; line-height: normal; background-color: #ffffff;">&nbsp;(data about data).&nbsp;<br /></span><em style="font-family: verdana, sans-serif; font-size: 19px; line-height: normal; background-color: #ffffff;"><a data-book="1" class="docLink" href="http://ezproxy.stevens.edu:2155/9780672333583/app06#gloss65" style="text-decoration: none; outline: none; color: #003399; font-weight: bold;"><br /><span style="font-family: Arial; font-size: 12pt;">Reflection</span></a></em><a name="dynamically inspect" style="font-family: verdana, sans-serif; font-size: 19px; line-height: normal; background-color: #ffffff; width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat;"></a><span style="font-family: Arial; font-size: 12pt; line-height: normal; background-color: #ffffff;">&nbsp;is the process of programmatically obtaining type information. Programs can dynamically inspect (&#8220;reflect upon&#8221;) the metadata for any assemblies, dynamically instantiate objects and invoke members, and even emit metadata dynamically (a technology called&nbsp;</span><span class="docEmphasis" style="font-style: italic; font-family: Arial; font-size: 12pt; line-height: normal; background-color: #ffffff;">Refection Emit</span><span style="font-family: Arial; font-size: 12pt; line-height: normal; background-color: #ffffff;">). Reflection provides late binding facilities like COM&#8217;s&nbsp;</span><tt style="color: green; font-family: 'Courier New', Courier, monospace; font-size: 19px; line-height: normal; background-color: #ffffff;"><span style="font-family: Arial; font-size: 12pt;">IDispatch</span></tt><span style="font-family: Arial; font-size: 12pt; line-height: normal; background-color: #ffffff;">&nbsp;and&nbsp;</span><tt style="color: green; font-family: 'Courier New', Courier, monospace; font-size: 19px; line-height: normal; background-color: #ffffff;"><span style="font-family: Arial; font-size: 12pt;">IDispatchEx</span></tt><span style="font-family: Arial; font-size: 12pt; line-height: normal; background-color: #ffffff;">&nbsp;interfaces, type inspection like COM&#8217;s&nbsp;</span><tt style="color: green; font-family: 'Courier New', Courier, monospace; font-size: 19px; line-height: normal; background-color: #ffffff;"><span style="font-family: Arial; font-size: 12pt;">ITypeInfo</span></tt><span style="font-family: Arial; font-size: 12pt; line-height: normal; background-color: #ffffff;">&nbsp;and&nbsp;</span><tt style="color: green; font-family: 'Courier New', Courier, monospace; font-size: 19px; line-height: normal; background-color: #ffffff;"><span style="font-family: Arial; font-size: 12pt;">ITypeInfo2</span></tt><span style="font-family: Arial; font-size: 12pt; line-height: normal; background-color: #ffffff;">&nbsp;interfaces, and much more.<br /></span><br /><h3><span style="font-family: Arial; font-size: 12pt;">How Unmanaged Code Interacts with Managed Code</span></h3><p style="margin: 16px 0px 12px; padding: 0px; font-size: 19px; line-height: normal; font-family: verdana, sans-serif; background-color: #ffffff;"><span style="font-family: Arial; font-size: 12pt;">Three technologies exist that enable the interaction between unmanaged and managed code:</span></p><ul style="font-family: verdana, sans-serif; font-size: 18px; line-height: normal; background-color: #ffffff;"><li><p style="margin: 16px 0px 12px; padding: 0px; font-size: 19px;"><span style="font-family: Arial; font-size: 12pt;">Platform Invocation Services (PInvoke)</span><br /></p><pre style="font-size: 16px; margin: 0px 10px 12px; padding: 6px 0px;"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;GameSharp<br /><span style="color: #008080; ">&nbsp;2</span>&nbsp;{<br /><span style="color: #008080; ">&nbsp;3</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #808080; ">///</span><span style="color: #008000; ">&nbsp;The&nbsp;native&nbsp;methods&nbsp;in&nbsp;the&nbsp;DLL's&nbsp;unmanaged&nbsp;code.</span><span style="color: #808080; "><br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #808080; "></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">internal</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;UnsafeNativeMethods<br /><span style="color: #008080; ">&nbsp;5</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /><span style="color: #008080; ">&nbsp;6</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;<span style="color: #0000FF; ">string</span>&nbsp;_dllLocation&nbsp;=&nbsp;"CoreDLL.dll";<br /><span style="color: #008080; ">&nbsp;7</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[DllImport(_dllLocation)]<br /><span style="color: #008080; ">&nbsp;8</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">extern</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;SimulateGameDLL(<span style="color: #0000FF; ">int</span>&nbsp;a,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;b);<br /><span style="color: #008080; ">&nbsp;9</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">10</span>&nbsp;}</div><div><span style="font-family: Arial; font-size: 12pt;"><h4>Choosing a Calling Convention</h4><p style="margin: 16px 0px 12px; padding: 0px; font-family: verdana, sans-serif; white-space: normal;">The calling convention of an entry point can be specified using another&nbsp;<tt style="color: green; font-family: 'Courier New', Courier, monospace;">DllImportAttribute</tt>&nbsp;named parameter, called&nbsp;<tt style="color: green; font-family: 'Courier New', Courier, monospace;">CallingConvention</tt>. The choices for this are as follows:</p><ul style="font-family: verdana, sans-serif; font-size: 15px; white-space: normal;"><li><p style="margin: 16px 0px 12px; padding: 0px; font-size: 16px;"><a name="idd1e150470"></a><tt style="color: green; font-family: 'Courier New', Courier, monospace;">CallingConvention.Cdecl</tt>.&nbsp;The caller is responsible for cleaning the stack. Therefore, this calling convention is appropriate for methods that accept a variable number of parameters (like&nbsp;<tt style="color: green; font-family: 'Courier New', Courier, monospace;">printf</tt>).</p></li><li><p style="margin: 16px 0px 12px; padding: 0px; font-size: 16px;"><a name="idd1e150483"></a><tt style="color: green; font-family: 'Courier New', Courier, monospace;">CallingConvention.FastCall</tt>. This is not supported by version 1.0 of the .NET Framework.</p></li><li><p style="margin: 16px 0px 12px; padding: 0px; font-size: 16px;"><a name="idd1e150493"></a><tt style="color: green; font-family: 'Courier New', Courier, monospace;">CallingConvention.StdCall</tt>. This is the default convention for PInvoke methods running on Windows. The callee is responsible for cleaning the stack.</p></li><li><p style="margin: 16px 0px 12px; padding: 0px; font-size: 16px;"><a name="idd1e150503"></a><tt style="color: green; font-family: 'Courier New', Courier, monospace;">CallingConvention.ThisCall</tt>. This is used for calling unmanaged methods defined on a class. All but the first parameter is pushed on the stack since the first parameter is the&nbsp;<span style="font-style: italic;">this</span>&nbsp;pointer, stored in the ECX register.</p></li><li><p style="margin: 16px 0px 12px; padding: 0px; font-size: 16px;"><a name="idd1e150516"></a><tt style="color: green; font-family: 'Courier New', Courier, monospace;">CallingConvention.Winapi</tt>. This isn&#8217;t a real calling convention, but rather indicates to use the default calling convention for the current platform. On Windows (but not Windows CE), the default calling convention is&nbsp;<tt style="color: green; font-family: 'Courier New', Courier, monospace;">StdCall</tt>.</p></li></ul><p style="margin: 16px 0px 12px; padding: 0px; font-family: verdana, sans-serif; white-space: normal;"><tt style="color: green; font-family: 'Courier New', Courier, monospace;">Declare</tt>&nbsp;always uses&nbsp;<tt style="color: green; font-family: 'Courier New', Courier, monospace;">Winapi</tt>, and the default for&nbsp;<tt style="color: green; font-family: 'Courier New', Courier, monospace;">DllImportAttribute</tt>&nbsp;is also&nbsp;<tt style="color: green; font-family: 'Courier New', Courier, monospace;">Winapi</tt>. As you might guess, this is the calling convention used by Win32 APIs, so this setting doesn&#8217;t need to be used in this chapter&#8217;s examples.<br /></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #0000FF; ">using</span>&nbsp;System;<br /><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #0000FF; ">using</span>&nbsp;System.Runtime.InteropServices;<br /><span style="color: #008080; ">&nbsp;3</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;LibWrap<br /><span style="color: #008080; ">&nbsp;5</span>&nbsp;{<br /><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;C#&nbsp;doesn't&nbsp;support&nbsp;varargs&nbsp;so&nbsp;all&nbsp;arguments&nbsp;must&nbsp;be&nbsp;explicitly&nbsp;defined.&nbsp;<br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #008000; "></span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;CallingConvention.Cdecl&nbsp;must&nbsp;be&nbsp;used&nbsp;since&nbsp;the&nbsp;stack&nbsp;is&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #008000; "></span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;cleaned&nbsp;up&nbsp;by&nbsp;the&nbsp;caller.&nbsp;<br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #008000; "><br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #008000; "></span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;int&nbsp;printf(&nbsp;const&nbsp;char&nbsp;*format&nbsp;[,&nbsp;argument]<img src="http://www.cppblog.com/Images/dot.gif"  alt="" />&nbsp;)</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #008000; "></span><br /><span style="color: #008080; ">12</span>&nbsp;[DllImport("msvcrt.dll",&nbsp;CharSet=CharSet.Unicode,&nbsp;CallingConvention=CallingConvention.Cdecl)]<br /><span style="color: #008080; ">13</span>&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">extern</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;printf(String&nbsp;format,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;i,&nbsp;<span style="color: #0000FF; ">double</span>&nbsp;d);&nbsp;<br /><span style="color: #008080; ">14</span>&nbsp;<br /><span style="color: #008080; ">15</span>&nbsp;[DllImport("msvcrt.dll",&nbsp;CharSet=CharSet.Unicode,&nbsp;CallingConvention=CallingConvention.Cdecl)]<br /><span style="color: #008080; ">16</span>&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">extern</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;printf(String&nbsp;format,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;i,&nbsp;String&nbsp;s);&nbsp;<br /><span style="color: #008080; ">17</span>&nbsp;}<br /><span style="color: #008080; ">18</span>&nbsp;<br /><span style="color: #008080; ">19</span>&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;App<br /><span style="color: #008080; ">20</span>&nbsp;{<br /><span style="color: #008080; ">21</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;Main()<br /><span style="color: #008080; ">22</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /><span style="color: #008080; ">23</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LibWrap.printf("\nPrint&nbsp;params:&nbsp;%i&nbsp;%f",&nbsp;99,&nbsp;99.99);<br /><span style="color: #008080; ">24</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LibWrap.printf("\nPrint&nbsp;params:&nbsp;%i&nbsp;%s",&nbsp;99,&nbsp;"abcd");<br /><span style="color: #008080; ">25</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">26</span>&nbsp;}</div></span></div></pre></li><li><p style="margin: 16px 0px 12px; padding: 0px; font-size: 19px;"><span style="font-family: Arial; font-size: 12pt;">Mixed-Mode Programming Using Managed Extensions to C++</span></p></li><li><p style="margin: 16px 0px 12px; padding: 0px; font-size: 19px;"><span style="font-family: Arial; font-size: 12pt;">COM Interoperability</span></p></li></ul>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://ezproxy.stevens.edu:2155/getfile?item=ZHIyZ2E5YTM3LzhyZzcwYy9pdHNwLzVlMzZtMzM4cGlwZl9nYWxpajVodDBzMC9jZy4z"  alt="" /><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Good COM server implementation in C#<br /><h1><span style="font-size: 14px;">&nbsp; &nbsp;</span><span style="font-size: 14px;">&nbsp; &nbsp;</span><a href="http://www.codeproject.com/Articles/7859/Building-COM-Objects-in-C#_rating" style="font-family: Arial; font-size: 12pt;">Building COM Objects in C#</a></h1><div style="font-family: verdana, sans-serif; font-size: 18px; line-height: normal; background-color: #ffffff;"><h1><span style="font-size: 18px;">&nbsp; &nbsp;</span><span style="font-size: 18px;">&nbsp; </span><a href="http://www.codeproject.com/Articles/12579/Building-COM-Servers-in-NET" style="font-family: Arial; font-size: 12pt;">Building COM Servers in .NET</a></h1><h1><span style="font-family: Arial; font-size: 12pt;"><a href="http://www.codeproject.com/Articles/12579/Building-COM-Servers-in-NET"><br /><br /></a></span></h1></div><br /><br /><br /><br /><br /><div id="LCS_C4CFC0DE_134F_4466_B2A2_FF7C59A8BFAD_communicationDiv"></div><img src ="http://www.cppblog.com/ylfeng/aggbug/201328.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ylfeng/" target="_blank">鹰击长空</a> 2013-06-27 03:32 <a href="http://www.cppblog.com/ylfeng/archive/2013/06/27/201328.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Learning notes of Python</title><link>http://www.cppblog.com/ylfeng/archive/2012/12/20/196475.html</link><dc:creator>鹰击长空</dc:creator><author>鹰击长空</author><pubDate>Thu, 20 Dec 2012 04:41:00 GMT</pubDate><guid>http://www.cppblog.com/ylfeng/archive/2012/12/20/196475.html</guid><wfw:comment>http://www.cppblog.com/ylfeng/comments/196475.html</wfw:comment><comments>http://www.cppblog.com/ylfeng/archive/2012/12/20/196475.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/ylfeng/comments/commentRss/196475.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ylfeng/services/trackbacks/196475.html</trackback:ping><description><![CDATA[As demand of project, I need to learn this language a little bit more. Although I have written some Python script before, still there is numerous knowledge need to learn.<br /><br />eg: y = raw_input(&#8216;Enter a number&#8217;)<br />#&nbsp;y is a string<br /><br /><pre xml:space="preserve" style="margin-top: 0px; margin-bottom: 10px; padding: 5px; border: 1px solid #d6d6d6; font-family: Monaco, Courier, monospace; line-height: 19.983333587646484px; background-color: #eeeeee; width: 653.683349609375px; font-size: 12px; white-space: pre-wrap;"><span style="margin: 0px; padding: 0px;">list </span><span style="margin: 0px; padding: 0px; color: #666600;">=</span> <span style="margin: 0px; padding: 0px; color: #666600;">[</span> <span style="margin: 0px; padding: 0px; color: #008800;">'abcd'</span><span style="margin: 0px; padding: 0px; color: #666600;">,</span> <span style="margin: 0px; padding: 0px; color: #006666;">786</span> <span style="margin: 0px; padding: 0px; color: #666600;">,</span> <span style="margin: 0px; padding: 0px; color: #006666;">2.23</span><span style="margin: 0px; padding: 0px; color: #666600;">,</span> <span style="margin: 0px; padding: 0px; color: #008800;">'john'</span><span style="margin: 0px; padding: 0px; color: #666600;">,</span> <span style="margin: 0px; padding: 0px; color: #006666;">70.2</span> <span style="margin: 0px; padding: 0px; color: #666600;">]</span><span style="margin: 0px; padding: 0px;"> tinylist </span><span style="margin: 0px; padding: 0px; color: #666600;">=</span> <span style="margin: 0px; padding: 0px; color: #666600;">[</span><span style="margin: 0px; padding: 0px; color: #006666;">123</span><span style="margin: 0px; padding: 0px; color: #666600;">,</span> <span style="margin: 0px; padding: 0px; color: #008800;">'john'</span><span style="margin: 0px; padding: 0px; color: #666600;">]</span><span style="margin: 0px; padding: 0px;">  <br /></span><span style="margin: 0px; padding: 0px; color: #000088;">print</span><span style="margin: 0px; padding: 0px;"> list          </span><span style="margin: 0px; padding: 0px; color: #880000;"># Prints complete list</span><span style="margin: 0px; padding: 0px;"> <br /></span><span style="margin: 0px; padding: 0px; color: #000088;">print</span><span style="margin: 0px; padding: 0px;"> list</span><span style="margin: 0px; padding: 0px; color: #666600;">[</span><span style="margin: 0px; padding: 0px; color: #006666;">0</span><span style="margin: 0px; padding: 0px; color: #666600;">]</span> <span style="margin: 0px; padding: 0px; color: #880000;"># Prints first element of the list</span><span style="margin: 0px; padding: 0px;"> <br /></span><span style="margin: 0px; padding: 0px; color: #000088;">print</span><span style="margin: 0px; padding: 0px;"> list</span><span style="margin: 0px; padding: 0px; color: #666600;">[</span><span style="margin: 0px; padding: 0px; color: #006666;">1</span><span style="margin: 0px; padding: 0px; color: #666600;">:</span><span style="margin: 0px; padding: 0px; color: #006666;">3</span><span style="margin: 0px; padding: 0px; color: #666600;">]</span> <span style="margin: 0px; padding: 0px; color: #880000;"># Prints elements starting from 2nd till 3rd </span><span style="margin: 0px; padding: 0px;"> <br /></span><span style="margin: 0px; padding: 0px; color: #000088;">print</span><span style="margin: 0px; padding: 0px;"> list</span><span style="margin: 0px; padding: 0px; color: #666600;">[</span><span style="margin: 0px; padding: 0px; color: #006666;">2</span><span style="margin: 0px; padding: 0px; color: #666600;">:]</span> <span style="margin: 0px; padding: 0px; color: #880000;"># Prints elements starting from 3rd element</span><span style="margin: 0px; padding: 0px;"> <br /></span><span style="margin: 0px; padding: 0px; color: #000088;">print</span><span style="margin: 0px; padding: 0px;"> tinylist </span><span style="margin: 0px; padding: 0px; color: #666600;">*</span> <span style="margin: 0px; padding: 0px; color: #006666;">2</span> <span style="margin: 0px; padding: 0px; color: #880000;"># Prints list two times</span><span style="margin: 0px; padding: 0px;"> <br /></span><span style="margin: 0px; padding: 0px; color: #000088;">print</span><span style="margin: 0px; padding: 0px;"> list </span><span style="margin: 0px; padding: 0px; color: #666600;">+</span><span style="margin: 0px; padding: 0px;"> tinylist </span><span style="margin: 0px; padding: 0px; color: #880000;"># Prints concatenated list<br /><br /><pre xml:space="preserve" style="margin-top: 0px; margin-bottom: 10px; padding: 5px; border: 1px solid #d6d6d6; font-family: Monaco, Courier, monospace; color: #000000; width: 653.683349609375px; white-space: pre-wrap;"><span style="margin: 0px; padding: 0px;">tuple </span><span style="margin: 0px; padding: 0px; color: #666600;">=</span> <span style="margin: 0px; padding: 0px; color: #666600;">(</span> <span style="margin: 0px; padding: 0px; color: #008800;">'abcd'</span><span style="margin: 0px; padding: 0px; color: #666600;">,</span> <span style="margin: 0px; padding: 0px; color: #006666;">786</span> <span style="margin: 0px; padding: 0px; color: #666600;">,</span> <span style="margin: 0px; padding: 0px; color: #006666;">2.23</span><span style="margin: 0px; padding: 0px; color: #666600;">,</span> <span style="margin: 0px; padding: 0px; color: #008800;">'john'</span><span style="margin: 0px; padding: 0px; color: #666600;">,</span> <span style="margin: 0px; padding: 0px; color: #006666;">70.2</span> <span style="margin: 0px; padding: 0px; color: #666600;">)</span><span style="margin: 0px; padding: 0px;"> tinytuple </span><span style="margin: 0px; padding: 0px; color: #666600;">=</span> <span style="margin: 0px; padding: 0px; color: #666600;">(</span><span style="margin: 0px; padding: 0px; color: #006666;">123</span><span style="margin: 0px; padding: 0px; color: #666600;">,</span> <span style="margin: 0px; padding: 0px; color: #008800;">'john'</span><span style="margin: 0px; padding: 0px; color: #666600;">)</span><span style="margin: 0px; padding: 0px;">  <br /></span><span style="margin: 0px; padding: 0px; color: #000088;">print</span><span style="margin: 0px; padding: 0px;"> tuple           </span><span style="margin: 0px; padding: 0px; color: #880000;"># Prints complete list</span><span style="margin: 0px; padding: 0px;"> <br /></span><span style="margin: 0px; padding: 0px; color: #000088;">print</span><span style="margin: 0px; padding: 0px;"> tuple</span><span style="margin: 0px; padding: 0px; color: #666600;">[</span><span style="margin: 0px; padding: 0px; color: #006666;">0</span><span style="margin: 0px; padding: 0px; color: #666600;">]</span> <span style="margin: 0px; padding: 0px; color: #880000;"># Prints first element of the list</span><span style="margin: 0px; padding: 0px;"> <br /></span><span style="margin: 0px; padding: 0px; color: #000088;">print</span><span style="margin: 0px; padding: 0px;"> tuple</span><span style="margin: 0px; padding: 0px; color: #666600;">[</span><span style="margin: 0px; padding: 0px; color: #006666;">1</span><span style="margin: 0px; padding: 0px; color: #666600;">:</span><span style="margin: 0px; padding: 0px; color: #006666;">3</span><span style="margin: 0px; padding: 0px; color: #666600;">]</span> <span style="margin: 0px; padding: 0px; color: #880000;"># Prints elements starting from 2nd till 3rd </span><span style="margin: 0px; padding: 0px;"> <br /></span><span style="margin: 0px; padding: 0px; color: #000088;">print</span><span style="margin: 0px; padding: 0px;"> tuple</span><span style="margin: 0px; padding: 0px; color: #666600;">[</span><span style="margin: 0px; padding: 0px; color: #006666;">2</span><span style="margin: 0px; padding: 0px; color: #666600;">:]</span> <span style="margin: 0px; padding: 0px; color: #880000;"># Prints elements starting from 3rd element</span><span style="margin: 0px; padding: 0px;"> <br /></span><span style="margin: 0px; padding: 0px; color: #000088;">print</span><span style="margin: 0px; padding: 0px;"> tinytuple </span><span style="margin: 0px; padding: 0px; color: #666600;">*</span> <span style="margin: 0px; padding: 0px; color: #006666;">2</span> <span style="margin: 0px; padding: 0px; color: #880000;"># Prints list two times</span><span style="margin: 0px; padding: 0px;"> <br /></span><span style="margin: 0px; padding: 0px; color: #000088;">print</span><span style="margin: 0px; padding: 0px;"> tuple </span><span style="margin: 0px; padding: 0px; color: #666600;">+</span><span style="margin: 0px; padding: 0px;"> tinytuple </span><span style="margin: 0px; padding: 0px; color: #880000;"># Prints concatenated lists<br /><br /></span></pre></span></pre><img src ="http://www.cppblog.com/ylfeng/aggbug/196475.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ylfeng/" target="_blank">鹰击长空</a> 2012-12-20 12:41 <a href="http://www.cppblog.com/ylfeng/archive/2012/12/20/196475.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Some tricks of VS2008</title><link>http://www.cppblog.com/ylfeng/archive/2012/10/11/193156.html</link><dc:creator>鹰击长空</dc:creator><author>鹰击长空</author><pubDate>Thu, 11 Oct 2012 03:08:00 GMT</pubDate><guid>http://www.cppblog.com/ylfeng/archive/2012/10/11/193156.html</guid><wfw:comment>http://www.cppblog.com/ylfeng/comments/193156.html</wfw:comment><comments>http://www.cppblog.com/ylfeng/archive/2012/10/11/193156.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/ylfeng/comments/commentRss/193156.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ylfeng/services/trackbacks/193156.html</trackback:ping><description><![CDATA[<br />I didn't use VS2008 for a long time, but today I need to build a project with it. It cost me several hours to solve some small issues. It seems have lots of bug. I will list them as follows:<br /><br />First of all, I cannot edit the resource file with the default program. Searched with Google, this is a bug of VS. Just replace the slash in absolute including path with double slash;<br /><br />The second issue is additional lib. In VS2010, multiply lib file names is separate by semicolon, but in VS2009 it is space;<img src ="http://www.cppblog.com/ylfeng/aggbug/193156.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ylfeng/" target="_blank">鹰击长空</a> 2012-10-11 11:08 <a href="http://www.cppblog.com/ylfeng/archive/2012/10/11/193156.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>我读《程序员的自我修养》</title><link>http://www.cppblog.com/ylfeng/archive/2012/07/17/183956.html</link><dc:creator>鹰击长空</dc:creator><author>鹰击长空</author><pubDate>Tue, 17 Jul 2012 14:20:00 GMT</pubDate><guid>http://www.cppblog.com/ylfeng/archive/2012/07/17/183956.html</guid><wfw:comment>http://www.cppblog.com/ylfeng/comments/183956.html</wfw:comment><comments>http://www.cppblog.com/ylfeng/archive/2012/07/17/183956.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/ylfeng/comments/commentRss/183956.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ylfeng/services/trackbacks/183956.html</trackback:ping><description><![CDATA[&nbsp;<br />在编写共享库时，为保证ABI（app binary interface）兼容：<br />&nbsp; 1&nbsp;尽量使用C语言 2不要在接口类使用虚函数和模板； 3 不要改变成员函数的访问权限； 4 不要使用STL 5 不要依赖使用虚拟析构函数，最好自己实现，显式调用；<br />6 不要在DLL里面申请内存，DLL外释放，DLL和APP可能不在同一个内存堆；<br /><br />可重入（reentrant）函数可以由多于一个任务并发使用，而不必担心数据错误。相反， 不可重入（non-reentrant）函数不能由超过一个任务所共享，除非能确保函数的互斥（或者使用信号量，或者在代码的关键部分禁用中断）。可重入函数可以在任意时刻被中断，稍后再继续运行，不会丢失数据。可重入函数要么使用本地变量，要么在使用全局变量时保护自己的数据。<br />Reentrant Function:A function whose effect, when called by two or more threads,is guaranteed to be as if the threads each executed thefunction one after another in an undefined order, even ifthe actual execution is interleaved. <br />Thread-Safe Function：A function that may be safely invoked concurrently by multiple threads. <br /><br />函数可重入的必要条件：<br />1 不使用任何（局部）静态变量或者全局的非常量；<br />2 不返回任何局部静态或者全局非常量指针；<br />3 仅依赖调用方的参数；<br />4 不依赖任何单个资源的锁；<br />5 不调用任何不可重入的函数；<br /><br />In classical OS, stack grows downwards. After&nbsp;each&nbsp;push operatation, the value of ebp becomes small, and vice versa.<br />
<p>esp is the top of the stack.</p>
<p>ebp is usually set to esp at the start of the function. Local variables are accessed by subtracting a constant offset from ebp. All x86 calling conventions define ebp as being preserved across function calls. ebp itself actually points to the previous frame's base pointer, which enables stack walking in a debugger and viewing other frames local variables to work. </p>
<p>Most function prologs look something like:<br /><code><span class="pln">push ebp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; Preserve current frame pointer <br />mov ebp, esp&nbsp; ; Create new frame pointer pointing to current stack top <br />sub esp, 20&nbsp;&nbsp; ; allocate 20 bytes worth of locals on stack.&nbsp;<br /> </span></code></p>
<p>Then later in the function you may have code like (presuming both local variables are 4 bytes)<br /><code><span class="pln">mov [ebp-4], eax&nbsp;&nbsp;&nbsp; ; Store eax in first local <br />mov ebx, [ebp - 8]&nbsp; ; Load ebx from second local <br /><br /></p>
<p><strong>objdump</strong> is a program for displaying various information about object files. For instance, it can be used as a disassembler to view executable in assembly form. It is part of the GNU Binutils for fine-grained control over executable and other binary data.</p>
<p>For example, to completely disassemble a binary:<br />objdump -Dslx <em>file<br /><br /></em><br /></span></code></p><img src ="http://www.cppblog.com/ylfeng/aggbug/183956.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ylfeng/" target="_blank">鹰击长空</a> 2012-07-17 22:20 <a href="http://www.cppblog.com/ylfeng/archive/2012/07/17/183956.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>How Cocoa Bindings Work</title><link>http://www.cppblog.com/ylfeng/archive/2012/07/16/183754.html</link><dc:creator>鹰击长空</dc:creator><author>鹰击长空</author><pubDate>Mon, 16 Jul 2012 08:27:00 GMT</pubDate><guid>http://www.cppblog.com/ylfeng/archive/2012/07/16/183754.html</guid><wfw:comment>http://www.cppblog.com/ylfeng/comments/183754.html</wfw:comment><comments>http://www.cppblog.com/ylfeng/archive/2012/07/16/183754.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/ylfeng/comments/commentRss/183754.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ylfeng/services/trackbacks/183754.html</trackback:ping><description><![CDATA[<p>How Cocoa Bindings Work (via KVC and KVO)</p>
<p>Cocoa bindings can be a little confusing, especially to newcomers. Once you have an understanding of the underlying concepts, bindings aren&#8217;t too hard. In this article, I&#8217;m going to explain the concepts behind bindings from the ground up; first explaining Key-Value Coding (KVC), then Key-Value Observing (KVO), and finally explaining how Cocoa bindings are built on top of KVC and KVO.</p>
<p>&nbsp;</p>
<p>Key-Value Coding (KVC)</p>
<p>The first concept you need to understand is Key-Value Coding (KVC), as KVO and bindings are built on top of it.</p>
<p>&nbsp;</p>
<p>Objects have certain "properties". For example, a Person object may have an name property and an address property. In KVC parlance, the Person object has a value for the name key, and for the address key. "Keys" are just strings, and "values" can be any type of object[1]. At it&#8217;s most fundamental level, KVC is just two methods: a method to change the value for a given key (mutator), and a method to retrieve the value for a given key (accessor). Here is an example:</p>
<p>&nbsp;</p>
<p>void ChangeName(Person* p, NSString* newName)</p>
<p>{</p>
<p><span>&nbsp;&nbsp;&nbsp; //using the KVC accessor (getter) method</span></p>
<p><span>&nbsp;&nbsp;&nbsp; NSString* originalName = [p valueForKey:@"name"];</span></p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp; //using the KVC mutator (setter) method.</span></p>
<p><span>&nbsp;&nbsp;&nbsp; [p setValue:newName forKey:@"name"];</span></p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp; &nbsp;NSLog(@"Changed %@'s name to: %@", originalName, newName);</span></p>
<p>}</p>
<p>Now let&#8217;s say the Person object has a third key: a spouse key. The value for the spouse key is another Person object. KVC allows you to do things like this:</p>
<p>&nbsp;</p>
<p>void LogMarriage(Person* p)</p>
<p>{</p>
<p><span>&nbsp;&nbsp;&nbsp; //just using the accessor again, same as example above</span></p>
<p><span>&nbsp;&nbsp;&nbsp; NSString* personsName = [p valueForKey:@"name"];</span></p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp; //this line is different, because it is using</span></p>
<p><span>&nbsp;&nbsp;&nbsp; //a "key path" instead of a normal "key"</span></p>
<p><span>&nbsp;&nbsp;&nbsp; NSString* spousesName = [p valueForKeyPath:@"spouse.name"];</span></p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp; NSLog(@"%@ is happily married to %@", personsName, spousesName);</span></p>
<p>}</p>
<p>Cocoa makes a distinction between "keys" and "key paths". A "key" allows you to get a value on an object. A "key path" allows you to chain multiple keys together, separated by dots. For example, this&#8230;</p>
<p>&nbsp;</p>
<p>[p valueForKeyPath:@"spouse.name"];</p>
<p><span style="font-family: 宋体">&#8230;</span> is exactly the same as this&#8230;</p>
<p>&nbsp;</p>
<p>[[p valueForKey:@"spouse"] valueForKey:@"name"];</p>
<p>That&#8217;s all you need to know about KVC for now.</p>
<p>&nbsp;</p>
<p>Let&#8217;s move on to KVO.</p>
<p>&nbsp;</p>
<p>Key-Value Observing (KVO)</p>
<p>Key-Value Observing (KVO) is built on top of KVC. It allows you to observe (i.e. watch) a KVC key path on an object to see when the value changes. For example, let&#8217;s write some code that watches to see if a person&#8217;s address changes. There are three methods of interest in the following code:</p>
<p>&nbsp;</p>
<p>watchPersonForChangeOfAddress: begins the observing</p>
<p>observeValueForKeyPath:ofObject:change:context: is called every time there is a change in the value of the observed key path</p>
<p>dealloc stops the observing</p>
<p>static NSString* const KVO_CONTEXT_ADDRESS_CHANGED = @"KVO_CONTEXT_ADDRESS_CHANGED"</p>
<p>&nbsp;</p>
<p>@implementation PersonWatcher </p>
<p>&nbsp;</p>
<p>-(void) watchPersonForChangeOfAddress:(Person*)p;</p>
<p>{</p>
<p><span>&nbsp;&nbsp;&nbsp; //this begins the observing</span></p>
<p><span>&nbsp;&nbsp;&nbsp; [p addObserver:self </span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;forKeyPath:@"address" </span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; options:0 </span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context:KVO_CONTEXT_ADDRESS_CHANGED];</span></p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp; //keep a record of all the people being observed,</span></p>
<p><span>&nbsp;&nbsp;&nbsp; //because we need to stop observing them in dealloc</span></p>
<p><span>&nbsp;&nbsp;&nbsp; [m_observedPeople addObject:p];</span></p>
<p>}</p>
<p>&nbsp;</p>
<p>//whenever an observed key path changes, this method will be called</p>
<p>- (void)observeValueForKeyPath:(NSString *)keyPath </p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ofObject:(id)object </span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; change:(NSDictionary *)change </span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context:(void *)context;</span></p>
<p>{</p>
<p><span>&nbsp;&nbsp;&nbsp; //use the context to make sure this is a change in the address,</span></p>
<p><span>&nbsp;&nbsp;&nbsp; //because we may also be observing other things </span></p>
<p><span>&nbsp;&nbsp;&nbsp; if(context == KVO_CONTEXT_ADDRESS_CHANGED){</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NSString* name = [object valueForKey:@"name"];</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NSString* address = [object valueForKey:@"address"];</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NSLog(@"%@ has a new address: %@", name, address);</span></p>
<p><span>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p>}</p>
<p>&nbsp;</p>
<p>-(void) dealloc;</p>
<p>{</p>
<p><span>&nbsp;&nbsp;&nbsp; //must stop observing everything before this object is</span></p>
<p><span>&nbsp;&nbsp;&nbsp; //deallocated, otherwise it will cause crashes</span></p>
<p><span>&nbsp;&nbsp;&nbsp; for(Person* p in m_observedPeople){</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [p removeObserver:self forKeyPath:@"address"];</span></p>
<p><span>&nbsp;&nbsp;&nbsp; }</span></p>
<p><span>&nbsp;&nbsp;&nbsp; [m_observedPeople release]; m_observedPeople = nil;</span></p>
<p><span>&nbsp;&nbsp;&nbsp; [super dealloc];</span></p>
<p>}</p>
<p>&nbsp;</p>
<p>-(id) init;</p>
<p>{</p>
<p><span>&nbsp;&nbsp;&nbsp; if(self = [super init]){</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_observedPeople = [NSMutableArray new];</span></p>
<p><span>&nbsp;&nbsp;&nbsp; }</span></p>
<p><span>&nbsp;&nbsp;&nbsp; return self;</span></p>
<p>}</p>
<p>&nbsp;</p>
<p>@end</p>
<p>This is all that KVO does. It allows you to observe a key path on an object to get notified whenever the value changes.</p>
<p>&nbsp;</p>
<p>Cocoa Bindings</p>
<p>Now that you understand the concepts behind KVC and KVO, Cocoa bindings won&#8217;t be too mysterious.</p>
<p>&nbsp;</p>
<p>Cocoa bindings allow you to synchronise two key paths[2] so they have the same value. When one key path is updated, so is the other one.</p>
<p>&nbsp;</p>
<p>For example, let&#8217;s say you have a Person object and an NSTextField to edit the person&#8217;s address. We know that every Person object has an address key, and thanks to the Cocoa Bindings Reference, we also know that every NSTextField object has a value key that works with bindings. What we want is for those two key paths to be synchronised (i.e. bound). This means that if the user types in the NSTextField, it automatically updates the address on the Person object. Also, if we programmatically change the the address of the Person object, we want it to automatically appear in the NSTextField. This can be achieved like so:</p>
<p>&nbsp;</p>
<p>void BindTextFieldToPersonsAddress(NSTextField* tf, Person* p)</p>
<p>{</p>
<p><span>&nbsp;&nbsp;&nbsp; //This synchronises/binds these two together:</span></p>
<p><span>&nbsp;&nbsp;&nbsp; //The `value` key on the object `tf`</span></p>
<p><span>&nbsp;&nbsp;&nbsp; //The `address` key on the object `p`</span></p>
<p><span>&nbsp;&nbsp;&nbsp; [tf bind:@"value" toObject:p withKeyPath:@"address" options:nil];</span></p>
<p>}</p>
<p>What happens under the hood is that the NSTextField starts observing the address key on the Person object via KVO. If the address changes on the Person object, the NSTextField gets notified of this change, and it will update itself with the new value. In this situation, the NSTextField does something similar to this:</p>
<p>&nbsp;</p>
<p>- (void)observeValueForKeyPath:(NSString *)keyPath </p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ofObject:(id)object </span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; change:(NSDictionary *)change </span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context:(void *)context;</span></p>
<p>{</p>
<p><span>&nbsp;&nbsp;&nbsp; if(context == KVO_CONTEXT_VALUE_BINDING_CHANGED){</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [self setStringValue:[object valueForKeyPath:keyPath]];</span></p>
<p><span>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p>}</p>
<p>When the user starts typing into the NSTextField, the NSTextField uses KVC to update the Person object. In this situation, the NSTextField does something similar to this:</p>
<p>&nbsp;</p>
<p>- (void)insertText:(id)aString;</p>
<p>{</p>
<p><span>&nbsp;&nbsp;&nbsp; NSString* newValue = [[self stringValue] stringByAppendingString:aString];</span></p>
<p><span>&nbsp;&nbsp;&nbsp; [self setStringValue:newValue];</span></p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp; //if "value" is bound, then propagate the change to the bound object</span></p>
<p><span>&nbsp;&nbsp;&nbsp; if([self infoForBinding:@"value"]){</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id boundObj = ...; //omitted for brevity</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NSString* boundKeyPath = ...; //omitted for brevity</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [boundObj setValue:newValue forKeyPath:boundKeyPath];</span></p>
<p><span>&nbsp;&nbsp;&nbsp; }</span></p>
<p>}</p>
<p>For a more complete look at how views propagate changes back to the bound object, see my article: Implementing Your Own Cocoa Bindings.</p>
<p>&nbsp;</p>
<p>Conclusion</p>
<p>That&#8217;s that basics of how KVC, KVO and bindings work. The views use KVC to update the model, and they use KVO to watch for changes in the model. I have left out quite a bit of detail in order to keep the article short and simple, but hopefully it has given you a firm grasp of the concepts and principles.</p>
<p>&nbsp;</p>
<p>Footnotes</p>
<p>[1] KVC values can also be primitives such as BOOL or int, because the KVC accessor and mutator methods will perform auto-boxing. For example, a BOOL value will be auto-boxed into an NSNumber*.</p>
<p>[2] When I say that bindings synchronise two key paths, that&#8217;s not technically correct. It actually synchronises a "binding" and a key path. A "binding" is a string just like a key path but it&#8217;s not guaranteed to be KVC compatible, although it can be. Notice that the example code uses @"address" as a key path but never uses @"value" as a key path. This is because @"value" is a binding, and it might not be a valid key path.</p>
<p>&nbsp;</p><img src ="http://www.cppblog.com/ylfeng/aggbug/183754.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ylfeng/" target="_blank">鹰击长空</a> 2012-07-16 16:27 <a href="http://www.cppblog.com/ylfeng/archive/2012/07/16/183754.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Git Usage</title><link>http://www.cppblog.com/ylfeng/archive/2012/07/09/182465.html</link><dc:creator>鹰击长空</dc:creator><author>鹰击长空</author><pubDate>Mon, 09 Jul 2012 14:04:00 GMT</pubDate><guid>http://www.cppblog.com/ylfeng/archive/2012/07/09/182465.html</guid><wfw:comment>http://www.cppblog.com/ylfeng/comments/182465.html</wfw:comment><comments>http://www.cppblog.com/ylfeng/archive/2012/07/09/182465.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/ylfeng/comments/commentRss/182465.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ylfeng/services/trackbacks/182465.html</trackback:ping><description><![CDATA[<strong>Create a new local repository:</strong><br />prompt&gt; <strong>mkdir /path/to/repo</strong>:<br />prompt&gt; <strong>cd /path/to/repo</strong><br />prompt&gt; <strong>git init</strong><br />Initialized empty Git repository in /path/to/repo/.git/<br />prompt&gt;<br />... create file(s) for first commit ...<br />prompt&gt; <strong>git add .</strong><br />prompt&gt; <strong>git commit -m 'initial import'</strong><br />Created initial commit bdebe5c: initial import. <br /><br />1 files changed, 1 insertions(+), 0 deletions(-)<br />Note that the commit action <em>only</em> commits to your local repository. <br /><br />Change one of my github repo name<span style="background-color: #ffffff; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; line-height: 18px;">&nbsp;in two steps:<br /><br /></span><p style="margin: 0px 0px 1em; padding: 0px; border: 0px; vertical-align: baseline; background-color: #ffffff; clear: both; word-wrap: break-word; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; line-height: 18px;">Firstly, cd to your local git directory, and find out what remote name(s) refer to that URL</p><pre style="margin-top: 0px; margin-bottom: 10px; padding: 5px; border: 0px; vertical-align: baseline; background-color: #eeeeee; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; overflow: auto; width: auto; max-height: 600px; line-height: 18px;"><code style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif;">$ git remote -v origin  git@github.com:someuser/someproject.git </code></pre><p style="margin: 0px 0px 1em; padding: 0px; border: 0px; vertical-align: baseline; background-color: #ffffff; clear: both; word-wrap: break-word; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; line-height: 18px;">Then, set the new URL</p><pre style="margin-top: 0px; margin-bottom: 10px; padding: 5px; border: 0px; vertical-align: baseline; background-color: #eeeeee; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; overflow: auto; width: auto; max-height: 600px; line-height: 18px;"><code style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif;">$ git remote set-url origin git@github.com:someuser/newprojectname.git </code></pre><p style="margin: 0px 0px 1em; padding: 0px; border: 0px; vertical-align: baseline; background-color: #ffffff; clear: both; word-wrap: break-word; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; line-height: 18px;">or in older versions of git, you might need</p><pre style="margin-top: 0px; margin-bottom: 10px; padding: 5px; border: 0px; vertical-align: baseline; background-color: #eeeeee; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; overflow: auto; width: auto; max-height: 600px; line-height: 18px;"><code style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif;">$ git remote rm origin $ git remote add origin git@github.com:someuser/newprojectname.git </code></pre><p style="margin: 0px 0px 1em; padding: 0px; border: 0px; vertical-align: baseline; background-color: #ffffff; clear: both; word-wrap: break-word; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; line-height: 18px;">(origin is the most common remote name, but it might be called something else.)</p><p style="margin: 0px 0px 1em; padding: 0px; border: 0px; vertical-align: baseline; background-color: #ffffff; clear: both; word-wrap: break-word; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; line-height: 18px;">But if there's lots of people who are working on your project, they will all need to do the above steps, and maybe you don't even know how to contact them all to tell them. That's what #1 is about.</p><p style="margin: 0px 0px 1em; padding: 0px; border: 0px; vertical-align: baseline; background-color: #ffffff; clear: both; word-wrap: break-word; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; line-height: 18px;">Further reading:</p><ul style="margin: 0px 0px 1em 30px; padding: 0px; border: 0px; vertical-align: baseline; background-color: #ffffff; list-style-position: initial; list-style-image: initial; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; line-height: 18px;"><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; background-color: transparent; word-wrap: break-word;"><a href="http://help.github.com/remotes/" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; background-color: transparent; color: #4a6b82; text-decoration: initial; cursor: pointer;">github - working with remotes</a></li><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; background-color: transparent; word-wrap: break-word;"><a href="http://gitref.org/remotes/" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; background-color: transparent; color: #4a6b82; text-decoration: initial; cursor: pointer;">Git Reference - remotes</a></li><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; background-color: transparent; word-wrap: break-word;"><a href="http://book.git-scm.com/3_distributed_workflows.html" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; background-color: transparent; color: #4a6b82; text-decoration: initial; cursor: pointer;">Git Book - Distributed Workflows</a></li></ul><p style="margin: 0px 0px 1em; padding: 0px; border: 0px; vertical-align: baseline; background-color: #ffffff; clear: both; word-wrap: break-word; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; line-height: 18px;">Footnotes:</p><p style="margin: 0px 0px 1em; padding: 0px; border: 0px; vertical-align: baseline; background-color: #ffffff; clear: both; word-wrap: break-word; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; line-height: 18px;">1 The exact format of your URL depends on which protocol you are using, e.g.</p><ul style="margin: 0px 0px 1em 30px; padding: 0px; border: 0px; vertical-align: baseline; background-color: #ffffff; list-style-position: initial; list-style-image: initial; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; line-height: 18px;"><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; background-color: transparent; word-wrap: break-word;">SSH = git@github.com:someuser/someproject.git</li><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; background-color: transparent; word-wrap: break-word;">HTTPS =&nbsp;<a href="https://someuser@github.com/someuser/someproject.git" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; background-color: transparent; color: #4a6b82; text-decoration: initial; cursor: pointer;">https://someuser@github.com/someuser/someproject.git</a></li><li style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; background-color: transparent; word-wrap: break-word;">GIT = git://github.com/someuser/someproject.git</li></ul><strong>push your local repository into remote repository:</strong><br />prompt&gt;git push origin master<br />
<div>
<div></div>
<div><span style="line-height: 18px; border-collapse: collapse; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif"><strong>To <span style="line-height: 18px; border-collapse: collapse; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif">amend the last wrong commit:</span></strong></span></div>
<div><span style="line-height: 18px; border-collapse: collapse; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif">
<p style="background-color: #eeeeee; margin: 0px; font: 14px Consolas">git commit --amend -m "New commit message"</p></span></div>
<div><span style="line-height: 18px; border-collapse: collapse; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif"></span>&nbsp;</div>
<div><span style="line-height: 18px; border-collapse: collapse; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif"><br /></span></div>
<div><span style="border-collapse: collapse;">
<p style="padding-bottom: 0px; line-height: 18px; border-right-width: 0px; background-color: transparent; margin: 0px 0px 1em; padding-left: 0px; padding-right: 0px; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; word-wrap: break-word; border-top-width: 0px; border-bottom-width: 0px; clear: both; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px">If the commit you want to fix isn&#8217;t the most recent one:</p>
<ol style="padding-bottom: 0px; line-height: 18px; border-right-width: 0px; background-color: transparent; list-style-type: decimal; margin: 0px 0px 1em 30px; padding-left: 0px; padding-right: 0px; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; border-top-width: 0px; border-bottom-width: 0px; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px"><li style="padding-bottom: 0px; border-right-width: 0px; background-color: transparent; margin: 0px; padding-left: 0px; padding-right: 0px; word-wrap: break-word; border-top-width: 0px; border-bottom-width: 0px; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px; background-origin: initial; background-clip: initial">
<p style="padding-bottom: 0px; border-right-width: 0px; background-color: transparent; margin: 0px 0px 1em; padding-left: 0px; padding-right: 0px; word-wrap: break-word; border-top-width: 0px; border-bottom-width: 0px; clear: both; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px; background-origin: initial; background-clip: initial"><code style="padding-bottom: 1px; border-right-width: 0px; background-color: #eeeeee; margin: 0px; padding-left: 5px; padding-right: 5px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; border-top-width: 0px; border-bottom-width: 0px; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 1px; background-origin: initial; background-clip: initial">git rebase --interactive $parent_of_flawed_commit</code></p>
<p style="padding-bottom: 0px; border-right-width: 0px; background-color: transparent; margin: 0px 0px 1em; padding-left: 0px; padding-right: 0px; word-wrap: break-word; border-top-width: 0px; border-bottom-width: 0px; clear: both; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px; background-origin: initial; background-clip: initial">If you want to fix several flawed commits, pass the parent of the oldest one of them.</p></li><li style="padding-bottom: 0px; border-right-width: 0px; background-color: transparent; margin: 0px; padding-left: 0px; padding-right: 0px; word-wrap: break-word; border-top-width: 0px; border-bottom-width: 0px; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px; background-origin: initial; background-clip: initial">
<p style="padding-bottom: 0px; border-right-width: 0px; background-color: transparent; margin: 0px 0px 1em; padding-left: 0px; padding-right: 0px; word-wrap: break-word; border-top-width: 0px; border-bottom-width: 0px; clear: both; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px; background-origin: initial; background-clip: initial">An editor will come up, with a list of all commits since the one you gave.</p>
<ol style="padding-bottom: 0px; border-right-width: 0px; background-color: transparent; list-style-type: decimal; margin: 0px 0px 0px 30px; padding-left: 0px; padding-right: 0px; border-top-width: 0px; border-bottom-width: 0px; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px; background-origin: initial; background-clip: initial"><li style="padding-bottom: 0px; border-right-width: 0px; background-color: transparent; margin: 0px; padding-left: 0px; padding-right: 0px; word-wrap: break-word; border-top-width: 0px; border-bottom-width: 0px; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px; background-origin: initial; background-clip: initial">Change&nbsp;<code style="padding-bottom: 0px; border-right-width: 0px; background-color: #eeeeee; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; border-top-width: 0px; border-bottom-width: 0px; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px; background-origin: initial; background-clip: initial">pick</code>&nbsp;to&nbsp;<code style="padding-bottom: 0px; border-right-width: 0px; background-color: #eeeeee; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; border-top-width: 0px; border-bottom-width: 0px; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px; background-origin: initial; background-clip: initial">reword</code>&nbsp;(or on old versions of Git, to&nbsp;<code style="padding-bottom: 0px; border-right-width: 0px; background-color: #eeeeee; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; border-top-width: 0px; border-bottom-width: 0px; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px; background-origin: initial; background-clip: initial">edit</code>) in front of any commits you want to fix.</li><li style="padding-bottom: 0px; border-right-width: 0px; background-color: transparent; margin: 0px; padding-left: 0px; padding-right: 0px; word-wrap: break-word; border-top-width: 0px; border-bottom-width: 0px; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px; background-origin: initial; background-clip: initial">Once you save, git will replay the listed commits.&nbsp;<br /><br /></li></ol></li><li style="padding-bottom: 0px; border-right-width: 0px; background-color: transparent; margin: 0px; padding-left: 0px; padding-right: 0px; word-wrap: break-word; border-top-width: 0px; border-bottom-width: 0px; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px; background-origin: initial; background-clip: initial">
<p style="padding-bottom: 0px; border-right-width: 0px; background-color: transparent; margin: 0px 0px 1em; padding-left: 0px; padding-right: 0px; word-wrap: break-word; border-top-width: 0px; border-bottom-width: 0px; clear: both; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px; background-origin: initial; background-clip: initial">Git will drop back you into your editor for every commit you said you want to&nbsp;<em style="padding-bottom: 0px; border-right-width: 0px; background-color: transparent; font-style: italic; margin: 0px; padding-left: 0px; padding-right: 0px; border-top-width: 0px; border-bottom-width: 0px; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px; background-origin: initial; background-clip: initial">reword</em>, and into the shell for every commit you wanted to&nbsp;<em style="padding-bottom: 0px; border-right-width: 0px; background-color: transparent; font-style: italic; margin: 0px; padding-left: 0px; padding-right: 0px; border-top-width: 0px; border-bottom-width: 0px; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px; background-origin: initial; background-clip: initial">edit</em>. If you&#8217;re in the shell:</p>
<ol style="padding-bottom: 0px; border-right-width: 0px; background-color: transparent; list-style-type: decimal; margin: 0px 0px 0px 30px; padding-left: 0px; padding-right: 0px; border-top-width: 0px; border-bottom-width: 0px; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px; background-origin: initial; background-clip: initial"><li style="padding-bottom: 0px; border-right-width: 0px; background-color: transparent; margin: 0px; padding-left: 0px; padding-right: 0px; word-wrap: break-word; border-top-width: 0px; border-bottom-width: 0px; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px; background-origin: initial; background-clip: initial">Change the commit in any way you like.</li><li style="padding-bottom: 0px; border-right-width: 0px; background-color: transparent; margin: 0px; padding-left: 0px; padding-right: 0px; word-wrap: break-word; border-top-width: 0px; border-bottom-width: 0px; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px; background-origin: initial; background-clip: initial"><code style="padding-bottom: 0px; border-right-width: 0px; background-color: #eeeeee; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; border-top-width: 0px; border-bottom-width: 0px; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px; background-origin: initial; background-clip: initial">git commit --amend</code></li><li style="padding-bottom: 0px; border-right-width: 0px; background-color: transparent; margin: 0px; padding-left: 0px; padding-right: 0px; word-wrap: break-word; border-top-width: 0px; border-bottom-width: 0px; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px; background-origin: initial; background-clip: initial"><code style="padding-bottom: 0px; border-right-width: 0px; background-color: #eeeeee; margin: 0px; padding-left: 0px; padding-right: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; border-top-width: 0px; border-bottom-width: 0px; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 0px; background-origin: initial; background-clip: initial">git rebase --continue<br /></code></li></ol></li></ol>
<p style="padding-bottom: 0px; border-right-width: 0px; background-color: transparent; margin: 0px 0px 1em; padding-left: 0px; padding-right: 0px; word-wrap: break-word; border-top-width: 0px; border-bottom-width: 0px; clear: both; vertical-align: baseline; border-left-width: 0px; padding-top: 0px"><font face="Arial, Liberation Sans, DejaVu Sans, sans-serif"><span style="line-height: 18px">Most of this sequence will be explained to you by the output of the various commands as you go. It&#8217;s very easy, you don&#8217;t need to memorise it &#8211; just remember that&nbsp;</span></font><code style="padding-bottom: 1px; line-height: 18px; border-right-width: 0px; background-color: #eeeeee; margin: 0px; padding-left: 5px; padding-right: 5px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; border-top-width: 0px; border-bottom-width: 0px; font-size: 14px; vertical-align: baseline; border-left-width: 0px; padding-top: 1px">git rebase --interactive</code><font face="Arial, Liberation Sans, DejaVu Sans, sans-serif"><span style="line-height: 18px">&nbsp;lets you correct commits no matter how long ago they were.</span></font><br /><br /><font face="Arial, Liberation Sans, DejaVu Sans, sans-serif"><span style="line-height: 18px">Today, when I try to push some code to the remote, it told me the there is a permission issue, I finally fixed it by created a new key, add it to my git account and local account. Here is the process of adding to local</span></font><br /><br />
</p><div><span style="line-height: 18px"><br /></span></div>
<div><span style="line-height: 18px">$ git push -u origin master</span></div>
<div><span style="line-height: 18px">Permission denied (publickey).</span></div>
<div><span style="line-height: 18px">fatal: The remote end hung up unexpectedly</span></div>
<div><span style="line-height: 18px"><br /></span></div>
<div><span style="line-height: 18px">$ ssh -vT git@github.com</span></div>
<div><span style="line-height: 18px">OpenSSH_4.6p1, OpenSSL 0.9.8e 23 Feb 2007</span></div>
<div><span style="line-height: 18px">debug1: Connecting to github.com [207.97.227.239] port 22.</span></div>
<div><span style="line-height: 18px">debug1: Connection established.</span></div>
<div><span style="line-height: 18px">debug1: No more authentication methods to try.</span></div>
<div><span style="line-height: 18px">Permission denied (publickey).</span></div>
<div><span style="line-height: 18px"><br /></span></div>
<div><span style="line-height: 18px">$ &nbsp;ssh-add -l</span></div>
<div><span style="line-height: 18px">Could not open a connection to your authentication agent.</span></div>
<div><span style="line-height: 18px"><br /></span></div>
<div><span style="line-height: 18px">$ eval `ssh-agent`</span></div>
<div><span style="line-height: 18px">Agent pid 4968</span></div>
<div><span style="line-height: 18px"><br />If you did not have a key, generate one according this&nbsp;</span>https://help.github.com/articles/generating-ssh-keys</div>
<div><span style="line-height: 18px"><br />then add the key<br />$ &nbsp;ssh-add /c/Users/li/.ssh/key</span></div>
<div><span style="line-height: 18px">Identity added: /c/Users/li/.ssh/key</span></div>
<div><span style="line-height: 18px"><br /></span></div>
<div><span style="line-height: 18px">$ ssh -vT git@github.com</span></div>
<div><span style="line-height: 18px">OpenSSH_4.6p1, OpenSSL 0.9.8e 23 Feb 2007</span></div>
<div><span style="line-height: 18px">debug1: Connecting to github.com [207.97.227.239] port 22.</span></div>
<div><span style="line-height: 18px">debug1: Connection established.</span></div>
<div><span style="line-height: 18px">debug1: identity file /c/Users/li/.ssh/identity type -1</span></div>
<div><span style="line-height: 18px"><br /></span></div>
<div><span style="line-height: 18px">Hi ***! You've successfully authenticated, but GitHub does not provide shel</span><span style="line-height: 18px">l access.</span></div>
<div><span style="line-height: 18px">debug1: channel 0: free: client-session, nchannels 1</span></div>
<div><span style="line-height: 18px">debug1: Transferred: stdin 0, stdout 0, stderr 0 bytes in 0.3 seconds</span></div>
<div><span style="line-height: 18px">debug1: Bytes per second: stdin 0.0, stdout 0.0, stderr 0.0</span></div>
<div><span style="line-height: 18px">debug1: Exit status 1</span></div>
<div><span style="line-height: 18px"><br /></span></div>
<div><span style="line-height: 18px"><br /></span></div>
<div><span style="line-height: 18px">$ git push -u origin master</span></div>
<div><span style="line-height: 18px">Counting objects: 46, done.</span></div>
<div><span style="line-height: 18px">Delta compression using up to 4 threads.</span></div>
<div><span style="line-height: 18px">Compressing objects: 100% (42/42), done.</span></div>
<div><span style="line-height: 18px">Writing objects: 100% (46/46), 21.33 KiB, done.</span></div>
<div><span style="line-height: 18px">Total 46 (delta 1), reused 0 (delta 0)<br /><br />
<div class="titlepage">
<div>
<div>
<h3 class="title">Clone your repository </h3></div></div></div>
<p>Create a new repository in a new directory via the following commands. </p>
<p>&nbsp;</p><pre class="programlisting"># Switch to home
cd ~
# Make <span class="hl-keyword">new</span> directory
mkdir repo02

# Switch to <span class="hl-keyword">new</span> directory
cd ~/repo02
# Clone
git clone ../remote-repository.git . </pre></span></div>
<p>&nbsp;</p></span></div></div><img src ="http://www.cppblog.com/ylfeng/aggbug/182465.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ylfeng/" target="_blank">鹰击长空</a> 2012-07-09 22:04 <a href="http://www.cppblog.com/ylfeng/archive/2012/07/09/182465.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Notes for Professnal CPP</title><link>http://www.cppblog.com/ylfeng/archive/2012/07/09/182446.html</link><dc:creator>鹰击长空</dc:creator><author>鹰击长空</author><pubDate>Mon, 09 Jul 2012 11:41:00 GMT</pubDate><guid>http://www.cppblog.com/ylfeng/archive/2012/07/09/182446.html</guid><wfw:comment>http://www.cppblog.com/ylfeng/comments/182446.html</wfw:comment><comments>http://www.cppblog.com/ylfeng/archive/2012/07/09/182446.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/ylfeng/comments/commentRss/182446.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ylfeng/services/trackbacks/182446.html</trackback:ping><description><![CDATA[Chapter 4 <br />Some people find the &#8220;90/10&#8221; rule helpful: 90 percent of the running time of most programs is spent in only<br />10 percent of the code (Hennessy and Patterson, 2002)<br /><br />Use a vector instead of an array whenever possible.<br />Vectors provide fast (constant time) element insertion and deletion at the end of the vector, but slow<br />(linear time) insertion and deletion anywhere else. Insertion and deletion are slow because the operation<br />must move all the elements &#8220;down&#8221; or &#8220;up&#8221; by one to make room for the new element or to fill the<br />space left by the deleted element. Like arrays, vectors provide fast (constant time) access to any of their<br />elements.<br />You should use a vector in your programs when you need fast access to the elements, but do not plan to<br />add or remove elements often. A good rule of thumb is to use a vector whenever you would have used<br />an array.
<p>The name deque is an abbreviation for a double-ended queue. A deque is partway between a vector and a<br />list, but closer to a vector. Like a vector, it provides quick (constant time) element access. Like a list, it<br />provides fast (amortized constant time) insertion and deletion at both ends of the sequence. However,<br />unlike a list, it provides slow (linear time) insertion and deletion in the middle of the sequence.<br />You should use a deque instead of a vector when you need to insert or remove elements from either end<br />of the sequence but still need fast access time to all elements. However, this requirement does not apply<br />to many programming problems; in most cases a vector or queue should suffice.</p>
<p><br />A set in STL is a collection of elements. Although the mathematical definition of a set implies an<br />unordered collection, the STL set stores the elements in an ordered fashion so that it can provide reasonably<br />fast lookup, insertion, and deletion.<br />Use a set instead of a vector or list if you want equal performance for insertion, deletion,and lookup.<br />Note that a set does not allow duplication of elements. That is, each element in the set must be unique. If<br />you want to store duplicate elements, you must use a multiset.</p><br />Chapter8 <br />Initializer lists allow initialization of data members at the time of their creation.<br />An initializer list allows you to provide initial values for data members as they are created, which is more efficient than assigning values to them later.<br />However, several data types must be initialized in an initializer list. The following table summarizes them:a、 const data members； b、Reference data members C、Object data members or&nbsp;Superclasses without default constructors<br />Initializer lists initialize data members in their declared order in the class definition,not their order in the list.<br /><br />Chapter9<br />Pass objects by const reference instead of by value.<br />The default semantics for passing arguments to functions in C++ is pass-by-value. That means that the function or method receives a copy of the variable, not the variable itself. Thus, whenever you pass an object to a function or method the compiler calls the copy constructor of the new object to initialize it. The copy constructor is also called whenever you return an object from a function or method. <img src ="http://www.cppblog.com/ylfeng/aggbug/182446.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ylfeng/" target="_blank">鹰击长空</a> 2012-07-09 19:41 <a href="http://www.cppblog.com/ylfeng/archive/2012/07/09/182446.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Algorithm for Permutation and Subarray</title><link>http://www.cppblog.com/ylfeng/archive/2012/07/05/181491.html</link><dc:creator>鹰击长空</dc:creator><author>鹰击长空</author><pubDate>Thu, 05 Jul 2012 09:51:00 GMT</pubDate><guid>http://www.cppblog.com/ylfeng/archive/2012/07/05/181491.html</guid><wfw:comment>http://www.cppblog.com/ylfeng/comments/181491.html</wfw:comment><comments>http://www.cppblog.com/ylfeng/archive/2012/07/05/181491.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/ylfeng/comments/commentRss/181491.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ylfeng/services/trackbacks/181491.html</trackback:ping><description><![CDATA[<p>print all permutations of a given string. A permutation, also called an &#8220;arrangement number&#8221; or &#8220;order,&#8221; is a rearrangement of the elements of an ordered list S into a one-to-one correspondence with S itself. A string of length n has n! permutation.<br /></p>
<table style="width: 409px; height: 701px" border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="width: 407px; height: 699px" class="code">
<div class="line number1 index0 alt2"><code class="cpp preprocessor"># include &lt;stdio.h&gt; </code></div>
<div class="line number2 index1 alt1"><code class="cpp spaces">&nbsp;</code>&nbsp;</div>
<div class="line number3 index2 alt2"><code class="cpp comments">/* Function to swap values at two pointers */</code></div>
<div class="line number4 index3 alt1"><code class="cpp keyword bold">void</code> <code class="cpp plain">swap (</code><code class="cpp color1 bold">char</code> <code class="cpp plain">*x, </code><code class="cpp color1 bold">char</code> <code class="cpp plain">*y) </code></div>
<div class="line number5 index4 alt2"><code class="cpp plain">{ </code></div>
<div class="line number6 index5 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp color1 bold">char</code> <code class="cpp plain">temp; </code></div>
<div class="line number7 index6 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">temp = *x; </code></div>
<div class="line number8 index7 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">*x = *y; </code></div>
<div class="line number9 index8 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">*y = temp; </code></div>
<div class="line number10 index9 alt1"><code class="cpp plain">} </code></div>
<div class="line number11 index10 alt2"><code class="cpp spaces">&nbsp;&nbsp;</code>&nbsp;</div>
<div class="line number12 index11 alt1 highlighted"><code class="cpp comments">/* Function to print permutations of string </code></div>
<div class="line number13 index12 alt2 highlighted"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp comments">This function takes three parameters: </code></div>
<div class="line number14 index13 alt1 highlighted"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp comments">1. String </code></div>
<div class="line number15 index14 alt2 highlighted"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp comments">2. Starting index of the string </code></div>
<div class="line number16 index15 alt1 highlighted"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp comments">3. Ending index of the string. */</code></div>
<div class="line number17 index16 alt2 highlighted"><code class="cpp keyword bold">void</code> <code class="cpp plain">permute(</code><code class="cpp color1 bold">char</code> <code class="cpp plain">*a, </code><code class="cpp color1 bold">int</code> <code class="cpp plain">i, </code><code class="cpp color1 bold">int</code> <code class="cpp plain">n)&nbsp; </code></div>
<div class="line number18 index17 alt1 highlighted"><code class="cpp plain">{ </code></div>
<div class="line number19 index18 alt2 highlighted"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp color1 bold">int</code> <code class="cpp plain">j;&nbsp; </code></div>
<div class="line number20 index19 alt1 highlighted"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">if</code> <code class="cpp plain">(i == n) </code></div>
<div class="line number21 index20 alt2 highlighted"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp functions bold">printf</code><code class="cpp plain">(</code><code class="cpp string">"%s\n"</code><code class="cpp plain">, a); </code></div>
<div class="line number22 index21 alt1 highlighted"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">else</code></div>
<div class="line number23 index22 alt2 highlighted"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">{ </code></div>
<div class="line number24 index23 alt1 highlighted"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">for</code> <code class="cpp plain">(j = i; j &lt;= n; j++) </code></div>
<div class="line number25 index24 alt2 highlighted"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">{ </code></div>
<div class="line number26 index25 alt1 highlighted"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">swap((a+i), (a+j)); </code></div>
<div class="line number27 index26 alt2 highlighted"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">permute(a, i+1, n); </code></div>
<div class="line number28 index27 alt1 highlighted"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">swap((a+i), (a+j)); </code><code class="cpp comments">//backtrack </code></div>
<div class="line number29 index28 alt2 highlighted"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">} </code></div>
<div class="line number30 index29 alt1 highlighted"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">} </code></div>
<div class="line number31 index30 alt2 highlighted"><code class="cpp plain">}&nbsp; </code></div>
<div class="line number32 index31 alt1"><code class="cpp spaces">&nbsp;</code>&nbsp;</div>
<div class="line number33 index32 alt2"><code class="cpp comments">/* Driver program to test above functions */</code></div>
<div class="line number34 index33 alt1"><code class="cpp color1 bold">int</code> <code class="cpp plain">main() </code></div>
<div class="line number35 index34 alt2"><code class="cpp plain">{ </code></div>
<div class="line number36 index35 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp color1 bold">char</code> <code class="cpp plain">a[] = </code><code class="cpp string">"ABC"</code><code class="cpp plain">;&nbsp;&nbsp; </code></div>
<div class="line number37 index36 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">permute(a, 0, 2); </code></div>
<div class="line number38 index37 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp functions bold">getchar</code><code class="cpp plain">(); </code></div>
<div class="line number39 index38 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">return</code> <code class="cpp plain">0; </code></div>
<div class="line number40 index39 alt1"><code class="cpp plain">}</code></div></td></tr></tbody></table>
<p>2. find the sum of contiguous subarray within a one-dimensional array of numbers which has the largest sum.<br />
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp preprocessor">#include&lt;stdio.h&gt; </code></div>
<div class="line number2 index1 alt1"><code class="cpp color1 bold">int</code> <code class="cpp plain">maxSubArraySum(</code><code class="cpp color1 bold">int</code> <code class="cpp plain">a[], </code><code class="cpp color1 bold">int</code> <code class="cpp plain">size) </code></div>
<div class="line number3 index2 alt2"><code class="cpp plain">{ </code></div>
<div class="line number4 index3 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp color1 bold">int</code> <code class="cpp plain">max_so_far = 0, max_ending_here = 0; </code></div>
<div class="line number5 index4 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp color1 bold">int</code> <code class="cpp plain">i; </code></div>
<div class="line number6 index5 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">for</code><code class="cpp plain">(i = 0; i &lt; size; i++) </code></div>
<div class="line number7 index6 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">{ </code></div>
<div class="line number8 index7 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">max_ending_here = max_ending_here + a[i]; </code></div>
<div class="line number9 index8 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">if</code><code class="cpp plain">(max_ending_here &lt; 0) </code></div>
<div class="line number10 index9 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">max_ending_here = 0; </code></div>
<div class="line number11 index10 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">if</code><code class="cpp plain">(max_so_far &lt; max_ending_here) </code></div>
<div class="line number12 index11 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">max_so_far = max_ending_here; </code></div>
<div class="line number13 index12 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">} </code></div>
<div class="line number14 index13 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">return</code> <code class="cpp plain">max_so_far; </code></div>
<div class="line number15 index14 alt2"><code class="cpp plain">}&nbsp; </code></div>
<div class="line number16 index15 alt1">&nbsp;</div>
<div class="line number17 index16 alt2"><code class="cpp comments">/*Driver program to test maxSubArraySum*/</code></div>
<div class="line number18 index17 alt1"><code class="cpp color1 bold">int</code> <code class="cpp plain">main() </code></div>
<div class="line number19 index18 alt2"><code class="cpp plain">{ </code></div>
<div class="line number20 index19 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp color1 bold">int</code> <code class="cpp plain">a[] = {-2, -3, 4, -1, -2, 1, 5, -3}; </code></div>
<div class="line number21 index20 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp color1 bold">int</code> <code class="cpp plain">max_sum = maxSubArraySum(a, 8); </code></div>
<div class="line number22 index21 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp functions bold">printf</code><code class="cpp plain">(</code><code class="cpp string">"Maximum contiguous sum is %d\n"</code><code class="cpp plain">, max_sum); </code></div>
<div class="line number23 index22 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp functions bold">getchar</code><code class="cpp plain">(); </code></div>
<div class="line number24 index23 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">return</code> <code class="cpp plain">0; </code></div>
<div class="line number25 index24 alt2"><code class="cpp plain">}</code></div></div></td></tr></tbody></table><br /></p><img src ="http://www.cppblog.com/ylfeng/aggbug/181491.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ylfeng/" target="_blank">鹰击长空</a> 2012-07-05 17:51 <a href="http://www.cppblog.com/ylfeng/archive/2012/07/05/181491.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Carbon Window in OSX</title><link>http://www.cppblog.com/ylfeng/archive/2012/07/04/181340.html</link><dc:creator>鹰击长空</dc:creator><author>鹰击长空</author><pubDate>Wed, 04 Jul 2012 02:39:00 GMT</pubDate><guid>http://www.cppblog.com/ylfeng/archive/2012/07/04/181340.html</guid><wfw:comment>http://www.cppblog.com/ylfeng/comments/181340.html</wfw:comment><comments>http://www.cppblog.com/ylfeng/archive/2012/07/04/181340.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/ylfeng/comments/commentRss/181340.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ylfeng/services/trackbacks/181340.html</trackback:ping><description><![CDATA[<div>From <a href="http://www.newsmth.net/nForum/#!article/Apple/136327">http://www.newsmth.net/nForum/#!article/Apple/136327</a><br />窗口 <br />---- <br />&nbsp;&nbsp;<br />其实 Mac OS X 的老用户们都该熟悉了，和 Windows 不一样，这个系统里&#8220;窗口&#8221;并非 <br />最重要的概念，一个程序的逻辑结构是：&nbsp;&nbsp;<br />&nbsp;&nbsp;<br />+---------------------------------------------+ <br />| Application&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; | <br />| +-------------------------+&nbsp;&nbsp;+-----------+&nbsp;&nbsp;| <br />| | Window&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;| Menu&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;| <br />| |&nbsp;&nbsp; +----------------+&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;+-----------+&nbsp;&nbsp;| <br />| |&nbsp;&nbsp; | Control&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; | <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; | <br />| |&nbsp;&nbsp; | | Control |&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;&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <br />+---------------------------------------------+ <br />&nbsp;&nbsp;<br />也就是说，菜单是独立于窗口的存在，有窗口和控件的区别。这和 Windows 中一切的 <br />本质都是窗口有很大的区别。&nbsp;&nbsp;<br />&nbsp;&nbsp;<br />虽然 Mac OS X 中区分 Window, Control 和 Menu 这几种概念，但并不代表其设计上 <br />没有考虑到它们之间的一致性。在 Carbon 中，这些实体都是用 FooRef 的形式来表示 <br />的，Ref 就有指针的意思，比如你创建了一个窗口之后，就会得到对应的&nbsp;&nbsp;<br />WindowRef，其实这就是一个用来操纵这个窗口的指针，而你创建控件之后，对应的 <br />是 ControlRef，创建菜单对应的自然是 MenuRef 了，还是很好理解的吧。&nbsp;&nbsp;<br />&nbsp;&nbsp;<br />我们这里先只谈窗口。很显然，要创建窗口，还得有些其他的属性，让我们看看&nbsp;&nbsp;<br />Carbon 的 CreateNewWindow 这个函数的原形是怎么要求的：&nbsp;&nbsp;<br />&nbsp;&nbsp;<br />OSStatus CreateNewWindow ( <br />&nbsp;&nbsp;&nbsp;&nbsp;WindowClass windowClass, <br />&nbsp;&nbsp;&nbsp;&nbsp;WindowAttributes attributes, <br />&nbsp;&nbsp;&nbsp;&nbsp;const Rect *contentBounds, <br />&nbsp;&nbsp;&nbsp;&nbsp;WindowRef *outWindow <br />); <br />&nbsp;&nbsp;<br />WindowClass 是一个常量，我们最常见的一种是 kDocumentWindowClass (也是下面 <br />打算要用的)，还有 kDrawerWindowClass，这也很好理解：那种可以伸缩的 Drawer&nbsp;&nbsp;<br />嘛，kAlertWindowClass 呢？就是我们常见的提示框了。&nbsp;&nbsp;<br />&nbsp;&nbsp;<br />WindowAttributes 则是针对具体 WindowClass 再作更仔细的属性定制了，这也是一个&nbsp;&nbsp;<br />32 位的无符号整数，但和 WindowClass 只能 n 选 1 不同，你可以把属性用位或 (|) 组 <br />合起来使用。反正一时也记不住那么多，就先设置为&nbsp;&nbsp;<br />kWindowStandardDocumentAttributes | kWindowStandardHandlerAttribute 好了。前 <br />者保证我们的窗口具有其他标准的文档窗口相同的特性，而后者给窗口加上系统提供的 <br />标准 event handler，以自动处理一般的 event。下面是用于设置的代码：&nbsp;&nbsp;<br />&nbsp;&nbsp;<br />WindowAttributes windowAttrs; <br />&nbsp;&nbsp;<br />windowAttrs = kWindowStandardDocumentAttributes | <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; kWindowStandardHandlerAttribute; <br />&nbsp;&nbsp;<br />直到这里，&#8220;event&#8221;都还是一个很模糊的概念，虽然我们前面多次提到了它，但为了避 <br />免过多的讲理论，我拖到现在才来介绍它。&nbsp;&nbsp;<br />&nbsp;&nbsp;<br />Event (事件) 其实是 Carbon 编程的基础。鼠标点击、键盘输入、菜单命令都是以&nbsp;&nbsp;<br />event 的形式发出的。窗口需要重绘、移动和放缩时，也会告知你的应用程序一个&nbsp;&nbsp;<br />event。当你的程序切换到前端或者后端时，你也会收到 event 告知你这个信息。 <br />Carbon 程序的工作就是通过回应 event 来实现与用户和系统交互。&nbsp;&nbsp;<br />&nbsp;&nbsp;<br />Carbon 的 event 处理是基于回调 (callback) 机制的。你可以定义针对不同 event 类型 <br />的 event handler，然后在 Carbon Event Manager 中注册 (Install) 之。然后每当&nbsp;&nbsp;<br />event 发生时，Carbon Event Manager 就会调用你注册的 handler 函数。每个 event&nbsp;&nbsp;<br />handler 都必须与一个具体的 event target 对象关联起来，比如 target 是菜单、窗口或 <br />整个程序。&nbsp;&nbsp;<br />&nbsp;&nbsp;<br />应用程序包含窗口和菜单，窗口包含控件，控件还能进一步包含控件。一旦 event 出 <br />现，首先得到通知的是最里层的 target，比如点击 button 的 event 首先发到 button 控 <br />件上。如果最里面的 target 没有相关的 handler，就把 event 传播到更外层的包含它的&nbsp;&nbsp;<br />target 上。Carbon 给窗口和应用程序的 event target 提供了标准的 handler。标准&nbsp;&nbsp;<br />handler 可以负责处理类似窗口针对鼠标的操作，比如拖拽，伸缩等等。这样一来，你 <br />就只需要关心自己的程序里针对拖拽或伸缩的特殊反映，而不比费神于那些所有程序都 <br />通用的部分了。&nbsp;&nbsp;<br />&nbsp;&nbsp;<br />当然，如果你愿意，也可以覆盖标准的 handler，比如有人可能会写个针对拉伸窗口的&nbsp;&nbsp;<br />handler，给窗口的伸缩增加音效。我们这里没那么复杂，用标准的就好啦。&nbsp;&nbsp;<br />&nbsp;&nbsp;<br />第三个参数就更好理解了，是一个指向 Rect 这个结构体的指针，说明了窗口在屏幕坐 <br />标系 [1] 中的位置和大小。这个东西其实还是 QuickDraw 中的概念，所以在程序中我 <br />们也调用 QuickDraw 的 API 来完成设置：&nbsp;&nbsp;<br />&nbsp;&nbsp;<br />#define kWindowTop&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;100 <br />#define kWindowLeft&nbsp;&nbsp;&nbsp;&nbsp; 50 <br />#define kWindowRight&nbsp;&nbsp;&nbsp;&nbsp;800 <br />#define kWindowBottom&nbsp;&nbsp; 600 <br />&nbsp;&nbsp;<br />Rect contentRect; <br />&nbsp;&nbsp;<br />SetRect(&amp;contentRect, kWindowLeft, kWindowTop, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; kWindowRight, kWindowBottom); <br />&nbsp;&nbsp;<br />设置的正是这个矩形四个点的坐标。&nbsp;&nbsp;<br />&nbsp;&nbsp;<br />[1]: 注意屏幕坐标系中左上角是 (0, 0)。 <br />&nbsp;&nbsp;<br />最后一个参数是一个输出，也就是我们最终创建出来的那个新窗口的指针了。所以，我 <br />们一般是这样创建窗口的：&nbsp;&nbsp;<br />&nbsp;&nbsp;<br />WindowRef theWindow; <br />CreateNewWindow(kDocumentWindowClass, windowAttrs,&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;contentRect, &amp;theWindow); <br />&nbsp;&nbsp;<br />等等，窗口是创建好了，存在 theWindow 指针里，可窗口的标题呢？我们这样设置：&nbsp;&nbsp;<br />&nbsp;&nbsp;<br />SetWindowTitleWithCFString(theWindow, CFSTR("Hello Carbon")); <br />&nbsp;&nbsp;<br />注意这里的 CFSTR 是一个宏，用于把 C 的 const char * 字符串转换为 Core&nbsp;&nbsp;<br />Foundation 定义的 CFStringRef 字符串，对于 CFString 的详细介绍可以看 Strings&nbsp;&nbsp;<br />Programming Guide for Core Foundation [2]，不过其实现在我们知道它包括的是一个 <br />数组和数组的长度，数组的元素都是 Unicode 字符 (UniChar)，就行了，具体的转换细 <br />节暂时不必考虑。 <br />&nbsp;&nbsp;<br />[2]: <a href="http://developer.apple.com/documentation/CoreFoundation/Conceptual/" target="_blank">http://developer.apple.com/documentation/CoreFoundation/Conceptual/</a> <br />CFStrings/CFStrings.html <br />&nbsp;&nbsp;<br />一切完毕之后，我们就可以显示这个窗口了：&nbsp;&nbsp;<br />&nbsp;&nbsp;<br />ShowWindow(theWindow); <br />&nbsp;&nbsp;<br />下面把完整的代码列出 (你也可以看附件里面的)：&nbsp;&nbsp;<br />&nbsp;&nbsp;<br />/* hello.c: testing Carbon basics */ <br />&nbsp;&nbsp;<br />#include &lt;Carbon/Carbon.h&gt; <br />&nbsp;&nbsp;<br />#define kWindowTop&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;100 <br />#define kWindowLeft&nbsp;&nbsp;&nbsp;&nbsp; 50 <br />#define kWindowRight&nbsp;&nbsp;&nbsp;&nbsp;800 <br />#define kWindowBottom&nbsp;&nbsp; 600 <br />&nbsp;&nbsp;<br />int main(int argc, char *argv[]) <br />{ <br />&nbsp;&nbsp;&nbsp;&nbsp; WindowRef&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; theWindow; <br />&nbsp;&nbsp;&nbsp;&nbsp; WindowAttributes&nbsp;&nbsp;windowAttrs; <br />&nbsp;&nbsp;&nbsp;&nbsp; Rect&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;contentRect; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; windowAttrs = kWindowStandardDocumentAttributes | <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; kWindowStandardHandlerAttribute; <br />&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; SetRect(&amp;contentRect, kWindowLeft,&nbsp;&nbsp;kWindowTop, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; kWindowRight, kWindowBottom); <br />&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; CreateNewWindow(kDocumentWindowClass, windowAttrs, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;contentRect, &amp;theWindow); <br />&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; SetWindowTitleWithCFString(theWindow,&nbsp;&nbsp;<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;CFSTR("Hello Carbon")); <br />&nbsp;&nbsp;&nbsp;&nbsp; ShowWindow(theWindow); <br />&nbsp;&nbsp;&nbsp;&nbsp; RunApplicationEventLoop(); <br />&nbsp;&nbsp;&nbsp;&nbsp; return 0; <br />} <br />&nbsp;&nbsp;<br />这一节的内容，呃，还是超出了我的预计，你要是有兴趣不妨再看看 Carbon Event&nbsp;&nbsp;<br />Manager Programming Guide，event 还是一个比较 tricky 的概念，而我们要到后面 <br />用到的时候才会深谈。下一节讲菜单的创建。&nbsp;&nbsp;</div><img src ="http://www.cppblog.com/ylfeng/aggbug/181340.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ylfeng/" target="_blank">鹰击长空</a> 2012-07-04 10:39 <a href="http://www.cppblog.com/ylfeng/archive/2012/07/04/181340.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Efficient auto-complete with a ternary search tree</title><link>http://www.cppblog.com/ylfeng/archive/2012/06/25/180220.html</link><dc:creator>鹰击长空</dc:creator><author>鹰击长空</author><pubDate>Mon, 25 Jun 2012 15:26:00 GMT</pubDate><guid>http://www.cppblog.com/ylfeng/archive/2012/06/25/180220.html</guid><wfw:comment>http://www.cppblog.com/ylfeng/comments/180220.html</wfw:comment><comments>http://www.cppblog.com/ylfeng/archive/2012/06/25/180220.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/ylfeng/comments/commentRss/180220.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ylfeng/services/trackbacks/180220.html</trackback:ping><description><![CDATA[<div><span><br />The original post is </span><a href="http://igoro.com/archive/efficient-auto-complete-with-a-ternary-search-tree/"><span>http://igoro.com/archive/efficient-auto-complete-with-a-ternary-search-tree/</span></a><br />
<p><span>Over the past couple of years, auto-complete has popped up all over the web. Facebook, YouTube, Google, Bing, MSDN, LinkedIn and lots of other websites all try to complete your phrase as soon as you start typing.</span></p>
<p><span>Auto-complete definitely makes for a nice user experience, but it can be a challenge to implement efficiently. In many cases, an efficient implementation requires the use of interesting algorithms and data structures. In this blog post, I will describe one simple data structure that can be used to implement auto-complete: a ternary search tree.</span></p>
<h3><span>Trie: simple but space-inefficient</span></h3>
<p><span id="more-177"></span>
<p><span>Before discussing ternary search trees, let&#8217;s take a look at a simple data structure that supports a fast auto-complete lookup but needs too much memory: a </span><em>trie</em>. A trie is a tree-like data structure in which each node contains an array of pointers, one pointer for each character in the alphabet. Starting at the root node, we can trace a word by following pointers corresponding to the letters in the target word.</p>
<p><span>Each node could be implemented like this in C#:</span></p><pre class="code"><span style="color: blue">class </span><span style="color: #2b91af">TrieNode
</span><span>{
</span><span style="color: blue">public const int </span><span>ALPHABET_SIZE = 26;
</span><span style="color: blue">public </span><span style="color: #2b91af">TrieNode</span><span>[] m_pointers = </span><span style="color: blue">new </span><span style="color: #2b91af">TrieNode</span><span>[ALPHABET_SIZE];
</span><span style="color: blue">public bool </span><span>m_endsString = </span><span style="color: blue">false</span><span>;
}</span></pre>
<p><span>Here is a trie that stores words AB, ABBA, ABCD, and BCD. Nodes that terminate words are marked yellow:</span></p>
<p>&nbsp;</p>
<p><img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="gif_1" src="http://igoro.com/wordpress/wp-content/uploads/2009/08/gif-1.gif" width="577" height="545" /></p>
<p>&nbsp;</p>
<p><span>Implementing auto complete using a trie is easy. We simply trace pointers to get to a node that represents the string the user entered. By exploring the trie from that node down, we can enumerate all strings that complete user&#8217;s input.</span></p>
<p><span>But, a trie has a major problem that you can see in the diagram above. The diagram only fits on the page because the trie only supports four letters {A,B,C,D}. If we needed to support all 26 English letters, each node would have to store 26 pointers. And, if we need to support international characters, punctuation, or distinguish between lowercase and uppercase characters, the memory usage grows becomes untenable.</span></p>
<p><span>Our problem has to do with the memory taken up by all the null pointers stored in the node arrays. We could consider using a different data structure in each node, such as a hash map. However, managing thousands and thousands of hash maps is generally not a good idea, so let&#8217;s take a look at a better solution.</span></p>
<h3><span>Ternary search tree to the rescue</span></h3>
<p><span>A ternary tree is a data structure that solves the memory problem of tries in a more clever way. To avoid the memory occupied by unnecessary pointers, each trie node is represented as a tree-within-a-tree rather than as an array. Each non-null pointer in the trie node gets its own node in a ternary search tree.</span></p>
<p><span>For example, the trie from the example above would be represented in the following way as a ternary search tree:</span></p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://igoro.com/wordpress/wp-content/uploads/2009/09/image.png" width="183" height="375" /></p>
<p><span>The ternary search tree contains three types of arrows. First, there are arrows that correspond to arrows in the corresponding trie, shown as dashed down-arrows. Traversing a down-arrow corresponds to &#8220;matching&#8221; the character from which the arrow starts. The left- and right- arrow are traversed when the current character does not match the desired character at the current position. We take the left-arrow if the character we are looking for is alphabetically before the character in the current node, and the right-arrow in the opposite case.</span></p>
<p><span>For example, green arrows show how we&#8217;d confirm that the ternary tree contains string ABBA:</span></p>
<p>&nbsp;<img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://igoro.com/wordpress/wp-content/uploads/2009/09/image1.png" width="183" height="375" /></p>
<p><span>And this is how we&#8217;d find that the ternary string does not contain string ABD:</span></p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://igoro.com/wordpress/wp-content/uploads/2009/09/image2.png" width="183" height="375" />&nbsp;</p>
<h3><span>Ternary search tree on a server</span></h3>
<p><span>On the web, a significant chunk of the auto-complete work has to be done by the server. Often, the set of possible completions is large, so it is usually not a good idea to download all of it to the client. Instead, the ternary tree is stored on the server, and the client will send prefix queries to the server.</span></p>
<p><span>The client will send a query for words starting with &#8220;bin&#8221; to the server:</span></p>
<p>&nbsp; <img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://igoro.com/wordpress/wp-content/uploads/2009/09/image3.png" width="639" height="218" /></p>
<p><span>And the server responds with a list of possible words:</span></p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://igoro.com/wordpress/wp-content/uploads/2009/09/image4.png" width="452" height="218" />&nbsp;</p>
<h3><span>Implementation</span></h3>
<p><span>Here is a simple ternary search tree implementation in C#:</span></p><pre class="code"><span style="color: blue">public </span><span style="color: blue">class </span><span style="color: #2b91af">TernaryTree
</span><span>{
</span><span style="color: blue">private </span><span style="color: #2b91af">Node </span><span>m_root = </span><span style="color: blue">null</span><span>;
</span><span style="color: blue">private void </span><span>Add(</span><span style="color: blue">string </span><span>s, </span><span style="color: blue">int </span><span>pos, </span><span style="color: blue">ref </span><span style="color: #2b91af">Node </span><span>node)
{
</span><span style="color: blue">if </span><span>(node == </span><span style="color: blue">null</span><span>) { node = </span><span style="color: blue">new </span><span style="color: #2b91af">Node</span><span>(s[pos], </span><span style="color: blue">false</span><span>); }
</span><span style="color: blue">if </span><span>(s[pos] &lt; node.m_char) { Add(s, pos, </span><span style="color: blue">ref </span><span>node.m_left); }
</span><span style="color: blue">else if </span><span>(s[pos] &gt; node.m_char) { Add(s, pos, </span><span style="color: blue">ref </span><span>node.m_right); }
</span><span style="color: blue">else
</span><span>{
</span><span style="color: blue">if </span><span>(pos + 1 == s.Length) { node.m_wordEnd = </span><span style="color: blue">true</span><span>; }
</span><span style="color: blue">else </span><span>{ Add(s, pos + 1, </span><span style="color: blue">ref </span><span>node.m_center); }
}
}
</span><span style="color: blue">public void </span><span>Add(</span><span style="color: blue">string </span><span>s)
{
</span><span style="color: blue">if </span><span>(s == </span><span style="color: blue">null </span><span>|| s == </span><span style="color: #a31515">""</span><span>) </span><span style="color: blue">throw new </span><span style="color: #2b91af">ArgumentException</span><span>();
Add(s, 0, </span><span style="color: blue">ref </span><span>m_root);
}
</span><span style="color: blue">public bool </span><span>Contains(</span><span style="color: blue">string </span><span>s)
{
</span><span style="color: blue">if </span><span>(s == </span><span style="color: blue">null </span><span>|| s == </span><span style="color: #a31515">""</span><span>) </span><span style="color: blue">throw new </span><span style="color: #2b91af">ArgumentException</span><span>();
</span><span style="color: blue">int </span><span>pos = 0;
</span><span style="color: #2b91af">Node </span><span>node = m_root;
</span><span style="color: blue">while </span><span>(node != </span><span style="color: blue">null</span><span>)
{
</span><span style="color: blue">int </span><span>cmp = s[pos] - node.m_char;
</span><span style="color: blue">if </span><span>(s[pos] &lt; node.m_char) { node = node.m_left; }
</span><span style="color: blue">else if </span><span>(s[pos] &gt; node.m_char) { node = node.m_right; }
</span><span style="color: blue">else
</span><span>{
</span><span style="color: blue">if </span><span>(++pos == s.Length) </span><span style="color: blue">return </span><span>node.m_wordEnd;
node = node.m_center;
}
}
</span><span style="color: blue">return false</span><span>;
}
}</span></pre>
<p><a href="http://11011.net/software/vspaste" jquery1340637368540="1"></a></p>
<p><a href="http://11011.net/software/vspaste" jquery1340637368540="2"></a></p>
<p><strong></strong></p>
<p><span>And here is the Node class:</span></p><pre class="code"><span style="color: blue">class </span><span style="color: #2b91af">Node
</span><span>{
</span><span style="color: blue">internal char </span><span>m_char;
</span><span style="color: blue">internal </span><span style="color: #2b91af">Node </span><span>m_left, m_center, m_right;
</span><span style="color: blue">internal bool </span><span>m_wordEnd;
</span><span style="color: blue">public </span><span>Node(</span><span style="color: blue">char </span><span>ch, </span><span style="color: blue">bool </span><span>wordEnd)
{
m_char = ch;
m_wordEnd = wordEnd;
}
}</span></pre>
<p><a href="http://11011.net/software/vspaste" jquery1340637368540="3"></a></p>
<h3><span>Remarks</span></h3></font>
<p><span>For best performance, strings should be inserted into the ternary tree in a random order. In particular, do not insert strings in the alphabetical order. Each mini-tree that corresponds to a single trie node would degenerate into a linked list, significantly increasing the cost of lookups. Of course, more complex self-balancing ternary trees can be implemented as well.</span></p>
<p><span>And, don&#8217;t use a fancier data structure than you have to. If you only have a relatively small set of candidate words (say on the order of hundreds) a brute-force search should be fast enough.</span></p>
<h3><span>Further reading</span></h3>
<p><span>Another article on tries is available on DDJ (careful, their implementation assumes that no word is a prefix of another):</span></p>
<p><a title="http://www.ddj.com/windows/184410528" href="http://www.ddj.com/windows/184410528" jquery1340637368540="4"><span>http://www.ddj.com/windows/184410528</span></a></p>
<p><span>If you like this article, also check out these posts on my blog:</span></p>
<ul><li><a href="http://igoro.com/archive/skip-lists-are-fascinating/"><span>Skip lists are fascinating!</span></a></li><li><a href="http://igoro.com/archive/numbers-that-cannot-be-computed/"><span>Numbers that cannot be computed</span></a></li><li><a href="http://igoro.com/archive/quicksort-killer/"><span>Quicksort killer</span></a> </li></ul><br /></font></div><img src ="http://www.cppblog.com/ylfeng/aggbug/180220.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ylfeng/" target="_blank">鹰击长空</a> 2012-06-25 23:26 <a href="http://www.cppblog.com/ylfeng/archive/2012/06/25/180220.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>