2009年2月28日星期六

Unicode, A programmer should know

首先说说这个标题,因为我最近非常迷星战,所以顺带也喜欢上了Yoda大师说话的腔调,以后可能会用的更多,情别见怪(反正也没人看)。

“曹操”为什么会变成“变巨”一文中,我提到了Unicode是多语言共存的解决方案,本文将详细介绍Unicode,以及为什么解决了各种令人头疼的编码问题。

那unicode解决了哪些问题呢?其实最主要的是这几个问题:

  1. 人们希望有一个单一的字符集,能包含这个星球上所有的字符
  2. 每个字符都有一个独立的编号,不会出现一个编号对应不同字符的事情
  3. 可以根据需要变换不同的编码方式,但是不会影响字符编号
那么看看unicode是怎么解决这些问题的呢?

Unicode 是一个国际标准,它主要包含了:
  • 超大的字符集,可以有1,000,000个字符,code space为[0x0-0x10FFFF]
  • 每个字符的code point编码方法
  • 一个标准的字符集
  • 一组字符属性的枚举值
  • 提供字符集的多种编码
有很多人把unicode 与utf8,utf16这些编码混为一谈,看完本文后,应该不会再存在这样的混淆了。

Unicode有其标准的书写格式。要表示一个字符的Unicode码,可以这样写:
U+0041 
这就是大写字母A的Unicode码,U+表示这是Unicode码,后面的十六进制数字是这个字符的unicode code point。比如hello的code point就是U+0048 U+0065 U+006C U+006C U+006F。可以看到,这些码值去掉前面的00,就跟ASCII码一样了,是的,unicode最大限度跟ASCII保持兼容。

Unicode的字符集可以说包括了这个星球上所有的字符。包括一些我们可能永远也不会遇到的字符。不过Unicode标准把一些最常用的字符放在0x0000-0xFFFF这个区间中,这样有些系统实现的时候就不需要用那么多空间来存放不常用的字符了。这个区间被称为BMP(Basic Multilingual Plane)。Unicode一共有17个Plane,有6个已经被占用,剩下的都是空的。如下表所示:

Plane RangeDescriptionAbbreviation
0 0000-FFFFBasic Multilingual PlaneBMP
1 10000-1FFFFSupplementary Multilingual PlaneSMP
2 20000-2FFFFSupplementary Ideographic PlaneSIP
3-13 30000-DFFFFcurrently unassigned
14 E0000-EFFFFSupplementary Special-purpose PlaneSSP
15 E0000-EFFFFSupplementary Private Use Area-A 
16 E0000-EFFFFSupplementary Private Use Area-B 

在BMP中的任何一个code point都用4位16进制数来表示。其他的plane中的code point用5-6位。

Unicode的编码问题是我们最关心的。Unicode允许使用不同的编码方式,也就是你平时看到的utf8, utf16之类的名字。他们的特点在于编码出来的值各不相同,但是解码之后,都对应到一个唯一的unicode code point。这样保证了unicode编码之间可以无损(在BMP中)转换以及映射(mapping)的唯一性。Unicode中把一个值的code point及其使用某种编码得到的码值称为一个映射(mapping)。

在unicode发展过程中,出现过多种编码。我这里就介绍几种主要的编码,在此过程中出现过两个组织,各自发展出一套映射方法,称为Unicode Transformation Format(UTF)和 Universal Character Set(UCS)。 后来两个组织合并在一起,UTF和UCS也随之合并了。简单的说它们之间的对应关系是UTF后面跟的是一个编码的位数,UCS后面跟的数字是编码的字节数(以八位作为一个字节),比如UTF-16和UCS2几乎是同一个东西。但实际上UCS2只实现了BMP内的字符编码,而UTF16则实现了所有unicode编码。但为了简单期间,我们在这里认为它们是一个东西。

UTF-16/UCS2
最直观的编码方式就是一一映射。一个unicode码对应一个UTF-16编码。比如上面所说的hello,其编码为00 48 00 65 00 6C 00 6C 00 6F。但是问题马上来了,在大端法(big endian)和小端法(little-endian)的机器上编码得到的串的顺序不一样。在大端法的机器上,同样hello经过编码得到的是48 00 65 00 6C 00 6C 00 6F 00。而48 00也是一个合法的unicode code point,因此把在大端法机器上保存的文件拿到小端法机器上读就会解析成完全不同的东西。人们于是想到用最前面的两个字节来标明字节顺序。这两个字同样是unicode码,U+FEFF,一般被称为BOM(Byte Order Mark)。FE FF表明大端法,FF FE表明小端法。

UTF-16使用2个字节来进行编码,因此只能编码到BMP的code point。对于其他的plane,UTF-16采用一种额外的编码方式,达到3,4字节的编码。但是一般情况下,UTF16指的就是2字节的编码。这样的编码非常方便,所有的字符都占用一个unsigned short,对于传统的c字符串函数就非常方便。

在windows上,为了方便utf16被直接称为unicode编码,与ANSI对应。你在使用notepade时可以保存成unicode,指的便是utf16。

