晓明 的个人资料Garden of Lazy Cat照片日志列表更多 工具 帮助

日志


2月27日

再说在LaTeX中使用中文字体

  在刚开始学用LaTeX的时候,曾经花了相当大的精力去折腾中文字体。最近才发现,原来用XeTeX处理中文非常方便,不需要任何设置,就能够使用系统中安装的TrueType和OpenType字体。

  MikTeX2.7中已经集成了XeTeX 0.999.7,所以安装了MikTeX2.7之后,就已经有了XeTeX了。只需要在编译的时候,使用xetex代替tex;xelatex代替latex命令即可。下面就是一个简单的例子,将下面的代码以UTF-8编码方式保存成一个文本文件,命名为test.tex

\documentclass[12pt,a4paper]{article}
\usepackage{fontspec}
\usepackage{hyperref}
 
\setmainfont{SimSun}
\begin{document}
    \tableofcontents
    \newpage
    \section{宋体}
        测试简体字
    \section{细明体}
        \fontspec{PMingLiU}\selectfont 測試繁體字
\end{document}

  然后执行xelatex test两次,就可以生成带有中文书签的pdf文件了。包括CJK extB的字体都可以直接使用,非常方便。生成的pdf文件是内嵌字体的,而且可以直接copy。所以需要考虑所用的字体是否被授权可以嵌入pdf。

  XeTeX无法和CJK包一起使用,不过可以到ctex论坛上下载一个xeCJK包。xeCJK可以和XeTeX一起使用,这个包处理了诸如中文标点之类的问题,还支持分别设置中英文的默认字体,使用起来比较方便。

  文件中使用的字体名称,比如SimSun,PMingLiU等,可以用fc-list命令获得。在命令行窗口中执行fc-list可以看到所有能够检索到的字体,也可以后边跟上语言名称来缩小范围。比如我的机器上执行fc-list :lang=zh-cn命令查询简体中文的字体,结果如下:

STCaiyun,华文彩云:style=Regular
YouYuan,幼圆:style=Regular
STHupo,华文琥珀:style=Regular
FZYaoTi,方正姚体:style=Regular
NSimSun,新宋体:style=Regular
FangSong,仿宋:style=Regular,Normal,…
KaiTi,楷体:style=Regular,Normal,obyčejné,Standard,...
Microsoft YaHei,微软雅黑:style=Regular,Normal,obyčejné,…
SimSun,宋体:style=Regular
STFangsong,华文仿宋:style=Regular
STXinwei,华文新魏:style=Regular
Arial Unicode MS:style=Regular,Normal,obyčejné,Standard,…
STXingkai,华文行楷:style=Regular
STLiti,华文隶书:style=Regular
SimHei,黑体:style=Regular,Normal,…
Adobe Heiti Std R,Adobe Heiti Std,Adobe 黑体 Std,Adobe 黑体 Std R:style=Regular,R
STZhongsong,华文中宋:style=Regular
Microsoft YaHei,微软雅黑:style=Bold,Negreta,tučné,fed,Fett,…
FZShuTi,方正舒体:style=Regular
Adobe Song Std L,Adobe Song Std,Adobe 宋体 Std,Adobe 宋体 Std L:style=Regular,L
STXihei,华文细黑:style=Regular
LiSu,隶书:style=Regular
STKaiti,华文楷体:style=Regular

  同理查询繁体中文字体可以用fc-list :lang=zh-tw命令,查询日语字体可以用fc-list :lang=ja。

2月20日

万恶的IE!

  最近有这么一个需求:在浏览器中的一个能够显示HTML的输入框中,即时检测输入内容的变化以及字符数目。

  首先<input>和<textarea>被排除了,因为这两者只能显示纯文本。如果是HTML文本,就会被近乎原封不动[1]显示出来。那么就只能用<div contenteditable>这种东西来做了,然后问题就出现了。对于欧洲文字来说,这个没有问题,我只需要响应这个HTML element的onKeyPress和onKeyDown事件就可以处理绝大多数的情况。可是对于亚洲语言来说,因为有输入法的存在,这个问题就变得离奇地困难。因为通过onKeyPress和onKeyUp第一无法获知用户输入的是什么字符,第二无法获知长度,第三无法获知什么时候输入结束。

  于是决定响应DIV的onPropertyChange事件,结果发现在IE中居然没有反应。google之,说是IE的著名bug,拥有contenteditable=TRUE属性的element不会发出onPropertyChange和onChange事件。tnnd!

  于是乎,这个问题现在无解了……。


[1] textarea会很“聪明”地帮你去解释转义字符。比如<textarea>&gt;</textarea>会显示成>

11月8日

市场啊市场

  著名市场调查公司Canalys前天(11月6日)发布了08年3季度的全球智能手机出货量调查报告(原文见此)。其主要结论如下:

  • 2008年3季度全球智能手机出货量为39.9M部。
  • 美国市场出货量翻倍,但日本市场下降。
  • EMEA(欧洲,中东,亚洲)市场增长21%,其中中部欧洲和东部欧洲增长43%
  • Nokia依然为市场头羊,但份额被Apple和RIM吃掉不少。
  • 尽管排名被Apple超越,但微软的市场份额有所上涨。

 

  看来经济的萧条并不影响人们的手机消费。而Apple的增长是情理之中的。只不过523%的确是一个相当惊人的数字。微软去年还是第二,现在已经被Apple和RIM赶超了。

  抛开水果粉们宗教般的狂热,平心而论,iPhon的确是够酷够眩,而在欧美2代的签约价也相对来说更容易接受。Symbian和RIM也在努力推陈出新。比如Nokia的E71, 5800XM,还有Blackberry 8120, 以及最近热炒的Storm,都十足吸引我的眼球。

  反观微软的WM,最大的问题在于生产周期太长,其次便是易用性太差,和缺乏创新性的UI。像Dopod Touch以及Diamond,都是很不错的UI典范,相当值得微软去学习。在微软裹足不前的时候,竞争对手却花样百出,那么现在的市场结果是完全没有意外的。

8月11日

LaTeX菜鸟又学会一招

  以前都是用pdflatex来直接生成PDF文件。今天才知道,原来从dvi生成PDF是有好处的,虽然多了一个命令,需要用latex命令先生成dvi,然后再用dvipdfmx命令生成PDF。但是首先这样的PDF中的字符是可以正确copy的,其次是dvipdfmx可以正确使用TTF字体,生成的PDF更漂亮。

  以下边的测试代码为例:

  1 \documentclass{book}
  2 \usepackage{CJK}
  3 \begin{document}
  4 \begin{CJK*}{UTF8}{simsun}
  5 \CJKtilde
  6 \CJKindent
  7 测试
  8 \clearpage
  9 \end{CJK*}
 10 \end{document}

  下边是生成的PDF放大到1600%的效果。左边的是pdflatex直接生成的,右边的是latex+dvipdfmx生成的。
比较结果

  而前者copy出来是“KÕ”,后者则是正确的“测试”。

8月6日

本年度的Assembly夏季大会竞赛结果公布了.

  读书的时候超级喜欢看64K demo,崇拜到无可复加。虽然现在远不如当年那么喜欢技术了,不过看到竞赛结果还是很兴奋的去下载下来仔细膜拜了一下。我这里提供的下载地址是Assembly大会的官方网站,应该比较安全。

