2005年8月27日星期六

“海顿”和古尔德

今天坐飞机回到广州。一路上一直在听古尔德弹的那三首“海顿”奏鸣曲,也不知这是我第几次重听她们了。昨晚没睡好,飞机上一直昏昏沉沉的。伴着古尔德的琴声,我脑中迷迷糊糊的出现了一个场景:古尔德坐在那他那把矮矮的椅子上,随随便便地穿了一件衬衫,弓着腰伏在钢琴上用手指敲击着键盘,嘴巴还不停地随着哼唱着。这无疑是标准的古尔德弹钢琴的姿态,但是当那时耳朵里响起第三第二乐章的那个忧伤淡淡的 e 小调时,我突然感到一阵难以言喻的快乐。

一是贝多芬写这几首奏鸣曲时不过才 25 岁左右,那时的他和 52 岁的他比起来确实太年轻了,而那时的作品和“锤子键”等晚期作品比起来同样是太稚嫩了。但是简单就是美,我认为,“海顿”胜就胜在她的天真,她的纯洁,她的洛可可。

二是我似乎又找到我喜欢古尔德的新的原因。在刚才那一幕里面,任何一个不认识他的人肯定会觉得这人的举动十分可笑,但这正是因为古尔德全身心地投入到钢琴中,完全忘记了外在的这个世界。其实,我觉得很少有人比古尔德更爱钢琴,更爱音乐。我们知道,平时晚上一时兴起,就要通过电话和朋友聊上几小时的音乐。古尔德一生未婚,对于他来说,可能钢琴的地位已经取代了那个可能的妻子。他对待钢琴演奏就像母亲对待婴儿一般疼爱。另一方面,古尔德是一个很孩子气的人,天真,淘气,任性,纯洁,这些特点我觉得他都有。对待他喜欢的曲子,比如这三首“海顿”奏鸣曲,他常常会弹得很慢,慢慢得享受,慢慢得陶醉,就像孩子们总喜欢在沙滩上多呆一会儿。而对待他不喜欢但又不得不演奏的曲子,他就像孩子一样任性,以最快的速度敷衍过去,就像我小时候对待不喜欢吃但大人们逼着吃的菜。我喜欢的就是古尔德那孩子般纯洁的对音乐的爱。

2005年8月25日星期四

变长文件管理器

这段时间做了一个变长文件管理器(类似 WinRAR,可以把多个文件装进一个文件)。原本是学校的作业,但是我也算是认真对待了的。做的过程中遇到了很多比较抽象的问题,解决过程中也确实领悟到不少有用的编程思想,看来计算机科学这玩意儿还是要多动手写才会有提高,光看书还是不够的。(程序源码和客户端放在后面,有兴趣可以去下载)

记录文件的格式类似于FAT文件系统,采用簇作为存储单位,这样比较方便对文件进行操作。虽然这次程序引入了读取参数配置,压缩文件这些原来没有涉及过的方面,但是最终还是就一个 exe。原本觉得应该把管理器的类库做成一个 DLL,供客户端来调用,但是尝试后还是发现要把所有类库用的 .h 文件倒入到客户端那边去,而我又习惯在 .h 写类的实现,所以太麻烦,只好作罢。看来以后还是要改一改编写习惯。

这次写的过程中遇到一个问题,至今也没有想到解决办法。我本想做一个类似数据库的结构,用 Struct 模拟表中的字段,Struct 的成员变量类型相当于字段类型。用链表模拟整个表,链表传入的模版就是之间声明的 Struct,这样一个链表就可以存储任意多个具有相同成员类型的数据了,在这一点上还是很像数据库的。问题是,一个数据库可以容纳任意多的表,并且每个表的结构可以不同,这一点如何用模版实现呢?最开始想到的还是用一个链表来模拟数据库,用链表来保存链表。但是这是不行的,因为模拟表的链表本身就是模版了,都具有不同的模版类型,而链表只能存储相同类型的数据。想来想去,只能用类似 .NET 中 ArrayList 的方法,把模拟表的链表转化成类似 Object 的基类,使其具有相同类型。

那么如何在 C++ 里面模拟“所有类型具有共同基类”呢?我想到的是自己写一个 Object 类:

class MyObject
{
void* dataPtr;
int size;
}

dataPtr 保存数据所在的内存地址,size 保存数据大小。装箱时,要同时传入数据本身和数据所占字节数。然后 Object 到内存中分配一个 size 大小的空间,保存数据,并记录内存地址;拆箱时,将 void* 转化成需要的类型的指针,返回值即可。