下图显示了在linux上使用utf16编码



比较下在windows下使用utf16(unicode)编码,注意到BOM了吗?




UTF-8
UTF-8可以说是用得最广泛的编码方式了,很多Linux的发布版都使用UTF-8作为其系统编码。UTF-8的产生原因可能是由于有人觉得UTF-16太占用空间了。在美国英语系统下,每一个字符都有一个00,字符串大小凭空增加了一倍。于是人们研究出UTF-8这个可以兼容ASCII的变长编码方式。UTF8编码出来的字符占1-4字节。

具体占位如下图所示:


对于在U+0000到U+007F区间(是不是很熟,对了,就是ASCII码的区间)内字符,使用1个字节来编码,因此完全兼容ASCII码,而且省空间。

[U+0080, U+07FF] 区间内的字符,基本上是欧洲各国字符集,使用2个字节来编码。
图中的yyy是code point中的高位字节,由于最多到7,因此只要3个bit就可以编码。
图中的xxxxxxxx是code point中的低位字节,从00到FF,需要用的所有8个bit,在编码时,把低位的6个bit与10结合作为一个字节,剩下的2个bit与yyy,110结合作为一个字节。

[U+0800, U+FFFF] 区间内的字符,包括中文,日文,韩文等都使用3个byte来编码。详细的编码规则在图中已经解释的很清楚了,我这里不再重复。

下图显示了在linux使用utf8编码,于utf16的截图相比,utf8对曹操这两个中文各用了3个byte进行编码。



比较下在windows上使用utf8编码,首先是字节顺序不同。然后你还可以看到utf8的BOM,0xEF 0xBB 0xBF。这BOM不仅和系统,还和使用的软件有关。notepad无论什么编码都会加上BOM。



UTF32/UCS4
这是最浪费空间的一种编码方式,它也是一一映射,但是UTF32映射了所有的unicode code point。对于每一个code point,UTF32如其名字所示,使用32bit也就是4个字节来进行编码。比如A=00 00 00 41。

很多程序使用utf32作为内部编码,在保存的时候它可以无损的转换成其他编码。而且因为现在的硬件总线的关系,这种编码的寻址和读写更快。比如Apache的Xerce2 就是这么做得。



还有其他很多编码,比如国标的GB18030。只要符合unicode标准,你也可以创造自己的编码。


讲了这么多,最初的问题也算回答得差不多了。Jeffrey Richter[1], Joey Spolsky[2], Charles Petzold[3]等人都在各自的著作中强调unicode对现代编程的重要性。虽然我人微言轻,但是我还是想附和一句:unicode以及编码的知识应该是每一个专业的程序员需要了解的知识。现在,停止ANSI程序,开始用unicode编写你的正式程序吧。




注1:《Programming Applications for Microsoft Windows》, chapter 2, Jeffrey Richter
注2:《Joel on software》, Charpter 4, Joel Spolsky
注3:《Programming windows》,chapter 2, Charles Petzold

2009年2月27日星期五

一张14.74亿像素的照片

美国总统奥巴马就职大典downloading
你可以看清大部分人的脸
http://gigapan.org/viewGigapanFullscreen.php?auth=033ef14483ee899496648c2b4b06233c

下面是缩略图

2009年2月21日星期六

“曹操”为什么会变成“变巨”?


以前在PC上玩过三国志的人大多数都会记得一个奇怪的词——“变巨”。但大家都知道,那是曹操,因为头像放在那,一看就知道是曹操,一张枭雄的脸。可是为什么会显示成“变巨”呢?有些人会说,编码问题呗。是的,那到底是怎么回事儿呢?

这个问题的根本原因可以说是编码和解码方式不匹配

要解释这个问题,首先要解释下Code Page的概念。在Windows下,打开控制面板->区域和语言选项->高级,里面就有代码页转换表。我们在里面会看到类似936  (ANSI/OEM - 简体中文 GBK) 这样的选项。这就是一个Code Page(代码页)。

Code Page最早始于IBM,当时个人PC上只有ASCII码,用0x00-0x7F这128个code point(代码点)来编码控制字符,数字,大小写字母,特殊字符和打印符号等。但是很快ASCII码就无法适应需求了,更多的西欧字符要求被加入码表。于是出现了EBCDIC codepages。这些Code Pages扩充了ASCII码,成为256位的一个码表。前面0x00-0x7F与ASCII码保持一致,后面的128根据不同的语言定义不同的code page。微软一开始借用了这些CODE PAGE,之后用自己的ANSI(或者说ISO 8859-1)的code page作为补充,成为现在我们在Windows操作系统上的CodePage。

在Windows操作系统中,对CJK(Chinese,Japanese,Korean) 也用Code Page进行处理。但是中文等语言的字符实在太多,不可能用256位的code page来表示,那怎么办呢?一个直观的想法是用双字节来编码一个字符,理论上就可以安置65536个字符。也可以用多字节来表示,单字节部分可以兼容ASCII码,双字节部分编码CJK字符。在code page设计时是怎么考虑的我不知道,但最后还是采用了后一种方式。

看下图:


这是一张Windows Codepage 936(以下简称CP936)的示意图。前面0x00-0x7F和ASCII码一致,和Windows上其他的codepage保持一致。后面128个字节被称为lead byte,用来和另一个byte组合成一个CJK字符的编码。每个lead byte又对应一张子表,比如0x81这个lead byte对应的子表如下图所示:


于是汉字“丢”的GBK码就是0x8147。但是子表并不一定都是256个字符。理论上GBK码按照这种方式可以编码128*256个=32768个字符。但实际上中文字符要多的多。因此出现了其他更好的编码,这里先按下不说。Windows的设计的这个字符集被称为MBCS(Multi Byte Character Set)。

知道了codepage的概念,我们就可以解释“曹操”-“变巨”的问题了。为什么我开头说“编码和解码方式不匹配”呢?想想看,曹操是存放在什么地方的?用什么编码存放的?

对了,曹操两个字是存放在资源文件里面的。而我们玩的三国志是第三波汉化的繁体中文版,也就是说,曹操两个字是以BIG5码(CP950)进行编码的。从以下的CP950_B1可以看到,“曹”字的编码是:B1E4。而我们是在简体中文的Windows上玩这个游戏的,对于磁盘上存放的B1E4,我们用CP936 GBK码来解码的。从下面的CP936_B1可以看到B1E4正好就是“变”字。



同理可以知道操对应的是巨,繁体字赵云对应的简体字是化冻。

事实上,这小小的一个问题,牵涉到Locale,字符集,codepage,编码等各种问题。
而CodePage在使用过程中也暴露出很多问题;最主要的就是一个代码点(code point)在不同的codepage中代表不同的字符,变成了一对多的关系,导致在一个程序中没法使用多语言。不同的厂商在设计code page时缺少文档,不利于交流等。

解决这些问题的,就是Unicode。我会在最近的blog中详细介绍Unicode。因为Unicode是每个程序员需要了解的概念。

最后,我总结下Code Page的概念:
  • Code Page只在Windows和IBM的mainframe上有,Linux/Unix等操作系统并没有这个概念。
  • Code Page是为了解决多语言及本地化的问题而产生的。
  • 使用Code Page,无法在一个程序中支持多语言。
  • 在Windows中,一旦换了Code Page,我们需要重启。
  • Code Page提供了字符集和编码/解码方式。

更新于2009.2.28: 关于unicode的介绍已经写好了--Unicode, a programmer should know

雷到我了

From Reference Photos

不知道三分钟后,他们是不是全部下场了

2009年2月8日星期日

log to console when programming windows application

我们在开发Windows界面程序的时候往往需要打印一些运行过程中的调试信息。很多人都使用OutputDebugString来把信息打印到WINDOWS内部的调试器上。然后通过SysInternal的DebugView来查看。

今天我来介绍另外一个非常有用的方法--打开一个控制台窗口

Impossible! 你是在开发窗口程序,怎么可能打开控制台呢?或许有人会这样说。如果不可能,我还写这么多干什么?事实上只要2行代码就可以搞定:

AllocConsole();
freopen( "CONOUT$" , "a" , stdout );
这两行代码打开了一个和当前应用程序共享同一个进程空间的控制台。因此你可以简单的用cout来输出任何你想输出的信息。如下图:

不过一般在这两句话只会用在debug版本下,因此最好在外面加上对DEBUG版本的判断:
#ifdef _DEBUG
AllocConsole();
freopen( "CONOUT$" , "a" , stdout );
#endif
最后提一下,这两个窗口无论关掉哪一个,都会同时关闭另外一个,相当于同时退出进程。

该技巧在编写WinForm的时候也是适用的。所要做的只是把项目设置(Project Setting)中的Output Type改为"Console Application", 如下图:

有了这个Console,你就可以在程序中随意的使用System.Console.WriteLine输出调试信息了。

写windows程序的朋友不妨试一下。

WM_PAINT no end

今天在写程序的时候,发现一个自定义控件的WM_PAINT被不断的调用,以至于CPU占用率上升到40%以上。

我觉得很奇怪,我并没有移动窗口或者做什么引起重绘的操作,WM_PAINT为什么会被不断调用了。之后我发现一开始该控件没有不断重绘,只有第一次重绘之后才开始不断调用。
我的重绘代码是这样写的:

HDC hdc = GetDC(m_hWnd);
....do some drawing
Release(m_hWnd, hdc);
我很老实的遵守了调用DC的对称性规则,有创建也有释放。看来问题不在这里。

再一次仔细看了WM_PAINT的说明其中有几句引起了我的注意:
a WM_PAINT message may have been caused by both a non-NULL update region
仔细体会一下,就得出了这个问题的背后黑手--update region。