1. 4K intro
1st Nucleophile by: Portal Process & TBC 7598 pts. [下载地址]
2nd Stick Animation Engine 4000 by: Juippi & Trilkk 4531 pts. [下载地址]
3rd deep science by: fairlight 3575 pts. [下载地址]

2. 64K intro
1st panic room by: fairlight 10431 pts. [下载地址]
2nd Nebula by: SQNY 4306 pts. [下载地址]
3rd Incognito by: Traction 3683 pts. [下载地址]

3. Demo
1st Within Epsilon by: Pyrotech 5208 pts. [下载地址]
2nd Contre Jour by: PlayPsyCo 5141 pts. [下载地址]
3rd Deform by: Division 4511 pts. [下载地址]

7月23日

变态的##啊

  今天想写一个一个小工具类来作Profiler,来测我的一些代码的时间消耗。于是利用RAII,构造的时候记录时间,析构的时候再取一次时间,记录二者的差。代码大致看上去是这样的:


class MySomeLog
{
private:
    ...
public:
    MySomeLog( LPCSTR lpszFunc, int iCodeLine )
    {
        //record the begin time
    }

    ~MySomeLog()
    {
        //log (current time) - (begin time)
    }   
};

#define LogHere MySomeLog __obj##__LINE__( __FUNCTION__, __LINE__ )

 

  然后我调用的时候,差不多就是这样的:


int foo()
{
    ......
    {   
        LogHere;
        ......
    }
    ......

    return 0;   
}
 

  基本上这段代码工作的很好,我想要的东西都记录下来了。不过吃午饭的时候,突然意识到了一个问题,我的宏定义是有问题的。问题就在于,C++有规定, ## 两端的咚咚,不作为宏展开,该啥样就是啥样。(C++2003, 条款[16.3.3/2])。也就是说,如果我这个是这样的就傻眼了:


int foo()
{
    ......
    {   
        LogHere;
        ......
        LogHere;
    }
    ......

    return 0;   
}
 

  因为 LogHere 被展开为 MySomeLog __obj__LINE__ ( "foo", 1234 ) 而不是 MySomeLog __obj1234 ( "foo", 1234 ) 。这样的结果就是我重复声明了一个对象。尽管对于我的目的来说,不会出现这种调用,但是这的确是一个错误。因为我之所以把对象名加上 __LINE__ ,目的就是为了避免出现重名对象。

  其实 ## 的这个变态规定我是知道的,并且在面试中还问过被面试者…… -_-! 自己在写代码的时候,结果就糊里糊涂的忘记了。

  唔,谁能帮我解决这个问题,用一个宏去生成不重复名字的对象。想想这个问题还是有点伤脑筋的。

7月7日

LaTeX杂七杂八

  最近想写一些学习语言的笔记,考虑到乱七八糟的东西比较多,比如IPA,我又不会希腊语的输入法,用Word写起来太烦。于是决定用LaTeX来写。结果是遇到了不少稀奇古怪的问题,不过还好总算都解决掉了。把这些问题记在这里,以便自己或者别人以后查询。

  1. 希腊文的输入可以用babel包的greek,这个包真是相当不错,帮助文档很清晰明了。不过一开始就把我给郁闷住了,因为按照帮助文档里的做法,我还是没法输入抑扬音。按照帮助文档里说,用\textgreek{~h}就可以输出“”,可是不对,输出的是“ η”。这个问题把我搞的很抓狂。于是Google之,结果说用\ibygr输入古希腊语最方便。试用之,一头雾水,还不如原来的好用。只好接着Google,终于找到了答案,应该用\textgreek{\~h},这次就对了,是帮助文档写错了,唉唉。

  不过这个问题只解决了一半,当我输入带气符的抑扬音的时候,又出了两个问题问题。其一是\textgreek{>\~h}不对,出来的是“῏η”,而不是“”。另外一个是ι下标的问题。我用\textgreek{h|}能够出来正确的“”,但是我用\textgreek{\~h|}出来的不是“”,而是奇怪的“ῆι”。最后找到的解决方案是,用\char转义符就可以搞定了。好吧,总比没有强。好在有ι下标或者带气符的情况下同时发抑扬音的情况不是很多。-_-b

  2. 这个问题也很郁闷,之前从来没遇到过,就是只要写超过了一定的行数,CJK就抱错。这个很抓狂,错误信息是:

! Undefined control sequence.
\CJK@XXX ...endcsname {`#2}{`#3}\CJK@ignorespaces
\fi
l.43 \end{document}

  Google之,无果,只有寥寥几条问这个错误的,无人回答。尝试多次,均无法解决,最后只好悻悻放弃。今天突然想看看cjk-font这个包带的字体怎么样,于是仔细读了一下CJK包里的cjk.txt这个文档,发现这个问题赫然在列。 -_-! 原来是个well-known issue,解决问题的方法就是在\end{CJK}或者\end{CJK*}之前加入\newpage,\clearpage或者\cleardoublepage中的任一个,就可以解决问题。nnd,这个太坑人了。

  3. IPA,这个我用的tipa这个包,没有问题,相当相当好用。


我的一个代码小片段:

\documentclass{paper}
\usepackage[american,greek]{babel}
\usepackage{tipa}
\usepackage{CJKutf8}
\begin{document}
\newcommand{\bfg}[1]{\textbf{\textgreek{#1}}}
\selectlanguage{american}
\begin{CJK*}{UTF8}{simsun}
\CJKtilde
\paragraph{\textgreek{H h}} \textgreek{\char0170ta}},eta,拉丁转写为~e~。
\begin{enumerate}
\item \bfg{h} 发音为~\textipa{[E]}~,例~\textgreek{<'hlioc}~。
\item \bfg{h|} 发音同~\textgreek{h}~,例~\textgreek{tim\char0172}~。
\item \bfg{hu} 发音为~\textipa{[Ey]}~,例如~\textgreek{<h\char0220ron}~。
\end{enumerate}
\clearpage
\end{CJK*}
\end{document}

效果如下:
 example

5月29日

⿰⿱⿲⿳⿴⿵⿶⿷⿸⿹⿺⿻〾

这些字符好玩吧,喜欢做ASCII的人对这些字符肯定不陌生,好多漂亮的ASCII作品使用了这些字符中的一部分。不过我在这里可不是讲如何去做ASCII图案。虽然我偶尔也做,但是我的审美太差,从来都做不出来好看的。-_-b 要藏拙啊。

事实上这些符号被称为表意文字描述符,是用来描述表意文字(其实主要是汉语)字符的组成结构的。在Unicode标准中(4.1的chap 11,5.0的chap 12)详细描述了这些符号的用法。

描述符 Unicode码位 GB18030码位 功能含义

U+2FF0 A98A 左右结构
U+2FF1 A98B 上下结构
U+2FF2 A98C 左中右结构
U+2FF3 A98D 上中下结构
U+2FF4 A98E 全包围结构
U+2FF5 A98F 向下包围结构
U+2FF6 A990 向上包围结构
U+2FF7 A991 向右包围结构
U+2FF8 A992 向右下包围结构
U+2FF9 A993 向左下包围结构
U+2FFA A994 向右上包围结构
U+2FFB A995 嵌套结构
U+303E A989 相似而不等

这些符号在使用上就相当于一个运算操作符,不过是使用波兰表达式(Polish Notation)的方法,这样的好处是省略掉了括号,但是对于非IT业界的人来说,波兰表达式理解起来就有点别扭了。波兰表达式的基本概念是:第一,操作符放在操作对象的前边;第二,从操作对象开始计算,而不是操作符。比如:(1+2)*3 的波兰表达式就是:* + 1 2 3

我先举几个例子:

1. 从 = ⿰人人 这个含义就是从是“人”和“人”两个字符以左右结构组合。

2. 巫 = ⿻⿰人人工 根据波兰表达式的计算方法,这个相当于 (人⿰人)⿻工

3. 吴 = U303E吳 = U303E

嗯,我估计学过数据结构或者编译原理的人肯定能懂这个,没学过的还真不好说…… 再举一个稍微复杂点的例子,圝这个字怎么表示:

圝 = ⿴囗⿲糸言糸 这么写是因为汉字的笔顺是先外后内(当然囗要最后才封口,另外“囗”是个汉字,读wéi,就是“围"的古字),所以不写成⿴⿲糸言糸囗

现在明白这些字符的含义了吧,其实这些字符就是用来描述复杂字,或者码外字的。计算机无法输入的字就可以用这种方式来描述,再举一个例子:

 ,这个字是Unicode CJK ext-b的汉字,Unicode码位是U+25E16,没有支持CJK ext-b字体的话,就只能看到一个方框了。那么这个字用表意文字描述符描述就成了:

U25E16 = ⿳⺮鹵⿱⿶⿱曰口凵丨

再举一个Unicode未包含的字符,陕西著名的biangbiang面的biang字:

Biang = ⿺⿳穴⿲月⿱⿲糸言糸⿲長馬長刂心辶

好吧,我承认只有搞IT的人才会用这么复杂的方式来描述汉字……

5月21日

说说Windows里的常见字体

西文的字体大致可以分为衬线字体和无衬线字体两大类。之前我曾经在blog里推荐了李果正先生的一篇文章,里边对于衬线字体和无衬线字体的区别说的很清楚。中文字体有对应的区分方式,只不过在中文中称之为白体与黑体。衬线字体与白体因为在笔画的末端有修饰,并且笔画有粗细之分,容易区分出单个字符,所以适用于大篇幅的行文,比如书籍的正文。而无衬线字体和黑体笔画末端没有修饰,笔画基本上粗细一致,所以不适合于大篇幅的行文,但是由于其醒目,所以适合于作为标题或者需要着重突出的文字部分。

中文中的白体字与黑体字

中国传统的印刷字体都是白体字。在刻板印刷的时代,为了刻画的方便,汉字与木板的纹理是垂直的,这样汉字的横画因为与木纹平行,所以可以比较纤细;而竖划与木纹交叉,需要粗一些,以防止两侧木纹断裂处磨损严重而无法辨识。在横画的两端,仍然是出于避免因为磨损而漫灭不可识,要加上修饰。跟均中国传统书法的特点,这个修饰就是类似三角形的样子。在计算机中,常见的白体字有宋体(明体),仿宋,楷体等三大类。

宋体和明体是同一种字体,恰如其名,宋体起源于宋朝,但是在宋朝却并不流行。宋人较推崇颜欧柳三家,刻板时都要请名家手书底稿,所以“字大如钱,纸洁如玉”的宋版图书很少使用宋体。宋体因为间架固定,缺少变化,被讥讽为“匠体”。但是使用宋体字刻板成本低廉,所以一直没有失传,尤其是后来活字印刷开始流行后,宋体非常适合活字,所以在印刷品中所占比重越来越大了。明朝万历年间,宋体流传到了日本,被日本人称为“明朝体”,现在Windows中所带的日文字体MS Mincho就是这个名字。台湾最初的汉字照排系统从日本进口,所以在计算机领域,也依从日本的称谓,称之为明体。目前宋体是大陆,台湾,香港三地的标准印刷体。

宋体与新宋体 现在Windows XP中默认的简体中文字体为宋体,字体文件为simsun.ttc,这是一个字体集合,包含了宋体和新宋体。该字体由北京中易公司开发,在Windows XP中的版本为3.03,支持GBK字符集,2万多个汉字。在Windows Vista中的版本为5.0,支持Unicode CJK, CJK ext-A, CJK ext-B共计7万余汉字。CJK ext-B部分的汉字则单独保存为另一个字体文件simsunb.ttf。由于simsun字体缺乏hint信息,所以在过大或过小的字号下,都会出现笔画残缺等问题。由于这个原因,Vista中已经把简体中文默认字体改成了雅黑。而方正公司的宋体(18030超大字符集),常州华文公司的华文宋体则都没有这个问题。

细明体与新细明体 细明体是Windows XP中默认的繁体中文字体,字体文件为MingLiU.ttc,包含了细明体和新细明体。该字体由台湾的威锋数位(原名华康)开发,起初的版本只支持BIG-5字符(即没有简体中文字符),在后来的版本中支持Unicode CJK标准。同样在Vista下,CJK ext-B的字形放到了一个单独的字体文件MingLiUB.ttc中。新细明体和细明体的汉字部分是基本相同的,主要区别在于ASCII字符,新细明体更美观一些。Vista中繁体中文的默认字体为微软正黑。

仿宋体 仿宋体顾名思义,是从宋体演变出来的字体。有传说是秦桧发明,不知真伪。仿宋体吸收了楷体的一些特点,所以与宋体相比更类似手写体。Windows中的仿宋体文件名为simfang.ttf,XP及之前的版本只支持GB2312字符集。在中国大陆,仿宋体是公文的标准字体。

楷体 楷书一直以来是中国的标准手写字体。目前在台湾,使用楷体印刷也成为一种风尚,尤其是在学术文章和政府公文中。Windows中的简体中文楷体字体文件为simkai.ttf,也是中易公司开发的,XP及之前的版本只支持GB2312字符集。繁体中文楷体字体文件为KaiU.ttf,中文名称为标楷体,是威锋数位设计开发的。从Windows2000开始,标楷体支持Unicode。

黑体大致分为三类:传统黑体,圆体,以及综艺体。传统黑体的特点是笔画较粗,没有衬线;圆体的笔画端点以及转折点都比较圆滑;综艺体则是用直线,波浪线等代替部分笔画,富有动感。

传统黑体 Windows XP及之前的版本中,简体中文黑体使用中易公司的中易黑体,文件名为simhei.ttf,支持的字符集为GBK。在Vista中,除了中易黑体外,还提供了由方正设计开发的微软雅黑,文件名为msyh.ttf,支持的字符集为GBK。Vista繁体中文版本中则使用香港蒙纳(Monotype)设计开发的微软正黑,文件名为msjh.ttf。另外出于美观,Vista还为雅黑和正黑提供了加粗的字体,分别名为msyhbd.ttf和msjhbd.ttf。Microsoft Office中还带了个华文细黑,由常州华文公司设计开发,文件名为stxihei.ttf。Vista中的日文黑体字体为Meiryo,汉字部分由河野英一设计,西文和假名部分则由Bitstream和C&G两公司的创始人,字体大师Matthew Carter操刀。Meiryo中的hint做得非常出色,所以即使在小字号的情况下依然非常清晰(Meiryo中并没有像其它东亚字体那样为小字号嵌入点阵字型)。Meiryo的名字由此而来(日语中“明了”的发音)。

对于小字号来说,黑体要比宋体悦目,因此在Vista中,使用雅黑和正黑作为中文的默认字体,取代了原来的宋体。而苹果很早就使用华文细黑作为默认字体了。就我个人看,正黑设计的要比雅黑好看得多。而且雅黑由于hint作的不好,所以在小字号的时候能够看出很明显的大小不一致。

圆体 Windows中的圆体字主要是四通公司设计的幼圆,文件名为simyou.ttf,支持的字符集为GBK。

chn

西文中的衬线体和无衬线体

据石刻大师Edward M. Catich在其著作《Origin of the Serif》说,西文中的衬线字体来源于石刻,衬线有利于石工雕刻。衬线字体Serif一词源自荷兰语schreef,其含义为“笔迹”。而无衬线字体Sans Serif则是Sans(法语,=英语的without) + Serif。

西文的衬线体分为四类:Old Style,Transitional,Slab Serif,Modern。

旧体(Old Style):旧体的起源最早,也是最接近手写体的衬线体,线条比较纤细,粗细线不十分明显。一个很大的特点是衬线的方向并不是直的,看上去很有动感,比如字母t,j,i上端的衬线。旧体的代表字体是Garamond。Garamond是一大类旧体衬线字的名字,来源于法国铅字铸造师Claude Garamond。

过渡体(Transitional):过渡体的风格介于旧体和现代体之间,线条较粗,粗细线对比明显,但不如现代体那么明显。过渡体的代表字体是Times New Roman。Times New Roman是字体大师Stanley Morison为主的设计小组于1932年为英国泰晤士报所设计。Stanley非常喜爱古罗马的字体,所以在这个字体是吸收了很多罗马字体的元素,并称之为新罗马体。

粗衬线体(Slab Serif):顾名思义,粗衬线体的衬线和笔画粗细相同,和打字机有很深的渊源。粗衬线体中最出名的当数Courier。Courier本是上世纪50年代IBM为打字机设计的字体,但IBM并没有为Courier申请专利,结果Courier就成了打字机的行业标准了。Courier系列的字体由于是等宽字体,所以很适合于书写、阅读程序源代码。我现在使用的就是Windows中的Courier New。与fixedsys(无衬线)相比,Courier的可读性更高一些。

现代体(Modern):现代体强调竖画,衬线细长,装饰作用大于实用价值。Microsoft Office中的Bodoni MT就是一个典型的现代体字体。

西文的无衬线体也分为四类:Grotesque,Neo-Grotesque,Humanist和Geometric。早期的无衬线体都是大写字母,直到1835年,William Thorowgood才发明了第一套无衬线小写字母,当时印刷工人由于是第一次见到无衬线小写字母,觉得很怪异,于是称之为Grotesque(风格怪异)。之后公众对无衬线体仍然不太接受,直到1880年,Ferdinand Theinhardt为柏林普鲁士皇家科学院设计出Royal Grotesque字体,才标志着无衬线体被广泛接受。柏林普君主政体瓦解后,Royal Grotesque更名为Akzidenz Grotesk Condensed,即著名的AG系统。十九世纪初Morris Fuller Benton在American Type Founders工作期间设计了一系列的无衬线字体,称为哥特体(Gothic)。Gothic这个名字和Grotesque同样都有点歧视的味道,隐含的意思是说,这种字体来自于野蛮的哥特人,而不是文明的罗马人(Roman)。AG和Gothic对后来的无衬线字体影响颇为深远。

粗黑体(Grotesque):粗黑体的代表是Grotesque系列和Helvetica系列。Adobe曾设计了一系列的Helvetica字体。因为其价格昂贵,所以微软没有购买Helvetica系列的字体。

现实主义体(Neo-Grotesque):现实主义体的笔画平直,字宽变化小,因为其平实的特点,也被称为“无特点体(anonymous sans serif)”。其代表是Standard和Arial。Arial是Helvetica的派生字体,它的一个问题是大写的字母i与小写的字母L没有任何区别。

人文主义体(Humanist):人文体的笔画粗细变化较大,可读性强,是目前使用最广泛的无衬线体。Calibri,Lucida,Segoe,Frutiger都是人文主义体的代表。Vista中就使用Segoe UI作为西文界面的默认字体。Office 2007中西文的默认字体则是Calibri,之前则是Arial。

几何体(Geometric):几何体是利用几何构型来设计的一种字体,富有现代感。常见的几何体有Avant Garde和Century Gothic。

另外还有一些不太好分类的无衬线字体,常见的比如Tahoma和Verdana。这两个字体均为字体大师Matthew Carter为微软所设计。Verdana派生自Frutiger,于1996年出版,其名字由来是verdant + Ana。verdant代表西雅图(西雅图因其绿化程度高被称为翡翠之城),Ana则是当时微软字型部门经理Virginia Howlett女士的女儿的名字。Tahoma派生自Arial,也有人将其归入到人文主义体中,于1999年出版。Tahoma名字来源于华盛顿州第三大城市Tacoma,为印第安语,含义为“众水之母”。Tahoma比Arial丰满,且I与l很容易区分,所以用户很多。

ascii


主要参考资料:
[1] 维基百科(http://en.wikipedia.org
[2] [英]约翰·曼《改变西方世界的26个字母》 生活·读书·新知三联书店 ISBN: 9787108027450

3月30日

玩LaTeX - 配置中文字体

话说某日小芃芃问我什么排版软件好用,我脱口而出:LaTeX。不过结果是小芃芃装了之后觉得太难用,改投Microsoft Publisher门下了。汗啊....

我到是被自己钩起来玩LaTeX的兴趣了。主要的原因还是怕丢人,我自己都不会用,还敢大言不惭地推荐给别人用。要是被问起来某个相关问题,答不出来岂不是太糗? -_-b

不过话说回来了,我得冠冕点,得说我现在很喜欢这东西,想学学.... 于是某日跟小芃芃夸口说,我要去学LaTeX,回头用LaTeX作一个带双行夹批的脂本《红楼梦》出来。

这下子牛皮吹大了…… 遇到的第一个问题就是没法处理中文。我倒是知道网上有现成的解决方案,就是CTeX,不过这东西里边有不少违反版权的东西,比如WinEdt,比如Windows字体。想想就不爽,于是决定还是自己来搞好了。

貌似Windows下也没有别的选择,LaTeX只能安装MikTeX。其实这个发布版本挺好的,包管理也挺好用的,目前的稳定版本是2.7。不需要全部都装,缺少的包会在编译的过程中自动提示安装,所以只需要安装一个basic版本就好了。装好了之后,启动start->all programs->MiKTeX 2.7->Browse Packages,在name栏输入CJK,点击Filter,能够列出3个包来,我只安装了CJK,没有安装font和font utils.

现在的问题就是没有中文字体了,我还是决定选用SimSun,主要是这个用的最普遍。于是到网上找了如何加入ttf字体的说明,自己开始动手DIY。基本的步骤如下:

1. 生成TFM文件,创建如下目录%_MIKTEXROOT%\fonts\tfm\arphic\simsun,打开console,进入该目录,执行:
ttf2tfm c:\windows\fonts\simsun.ttc -P 3 -E 1 simsun@Unicode@
ttf2tfm c:\windows\fonts\simsun.ttc -s 0.25 -P 3 -E simsunsl@Unicode@

之所以这里我用了Unicode,而不是GB,是因为我觉得UTF8更方便一些,后来事实证明我的想法是正确的。

2. 修改%_MIKTEXROOT%\tex\latex\cjk\UTF8\c70song.fd,我的修改是这样的:

\DeclareFontFamily{C70}{song}{}
\DeclareFontShape{C70}{song}{m}{n}{<-> CJK * simsun}{}
\DeclareFontShape{C70}{song}{bx}{n}{<-> CJKb * simsun}{\CJKbold}
\endinput

3. 执行initexmf -u.

这样就搞定了,hoho,我真是冰雪聪明啊。不过考虑到我最初的目的是要用LaTeX来编辑古籍,所以SimSun还是有些不适合,于是从网上下载了李果正先生作的繁体中文包,这个也是UTF8的,恰好可以和我的SimSun字体混排在一起。^_^

测试的LaTeX代码如下:

\documentclass[12pt]{book}
\usepackage{CJK}
\begin{document}
\center
\begin
{CJK}{UTF8}{song}
\section*{在\,\LaTeX\,中使用中文}
\end{CJK}
\begin{CJK}{UTF8}{song}
这一行使用简体宋体\\
\end{CJK}
\begin{CJK}{UTF8}{cwmu}
這一行使用繁體明體\\
\end{CJK}
\begin{CJK}{UTF8}{cwku}
這一行使用繁體楷書\\
\end{CJK}
\begin{CJK}{UTF8}{cwfsu}
這一行使用繁體仿宋體\\
\end{CJK}
\begin{CJK}{UTF8}{cwhbu}
這一行使用繁體粗黑體\\
\end{CJK}
\begin{CJK}{UTF8}{cwyu}
這一行使用繁體圓體\\
\end{CJK}
\end{document}

pdflatex命令转换为PDF文件后,效果如图:

untitled

万里长征走完了第半步,接着努力学习。给自己加油!

3月11日

C/C++中的++与--

心情啊心情,今天开始恢复更新blog,唉唉。先从一个无聊的话题开始吧。

对++/--操作这个问题折腾最多的应该是计算机等级考试,无聊且没劲。:( 不过有些常识还是有必要知道的。

1. 前置运算返回l-value,而后置运算返回r-value。在逻辑上前置运算返回自身,而后置运算返回一个临时copy。(假设变量类型均为int
j = ++i; 等价i+=1; j = i;
j = i++; 相当int tmp = i; i+=1; j = tmp;
由l-value/r-value的定义可以得到下面这个表格:

合法 非法
++i = 5;
int* p = &(++i);
int& j = ++i;
i++ = 5;
int* p = &(i++);
int& j = i++;

2. 无论前置运算还是后置运算的,其操作数类型只能是l-value。结合上一条规则,可以知道:
int j = ++(++i);  //合法,(++i)结果是l-value
int j = (i++)++;  //非法,(i++)结果是r-value

3. ++的操作数可以是bool类型,--的操作数不可以是bool类型。对于bool类型的变量,无论其值为truefalse,执行++后,结果为true. 此规则不建议使用。

4. C/C++中规定,在一个表达式中,任一变量只能至多被改变一次,否则其行为未被定义,完全依赖于编译器的实现。
C++标准中举了一个例子:i = ++i + 1;  此表达式合法,但其的结果未定义(ill-form)。而 i = i + 1; 则是合理并且合法的表达式,因为i的值只被改变了一次。所以最好永远不要书写类似的代码,而好多无聊的面试、等级考试、三流教材最喜欢出这种问题了。

5. C/C++在分析语句的时候,token按最长匹配,而不考虑其是否合法。例如:
int k = i+++j;  //合法,解析结果是 i++ + j; 而不是i + ++j;
int m = i+++++j; //非法,解析结果是i++ ++ + j; 而不是 i++ + ++j; 尽管后者才是合法的表达式。(前者违反了上述第2条)

1月3日

可恶的GetDC()

  最近写了段代码去查询当前输入窗口中的字符高度,大致的样子是这样的:

LONG GetTextHeight( HWND hwnd )
{
    ASSERT( IsWindow( hwnd ) );
    TEXTMETRIC tm = {0};

    HDC hDC = GetDC( hwnd );
    if (hDC != NULL)
    {
        GetTextMetrics( hDC, &tm );
        ReleaseDC( hwnd, hDC );
    }

    return tm.tmHeight + tm.tmExternalLeading;
}

  可是结果有的时候正确,有的时候不正确。折腾了许久都没有搞定,最后还是在MSDN里找到了门道,在GetTextMetrics的文档中,Remark部分提到:

Note that GetDC returns an uninitialized DC, which has "System" (a bitmap font) as the default font; thus the need to select a font into the DC.

  顿时明白了自己什么地方搞错了,忘记了GetDC获取的其实是系统默认的DC,这样得到的TEXTMETRIC也是系统默认的。所以如果输入窗口用了系统的默认字体和字号,自然就是没有问题的,反之就不行了。于是把代码修改成这样,结果就正确了。

LONG GetTextHeight( HWND hwnd )
{
    ASSERT( IsWindow( hwnd ) );
    TEXTMETRIC tm = {0};

    HDC hDC = GetDC( hwnd );
    if (hDC != NULL)
    {
        HFONT hRealFont = (HFONT)SendMessage( hwnd, WM_GETFONT, NULL, NULL );
        if (hRealFont != NULL)
        {
            HFONT hOldFont = (HFONT)SelectObject( hDC, hRealFont );
            GetTextMetrics( hDC, &tm );
            SelectObject( hDC, hOldFont );
        }
        ReleaseDC( hwnd, hDC );
    }

    return tm.tmHeight + tm.tmExternalLeading;
}

  结论是:看MSDN的时候,一定要认真读Remark...

11月2日

邪恶的main函数

1. main可以递归么?

  C++2003,3.6.1/3条款说,程序里不要使用main。事实上,无论用VS2005还是GCC3.4.2,递归调用main,或者在某个函数中调用main都可以编译成功,就像这样,虽然这没啥意义.... (IOCCC的获奖作品倒是很多都用到了main的递归)

int main( int argc, char* argv[] )
{
  if (argc > 0)
  {
    cout<<argv[argc-1]<<endl;
    main( argc-1, argv );
  }
}

2. main可以重载么?

  C++2003,3.6.1/2条款说,main不可以重载。VS2005和GCC3.4.2都支持这个条款。不过在3.6.1/3条款中又说:main并非保留字。这样在命名空间里,或者类成员函数中,都可以声明叫main的函数。

namespace Myspace
{
  double main() { ... }
};
int main() { ... }

3. main不可以声明为inline或者static.

4. main函数的定义方式.

  main函数的返回值类型只能是int,不能是其他类型,包括void. 在C89中,如果不声明返回值类型,则编译器认为是int。但是不写和void是两回事儿,估计很多人是因为这个所以才认为main的返回值可以为void了。而在C99和C++中,这是不允许的。也就是说开发者必须声明函数的返回值类型。main函数的返回值是提供给OS使用的,OS通过返回值判断程序是否正确执行,0表示没有错误。这就是为什么必须使用int作为返回值类型的原因。

  在C++2003,3.6.1/2条款中说:“[main function] It shall have a return type of type int, but otherwise its type is implementation-defined.” 这句话相当猥琐,我第一次读的时候就把otherwise后边理解为main函数的返回值类型可以是implementation-defined的了。后来反复折腾,才明白原来这句话的含义是说,main函数的参数列表是implementation-defined的,而不是返回值类型。

  3.6.1/2条款中要求编译器必须支持以下两种定义:

int main() { /* ... */ }
int main(int argc, char* argv[]) { /* ... */ }

  C99则叙述更加精确,要求也支持等价定义。比如可以用char** argv代替char* argv[]

  void main() 在VS2005下可通过编译,在GCC3.4.2下编译失败。

  int main( double somePara ) 在VS2005和GCC3.4.2下均通过编译。不过这个声明委实没有任何意义。除非编译器的装载器对此有特定的含义。

3月22日

偶像的力量

  前一阵子参加一个很有趣的培训,快结束的时候,老师跟我们闲聊。越聊越高兴,于是就谈起来了IT界的牛牛们,老师很郁闷地发现,我们居然没有人听说过Grace Hopper。于是,他给我们留的家庭作业就是去了解Grace Hopper。

  我这个人一向比较八卦,最喜欢看名人的小道消息,于是很兴奋的完成了家庭作业。完成后才明白老师为什么那么遗憾,Grace在IT业界真的属于里程碑式的人物,从来没听说过她的确是我的错。

  现在开始八卦:

  1. 1943年Grace加入了海军,在Mark I, II, III上开发程序。她是当时Mark I上唯一个女程序员。

  2. 1945年9月9日,Mark II宕机了,原因是一只飞蛾死在了一只继电器中,造成了电路故障。最后15:45时,Hopper找到了那只飞蛾,用发夹把飞蛾夹了出来,并把这只飞蛾的尸体用胶布贴到了她的日志里。虽然之前就有用bug代表缺陷的用法,但是bug和debug这两个单词被广泛使用,则是从这件事儿而起。 同时这只可怜的蛾子被认为是计算机历史上第一个bug。

   3. Grace在50年代发明了第一个程序语言的编译器A-0。在此之前,程序员需要把程序手工转成01序列,打孔后交给计算机执行。Grace觉得可以有这么一种程序,把英语翻译成程序。当时她的同事都觉得这是天方夜谭,计算机只能处理数字。Grace对嘲讽她的人说了这么一句话,“It's always easier to ask forgiveness than it is to get permission.”。1952年,Grace成功地写出来了A-0,不仅支持英语还支持法语和德语。在之后地年代里,又升级成A-1, A-2... Thanks God. 要是没有编译器,我们程序员今天怎么活啊?

  4. 1959年Grace发明了COBOL语言。虽然现在已经很少有人熟悉COBOL,但是在商业应用领域COBOL还是有着不可替代的作用。而COBOL的Validation思想至今在计算机领域仍然被使用。

  5. Grace一生入伍三次。第一次是1943年入伍,1966年Grace年满60周岁,光荣退役,当时的军衔是中校。Grace退休之后,海军郁闷到渣,因为他们发现,老太太一走,好多东西都玩不转了,于是海军赶紧给Grace写信要求她复职。于是1967年,Grace又入伍了,主要作为顾问和培训新人,1971年又退役了。1972年,还是因为海军实在离不开她,Grace以66岁高龄又入伍了,1973年老太太升职为上校。1985年,Grace成为美国第一个女性海军少将,1986年,老太太年满80,终于第三次光荣退休了。

  6. 1934年Grace在26岁的时候获得了数学博士学位,在之后的岁月里,她一共获得了47个荣誉博士学位。

  7. 这是Grace给一位年轻后进颁发奖状的照片。看出来这位年轻人是谁了么?Knuth!

 

  永远不要以为女性不适合IT行业,Grace对于绝大部分从事IT行业的人来说都是一座难以逾越的高山!向偶像致敬!

2月8日

Wonderful 3D Online Treasure Books

  借用别人的一句话:Friggin' awesome!其实除了这句话,我还真不知道该如何评价这个3D电子书

  2007年1月30日,一项被称为Turning the Pages™的技术被发表,第二天,大英图书馆就推出了使用这个技术的在线电子书库。Turning the Pages™本质上是一个XBAP应用。XBAP是XAML Browser Application的缩写,是一种利用XAML技术构建Internet应用的技术。XAML是Vista引入的一种标记语言,可以用来定义文本、图象和控件的布局,与HTML相似,但是表达能力更为丰富。 在非Vista操作系统中,则需要安装.Net 3.0.

  这个在线电子书库主要内容是大英图书馆收藏的珍品孤本等,进入网站,第一本就是达芬奇著名的《阿蓝道抄本》(Codex Arundel)。整个系统界面简洁明了。

   我找了一本希伯来文的书,因为希伯来文是从右到左书写,所以和中国传统书籍类似,书页从左到右排列,这是扉页。

  这个电子书系统的一大特色是提供了文本信息,点击下边的“Text”按钮,会弹出一个Text窗口,内容是对电子书该章节的评价以及翻译。在Text按钮右边,还有一个Audio按钮,按下会听到语音讲解。

  书页可以根据需要进行放大缩小。

  翻动页面的时候,做得很有真实感。

 

  虽然说使用应用程序很容易做到这个效果,但是考虑到这是使用标记语言编写的浏览器应用,还是相当有震撼力的。我非常喜欢这个系统中的Text和Audio功能,很贴心,也很专业。操作起来也很简单明了。

  虽然现在XAML还褒贬不一,B/S结构的Rich应用(我不知道这个rich该怎么翻译)也刚刚起步,但是从现在的发展来看,让人感觉前途还不算那么黑暗。

1月17日

网络时代,我们该相信什么?

  一个名为《世界最罕见的七种花》的贴子在网上各大论坛被反复转载。里边列出的7种花为:火红郁金香,芹叶铁线,昙花,羊乳花,绿玫瑰,豹皮花,淡烟色郁金香。

  不知道原帖是怎么写的,我看到的版本都是把芹叶铁线莲写成芹叶铁线。这里边剩下三种我不清楚,但是芹叶铁线莲,昙花,羊乳花,豹皮花都不算罕见。芹叶铁线莲和羊乳在华北地区分布颇广。不知道这“最罕见”是根据什么标准评定出来的。

  类似的现象数见不鲜。在互联网高度发达的今天,人们最习惯的就是“外事不决问google,内事不决问baidu”。然而一个问题是,谁来保证互联网信息的正确性。转贴和剽窃是互联网上最流行两种信息传播方式,貌似区别只是是前者不是为了谋名谋利。绝大部分的转贴者和剽窃者只是原封不动地将某个信息从一个网站搬到另一个网站,大概在他们看来,并没有验证其正确性的义务。

  有很大一部分人习惯用网络搜索的结果多少作为验证正确性的手段,而这个方法是不可靠的。举例子说,用google和百度搜索“床第”和“床笫”,其结果如下:

    google:  床第-410,000条结果。床笫-83,700条结果。

    baidu: 床第-649,000条结果。床笫-106,000条结果。

  单从搜索引擎返回的结果来说,看起来仿佛“床第”才是对的。然而事实上“床笫”才是正确的。“笫”的含义是竹席,床笫泛指贴身的卧具,所以有“床笫之欢”,“床笫之私”等等说法。可见单看搜索引擎的结果多少是不太可靠的。

  前两天看到一篇贴子,是某专家评论红牛的,其中说“牛磺酸是人体必须氨基酸”。高中学生物的时候应该就会学到人体必须氨基酸只有8种,牛磺酸不参与蛋白质的和成,再重要也不会被归入必须氨基酸之内的。而在搜索引擎中搜索,与此专家相同意见的条目还是很多的。

  又及,百度知道和百度百科中很多条目是抄袭的维基百科。

11月29日

编程的毛病——C++之父访谈

    原文见:http://www.technologyreview.com/InfoTech/17831/

    翻译:jowtte@hotmail.com 11/29/2006

  在20世纪的80年代和90年代,Bjarne Stroustrup设计并实现了C++程序语言。C++普及了面向对象编程,同时也影响了包括Java在内的诸多的程序语言。
  C++仍然是“高级”原型计算机语言(保留了自然语言的特性),时至今日仍然有数以百万计的程序员在使用C++。在PC与Internet时代,C++编写出了众多的系统与应用程序。即使如此,C++仍然饱受争议,其主要原因一是臭名昭著地难学难用,一是Stroustrup的设计允许开发者为了自由而犯下严重的程序错误。
  在AT&T贝尔实验室做了多年研究员的Stroustrup,现在是休斯敦附近的德州农工大学(Texas A&M University)工程学部计算机科学教授。

  Technology Review: 为什么绝大多数的软件糟糕透顶?
  Bjarne Stroustrup: 有些软件无论用任何尺度衡量都是相当优秀。 想一想火星漫步者探测器,Google以及人类基因组计划。这就是高质量软件!15年前,大多数人,尤其是大多数专家,都会说上述例子简直就是异想天开。我们的技术文明依赖于软件,所以如果软件真的如同其糟糕的名声一样不堪的话,我们中的大多数人现在就应该作古了。
  另一方面,看看那些“平均水平”的代码段都会让我失声痛哭。软件结构骇人听闻,程序员压根就不会深思熟虑正确性、算法、数据结构以及可维护性。大多数人不会真正地去读代码,他们只是发现IE或者Windows挂了,他们的手机丢失来电,从报纸上读到了最新的病毒新闻,然后呢,他们开始打寒战。
  真正的问题是“我们”(我们软件开发人员)永远处于一种紧急状态,不放过任何一根救命稻草来完成工作。我们会创造很多小奇迹,这是通过试用并发现错误,过分使用暴力方式,以及许许多多的测试做到的。但是,尽管如此,这仍然远远不足。
  软件开发人员开始善于这种巧技,脱离开不可靠部分来搭建相对可靠的系统。障碍在于,我们通常并不确切知道是如何做到这一点的:一个系统只是“有那么一点儿进化”成为最低限度可以接受。我个人更倾向于了解一个系统何时可以运转,以及为什么它会运转。

  TR:我们怎么样来弥补现在的尴尬处境?
  BS:理论上讲,答案相当简单:给予软件开发者更好的教育,使用更加合适的设计方法,设计时考虑灵活性与持久。奖励那些正确,稳定,安全的系统。惩罚那些乱七八糟的东西。
  实际上这是不可能的。人们总是奖励那些第一个完成廉价且漏洞百出的软件的开发者。这是因为人们现在想要的是新奇的小玩意。他们不想要麻烦,不想学习与计算机交互的新方法,不想为了质量而花费额外的付出(除非这是事先就很明显的问题。但即使如此,仍然经常被刻意忽视)。如果用户行为没有发生真正的变化,软件提供商根本不希望变化。
  我们没法让时光暂停10年,以便来重新编写所有的程序,从咖啡机到金融系统。另一方面,虚度光阴是一件昂贵,危险,令人沮丧的事情。显著的提高是必须的,但这只能一步一步的来。而且提高必须是全方位的,一个单一的改变是不够的。
  一个问题是“理论壁垒”大行其道:太多的人们把某些东西当作能够医治百病的万灵丹。更好的设计方法能解决问题,更好的规范技术能解决问题,更好的程序语言能解决问题,更好的测试技术能解决问题,更好的操作系统能解决问题,更好的中间件基础架构能解决问题,更好的理解应用领域能解决问题,不一而足。例如,型论、基于模型开发、形式化方法无疑在某些领域可以提供显著的促进作用,但是如果把这些方法作为解决方案而排斥其它方法,在大规模的项目中是必然导致失败的。人们总是在推行他们知道的方法和他们看到确实生效的方法,要不然能怎么办呢?然而很少有人在技术上成熟到能够在需求与资源之间取得平衡。

  TR:程序员努力工作的回报是高效率的代码,这就是隐藏在C++背后的思想。贝尔实验室希望有这样一种语言,少数真正聪明的人可以用这种语言来为诸如电子开关系统(ESS)等低速计算机编写应用。今天,软件开发人员越来越多,计算机的速度越来越快。这有损于C++的观点么?
  BS:C++并不是特地为大型开关机设计的,而是为了林林总总的应用。贝尔实验室是这么一个地方,她拥有范围广阔到难以想象的有趣的项目,这些项目跨越各个范畴,基本上使用了所有总类的计算机和操作系统。但是有一点是肯定的,当时贝尔实验室的平均水平程序员(average programmer[1])比大多数人观念中的“平均水平程序员”更有才干,而且与绝大多数其它单位相比,贝尔实验室非常重视可靠性和性能(以这个顺序)的重要。
  在很多应用中,性能仍然是一个关键问题。这些应用中,我感兴趣的是:接口的敏感程度,应用的启动与关闭时间。现代计算机硬件的惊人性能被软件开发者牢牢压制,他们在过分详细的(软件)抽象层上边叠床架屋,添加了左一层右一层。看上去我们已经达到了硬件线性速度的极限,但是在很多情况下,我们从软件角度可以赢回若干个数量级的性能提高。
  有种说法,当平均水平软件开发者所接受的有效正式教育水平下降的时候,C++实际上就变成了非常的“专家友好(expert friendly)”。然而,因为某些人无法理解而修改程序语言并不是一个解决方案,应该使用不同类型的程序语言并且培养更多的专家。总是要有一些语言是为专家使用的,而C++就是其中的一员。

  TR:回顾一下,在设计C++的过程中,在程序员的效率、安全以及软件运行时效率可靠性上作出的取舍难道不是一个原则性错误么?
  BS:唔,我不认为我做过这种取舍。我想要的是优雅并有效的代码。有些时候我获得了。这种二分法(在效率和正确之间,效率与程序员时间之间,程序与高级之间,等等等等)纯粹是扯淡。
  我所做过的设计是这样的,C++首先要是一个系统级的编程语言:我希望能够编写设备驱动、嵌入式系统以及能够直接使用硬件的代码。其次,我希望对于设计工具来说,C++是一个好的语言。这除了对灵活性和性能有要求外,还能够表达出优雅的接口来。那时我的观点是:如果你想要做点儿高级的事儿,搭建完整的应用,你首先要去购买,编译,或者借用提供了适当抽象层的库。当人们使用C++有麻烦的时候,经常真正的问题是他们没有合适的库,或者他们不知道如何找到可用的库。
  其它的语言则尝试更直接地支持高级应用。
  这管用,但是这种支持是以特化作为代价的。以我个人来说,我不愿意设计一个只能做我想要的事的工具——我的目标是泛性。

  TR:你如何面对这种现象:C++被许多程序员广泛抨击的同时又被广泛使用?为什么C++如此成功?
  BS:俏皮点儿的回答是,世界上只有两种语言:一种是每个人都在抱怨的,一种是没有人用的。
  用“丑陋”的语言书写的有用的系统比用“漂亮”的语言写出来的更多,多很多。程序语言是用来搭建良好的系统,这里的“良好”可以用很多种途径来定义。我的简要定义是:正确,可维护,足够快。从美学角度(首要是这种语言必须有用)来说,语言必须允许现实世界的程序员简洁并以小额付出来表达现实世界的想法。
  C++成功的主要原因是它达到了它毫无野心的设计理念:C++可以直接有效地表达相当大范围的想法。C++并没有被设计成为了完美地解决某个特定问题或者去阻止人们做一些“不好”的事情。事实上,我把精力放在泛性和性能上。
  我确信对于每个不喜欢C++的程序员,总是会有一种语言让他喜欢。然而,我的一位朋友曾经参加一个会议,主要讲演者要求听众举手来回答两个问题。第一个是有多少人不喜欢C++,第二个是有多少人用C++写过程序。回答第一个问题的人数是回答第二个问题人数的两倍。对于你不知道的事情表示不喜欢,那么这就是一种偏见。同样的,反对者的声音永远比支持者高,态度永远比支持者坚定。这是因为理智的人们知道他们喜欢的事物是有瑕疵的。我想比起其它语言,我更了解C++的毛病,但是我也知道如何避免这些问题,如何利用C++的长处。
  当然,也不要指望那些败北于C++的语言的支持者能够对C++有多礼貌。软件开发没有那种程度的专业性质,尽管我希望最终会这样。科学在这方面是不同的,当一个新工具新技术,或者新理论胜出的时候,人们认为这是一种进步。在软件行业,竞争对手或者先辈作出的贡献并没有被广泛认知,感激,甚至理解。

  TR:在《C++语言的设计和演化》一书中,你声称Kierkegaard[2]是你的语言概念的影响因素之一。这是玩笑么?
  可能我有点儿自抬身价,不过这不是玩笑。许多关于软件开发的思考聚焦在小组,团队,公司上。这总是基于这个观点,个体被完全淹没在团体“文化”中,不考虑个体特有的才能和技能。团体实践可能对那些技能突出,对待技术主动的个体有着直接的恶劣影响。我认为对技术人群进行如此的管理是残忍且浪费的。Kierkegaard反对“扎堆”,是个体主义的坚定拥趸,他有一些关于美学与伦理行为重要性的严肃讨论。我没法指出某个特定的语言特性然后说:“看,这就是那个19世纪哲学家的影响结果”。但是我不愿意丢弃“专家级”特性,废除“误用”,以及限制一些特性使之只支持我认为有用的使用场景,Kierkegaard是这些概念的根源之一。尽管如此,我并不特别喜欢Kierkegaard的宗教哲学。

  TR:你最遗憾的是什么?
  BS:没有遗憾!唔,当然我梦想我能够做得不同,做得更好。但是严肃地说,我能对谁放马后炮呢?1984[3]年,那个处于丰产期的Bjarne?他可能比我经验少,但是绝对不会不如我聪明,甚至要更睿智一些,而且他对于1984年的世界比我了解得更好。C++已经被用来搭建了很多提高我们生活质量得系统,也对后来的语言与系统产生了很有意义的正面影响。这就是值得骄傲之处。

 

译注:

[1] average programmer见《Tao of Programming》一书,指介于wise programmer和foolish programmer之间的一类人。

[2] Kierkegaard是丹麦哲学家,全名Søron Aabye Kierkegaard,是一名虔诚的基督徒,强调个体的存在,反对教条主义。

[3] 1984年是C++从理论走向商业化重要的一年

9月27日

电话测谎

  韩国人正在研究提供一项技术可以分析打电话时的通话。一个功能叫做"Truthful Calls", 另一个功能叫"Love Detector"。简言之,前者是测谎,后者是分析“爱情有多深”。这个系统会每隔一个小的时间段分析一次,然后生成一个以时间为横轴的直方图以便观察结果。(相关新闻见这里)

  看起来这个功能非常有利于社会的和谐稳定。人们不需要绞尽脑汁来分析对方的言外之意,只需要简单的问问:“你是在说谎么?”,“你想要说的是xxx么?”就可以判断对方的目的了。

  谈恋爱的模式也会产生翻天覆地地变化,电话里大概最多的话是这个样子的:“老婆,你昨天对我的love level只有3.3,咱俩得好好谈谈了”……

9月20日

Unicode 5.0.0 Standard Released

  今天到Unicode官方网站上闲逛,无意中发现Unicode 5.0.0标准已经发布了,发布时间是8月26日。标准的实体书将在2007年一季度上市,在线的UCD(Unicode Character Database)则已经是最终的发布版本了。

  5.0.0没有带来惊喜。CJK Extension C仍然没有定稿,没有被包含到5.0.0的标准中。不过5.0.0支持以下这些编码规范的最新版本:大陆的GB18030,香港的HKSCS,日本的JIS X 0213。

  与4.1.0相比,5.0.0增加了1369个字符定义,一部分是对已有的字符集的补充,一部分是新添加的字符集。前者包括:西里尔字母(Cyrillic),希腊字母(Greek),希伯来字母(Hebrew),坎纳达字母(Kannada),拉丁字母(Latin),数学符号(math),音标扩展(phonetic extensions),符号(symbols)。后者则包含两种小语种字母:印尼的方言巴厘语字母(Balinese),非洲西部的一种方言字母N’Ko;以及三种已经消亡的书写系统:八思巴字母(Phags-pa),, 腓尼基字母(Phoenician)以及苏美尔-阿卡德楔形文字(Sumero-Akkadian Cuneiform)。

  这个表列出了Unicode 5.0.0的编码点情况:

字型 98,884
格式符 140
控制符 65
Private Use 137,468
Surrogate 2,048
非字符 66
保留字符 875,441

  对于简体中文用户来说,最重要的一点就是对GB18030最新版的支持。虽然GB18030设计得很屎,但是对于绝大多数人来说,编码标准是透明的,Usability才是最重要的事情。就是不知道我们日常用的OS们啥时候能支持Unicode 5.0.0的标准。

8月15日

Microsoft XNA

  微软宣布在本月底发布 Microsoft® XNA™ Game Studio Express的免费下载版本,这是一个很有意思的商业行为。
  XNA何许人也?其全称是Xbox/DirectX New Generation Architecture,即是一个在DirectX之上的游戏开发Framework。用户可以利用XNA Game Studio便捷开发Xbox的游戏,并且代码可以不经任何修改,只改变编译选项,便可以编译出Xbox 360或Windows Desktop的游戏来。
  根据Microsoft官方的说法,XNA Game Studio应该是集成到Visual Studio中,依赖于Visual Studio运行。Visual Studio 2005的debugger已经颇为人性化,相信微软也是考虑到这个因素。对于开发者来说,集成后不仅能够利用Visual Studio 2005的开发环境,也不需要花费时间去学习一种新的开发工具。
  之所以说这是个有意思的商业行为,是因为XNA的发布显然会刺激Xbox 360的消费。对于这种开放式的API,便捷的开发环境,统一的开发平台,肯定会吸引更多的公司和个人去开发更多的游戏。对于玩家来说,既可以有机会玩到更多更好的游戏,也可以尝试DIY,自己作游戏过把瘾。结果便是一个三赢的局面,当然XNA的质量如何尚不可知,还得拭目以待。