理论上要实现还是不难,但实际中这种转换很难办到。首先,C++ 对运行时动态类型转换支持并不好。比如,假设有 MyObject a = 1 ,如何实现 int b = a 呢?MyObject 怎么知道要把 void* 转换成 int* 呢?难道 int b = a.Convert(int) ,或者 int b = a.Convert("int") ?这些都不可能,C++ 不支持传入一个类型,更不可能根据字符串转换数据类型(C++ 之提供了一个动态获得类型的方法 type_id)。其次,C++ 中各种数据类型多种多样,很难只用一个 void* 一概而论。比如,要实现字符串 char* 怎么办?要实现 STL List 怎么办?

当然,要解决这些问题也不是绝对没有办法。如果 C++ 的标准就由我来制定,C++ 的所有代码就由我来写,那我完全可以自己写这个 Object,自己实现 Object 对所有类型的转换。可能有人会说,这根本不是一个办法的办法。其实,.NET 就做到了这一点,Java 就做到了这一点,我想关键还在于它们都是由一个公司开发出来的,语言的耦合度自然就比 C++ 大。耦合度大,语言确实失去了一定的自由度,但也确实更加方便。也是到现在,我才真正体会到 C# 原来是那么方便强大的一个语言。

现在再回想起初中时刚开始接触编程的那个时候,在看看现在的自己,发现自己确实在成长,曾经觉得要不可及的那些 C 语言代码,现在只是当作工具来用了。说来现在感觉自己又进入了一个新的高度,不再是原来的桌面应用程序,不再是 Flash 和 ASP,而是编译器,操作系统,文件系统,更多原理级的东西,更接近数学。当然,这也只是一个新的开始,在这条路上还有很长要去走,还有很多高度要去翻越。

变长文件管理器 RecordManager

假期结束

整个八月没有来写新的日志,总觉得有一些想记的东西,但又总是不知道从何下笔。

暑期的的生活还是那么有规律,我还是一个不喜欢外出的人。这个暑假其实也没干什么事,前半段用来上 TOEFL 了,后半段主要在做学校的数据结构作业。怎么说呢,其实这个假期觉得自己还是有一些新的认识,有一些改变,但是要具体说是什么又说不清了,总之,自己清楚。

请几天,在加拿大读书的表哥回来了,到我家来了 2 天。出去快 3 年了,感觉他还是老样子,应该有的性格和习惯都还在,不该有的东西还是没有。原本想在加拿大读书,接触的大多都是外国人,在兴趣爱好上和语言习惯上应该都会和以前不同了吧,结果他还是很流利、“很地道”的成都话,喜欢的除了上网聊天就是聚会结交。这些没什么不好,如果他不是这样我反而会认不出他了呢。但是从这里我发现,出国并不能从根本上改变一个人。

上次和 Alex 谈到这个问题的时候就觉得,其实现在很多人出国仅仅是赶时髦,随大流,绝大多数人对出国的目的并不明确,甚至抱有幻想。很多人认为出国留学就是为了移民,就认为出了国,成了老美,那我这一辈子,我的子子孙孙以后就可以享尽荣华富贵,就好像在国外就有金子等着中国人去捡,这一点我在新东方上课的时候就很有感受。是的,不可否认在国外,很多环境因素比国内要好,医疗,福利,人口,公共设施,等等。但是对于一个中国人来说,能不能融入别人的国家才是最重要的,文化差异,这不是一两天就可以消除的。其次,为什么会想国外就有金子等着中国人去捡呢?难道说我在国内都没有能力、找不到好工作,在国外还能去把别人踢开自己当老板?人在任何社会里受到的待遇都是公平的,就像在美国赚美元一样,赚的是美元,花的也是美元啊。我觉得,出国留学为的就是学习到更新更丰富的专业知识,是否留在国外,那得看当时情况。如果仅仅为出国而出国,那我是绝不愿意做的。

对了,前天得到一个 Gmail 帐号 crendking@gmail.com,不过还是不打算用,比较现在都两个邮箱了,够用了。最近 Google 炒的好像比较热,很多言论预测 Google 要取代 Microsoft 成为新一代的业界霸主。我倒不偏向哪一方,其实我对两家都比较喜欢的,只是我觉得 Microsoft 能走到今天这步绝对不是吹的,要扳倒它绝不是一天两天的事。愿两家各自走好吧。

明天就要回广州了,下一年的学习生活可能会非常紧张,总算现在已经是养足了精神。