我曾在Windows绘图概述一文中写道:
事实上WM_PAINT产生的条件就是有部分窗口失效了。如果不出现这种情况,就不会产生WM_PAINT
当窗口的Client Area发生改变的时候,系统给应用程序发送WM_PAINT消息。系统仅在消息队列中没有其他消息的时候发送该消息给应用程序。一般的用法是在WM_PAINT中调用BeginPaint获得DC,然后进行任何GDI绘图,最后通过EndPaint释放DC
BeginPaint会把需要更新的区域设为NULL,以防连续导致发送WM_PAINT消息。
这里的文字已经很清楚的告诉了我原因,很可惜,这些文字是翻译自MSDN,没有经过自己亲身经历,因此没有深刻的体会。而这次,我正是犯了这个错误。

我接收到的WM_PAINT的消息是由InvalidateRect(NULL)导致的。该函数把整个Client区域都变成了update region.而我在WM_PAINT中又恰恰用了GetDC而不是BeginPaint函数来获取DC,因此导致处理完WM_PAINT后,失效区域没有更新,让Window以为我一直没有重绘,因此DefWindowProc中不断的重复发送WM_PAINT到message queue中,导致了无限循环。

解决的方法有两个,一个是在WM_PAINT中用BeginPaint和EndPaint来处理。另外一种是在WM_PAINT中使用ValidateRect函数。

Bjarne Stroustrup说过,一知半解的程序员是危险的,这个问题没有花去我很多时间,但是它告诉我,不要小看任何一个小小的函数。它或许牵涉到很大的问题。

2009年2月5日星期四

我的第一次就这么没了

好吧,我承认,我有点标题党了。

今天去体检,遇到了一个以前从来没有过的体检项目--查痔疮。结果第一次被人爆了菊花,这感觉真是恶心,不过还算值得,因为查出了轻微的外痔。犯我菊花者说让我不要久坐,常起来走动,少吃辛辣食物。看来我也要注意了,做我这个工作的坏处就是一直坐着,容易引起腰椎问题不说,也容易得痔疮,还容易引起前列腺问题。建议和我一样干程序员的朋友常起来走动走动。

另一个第一次就是第一次洗牙。洗牙这东西,我从来没有好好了解过,一直自以为是的认为是一种奢侈的行为,或者是那些牙齿泛黄的人为了美观才去做的事情。但是今天却是好好得上了一堂课。牙科医生检查了一下我的牙齿,然后让我拿着一面镜子看我的牙齿内侧,真是不看不知道,一看吓一跳。我牙齿内侧就像糊着一层泥一样恶心。医生说这就是牙结石,而且我的牙结石已经很厉害了。当牙齿上的牙结石增多,牙龈(我们常说的牙肉)就会被挤下去,慢慢露出牙根,牙龈对牙齿的保护作用就随之退化和消失。这样就会产生牙周炎,牙龈肿痛之类的问题,牙齿也会慢慢损坏。她建议我尽快做洗牙,把这些牙结石全部洗掉。同时告诉我,洗掉之后,牙齿间就会露出缝隙,因为原来牙龈的部分都已经被牙结石代替了,结石没了之后,牙龈不会立刻恢复。而且随着年龄的增加,牙龈的恢复能力会越来越差,所以这个事情越早越好。

她告诉我,在发达国家,一般人都有这个意识,每半年去检查一次牙齿,如果有牙结石就洗掉它,这是一种常识性的东西。很可笑的是,我活了快30年了,这是生平第一次听到医生跟我解释这个事情。有人可能说她想赚我钱,但是她至少说服了我,虽然洗牙还挺贵(300块全套,因为我比较严重),但是我还是心甘情愿的掏了钱。而且我了解了这个常识,以后我每半年会去检查一次看看。我好吃,所以我不想我的牙齿有什么问题,否则美食在眼前,却无福享用,那可比杀了我还难受啊。

洗牙的过程不多说了,稍微有点小痛。结束之后医生说我的牙结石钙化非常严重,很多地方要洗好几次才能洗掉。现在回想起来,我以前自己用舌头舔牙齿内侧的时候,总归感觉牙缝之间好像被什么东西填住了。还有两个牙齿根部好像有硬硬的东西,当时还傻乎乎的以为自己又长了小牙齿出来。后来在洗牙过程中,医生用力的在牙根中间冲刷,我才知道那是一块钙化物,是牙结石最顽固也是危害最大的地方。如果你和我有同样的经历,建议你去医院检查一下牙齿。

最后由于我门牙附近几颗牙齿钙化特别严重,导致洗牙之后牙龈大量出血,医生给我用了进口药(感觉有点骗钱,不过大刀也宰了,就不在乎这点小刀了)又加了150元。第一次洗牙总共花了450块。最后医生说牙龈恢复很慢,而且像我这种情况也不大可能完全恢复,这是我唯一遗憾的地方了。

医生最后建议我用软一点的牙刷,因为我不抽烟喝酒,因此色素很少,用硬的牙刷还容易损坏牙齿,刷牙的正确方法我想也不用我说了,大家都知道,要上下刷,不要左右刷,里外都要刷,不能只刷外面。

最后,建议从来没有洗过牙的朋友也去医院检查一下,有备无患么,说不定还可以体验你的“第一次”。

2009年1月19日星期一

恭喜万猫喜得千金

这一个月来相当忙,家里的事,公司的事,学校的事,忙的我都没有时间写blog。不过还好,毕竟我的blog也没有什么人订。

这里先恭喜一下好友万猫,今天早上9点26分,我收到他短信,他的女儿出世了。具体时间有兴趣的朋友看他的blog: http://blog.morphinewan.com  不过我不知道他啥时候有空去发布这个消息。从大学第一天起认识到现在,也有十多年了,或许我还没有意识到时间流逝的速度。似乎前阵子还像在大学时聊天,没想到一眨眼,他竟然当爸爸了。我也由衷的为他高兴,真好,又有小囡可以给我捏捏了,哈哈。

2008年12月29日星期一

Pass thesis examination

今天是我这几年来的一个大日子,因为今天是我工程硕士论文答辩的日子。这是我6年前大学毕业以来第一次面对这么多老师进行严肃的答辩,再加上之前听说交大论文答辩是相当严格的,心里不免有些紧张。

答辩的学生一共有14个,我是第二个上去答辩的。因为我发现从坐下之后就开始紧张,第一位同学答辩的时候我想在脑子里面过一遍PPT的内容,结果越想越紧张。等到老师叫“第二个谁上”的时候,我觉得不能等了,越到后面压力越大,早死早超生,横竖横,拆牛棚,上了!

每 位同学的宣讲时间只有15分钟,关键是在15分钟之内将自己所作的工作阐述清楚,幸好我虽然紧张,但是思路还算清楚,比较流利的讲了下来,不过还是超过了 半分钟。最后几个老师稍微问了几个问题,就结束了答辩。总的来说,和我预期的差不多,比较顺利。毕竟我的准备工作做得很充分。


之后我就很轻松的坐在位置上看别人答辩了。当中有的同学阐述非常搞笑,老师提问,他答非所问;老师批评他,他还不服气,和老师死磕。有的同学PPT做的非常不认真,就把论文大段大段的往上贴,可想而知最后的结果是什么。


不过最后14个人都过了,但是其中7个人的论文需要修改,最严重的一个几乎要修改大半内容。最后只能说一句:态度决定一切!

2008年12月15日星期一

上海女仆咖啡店

今天无意中看到一个网友贴子,看得我热血沸腾。为啥?因为他介绍了一个上海的女仆店!不知道是不是上海第一家,毕竟我在这方面已经算是消息超闭塞人士。虽然我不是女仆控,但是看到那么可爱的女仆照片,又在自己所在的城市,心里还是激动了一把。毕竟宅男是无法抵挡女仆的诱惑的!
先给出信息,有兴趣的朋友一起去,哇哈哈哈!(感觉自己开始邪恶了!)

营业时间
上午11点 至 晚上9点
联系电话
021-63517385
地址
上海市浙江中路229号(百米香榭)204室
她们的网站是这个:
http://www.m-moe.cn/index.html

他们的blog
http://m.moe.blog.163.com/


 
女仆们排队恭候您的大驾光临!
 


在他们的网站上有每个女仆的介绍,感觉上都是初中生,高中生的样子,不知道这算不算童工啊。不过,管他呢,女仆不荫怎么行!

2008年11月19日星期三

文件搜索闪电侠

我一直很不满意Windows XP下的搜索,常常文件在那里也搜不到,每次还跑出来那只讨厌的小狗。可是公司里面不让装Google Desktop,MS自己出的MSN 搜索也不敢用,结果搜索就成了我一块心病。

前两天意外的发现了一个工具Everything, 我对其评价就如我题目写的--文件搜索闪电侠!

Everything是个小巧的工具,它能进行文件搜索,可以使用简单的正则表达式,而我最看重它的品质是,此软件小和快。小是指它的个头小,做的索引文件小,快是指做索引超快(我260G的硬盘几乎是立即完成,启动软件后就可以搜索了,官网写着速度为1分钟100万个文件),搜索文件速度快得令人发指!

其他的功能也很多,比如可以作为文件服务器,别人机器上开着这个服务,我就能去搜索他的电脑(牛逼)!

不过这个软件对我来说还有些不足,一是不能通过热键启动(就像金山词霸一样),而是不能进行全文检索。但是想想我做全文检索的几率也不大,这个就够了!

Everything的官网: http://www.voidtools.com/

另外有善用佳软小众软件对其的推荐。里面的介绍比我详细,有兴趣的人可以看看。

2008.11.28:
找到了热键启动的方法。
在Tool->Option的General标签页。设定好New window hotkey modifier 和New Window Hotkey key就可以了。

2008年11月14日星期五

有自己的域名啦!


在吗啡的多次,再三,不断地怂恿下,我终于买了一个自己的域名。

本来想买linghao.com的,可是被那种卖域名的人抢注了。而且还刚刚续了费,我只能放弃了。不过这个看起来也挺好。mog是moogle的简写,也是FinalFantasy里面飞天猪的名字,我99年一开始上网时所用的nick,挺有纪念意义的。

在吗啡的悉心帮助下(我发现我现在特懒-_-,而且对这种网络设置一窍不通,汗颜啊),一步一步把各种配置都搞好了。

以后我的blog地址变为:http://blog.mogling.com/
我的feed地址也随之变动:http://feeds.mogling.com/ (以前订阅过的朋友可以继续使用老地址,内容是一样的。)

2008年11月11日星期二

根据名字画出我的头像?

FriendFeed举办了一个24小时编程比赛Philipp的作品可以根据你的名字给你一个脸的图片。

网址:http://turnyournameintoaface.com/
 
我分别输入了我名字的拼音和中文和我最常用的网名,结果出来的是这副腾头死。

这张是linghao
这张是凌浩
 
这张是我常用的moogle
  是不是很惨,但是当我输入周杰伦,刘德华之流的名字之后,我发现我真TMD太帅了!

P.S. 2008/11/14
吗啡说用英文的没有好下场,我抱着科学的态度又求证了一下,用的是Mog,这个我最近刚捡起来的9年前刚上网时用的nick。感觉不错吧,不过就是奶油了点。

2008年11月7日星期五

File not found: ieframe.dll

When using Visual Basic 6 with Internet Explorer 7 installed, I encountered such a problem "File not found: c:\windows\system32\ieframe.dll\1" when loading a project.

Usually, the file does exist. Then why we get this problem? Well, the simplest answer is that some control referenced by your project has been replaced by ieframe.dll. I can not tell more since I am barely familiar with VB. Or to be frankly, I am neither not knowledgable of VB nor like it.

So the simplest way is to revert the reference from ieframe.dll to its ancestor. After google it, I find its ancestor is shdocvw.dll. It's in the same directory. Then register it:

regsvr32 c:\windows\system32\shdocvw.dll

Try to launch VB6.exe and load your project again, does the annoy error message disppear?

2008年11月5日星期三

pipe console program output to clipboard

I am making some demostration these days. I need run some console programs, get their output and put them into a nice slice as example. The trivial way is to redirect the output to a plain text file then open it, Ctrl+A to select all and copy, switch to PowerPoint, paste, which is exactly what I am doing.  Some days past, I feel I can't stand it anymore. A simple idea just jumped out of my mind, why not make a small tool the can read data from pipe and copy to clipboard? So I can do my jod like this(assume the program is called cmd2cb.exe):

dir|cmd2cb
type readme.txt|cmd2cb

thus, all output of dir command are read by cmd2cb and copy to clipboard. Then I simply switch to PowerPoint and Ctrl+V. Everything's done. Small tool, but cool!

When I share this tool to my colleages, it turns out that I am not the only one needs it.
So I decides to put it to my box. If you need, just download here. cmd2cb.exe (9k)
Chinese user can download from namipan(纳米盘): cmd2cb.exe (9k)

*This file can only be used in windows, console and after the pipe symbol and no warranty.
*If you're using Vista, you can use Clip.exe shipped with Vista.

2008年10月26日星期日

虬江路淘宝

自从我的磐正8RDA3G主板抽风之后,我的老电脑一直处于待业状态。我一直没有考虑好给它一个什么名份。上次为同事拍了结婚照之后,我觉得该有一台专门处理照片的机器了,我原先的配置基本不用动,只要换块主板,加个特丽珑的显示器就行了。我的CPU是Athlon XP1800+,搭配的主板可以用KT400,KT600和NF2芯片组。但我不想在上面投资太多,因此从一开始就打定主意要买二手的,花最小的代价,获得最大的利益。

原先想在pchome和pconline,taobao上面买的,但是每次都被人抢走了。于是只能瞄准上海滩最大的二手市场--虬江路。

买二手最重要是心态,就跟炒股一样。同时要做功课,认准自己要买的东西,任凭JS怎么忽悠你,都不能跟着他们走。

我在虬江路花了大概2个小时不到的时间,逛完了几乎所有的店,终于买到了一块成色非常新的工包微星K7N2主板,价格95块。可以说是非常超值。据老板说,这块板是全新的,工包批量出货拿的,我特意看了电容,散热片,PCI和AGP插槽,的确是没有用过。简直太超值了。


事实上整个虬江路NF2的主板也寥寥无几,我所有的店都兜了一下,加起来也不会超过30片。而且很多都是硕泰克,映泰之类的垃圾板子。我的原则是,二手的主板绝对不能买二流厂家的主板,要买只能买一线大厂的。为什么,因为那些二线厂家的主板寿命也就是2,3年。我的磐正主板就是活生生的例子。因此场子里面还有人推荐我磐正的,我说什么都不要。场子里面还有一块非常棒的ASUS的A7NX,可惜要150,从性价比来说不及我这块。

我这块板子是在赛格快关门前5分钟才掏到的,说来也算运气了。我之前几乎绝望了,因为场子里面基本都是754的板子了,462的板子在二手市场基本上也淘汰了。而我要的还是一线大场的NF2芯片的462主板,更是难上加难。不过我来买二手就是想买以前一手买不起的好东西的,比如可以算AGP的王者的1950PRO蓝宝石,当年2000多块的显卡,现在就布满灰尘躺在橱柜里面,罗技的蓝牙耳机之类的,这些东西看得我心痒啊。不过正事要紧,下次再来。

总的来说,在虬江路淘宝是很有意思的事情,我今年来已经很少关注硬件了,这次过去兜了一下,感觉自己还蛮喜欢这种事情的。与JS斗,其乐无穷啊。同时还能看到很多平时不知道的东西。比如我一直想买个激光打印机,全新的起码2K,而这里一个HP2015D才600;还有一套DIY的工具,包括网络工具,电工工具,都是进口的,质地看上去就不一样,开价80,感觉还行。另外就是我关注的特丽珑和钻石珑,居然让我看到一个EIZO的原膜T962,要知道这是EIZO旗舰机型,特丽珑超强色彩还原,比SONY的G520还高出一筹的极品啊。本来跟老板讲好了,可惜买好主板已经天黑,只能作罢。

2008年10月22日星期三

游戏不是这么玩的

我一向对时事很迟钝,特别是对于有微软,盗版,反黑等关键词的新闻,我从来都是略过的。但是现在我的同事已经开始用“今天你黑屏了没有?”来打招呼了,我再后知后觉也感觉到了一些不同。吗啡写了篇《整个民族心理有毛病》,仍旧秉承他一向的风格,语言尖锐,但是仔细想来的确是有道理。吗啡用的是一个IT行业从业者,受过高等教育,站在时代前端的身份来看待这件事的。而我,接触了很多不懂电脑的人,我想试着站在他们的立场上看看这件事的因果。

我在想,这件事是否是微软自食其果呢?或者是中国人自食其果呢?
在微软刚进入中国市场的时候,为了迅速扩大市场份额,他们默认了盗版的存在。反正你要用我的就成,只要不去用别人的,随你盗版还是正版。他打得好算盘,慢慢地用office 挤掉了WPS,IE挤掉了netscape,他或许想着,等到他一家独大的时候,还不是想怎么样就怎么样。他制定了这个游戏的规则。人们顺着他的规则玩了这么多年,突然,他改变规则了,那些玩游戏的还不跳起来!

当人们买电脑的时候,店里面的伙计帮他们装好了Windows,进去能看到五颜六色的界面。然后他们付钱走人。在他们付钱的时候,他们下意识的认为,这一堆铁疙瘩和里面五颜六色的界面都已经包括在他付的那点钱里面了。或许,很多人还不知道什么叫正版,什么叫盗版,版权对他们来说还是一个陌生而抽象的词语。只知道,要装软件,就去买盘。对他们来说,去街边买盘就和去菜场买菜一样。This is the way. 甚至很多人,连软件这个术语都不知道,他们可以叫出Word,IE,QQ,但是不知道这些就是软件,但这并不妨碍他们用电脑。其实美国人也这样,但是他们一开始就规定了一个正常秩序的游戏环境。

这就是这么多年来孕育出来的一种环境。这种环境的形成,政府和微软一样的领军软件企业难辞其咎。试想如果一开始,软件就是放在商店的橱窗里面出售,买电脑的时候装机店会明确告诉你价格不包含软件价格。久而久之,人们自然会习惯这样的模式。这种模式下,民众还是不用了解什么是盗版,什么是正版。有时候,你只要告诉别人,什么是对的,不用说什么是错的。这就是秩序,政府和大型软件企业在这时候就是强有力的秩序维护者。

别跟我说Windows太贵,买不起,三、四百的东西有时候还不及你一次拍拖花的钱呢。实在没钱,可以,用免费的操作系统,Linux, FreeBSD等。或许有人会说Linux,FreeBSD难用。我想说的是,这是因为在这样一个畸形的市场下面没法得到发展造成的。更何况,现在的Linux在可用性上面跟Windows相差也不多了。

或许,在这样一个环境中,不同的操作系统都能够发展起来,Windows, Linux大家各取所需,造成双赢的局面。为了构造一个独裁,垄断的环境,微软通过这种默认盗版的方式来打压其他对手,结果搬起石头砸自己的脚。政府默认这种畸形的市场不断扩大,最后不知道扼杀了多少创新成果。

有人说,就是因为盗版,中国的软件行业才能发展的这么快,我不敢苟同。我觉得正是因为盗版,中国的软件行业才发展的这么低层次,永远用别人的东西,为别人打工,我们促进了微软的发展,却限制了自己的发展。如同温水中的青蛙一样。

没必要指责那些骂微软的人,我们要骂就骂那些制定这个游戏规则的人吧。或者,像我一样,尽量离这个游戏远些。

PS: 吗啡骂那些不要脸的JS,我120%赞同。因为刚才看到有名人博客上写着“有理由相信,中国用户是全世界最热爱微软的用户”, 这句话就和“中国没有妓女”,“陈良宇没有贪污”一样可笑。

2008年10月16日星期四

Placement New的用法

在《C++中控制对象的创建》一文中,我曾经提到Placement New的一些用法。最近一段时间很碰巧用到了这个技术,因此有了更深刻的一些理解。

Placement New的原型很简单:


inline void* operator new (size_t t, void* p) {
return p;
}


可以看出,它仅仅就是返回传给他的那个指针地址,大小t不使用。
因此,我们一般先申请一块内存,然后用placement new在初始化一个对象。这里的初始化的意思就是先把那块内存映射成对象地址空间,然后再起始地址调用对象的构造函数。例如:


class Window
{
int width_, height_;
public:
....
Window(){}; // default ctor
Window(int w, int h){...}; // ctor with predefined height and width
}

void* p = (Window*)malloc(sizeof(Window));
Window* pWin = new(p) Window();
.... //use pWin
pWin->~Window();
free(p);

在上面的代码中,最后第二行很重要。一般来说,析构函数是当自动变量离开作用域时自动调用或者使用delete时调用。但是使用placement new时,不能在该对象上面使用delete操作,因此析构函数不会被自动调用。我们必须使用一种比较少见的方式——手动调用析构函数来释放在构造函数中获取的资源。

Placement new还常常用于对象数组的创建上。一般使用new[](读作array new)来创建对象数组的时候有一个缺点,就是只能调用其默认构造函数。这有时候非常不方便。

Window* pArrayWin = new Window[20]; //default ctor is called

但是使用placement new就可以让我们获得调用其他构造函数的能力。代码如下:

Window* pArrayWin = (Window*)(operator new(sizeof(Window)*20)); //
i = -1;
while( i <20){
Window* pTemp = new(&pArrayWin[i++])Window(i*i,i*i*i);
}


这里就可以使用Window类的另外一个构造函数了。在每一个Window类构造的时候就可以给其设置长和宽。
这里的Window类只有两个整型成员,这种情况下,可以不用调用其析构函数,直接delete分配的内存。因此用placement new来处理这种小型连续数据在某种程度上可以提高效率。

2008年10月11日星期六

The Big Bang Theory不太敬业

最近一直在看《The big bang theory》,因为风趣幽默,所以我反反复复的看了快第三遍了。但是今天看到一个场景,让我感觉有点失望,看看图中的包包。有没有看出来什么问题?

是的,太假了。连商标都在,宝宝里面这种鼓起来的样子一看就知道是放在商店里面展示用的,因此里面塞满了泡漠塑料,废报纸等。我估计是剧组资金不够,所以问旁边的商场借的吧,等演出结束就立刻送回去。看来美国经济大萧条已经影响很深了,连这样一个平常的包剧组都买不起了。但是我要说,这还是不太敬业,买不起就不要背包,拿演员自己的包也可以么,反正是生活喜剧。真不知道他们怎么想的。。。

2008年10月8日星期三

My VS2005 Color Scheme

我今天花了点时间改了改VS2005的配色和字体方案,把原来整体白色的效果改成了现在的灰暗的效果。主要原因是保护眼睛。白色虽然明快,对比度高,但是会反射所有的光线,而黑色则相反,可以保护程序员的视力,至少不会看着很吃力。不相信可以自己试一下,把液晶显示器的亮度调高,盯着看一段时间,然后再调暗,眼睛是不是轻松很多。

然后字体从原来的Courier New改成了现在Monaco,这个字体非常好看。也是网上很多人推荐的编程用字体。效果图如下:


我个人不太喜欢花里胡哨的配色,所以颜色看起来不是很鲜艳。这样的好处就是让眼睛少受刺激。颜色太多,眼睛受到的刺激也会增加,长时间盯着看反而会吃力。

我的配色方案如下:
Font: Monaco (size 10)
Background : RGB(25, 25, 25) Not completely black

Plain Text : White
Line Number: RGB(43, 145,175 )
Comment : RGB(135,206,235 ) bold
Identifier: RGB(207, 207, 207 ) bold
Keyword: RGB( 68, 68, 255 ) bold
Number: RGB( 0, 128, 128 ) bold
Preprocessor Keyword: RGB ( 175, 96, 255)
String: RGB(252, 71, 39) bold



在《Monospace/Fixed Width Programmer's Fonts》一文中,作者列出了他认为写程序用的字体,应该具备哪些条件:

  • Crisp clear characters.
  • Extended characterset.
  • Good use of whitespace.
  • 'l', '1' and 'i' are easily distinguished
  • '0', 'o' and 'O' are easily distinguished
  • forward quotes from back quotes are easily distinguished -prefer mirrored appearance
  • Clear punctuation characters, especially braces, parenthesis and brackets

简单的说,首先要清晰,然后才是美观。总的来说,我觉得还是有道理的。我以前一直使用Courier New就是因为这个字体很清晰,在VS2005中如果更改字体,那些加粗的都是等宽字体,也是写代码首选的字体。网上讨论的比较多的是三款字体,分别是Bitstream,Monaco,Consolas,分别是Linux,Mac,Windows三个平台上的代表字体。我选择了Monaco,这块字体乍看之下不怎么样,但是仔细看看还是很有味道的。有兴趣的朋友可以试试。

另外,这几个配色方案也是我比较推荐的:
Dark Visual Studio
Scott Hanselman's color scheme
Slimcode
Jeff Atwood

相关文章:
Programmer 最佳用字型 Monaco font
Best font for programming is...?