Akawa

ETY001的博客

上次的C++实验课第二个题,我一直在调试,今天终于搞出来了。下面我把整个过程写一写。
题目:

【题目2】编写程序,输入十个国家名称用字符指针数组实现排序输出。

【要求】
① 程序的功能是实现字符串的排序输出,例如,输入10个国家的名字分别是”China”,”USA”,”Australia”,”Austria”,”Brazil”,”Japan”,”England”,”Canada”,”Italy”,”France”,则排序后输出的结果为
“Australia”,”Austria”,”Brazil”,”Canada”,”China”,”England”,”France”,”Italy”,”Japan”,”USA”
② 设计一个独立的函数ccmp,实现相应的功能
③ 函数调用时,参数通过字符指针数组传递
【提示】
① ccmp函数可按如下方式定义:
void ccmp(char * a[]);;
其中,字符指针数组a中的指针分别指向10个国家的名称字符串
② 程序可用中的 strcmp(char *s1,char * s2) 函数对两个字符串的先后顺序进行判定,当s1<s2时,返回值<0,当s1=s2时,返回值=0 当s1>s2时,返回值>0

我写的成品代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<iostream>
#include<string.h>
using namespace std;
void ccmp(char *a[]);
int main()
{
int i=0;
char* num[10]; //申请一个指针数组
char a[][10]={"China","USA","Australia","Austria","Brazil","Japan","England","Canada","Italy","France"};//初始字符串

for(i=0;i<10;i++)num[i]=a[i];//把字符串数组发给一个指针数组

ccmp(num);

for(i=0;i<10;i++)cout<<num[i]<<endl;//输出结果

return 0;
}
void ccmp(char* a[])
{
char *temp;
for(int i=0;i<9;i++)
{
for(int j=0;j<9-i;j++)
{
if(strcmp(a[j],a[j+1])>0)
{
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
}

出现的第一个问题是,对于指针数组的理解刚开始有些模糊,不过现在已经算是明白了。先说一下什么是指针?指针就是一个存储地址的变量。比如说我们申请一个存储整型数据的空间来存储整数,那么这个空间的地址就是一个整型指针,申请方法如下:

1
2
3
4
//这里申请了一个整型指针,我习惯把*靠近int书写,这样更容易理解,这个下面会讲到
int* p;
int a=6;
p=&a;

上面这个小段程序,我们可以把变量a理解为一个小房子,这个小房子建设在内存里,而要找到这个房子需要有一个地址,这个地址就是平时我们所说的内存地址,而p也同样也是一个小房子,只是这个房子很特殊,只存储其他普通房子的地址,也就是变量a的地址。指针一直困惑人的地方就是p和p到底是什么意思?其实p在内存里面是没有空间的,也就是说p根本不是房子,p才是房子,就好比一把打开房门的钥匙,只有和p组合在一起成为p,才能读取出p中存放地址所指向空间内的内容(这里就是数字6)。那为什么申请普通变量的时候是int a;而申请指针变量的时候是int *p呢?这里a的地位难道和p不是一回事吗?很显然这不是一回事,但是就是这种书写导致了初学者的混淆,这也是为什么我习惯写成int* p;了,也就是说intint*不是一回事,而ap的地位是一样的,都是一个变量,只不过p只能用来存储地址。不知道我罗嗦这么多,大家是否看懂了,不过至少我现在明白了,嘿嘿~

那说完指针,就来看看指针数组。所谓的指针数组,就是一组变量每个变量都是用来并且只能用来存储地址的。在我写的那段程序中,用来存储全部字符串的数组a[][],第一维维数其实就是字符串的个数,第二维的维数即是每个字符串的最大字符个数。我出现的第一个错误就是在这里出现的。依照上面的分析,那么a[0]的值就是第一个字符串“China”的首字符的地址,如果用cout输出a[0]的话,得到的输出结果就是“China”,因此程序写出来的第一遍中没有那个num指针数组。我在第13行直接写的是 ccmp(a[]); 然后就是一系列的错误,后来发现不能这样写,而是应该把这些字符串的首字母的地址给一个指针数组,然后用这个指针数组进行传值。于是就有了num指针数组。但是在使用num时,又出现了很多错误,但是错误的本质都是相同的,都是出错在赋值运算上。也就是说从一个变量到另一个变量的赋值时出错,原因就是没有搞清楚你正在使用变量的类型,它里面存储的东西的类型,以及将要用来承接用的变量的类型和它能存储什么样的数据。前前后后调试了很多遍,把每一个变量的每种情形都搞明白了,这里的错误也就解决了。

第二个问题出在了strcmp()的使用上。最开始第26行,我写的是if(strcmp(a[j],a[j+1])),也就是没有那个”>0”。依照题目的意思只要a[j]>a[j+1],那么strcmp的返回值就是大于0的值,那么在if中就是真,但是运行的时候,排序就是不对。这里我插一句我是如何发现问题出现在这里的,下面的代码就是我的调试代码(只粘贴了ccmp函数),注意第8、11、12、13、17行的输出代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void ccmp(char* a[])
{
char *temp;
for(int i=0;i<9;i++)
{
for(int j=0;j<9-i;j++)
{
cout<<"wai:"<<strcmp(a[j],a[j+1])<<endl;
if(strcmp(a[j],a[j+1])>0)
{
cout<<strcmp(a[j],a[j+1])<<endl;
cout<<"a[j]"<<a[j]<<"::a[j+1]"<<a[j+1]<<endl;
cout<<j<<endl;
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
cout<<"a[j]"<<a[j]<<"::a[j+1]"<<a[j+1]<<endl;
}
}
}
}

最初的时候,我只是添加了第12行的代码,输出了每次循环体中的a[j]和a[j+1],观察结果发现i=0时的所有循环结果输出,“China”字符串一直在a[j]的位置,也就是说它一直都是被当作最大值的。为了验证想法,于是我又添加了第13和17行,又输出了一遍,我的判断被验证了,那么问题就出在了if的判断条件上了。我又添加第11行的代码,发现i=0时,这里输出的全是-1,然后我又添加了第9行代码,继续运行,结果使我很疑惑,因为我的概念搞混了。我在写程序的时候,想成了大于0的数代表真,小于等于0的数代表假。直到我开始写这篇文章了,我才反应过来,非0值都是真,只有0才是假(我为我自己学的不牢固感到悲哀啊……=_=)。问题找到,加上”>0”就解决了。

以上即为我的整个实验过程,希望对各位正在学习C的看客有所帮助吧。有理解不到位的地方,还请高人指点一二,小弟不胜感激~

前言:平时日记都是在我的人人网和QQ空间上发布,毕竟里面涉及点不想让所有人看的东西,但是今天这篇很中性,所以就晒出来在博客上,也为最近没啥更新的博客填充点东西。

今天从老蒋师哥的人人那里看到了一篇文章《程序员的十层楼》(www.domyself.me/archives/1237.html我已经转到我的博客里啦,哈哈)。看完后甚是无语,在别人眼里,大家都觉得我的电脑操作水平挺高,但是说实话,我一直不觉得是,尤其是看完这篇文章后,我终于找到了我现在的位置,不到一层的水平而已,而我希望能在40岁前达到第6层的水平,那我就已经很知足了~

今天下午上操作系统,又正好说到了这篇文章中提到过的一个人,迪杰斯特拉(Dijkstra),以及他的两个成就,信号量和PV操作。迪杰斯特拉1930年出生,如果我没记错的话,他是1956年左右提出pv操作和信号量概念的,也就是说,他在26岁就已经达到了第八层科学家的水平。我想这其中除了他可能是个天才,还有自己的努力外,跟学校的教育方法有很大的关系吧。想想我们从小到大接受的教育,那些是在教我们做什么,我不知道,我也不想多说。

另外今天路过创新工场网站的时候,又一次看了遍李开复写给大学生的信。首先,我要说,我每次看这个信的时候,总是很厌倦此人,我想原因就是因为人家的一系列成就自己做不到而眼红,正所谓“羡慕嫉妒恨”就是这样吧。其次,因为有厌倦和讨厌的情绪在里面,所以看他写的每句话总是很抵触,虽然知道这种心理很不健康,但是实在是克制不住,我觉得这个跟从小受到的中国教育应该脱离不了干系。这让我想起来《三傻大闹宝莱坞》中男主人公被virus强行带到课堂上给大家讲课时男一号所做的一切,每个人在听到任务后,想到的第一件事是竞争,而不是知识给我们带来的乐趣是什么,每个人的大脑都被“竞争”所绑架,然后压力就越来越大,进而心态就开始变化,最后就出现了“羡慕嫉妒恨”。

别的不想说,我只是感到我在大环境面前貌似只能选择去屈服,除非我后半辈子衣食住行无忧,也尽管我一直在提醒自己做自己喜欢做的事情,甚至我的博客域名都是domyself.me。

也许中国大学生可能是世界上最迷茫的一群人吧……

4月2号博客出现了未知的错误,导致一直无法访问。现在网站已经恢复正常了,但是数据是3月24号的,丢失了将近20条评论和几篇博文,遗憾啊……

自西方文艺复兴以来,中国在自然科学方面落后西方很多,软件领域也不例外。当然现在中国的许多程序员们对此可能有许多不同的意见,有些人认为中国的程序员水平远落后于西方,有些则认为中国的程序员个人能力并不比西方的程序员差,只是整个软件产业落后而已。
那么,到底中国的程序员水平比西方程序员水平差,还是中国有许多优秀的程序员达到或超过了西方程序员同等水平呢?要解决这个问题,必须先知道程序员有多少种技术层级,每个层级需要什么样的技术水平,然后再比较中国和西方在各个技术层级的人数,就可以知道到底有没有差距,差距有多大。
当然,对于如何划分程序员的技术层级,不同公司或不同人会有不同的划分标准,下面的划分仅代表个人的观点,如有不当之处,还请砸板砖予以纠正。

第1层  菜鸟

第1层楼属于地板层,迈进这层楼的门槛是很低的。基本上懂计算机的基本操作,了解计算机专业的一些基础知识,掌握一门基本的编程语言如C/C++,或者Java,或者JavaScript,…,均可入门迈进这层。
在这层上,中国有着绝对的优势,除了从计算机专业毕业的众多人数外,还有大量的通信、自动化、数学等相关专业的人士进入这一行,此外还有众多的其他专业转行的人士,人数绝对比西方多出甚多。并且还有一个优势就是我们这层人员的平均智商比西方肯定高。
没有多少人愿意一辈子做菜鸟,因为做”菜鸟”的滋味实在是不咋的,整天被老大们吆喝着去装装机器,搭建一下测试环境,或者对照着别人写好的测试用例做一些黑盒测试,好一点的可以被安排去写一点测试代码。当然如果运气”好”的话,碰到了国内的一些作坊式的公司,也有机会去写一些正式的代码。
所以,菜鸟们总是在努力学习,希望爬更高的一层楼去。

第2层 大虾

从第1层爬到第2层相对容易一些,以C/C++程序员为例,只要熟练掌握C/C++编程语言,掌握C标准库和常用的各种数据结构算法,掌握STL的基本实现和使用方法,掌握多线程编程基础知识,掌握一种开发环境,再对各种操作系统的API都去使用一下,搞网络编程的当然对socket编程要好好掌握一下,然后再学习一些面向对象的设计知识和设计模式等,学习一些测试、软件工程和质量控制的基本知识,大部分人经过2~3年的努力,都可以爬到第2层,晋升为”大虾”。
中国的”大虾”数量和”菜鸟”数量估计不会少多少,所以这层上仍然远领先于西方。
大虾们通常还是有些自知之明,知道自己只能实现一些简单的功能,做不了大的东西,有时候还会遇到一些疑难问题给卡住,所以他们对那些大牛级的人物通常是非常崇拜的,国外的如Robert C. Martin、Linus Torvalds,国内的如求伯君、王志东等通常是他们崇拜的对象。其中的有些人希望有一天也能达到这些大牛级人物的水平,所以他们继续往楼上爬去。

第3层 牛人

由于”大虾”们经常被一些疑难问题给卡住,所以有了”大虾”们只好继续学习,他们需要将原来所学的知识进一步熟练掌握,比如以熟练掌握C++编程语言为例,除了学一些基础性的C++书籍如《C++ Primer》,《Effective C++》,《Think in C++》,《Exception C++》等之外,更重要的是需要了解C++编译器的原理和实现机制,了解操作系统中的内部机制如内存管理、进程和线程的管理机制,了解处理器的基础知识和代码优化的方法,此外还需要更深入地学习更多的数据结构与算法,掌握更深入的测试和调试知识以及质量管理和控制方法,对各种设计方法有更好的理解等。
学习上面说的这些知识不是一挥而就的,不看个三五十本书并掌握它是做不到的。以数据结构算法来说,至少要看个5~10本这方面的著作;以软件设计来说,光懂结构化设计、面向对象设计和一些设计模式是不够的,还要了解软件架构设计、交互设计、面向方面的设计、面向使用的设计、面向数据结构算法的设计、情感化设计等,否则是很难进到这个楼层的。
当然除了上面说的知识外,大虾们还需要去学习各种经验和技巧。当然这点难不倒他们,现在出版的书籍众多,网络上的技术文章更是不胜数,然后再去各种专业论坛里泡一泡,把这些书籍和文章中的各种经验、技能、技巧掌握下来,再去学习一些知名的开源项目如Apache或Linux操作系统的源代码实现等。此时对付一般的疑难问题通常都不在话下,菜鸟和大虾们会觉得你很”牛”,你也就爬到了第3层,晋升为”牛人”了。
看了上面所讲的要求,可能有些大虾要晕过去了,成为牛人要学这么多东西啊!要求是不是太高了?其实要求一点也不高,这么点东西都掌握不了的话,怎么能让别人觉得你”牛”呢?
需要提一下的是,进入多核时代后,从第2层爬到第3层增加了一道多核编程的门槛。当然要迈过这道门槛并不难,已经有很多前辈高人迈进了这道门槛,只要循着他们的足迹前进就可以了。想迈进这道门槛者不妨去学习一下TBB开源项目的源代码(链接:http://www.threadingbuildingblocks.org/),然后上Intel的博客(http://softwareblogs-zho.intel.com/)和多核论坛(http://forum.csdn.net/Intel/IntelMulti-core/)去看看相关文章,再买上几本相关的书籍学习一下。
在国内, 一旦成为”牛人”,通常可以到许多知名的公司里去,运气好者可以挂上一个架构师的头衔,甚至挂上一个”首席架构师”或者”首席xx学家”的头衔也不足为奇。有不少爬到这层的人就以为到了楼顶了,可以眼睛往天上看了,开始目空一切起来,以为自己什么都可以做了,什么都懂了,经常在网络上乱砸板砖是这个群体的最好写照。由此也看出,国内的牛人数量仍然众多,远多于西方的牛人数量,在这层上仍然是领先的。
也有不少谦虚的”牛人”,知道自己现在还不到半桶水阶段。他们深知爬楼的游戏就像猴子上树一样,往下看是笑脸,往上看是屁股。为了多看笑脸,少看屁股,他们并没有在此停步不前,而是继续寻找到更上一层的楼梯,以便继续往上爬。

第4层 大牛

从第3层爬到第4层可不像上面说过的那几层一样容易,要成为大牛的话,你必须要能做牛人们做不了的事情,解决牛人们解决不了问题。比如牛人们通常都不懂写操作系统,不会写编译器,不懂得TCP/IP协议的底层实现,如果你有能力将其中的任何一个实现得象模象样的话,那么你就从牛人升级为”大牛”了。
当然,由于各个专业领域的差别,这里举操作系统、编译器、TCP/IP协议只是作为例子,并不代表成为”大牛”一定需要掌握这些知识,以时下热门的多核编程来说,如果你能比牛人们更深入地掌握其中的各种思想原理,能更加自如的运用,并有能力去实现一个象开源项目TBB库一样的东西,也可以成为”大牛”,又或者你能写出一个类似Apache一样的服务器,或者写出一个数据库,都可以成为”大牛”。
要成为”大牛”并不是一件简单的事情,需要付出比牛人们多得多的努力,一般来说,至少要看过200~400本左右的专业书籍并好好掌握它,除此之外,还得经常关注网络和期刊杂志上的各种最新信息。
当”牛人”晋升为”大牛”,让”牛人们”发现有比他们更牛的人时,对”牛人”们的心灵的震撼是可想而知的。由于牛人们的数量庞大,并且牛人对大虾和菜鸟阶层有言传身教的影响,所以大牛们通常能获得非常高的社会知名度,几乎可以用”引无数菜鸟、大虾、牛人竞折腰”来形容,看看前面提过的Linus Torvalds等大牛,应该知道此言不虚。
虽然成为”大牛”的条件看起来似乎很高似的,但是这层楼并不是很难爬的一层,只要通过一定的努力,素质不是很差,还是有许多”牛人”可以爬到这一层的。由此可知,”大牛”这个楼层的人数其实并不像想像的那么少,例如比尔·盖茨之类的人好像也是属于这一层的。
由于”大牛”这层的人数不少,所以也很难统计除到底是中国的”大牛”数量多还是西方的大牛数量多?我估计应该是个旗鼓相当的数量,或者中国的”大牛”们会更多一些。
看到这里,可能会有很多人会以为我在这里说瞎话,Linus Torvalds写出了著名的Linux操作系统,我国并没有人写出过类似的东西啊,我国的”大牛”怎么能和西方的比呢? 不知大家注意到没有,Linus Torvalds只是写出了一个”象模象样”的操作系统雏形,Linux后来真正发展成闻名全球的开源操作系统期间,完全是因为许多支持开源的商业公司如IBM等,派出了许多比Linus Torvalds更高楼层的幕后英雄在里面把它开发出来的。
可能有些菜鸟认为Linus Torvalds是程序员中的上帝,不妨说个小故事:
Linus,Richard Stallman和Don Knuth(高德纳)一同参加一个会议。
Linus 说:”上帝说我创造了世界上最优秀的操作系统。”
Richard Stallman自然不甘示弱地说:”上帝说我创造了世界上最好用的编译器。”
Don Knuth一脸疑惑的说:”等等,等等,我什么时候说过这些话?”
由此可以看出,Linus Torvalds的技术水平并不像想像中那么高,只是”牛人”和”大虾”觉得”大牛”比他们更牛吧了。在我国,有一些当时还处于”大虾”层的人物,也能写出介绍如何写操作系统的书,并且书写得非常出色,而且写出了一个有那么一点点象模象样的操作系统来。我想中国的”大牛”们是不会比西方差的,之所以没有人写出类似的商业产品来,完全是社会环境的原因,并不是技术能力达不到的原因。
“大牛”们之所以成为大牛,主要的原因是因为把”牛人”给盖了下去,并不是他们自己觉得如何牛。也许有很多菜鸟、大虾甚至牛人觉得”大牛”这层已经到顶了,但大多数”大牛”估计应该是有自知之明的,他们知道自己现在还没有爬到半山腰,也就勉强能算个半桶水的水平,其中有些爬到这层没有累趴下,仍然能量充沛,并且又有志者,还是会继续往更上一层楼爬的。
看到这里,也许有些菜鸟、大虾、牛人想不明白了,还有比”大牛”们更高的楼层,那会是什么样的楼层?下面就来看看第5层楼的奥妙。

第5层 专家

当大牛们真正动手做一个操作系统或者类似的其他软件时,他们就会发现自己的基本功仍然有很多的不足。以内存管理为例,如果直接抄袭Linux或者其他开源操作系统的内存管理算法,会被人看不起的,如果自动动手实现一个内存管理算法,他会发现现在有关内存管理方法的算法数量众多,自己并没有全部学过和实践过,不知道到底该用那种内存管理算法。
看到这里,可能有些人已经明白第5层楼的奥妙了,那就是需要做基础研究,当然在计算机里,最重要的就是”计算”二字,程序员要做基础研究,主要的内容就是研究非数值”计算”。
非数值计算可是一个非常庞大的领域,不仅时下热门的”多核计算”与”云计算”属于非数值计算范畴,就是软件需求、设计、测试、调试、评估、质量控制、软件工程等本质上也属于非数值计算的范畴,甚至芯片硬件设计也同样牵涉到非数值计算。如果你还没有真正领悟”计算”二字的含义,那么你就没有机会进到这层楼来。
可能有人仍然没有明白为什么比尔·盖茨被划在了大牛层,没有进到这层来。虽然比尔·盖茨大学未毕业,学历不够,但是家有藏书2万余册,进入软件这个行业比绝大部分人都早,撇开他的商业才能不谈,即使只看他的技术水平,也可以算得上是学富五车,顶上几个普通的计算机软件博士之和是没有问题的,比起Linus Torvalds之类的”大牛”们应该技高一筹才对,怎么还进不了这层楼呢?
非常遗憾的是,从Windows操作系统的实现来看,其对计算的理解是很肤浅的,如果把Google对计算方面的理解比做大学生,比尔·盖茨只能算做一个初中生,所以比尔·盖茨永远只能做个大牛人,成不了”专家”。
看到这里,也许国内的大牛们要高兴起来了,原来比尔·盖茨也只和我等在同一个层次,只要再升一层就可以超越比尔·盖茨了。不过爬到这层可没有从”牛人”升为”大牛”那么简单,人家比尔·盖茨都家有2万多册书,让你看个500~1000本以上的专业书籍并掌握好它应该要求不高吧。当然,这并不是主要的条件,更重要的是,需要到专业的学术站点去学习了,到ACM,IEEE,Elsevier,SpringerLink,SIAM等地方去下载论文应该成为你的定期功课,使用Google搜索引擎中的学术搜索更是应该成为你的日常必修课。此外,你还得经常关注是否有与你研究相关的开源项目冒出来,例如当听到有TBB这样针对多核的开源项目时,你应该第一时间到Google里输入”TBB”搜索一下,将其源代码下载下来好好研究一番,这样也许你的一只脚已经快迈进了这层楼的门槛。
当你象我上面说的那样去做了以后,随着时间的推移,总会有某天,你发现,在很多小的领域里,你已经学不到什么新东西了,所有最新出来的研究成果你几乎都知道。此时你会发现你比在做”牛人”和”大牛”时的水平不知高出了多少,但是你一点也”牛”不起来,因为你学的知识和思想都是别人提出来的,你自己并没有多少自己的知识和思想分享给别人,所以你还得继续往楼上爬才行。
我不知道国内的”专家”到底有多少,不过有一点可以肯定的是,如果把那些专门蒙大家的”砖家”也算上的话,我们的砖家比西方的要多得多。

第6层 学者

当”专家”们想继续往上一层楼爬时,他们几乎一眼就可以看到楼梯的入口,不过令他们吃惊的是,楼梯入口处竖了一道高高的门槛,上面写着”创新”二字。不幸的是,大多数人在爬到第5层楼时已经体能消耗过度,无力翻过这道门槛。
有少数体能充足者,可以轻易翻越这道门槛,但是并不意味着体力消耗过度者就无法翻越,因为你只是暂时还没有掌握恢复体能的方法而已,当掌握了恢复体能的方法,将体能恢复后,你就可以轻易地翻越这道门槛了。
怎么才能将体能恢复呢?我们的老祖宗”孔子”早就教导过我们”温故而知新”,在英文里,研究的单词是”research”,其前缀”re”和”search”分别是什么意思不用我解释吧。或许有些人觉得”温故而知新”和”research”有些抽象,不好理解,我再给打个简单的比方,比如你在爬一座高山,爬了半天,中途体力不支,怎么恢复体力呢?自然是休息一下,重新进食一些食物,体力很快就可以得到恢复。
由此可知,对体能消耗过度者,休息+重新进食通常是恢复体能的最佳选择。可惜的是,国内的老板们并不懂得这点,他们的公司里不仅连正常国家规定的休息时间都不给足,有些公司甚至有员工”过劳死”出现。所以国内能翻越”创新”这道门槛的人是”少之又少”,和西方比起来估计是数量级的差别。
再说说重新进食的问题,这个重新进食是有讲究的,需要进食一些基础性易消化的简单食物,不能进食山珍海味级的复杂食物,否则很难快速吸收。以查找为例,并不是去天天盯着那些复杂的查找结构和算法进行研究,你需要做的是将二分查找、哈希查找、普通二叉树查找等基础性的知识好好地复习几遍。
以哈希查找为例,首先你需要去将各种冲突解决方法如链式结构、二次哈希等编写一遍,再试试不同种类的哈希函数,然后还需要试试在硬盘中如何实现哈希查找,并考虑数据从硬盘读到内存后,如何组织硬盘中的数据才能快速地在内存中构建出哈希表来,…,这样你可能需要将一个哈希表写上十几个不同的版本,并比较各个版本的性能、功能方面的区别和适用范围。
总之,对任何一种简单的东西,你需要考虑各种各样的需求,以需求来驱动研究。最后你将各种最基础性的查找结构和算法都了然于胸后,或许某天你再看其他更复杂的查找算法,或者你在散步时,脑袋里灵光一现,突然间就发现了更好的方法,也就从专家晋升为”学者”了。
学者所做的事情,通常都是在前人的基础上,进行一些小的优化和改进,例如别人发明了链式基数排序的方法,你第1个发现使用一定的方法,可以用数组替代链表进行基数排序,性能还能得到进一步提高。
由于学者需要的只是一些小的优化改进,因此中国还是有一定数量的学者。不过和国外的数量比起来,估计少了一个数量级而已。
也许有人会觉得现在中国许多公司申请专利的数量达到甚至超过西方发达国家了,我们的学者数量应该不会比他们少多少。因此,有必要把专利和这里说的创新的区别解释一下。
所谓专利者,只要是以前没有的,新的东西,都可以申请专利;甚至是以前有的东西,你把他用到了一个新的领域的产品里去,也可以申请专利。比如你在房子里造一个水泥柱子,只要以前没有人就这件事申请专利,那么你就可以申请专利,并且下次你把水泥柱子挪一个位置,又可以申请一个新的专利;或者你在一个柜子上打上几个孔,下次又把孔的位置改一改,…,均可申请专利。
这层楼里所说的创新,是指学术层面的创新,是基础研究方面的创新,和专利的概念是完全不同的,难度也是完全不同的。你即使申请了一万个象那种打孔一类的专利,加起来也够不到这层楼里的一个创新。
当你爬到第6层楼时,你也许会有一种突破极限的快感,因为你终于把那道高高的写着”创新”二字的门槛给翻过去了,实现了”0”的突破。这时,你也许有一种”独上高楼,欲望尽天涯路”的感觉,但是很快你会发现看到的都是比较近的路,远处的路根本看不清楚。如果你还有足够的体力的话,你会想爬到更高一层的楼层去。

第7层 大师

从第6层楼爬到第7层楼,并没有多少捷径可走,主要看你有没有足够的能量。你如果能象Hoare一样设计出一个快速排序的算法;或者象Eugene W. Myers一样设计出了一个用编辑图的最短路径模型来解决diff问题的算法;或者象M.J.D. Powell一样提出了一个能够处理非线性规划问题的SQP方法;或者你发现基于比较的排序算法,它的复杂度下界为O(NLogN);或者你发现用栈可以将递归的算法变成非递归的;或者你设计出一个红黑树或者AVL树之类的查找结构;或者你设计出一个象C++或Java一样的语言;或者你发明了UML;…,你就爬到了第7层,晋升为”大师”了。
上面举的这些例子中,其中有些人站的楼层比这层高,这里只是为了形象说明而举例他们的某个成就。从上面列出的一些大师的贡献可以看出,成为大师必须要有较大的贡献。首先解决问题必须是比较重要的,其次你要比前辈们在某方面有一个较大的提高,或者你解决的是一个全新的以前没有解决过的问题;最重要的是,主要的思路和方法必须是你自己提供的,不再是在别人的思路基础上进行的优化和改进。
看了上面这些要求,如果能量不够的话,你也许会觉得有些困难,所以不是每个人都能成为”大师”的。中国软件业里能称得上是”大师”的人,用屈指可数来形容,估计是绰绰有余。值得一提得是,国外的”大师”就象我们的”大牛”一样满天飞的多。
我把我猜测本国有可能进到这层楼的大师列一下,以起个抛砖引玉的作用。汉王的”手写识别”技术由于是完全保密的,不知道它里面用了什么思想,原创思想占的比重有多少,因此不知道该把它划到这层楼还是更高一层楼去。原山东大学王小云教授破解DES和MD5算法时,用到的方法不知道是不是完全原创的,如果是的话也可进到这层楼来。
陈景润虽然没有彻底解决哥德巴赫猜想,但他在解决问题时所用的方法是创新的,因此也可以进到这层楼来。当然,如果能彻底解决哥德巴赫猜想,那么可以算到更高的楼层去。
求伯君和王志东等大牛们,他们在做WPS和表格处理之类的软件时,不知是否有较大的原创算法在里面,如果有的话就算我错把他们划到了大牛层。由于所学有限,不知道国内还有那些人能够得上”大师”的级别,或许有少量做研究的教授、院士们,可以达到这个级别,有知道的不妨回个帖子晾一晾。
鉴于”大师”这个称号的光环效应,相信有不少人梦想着成为”大师”。或许你看了前面举的一些大师的例子,你会觉得要成为大师非常困难。不妨说一下,现在有一条通往”大师”之路的捷径打开了,那就是多核计算领域,有大量的处女地等待大家去挖掘。
以前在单核时代开发的各种算法,现在都需要改写成并行的。数据结构与算法、图像处理、数值计算、操作系统、编译器、测试调试等各个领域,都存在大量的机会,可以让你进到这层楼来,甚至有可能让你进到更高一层楼去。

第8层 科学家

科学家向来都是一个神圣的称号,因此我把他放在了“大师”之上。要成为科学家,你的贡献必须超越大师,不妨随便举一些例子。
如果你象Dijkstra一样设计了ALGOL语言,提出了程序设计的三种基本结构:顺序、选择、循环,那么你可以爬到第8层楼来。顺便说一下,即使抛开这个成果,Dijkstra凭他的PV操作和信号量概念的提出,同样可以进到这层楼。
如果你象Don Knuth一样,是数据结构与算法这门学科的重要奠基者,你也可以进到这层楼来。当然,数据结构和算法这门学科不是某个人开创的,是许多大师和科学家集体开创的。
如果你象巴科斯一样发明了Fortran语言,并提出了巴科斯范式,对高级程序语言的发展起了重要作用,你也可以进到这层楼来。
或者你象Ken Thompson、Dennis Ritchie一样发明了Unix操作系统和功能强大、高效、灵活、表达力强的C语言,对操作系统理论和高级编程语言均作出重大贡献,那么你也可以进到这层楼来。
或者你有Frederick P. Brooks一样机会,可以去领导开发IBM的大型计算机System/360和OS/360操作系统,并在失败后反思总结,写出《人月神话》,对软件工程作出里程碑式的贡献,你也可以进到这层来。
或者你提出了面向对象设计的基本思想,或者你设计了互联网的TCP/IP协议,或者你象Steven A.Cook一样奠定NP完全性的理论基础,或者你象Frances Allen一样专注于并行计算来实现编译技术,在编译优化理论和技术取得基础性的成就,…,均可进入这层。
当然,如果你发明了C++语言或者Java语言,你进不到这层来,因为你用到的主要思想都是这层楼中的科学家提出的,你自己并没有没有多少原创思想在里面。
看了上面列出的科学家的成就,你会发现,要成为“科学家”,通常要开创一门分支学科,或者是这个分支学科的奠基者,或者在某个分支学科里作出里程碑式的重大贡献。如果做不到这些的话,那么你能象Andrew C. Yao(姚期智)一样在对计算理论的多个方向如伪随机数生成,密码学与通信复杂度等各个方向上作出重要贡献,成为集大成者,也可以进入这层楼。
成为“科学家”后,如果你有幸象Dijkstra一样,出现在一个非常重视科学的国度。当你去世时,你家乡满城的人都会自动地去为你送葬。不过如果不幸生错地方的话,能不挨“板砖”估计就算万幸了。
从上面随便举的一些例子中,你可能能猜到,西方科学家的数量是非常多的,于是你会想中国应该也有少量的科学家吧?我可以很负责任地告诉你一个不幸的结果,中国本土产生的科学家的数量为0。目前在国内,软件领域的唯一的科学家就是上面提过的姚期智,还是国外请回来的,并不是本土产生的。
可能你不同意我说的本土科学家数量为0的结论,因为你经常看到有许多公司里都有所谓“首席XX科学家”的头衔。我想说的是,这些所谓的“首席XX科学家”都是远远够不到这层楼的级别的,有些人的水平估计也就是一个“牛人”或“大牛”的级别,好一点的最多也就一个“学者”的级别。尤其是那些被称作“首席经X学家”的,基本上可以把称号改为“首席坑大家”。
虽然我国没有人能爬到这层楼上来,但是西方国家仍然有许多人爬到了比这层更高的楼上。如果要问我们比西方落后多少?那么可以简单地回答为:“落后了三层楼”。下面就来看看我们做梦都没有到过的更高一层楼的秘密。

第9层 大科学家

进入这层楼的门槛通常需要一些运气,比如某天有个苹果砸到你头上时,你碰巧发现了万有引力,那么你可以进到这层楼来。当然,万有引力几百年前就被人发现了,如果你现在到处嚷嚷着说你发现了万有引力,恐怕马上会有人打110,然后警察会把你送到不正常人类的聚集地去。因此,这里举万有引力的例子,只是说你要有类似的成就才能进到这层楼来。
牛顿发现万有引力定律开创了经典物理运动力学这门学科,如果你也能开创一门大的学科,那么你就从科学家晋升为“大科学家”。比如爱因斯坦创建了相对论,从一个小职员变成了大科学家。当然大科学家可远不止这两人,数学界里比物理学界更是多得多,如欧几里得创建了平面几何,笛卡尔开创解析几何,还有欧拉、高斯、莱布尼茨等数不清的人物,跟计算相关的大科学家则有图灵等人。
从上面列出的一些大科学家可以发现,他们的成就不仅是开创了一个大的学科,更重要的是他们的成就上升到了“公理”的层面。发现公理通常是需要一点运气的,如果你的运气不够好的话,另外还有一个笨办法也可以进到这层楼来,那就是成为集大成者。例如冯·诺伊曼,对数学的所有分支都非常了解,许多领域都有较大的贡献,即使撇开他对计算机的开创贡献,成为大科学家照样绰绰有余。
当然,程序员们最关心的是自己有没有机会变成大科学家。既然计算机这门大学科的开创性成果早就被冯·诺伊曼、图灵等人摘走了,那么程序员们是不是没有机会变成大科学家了呢?我们的古人说得好:“江山代有才人出,各领风骚数百年”,现在在计算机这门学科下面诞生了许多非常重要的大的分支,所以你还是有足够的机会进到这层楼的。
如果你能够彻底解决自然语言理解(机器翻译)这门学科中的核心问题, 或者你在人工智能或者机器视觉(图像识别)方面有突破性的发现,那么你同样可以轻易地晋升为“大科学家”。这样当某天你老了去世时,或许那天国人已经觉醒,你也能享受到如Dijkstra一样的待遇,有满城甚至全国的人去为你送葬。
现在还剩下另外一个大家感兴趣的问题没有讨论,那就是这层中已经出现了牛顿、爱因斯坦、高斯等我们平常人都认为是顶级的科学家,是不是这层已经是楼顶了呢?相信还记得本文标题的人应该知道现在仅仅是第9层,还有第10层没有到达呢。可能不少人现在要感到困惑了,难道还有人站在比牛顿、爱因斯坦、高斯等人更高的楼层上?
这个世界上确实存在可以用一只手的手指数得清的那么几个人,他们爬到了第10层楼上。因此,第10层楼不是虚构的,而是确实存在的。如果对此有疑惑或者认为我在胡诌一番的话,那么不妨继续往下看下去,窥一下第10层楼的秘密。

第10层 大哲

看了这层楼的名字“大哲”,可能不少人已经猜到了这层楼的秘密,那就是你的成果必须要上升到哲学的高度,你才有机会能进到这层来。
当然,上升到哲学高度只是一个必要条件,牛顿的万有引力似乎也上升到了哲学的高度,因为不知道引力到底是怎么来的,但是牛顿没有被划到这一层,因为进到这层还有另外的条件,那就是你的成果必须引起了哲学上的深度思考,并能让人们的世界观向前跨进一大步。窃以为牛顿、爱因斯坦等人的成就还达不到让人们世界观向前跨进一大步的程度。
所以,这层楼中的人的成就对我们普通人认识世界非常重要,你可以不学相对论,但是你不可以不对这层楼的人所作出的成就不了解,否则你的世界观就是极其不完整的,会犯许多认识上的错误。不幸的是,中国的科普知识普及还不够到位,知道这层楼成就的人好像并不多,程序员中恐怕更少。下面就来看看这些用一只手的手指数得清的大哲们,到底有什么成就,能比万有引力定律和相对论还重要。

1、希尔伯特 (1862~1943)

第1位进到此楼层是一位名叫“希尔伯特”的大数学家,如果你学过《泛函分析》,那么你在学习希尔伯特空间时可能已经对这位大数学家有所了解;如果你不是学数学出身的,又对数学史不感兴趣的话,恐怕你从来没有听说过这个名字。不过如果我问一下,知不知道二次世界大战前世界数学中心在那里,你肯定会有兴趣想知道。
不妨说一下,二战前整个世界的数学中心就在德国的哥廷根,而我们这位大数学家希尔伯特便是它的统帅和灵魂人物。即使在二战期间,希特勒和丘吉尔也有协定,德国不轰炸牛津和剑桥,作为回报,英国不轰炸海德堡和哥廷根。
整个二十世纪上半期的超一流数学家,几乎都出自其门下。这里不妨举几个我们熟悉的人物,例如冯·诺伊曼就曾受到他和他的学生施密特和外尔的思想影响,还到哥廷根大学任过希尔伯特的助手,钱学森的老师冯·卡门是在哥廷根取得博士学位的。顺便提一下,这位大数学家发现当时物理学上出了很多大的成果如相对论和量子力学,但是这些物理学家的数学功力明显不足,因此有一段时间带领他的学生们研究过物理学,并独立发现了广义相对论,只是不好意思和物理学家争功劳,将广义相对论的功劳全部让给了爱因斯坦。
广义相对论相对于这位大数学家在数学上的贡献,其实是算不了什么的,只是由此可看出这位大数学家品格的高尚之处。如果再去看看牛顿之流的人物的品行,整天和莱布尼茨、虎克等人争功劳,利用自己的优势地位打压他人,甚至闹得上法庭,和这位希尔伯特先生比起来,简直就是个小丑。
说到这里,你可能对这位大数学家“希尔伯特”有了一些初步映象,感觉到了他的重要性,不过他在数学上的主要成就可不是几句话说得清楚的。首先,他是一位集大成者,精通当时数学所有分支领域,在数学的各个领域都有较大的贡献,当然这些成就只能让他成为一个大科学家,不能带他进入这层楼。事实上这位“希尔伯特”解决的任何一个数学问题都够不到这层楼的高度,那么他怎么混到这层楼来了呢?
话得从1900年说起,当时还很年轻的希尔伯特在当时的世界数学大会上做了一个报告,高屋建瓯地提出了著名的23个未解决的数学问题,然后整个二十世纪上半期,全世界的数学家们都在这23个问题的指导下展开研究,直到现在仍然有许多数学家受这23个问题的指导在进行研究。例如我们熟知的哥德巴赫猜想,就属于其中第8个问题素数分布的一个子问题。
如果用“高瞻远瞩”来形容这位大数学家的话,那么这个世界上恐怕没有第二个人再配得上“高瞻远瞩”这四个字,不论是欧拉、高斯、牛顿、爱因斯坦还是被誉为最有才华的数学家伽罗华,概不例外。
虽然那23个问题是归纳总结出来的,并不全是原创,但是其中有不少问题是可以上升到哲学的高度,引起深度思考的。可能大多数人都会觉得希尔伯特是进不到这层楼的,我们知道提出问题的人和解决问题的人是一样伟大的,何况他提出的问题是如此之多,基于这点,个人觉得应该让希尔伯特跨进这层楼的门槛里。
看完这位希尔伯特的成就,你可能会觉得对你的世界观并没有产生任何影响。确实如此,他提出的问题不是用来影响你的,而是用来影响其他大科学家和大哲的,下面再来说说另一位对他提出的23个问题中的第2个问题有杰出贡献的大哲,你就会感觉到大哲们的成果的威力了。

2、哥德尔 (1906~1978)

这位大哲的名字叫“哥德尔 (G?del) ”,你可能从来也没有听说过这个名字,即使你读了一个数学系的博士学位,如果你的研究方向不和这位大哲对口的话,你也不一定了解这位大哲的成就,更不知道他的成果对我们这个世界有何意义。
简单地说,这位大哲20多岁时就证明了两个定理,一个叫做“哥德尔完全性定理”,另一个更重要的叫做“哥德尔不完全性定理”。你也许会觉得奇怪,第9层楼的成就就已经上升到了公理的高度,这种证明定理的事情不是学者和大师们做的事情吗?怎么能比第9层楼的成就还高呢?下面就来简单说一下这两个定理的含义,你就会明白这属于系统级的定理,绝不是普通的定理和公理所能比拟的。
“哥德尔完全性定理”证明了逻辑学的几条公理是完备的,即任何一个由这些公理所产生出的问题,在这个公理系统内可以判定它是真的还是假的,这个结论表明了我们人类所拥有的逻辑思维能力是完备的。这条定理并不能将其带入这层楼来,带其进入这层楼的是另一条定理。
“哥德尔不完全性定理”是在1930年证明的,它证明了现有数学的几条公理(ZF公理系统)是不完备的,即由这些公理产生出的问题,无法由这几条公理判断它是真的还是假的。例如希尔伯特23个问题中的第1个问题,也就是著名的康托尔连续统假设,哥德尔在1938年证明了现有公理系统中不能证明它是“假”的,科恩(Cohen,或许也可以称得上是“半”个大哲)在1963年证明了现有公理系统不能证明它是“真”的。最有趣的是,即使你将某个不可判定的问题,作为一条新的公理加入进去,所组成的新的公理系统仍然是不完备的,即你无法构造一个有限条公理的系统,让这个公理系统是完备的。
也许你仍然无法理解上面这段话的含义,不妨先说一下它对我们现实世界的影响。你可能知道1936年出现的图灵机是现代计算机的理论模型,如果没有哥德尔不完全性定理的思想,图灵机什么时候能出来是很难说的,所以这位哥德尔可以算作计算机理论的奠基者的奠基者。计算机对我们这个世界产生的影响比原子弹大了多少,我想不用我说大家也都清楚。当然,对现实世界的影响只能把哥德尔同图灵等人一样划到大科学家那一层去,能进入这层乃是另有原因。
可能你看过《未来战士》、《黑客帝国》、《I,Robot》之类的科幻电影,于是你产生制造一个和人一样或者比人更高一级的智能机器人的想法,这就引入了一个达到哲学高度的问题,“人到底能不能制造出具有和人一样的思维能力的机器来?”。
我只能告诉你,“你的愿望是良好的,但现实是残酷的”。如果你仔细思考一下不完全性定理的含义,并结合现代计算机所具有的能力分析一下,你会发现这个问题的答案暂时是否定的。如果你想造出和人一样思维能力的机器,那么你需要去好好学习这位大哲及其后续研究者的成果,并在他们的基础上有新的突破才行。
为了说明这位大哲所研究领域的重要性,这里顺便再讨论一个我们日常争议不休的问题,那就是孔夫子的“人之初、性本善”以及西方认为“人之初、性本恶”的观点孰优孰劣的问题。可能有许多人发现西方社会现在领先我们,于是就认为“性本恶”是对的,“性本善”是错的,中国应该抛弃以前的旧思想,改用西方的思想。当然也有一些老学究们,认为中国的人文思想是领先于西方的,自然而然地认为“性本善”是对的,“性本恶”是错的。
如果你学过大哲用过的公理化的分析方法,你就知道一套系统的多条公理间只要不会推导出矛盾的地方,即可以自圆其说,那么它可以看作是对的。这样你可以很轻易地给这个问题下一个结论,即“性本善”和“性本恶”是对等的,不存在孰优孰劣的问题,更不存在谁对谁错的问题。只要你不同时将“性本善”和“性本恶”放入一个系统内,那么是不会有问题的,甚至你也可以认为“人之初、既无善、亦无恶”,或者认为“人之初、部分善、部分恶”,都是可以自圆其说的,所以我们的老祖宗提出的思想并没有问题,之所以落后乃是其他原因造成的。这个问题其实在高斯所处的时代就有了结论,那时有人提出了非欧几何,即平行线公理问题,有人认为过一点可以作多条平行线,还有人认为平行线在无穷远点是相交的,和欧氏几何关于过一点只能作一条平行线的公理都是矛盾的,但是他们各自的系统内推导出的结论都是正确的。
上面说的只是对哥德尔不完全性定理的一些粗浅解析,实际上如果深入思考一下它的含义的话,你会发现它对物理学等许多学科有重大影响,包含的道理实在是深刻,远非一般的思想所能比拟,有兴趣者不妨“google”或“百度”一下“哥德尔”。或许只有我们的老祖宗“老子”提出的哲学思想,深度可以有得一比。
哥德尔不完全性定理也给那些认为科学是严谨的人当头一棒,原来连数学这样的纯理论学科都是不严谨的,其他学科就更不用说了。
至此,已经说完数学上的大哲,下面不妨再看看物理学上的大哲,物理学上好像只出过一位叫“海森堡”的大哲(注:由于本人对物理学不甚了解,不知道“霍金”够不够得上大哲的称号)。

3、海森堡 (1901~1976)

海森堡这个名字相信没有几个人不知道的,大部分人在学习物理时都学过他的“测不准关系”,也就是因为这个“测不准关系”,海森堡爬到了第十层楼。
如果你看过《时间简史》和《霍金讲演录-黑洞、婴儿宇宙及其他》,你也许已经了解测不准关系的威力,所以这里不想做过多的讨论,只谈一些和本土产生的哲学思想相关的东西。
首先看看争论了几千年,并且现在仍然有人在争论不休的“宿命论”问题。霍金认为,只要这个宇宙有一个初始状态,粒子的运动是按照一定物理定律进行的(比如相对论、量子力学属于这些物理定律的一部分),那么所有的粒子运动轨迹将是确定的,然后只要你承认唯物论,即精神是由物质决定的,那么宿命论就是“对”的。当然由于测不准关系的存在,对人而言,又是无法准确预测的,因此也可以将其看作是“不对”的。简单的说,可以认为宿命论是“对”的是绝对的,宿命论是“不对”的是相对的。
可能上面这段话你现在仍然难以理解,或许你又觉得你的命运并不是上天注定的,而是可以通过自己的努力可以改变的。我要告诉你的是,你在想什么也是事先已注定的,包括你在预测本身也是事先注定的,因为大脑思考问题最终是基本粒子运动的结果,而这些粒子的运动必然要遵循物理定律进行,所以你会不会努力,想不想努力,包括你在想你该不该努力这件事本身也是事先注定的。顺便说一下,你现在正在看这篇文章,可能正在想这个宿命论问题值得怀疑,或者觉得写得不够好,准备砸个板砖上来;或者你在想这篇问题写得有点意思,准备看完后转给朋友看一看;又或者你看到这里,觉得很累了,准备休息一下;…;这些都是上天事先就注定的。从你自身的相对角度看,因为你事先不知道后来会发生什么,也可以认为不是事先注定的,可能这句话有些不好理解,不妨好好理解前面说过的公理化思想。
如果你没看过《霍金讲演录-黑洞、婴儿宇宙及其他》,你可能会觉得很惊讶,宿命论历来不都被认为是唯心论吗,怎么由唯物论推导出了宿命论呢?现实就是这样和你开了一个大的玩笑,不过这个玩笑也是事先注定的。如果你再仔细用公理化的方法思考一下唯物论和唯心论的矛盾性,就像前面分析性善论和性恶论一样,你会发现唯物论、唯心论不一定就是冲突的,矛盾的双方是可以统一的,只要你不要同时将唯物和唯心放进同一个系统中就行。
当然也有聪明者仍然会怀疑宿命论问题的正确性,因为这里有一个前提条件,即宇宙要有一个初始状态。宇宙有没有初始状态,我们并不知道啊,虽然有大爆炸学说,但那也只是假说而已,并没有得到确证,有些人就认为宇宙是一直都存在的。这样看来似乎你又有合理的理由在怀疑宿命论了,不过我仍然要告诉你,你现在在怀疑宿命论仍然是事先注定的,不相信的话就来看看下面的分析。
虽然宇宙的初始状态值得怀疑,但是这个宇宙至少已经存在了一段时间,这点我想是毋庸置疑的。我们可以在我们已知的宇宙存在的这段时间内,任意取一个时间点t0,那么在这个时间点t0上,所有的粒子都有一个运动状态。在时间点t0之后的时间里,由于粒子运动是按照物理定律进行的,因此粒子运动轨迹由时间点t0的状态决定。说白一点,如果取100年前的一个时间点作为t0,那么现在的所有粒子运动状态100年前就已经确定了,如果取10000年前一个时间点作为t0,那么最近10000年内所有粒子运动的轨迹在10000年前就确定了,当然,你可以取更早的时间,比如100亿年前的时间点。
总之,现在你会发现宇宙有没有初始状态并不会影响宿命论的正确性,所以这个世界的一切都是注定的。只不过由于粒子间相互影响过于复杂,我们无法知道这些粒子的运动轨迹而已。当然,如果将测不准关系用上的话,那么就是这个运动轨迹对人来说是无法准确预测的,所以不妨开个玩笑:“算命先生经常算得不准大概是测不准关系的缘故吧”。
如果你再深入思考一下测不准关系,你会发现这是一个测量系统的问题。由于宿命论的存在,这个世界本身实际上是确定的,是“准“的,之所以测不准乃是我们人类所具有的测量能力依赖于基本粒子造成的。所以我在前面说宿命论是“不对”的是相对的,它是相对于我们人类的测量能力而言的。根岑(Gentzen,曾任希尔伯特的助手)在一个更强的系统内证明了ZF系统内的问题都是可判定的,从一个侧面说明这个世界本身是确定的。(注:它和哥德尔不完全性定理并不矛盾,由于数学上的复杂性,这里就不详细解释了)
不妨再想想我们老祖宗提出的“是庄周梦见了蝴蝶?还是蝴蝶梦见了庄周?”,“风动?幡动?还是心动?”之类的问题,当然以前你都认为这是纯粹的唯心主义,甚至认为是封建糟粕,但是如果结合测不准关系的内涵,再结合前面所说的公理化分析方法进行分析,估计你现在不敢轻易地下结论。
也许到现在你仍然无法理解为什么把大哲们划在了大科学家的上一层,你可能仍然觉得万有引力、相对论等成果是最伟大的。下面就来谈谈为什么大哲比大科学家高一层。
如果把人类在现有能力情况下,将来所能够拥有的知识总集看成是一个集合A,人类现在已有的知识总集看成是集合B,显然,集合B只是集合A的一个子集,并且是很小的一个子集。牛顿力学、相对论这些理论只能算作集合B里的一个子集,相对于集合A,只能算作是沧海一粟。 换句话说,在人类现有能力可做的事情集合中,牛顿力学和相对论等理论给出了详细的办法让你可以做其中的一些事情,当然剩下的更多的事情是牛顿力学和相对论所无法解决的。
哥德尔不完全性定理和测不准关系的意义在于,它指出集合A的范围,即将人类现有能力发挥到极限的情况下,那些事情是你能做到的,那些是你不能做到的。当然,它并没有给出具体的方法让你去做你能做到的事情,它只是告诉我们我们人类现在发现的能力所能达到的极限。或许将来发现人类有其他新的未发现的能力,那么这个极限就被打破了。比如将来能发现不依赖于基本粒子的其他测量方法,并且测量过程中不会改变其他粒子的状态,那么测不准关系就被打破了。
看到这里,估计你已经发现了一些秘密,科学兜了一大圈,最终还是回到了哲学,也就是我们所认为的玄学上。同时你也会发现,我们老祖宗提出的所谓玄学,原来和现代科学是相通的,并非象某些人想像的那样全是糟粕。如果有人认为西方现代暂时领先我们,进而就认为西方古代就已经超越我们,我们老祖宗就已经落后西方,他们的思想都是糟粕的话,那么我认为他可能犯了崇洋媚外的毛病。我不得不化用一句周杰伦在春晚上的歌词送给他:“你不妨抓一副我们祖传的中医良方,治一治你那崇洋媚外的内伤”。顺便告诉他一下,中医用的阴阳五行理论,它的前提假设就是宿命论。
上面说的这几位大哲的成果,可能对你的世界观会有很大的影响,于是你可能会羡慕起这些大哲们的成果来。如果你有大志的话,你会希望有朝一日你也能变成大哲,但是你发现上面的大哲是研究数学和物理学的,而你是学计算机的程序员,那么是不是没有机会变成大哲呢?
如果你能将NP难题给彻底解决掉,意味着计算机内的计算的奥秘基本被揭开,或许你可以进到这层楼来;或者你能发现另外一套计算机可以理解的数学公理系统,并且这个公理系统是完备的,那么计算机取代人类进行思维的一个必要条件就满足了,计算机将具有真正意义上的“逻辑思维和推理能力”,你可以轻松地进到这层楼来。如果你发现了新的方法可以打破测不准关系,同样你也可以轻松地进到这层楼来。
如果你能彻底揭开人类抽象思维的奥妙,并让计算机懂得了如何创建抽象,具备抽象思维能力,那么也就具备了“设计能力”,可以取代人类进行各种设计了,你也可以轻松地进到这层楼来。顺便说一下,如果你对软件设计有真正深刻理解的话,就会明白这不是在写科幻小说。对此感兴趣者,不妨好好地研究一下程序切片方面的技术,会让你对软件设计和测试等方面的理解有质的提高,或许有一天你能打开这扇大门。
当然,计算机要完全取代人还有其他必要条件,后面还会提及。
值得一提的是,虽然第10层楼是本文中所写的最高层,但是大哲们并没有觉得他们到了顶层,他们通常都还会努力寻找通往更高一层的楼梯。如果你也有成为天下第一的想法,那么你或许会想要做什么事情才能超越大哲们的成就,当然,这都得依赖于找到更高一层楼的楼梯。
个人认为,再往上一层楼的楼梯是通往天堂的道路,也就是说第11层楼的名字叫“天堂”,是“上帝”住的地方,而不是人住的地方。如果将来某天有人能爬到天堂的话,那么他已经不是人了,而是由人变成了“上帝”。
你也许会怀疑这个世界到底有没有“天堂”,“上帝”是否根本就不存在,我也很有同感。因此有必要再写上一段文字,讨论一下“上帝”的问题。如果你想了解天堂的奥妙,有没有办法让你变成“上帝”,不妨看看继续往下看看第11层楼的玄妙。注意我这里用的是“玄妙”二字,因为上帝在大部分人眼里估计都是“玄之又玄”的东西。

第11层 上帝

看了上面的小标题,你可能会觉得奇怪,这篇文章不是讲“程序员的十层楼”吗?怎么冒出了第11层来了?
其实这并不矛盾,程序员确实只有十层楼,因为爬到第11层时,已经变成上帝,不再是程序员了;所以超出10层楼本身并不重要,关键的问题是看你有没有能力变成上帝。

1、谁是上帝?

菜鸟们认为Linus Torvalds是程序员中的上帝,看完了前面各层楼的介绍,此时再看到这句话,相信你要忍不住在心里笑起来。当然,你会不会笑起来是事先注定的。Don Knuth也不是上帝,他离上帝还有三层楼的距离。即使是大哲们,他们离天堂也还差一层楼,因此这个世界上有史以来还没有任何一个人变成过上帝。
我们感兴趣的是,将来会不会有人爬到比大哲们更高的楼层上,变成了上帝。
要变成上帝,你得有上帝一样的能力,上帝会造人,你会吗?
你也许会怯生生地问:“我可以和爱人生小孩,算不算造人?”,你可能还会理直气壮地说:“现在生物学上都可以克隆人了,早就有人掌握了造人的方法”。
事实上克隆人需要有人的体细胞,必须要先有人才会有体细胞。上帝造人时,这个世界上并没有人,是从无生命的物质“尘土”中创造出的人。因此,用最原始的方法生人和克隆人都是从有生命信息的物质中生人,不能算作造人。
这样看来,你根本不会造人,不过我可以告诉你一个“玄方”,让你有机会学会如何造人。
如果你揭开了人类情感的奥秘,让计算机也可以拥有和人类一样的情感,那么计算机将可以理解人类的需求,具有了“情商”,将具有完整的和人一样的能力。此时,人类进化到了机器人,科幻小说将变成现实,也就是说你已经掌握了真正的造人能力,晋升为“上帝”了。
未来到底有没有人能变成“上帝”,人能不能进化到机器人,这是宿命论中事先注定了的。说到这里,不妨再告诉你一个打破宿命论的方法,这个方法就是你要爬到比上帝还要高的楼层。
“还有比上帝还高的楼层?”,你可能会第1时间内冒出这个问题,其实我也有同样的怀疑。因此在写第12层楼前,有必要弄清楚它到底存不存在,即你可不可以骑到上帝的头上的问题。

  1. 骑到上帝的头上?

为了解决是否可以骑到上帝的头上这个问题,不妨先假设存在比上帝高的楼层,也就是存在打破宿命论的方法。
宿命论的本质原因是因为时间是单向运行,不可逆转造成的。如果你找到一种可以使时间逆转的方法,那么你就打破了宿命论,爬到了比上帝还高的楼层。
看到这里,你也许会摆脱刚才陷于宿命论的困惑情绪,变得充满希望般高兴起来。不过,如果你的逻辑思维能力足够好,仔细思考一下,会发现存在一个逻辑上的悖论。
在你找到时间逆转的方法之前,显然这个世界仍然是需要服从宿命论的,也就是说你能不能找到打破宿命论的方法是事先注定的。假设你在某个时间点t0处找到了打破宿命论的方法,你在打破宿命论后,想利用时间逆转的方法回到某个时间点t2。下面来看看你到底能不能回到时间点t2。
取位于t0和t2之间的任意一个时间点t1,你在回到时间点t2之前,必须先经过时间点t1,考虑你到达t1的那一时刻,由于t1比t0要早,这个时间点上你还没有找到时间逆转的方法,所以到了时间t1点后,你无法再使用时间逆转的能力回到时间点t2去,所以你永远也回不到时间点t2,由于时间点t2是任意取的,因此,你永远也无法使时间逆转,或者说你根本就没打破过宿命论,这与你在时间点t0打破了宿命论产生了矛盾。
上面这段话看起来似乎有点像“人永远迈不出一步”的诡辩一样,你可能会想返回到时间点t1时,仍然可以拥有时间逆转能力啊。不过你又会发现一个新的问题,时间点t1本来是没有时间逆转能力的,现在又认为时间点t1又有时间逆转能力,那时间点t1到底是有还是没有时间逆转能力呢?或者说在时间点t0前,宿命论注定了时间点t1是没有时间逆转能力的,现在你又认为时间点t1具有时间逆转能力,那么这两个时间点t1究竟是不是同一个时间点?如果不是同一个时间点,说明你没有回到过去;如果是同一个时间点的话,岂不是自相矛盾吗?
为了说得更形象一些,不妨假设你坐一艘超光速飞船,准备从时间点t0回到时间点t2去,假设你回到t2后,随着时间的流逝,又达到了时间点t0,如果这时你又再次坐超光速飞船返回时间点t2,那么一个值得思考的问题就出现了,“你在时间点t2能不能看到上次返回时间点t2的飞船?”
如果回答不能看到飞船,那么上次返回的飞船那里去了呢?显然很难解释通。如果回答能看到飞船,那么你可以到达时间点t2后,下次时间到达t0时,你又坐飞船返回t2,这次你将可以看到上两次的两艘飞船。如果这样一直循环下去,最后你会发现你可以在时间点t2看到无穷多的飞船。用程序员的术语说,叫做“程序陷入了死循环”,最后系统必然会出现“Out of Memory”现象而崩溃。
当然,你也可以认为有其他的方法,不需要飞船,可以一次性从时间点t0直接跳跃到时间点t2,并不需要经过时间点t1。下面不妨来分析一下这个方法是否可行。
既然是直接跳跃到时间点t2,那么你必然是在一个无穷小的时间里出现在时间点t2的某个空间里,例如你要在时间点t2回到某个广场上。首先说明一下为什么是无穷小的时间里出现的,因为如果不是无穷小的时间里出现的话,那么必然可以取到一个时间点t1,会导致前面所说的时间点t1上出现悖论。
你在广场上出现的时,广场上的空气必然要为你让开空间,而这是在无穷小的时间里完成的,那么很容易推导出你周围的空气获得的加速度和速度都是无穷大,因而它具有的动能也是无穷大,无穷大的能量和无穷大的速度意味着什么?一只鸟都可以将飞机撞下来,如果宇宙是有限大的话,它可以让这个宇宙炸毁无穷次;即使宇宙是无限大,它也足以让宇宙炸毁一次。宇宙都毁灭了,又何来的时间?还能说你回到了时间点t2吗?
也许上面说的这些你仍然难以相信,不妨再说得更现实一些,假设你要回到100年前的一个时间点,这100年中,天上有多少流星湮灭了?有多少新星生成了?宇宙膨胀了多少?你有能力让湮灭的流星复原、生成的新星重新返回未生成前的状态,膨胀的宇宙收缩回去吗?如果这些东西的状态没有回复到100年前,又怎么能说明你回到的是100年前的时间点呢?
根据上面的推导和分析,个人认为使时间逆转的方法是不存在的,所以第12层楼是不存在的,自然没有人可以骑到“上帝”的头上。
宿命论将在有时间的时间里永远统治这个世界。

/我赚钱了/
我赚钱啦赚钱啦 我都不知道怎么去花 我左手买个诺基亚右手买个摩托罗拉 我移动联通小灵通一天换一个电话号码 我坐完奔驰开宝马 没事洗桑拿吃龙虾 干嘛呢干嘛呢干嘛呢 说你呢 病人家属在哪人儿(妈。。) 病人该吃药啦

/双向收费 /
COME ON BABY 双向收费了 它怎么那么黑啊 它赛过活李魁 它是气死猛张飞 要拿着手机聊会儿天啊 你银子哗哗没 你可想清楚了 我可这就要接通了 我掏四毛你掏四毛咱俩就开始聊了 我还忘了告诉你我卡里没多少钱了 我减四毛我去四毛我还剩一块六啦 我再去四毛再减四毛我还剩八毛钱啦 我再去四毛再减四毛我还剩一块六 我 别聊了 赔啦

/二百块钱罚三分/
COME ON BABY 我现在不能接你的电话 我在开车路上全是警察 一旦我不慎被拿下呀 二百块钱罚三分呀 弄不好还吊销本儿呀。。。。

/阿里巴巴/
阿里 阿里巴巴 阿里巴巴从来就不接电话 阿里 阿里巴巴 阿里巴巴从来就不接电话 噢噢噢噢 无人应答无人应答 啊啊啊啊,呆会儿再打呆会儿再打

/西门大关人/
潘金莲儿 挑春帘儿 砸得我手机断了线 我笑咪咪地对她说 给我出来赔钱 我的手机是分期付款 按揭一下就好多年 舍不得打我也舍不得接 今年毁在你的手里面 我说大哥大哥你好吗 啪啊。。。

/新年成语接龙/
新年好新年好 欢迎你打电话来参加新年成语接龙活动 嗯 干 成功干 干净利索 所向披靡呀 迷迷糊糊 呼来唤去 去去就来 来来去去 去去就来 砰 唉哟 来者不善 善者不来 嘿 来者不善 善者不来 砰啪 来来回回 回眸一笑啊 笑口常开嘛 开开心心 新年快乐
/吾酷快板/
哎 闲言碎语不要讲 机主现在特别忙 五点多钟就起床他半夜两点上不了炕 没白天没黑夜是名符其实工作狂 当里个当当里个当当里个当里个当里个当 哎 那么你这位说了 他到底是接了这个电话接不了呢 我可有急事找他呀 哎 不要急来不要慌 有我们吾酷来帮忙 跟你唱跟你跳是跟你说完跟你笑 让你听了心欢喜是忘了给谁打手机 这就是 手机进了新世纪 机主不接也可以 要嘛你就发短信 要嘛你就听我唠唠叨叨唠唠叨叨说到底 说到底 当里个当当里个当当里个当里个当里个当

/吃饱撑的/
哎哟吃饱撑的 闲得没事儿 给卡里设了个密码 已经输错两次了呀 啊呀,倒霉催的 手一哆嗦又摁了一个YES 现在全锁上了呀 哎哟赶紧跑到营业厅去找找解决办法 却发现登记名字不是自己的 啊呀苦思冥想终于想起机主曾经是谁啦 是五六年前分手的她 你让我现在哪儿找去呀 呃 这个故事告诉我们分手前一定要过户

/上课不能接手机/
食不言
食不言
寝不语
寝不语
上课不能接手机
上课偷着接手机
不对 是上课不能接手机
上课偷着接手机
怎么回事儿啊 还不对 是上课不能偷手机
上课不能接。。。
哎呀 什么呀 你们都把我说乱了 应该是上课偷着接手机
老师 老师老师 你做人也得厚道点儿吧 你一会儿让我们翻来覆去说多少遍呀 您到底是让我们上课不能偷手机还是上课偷着接手机还是上课接着偷手机还不一串儿的手机呀
你们 我 我 我 啊 统统给我关手机
吾酷提醒:上课不能接手机

/麻将夜话/
在这种寂静的夜里 我还在这个小屋里 因为寂寞会一直伴我到天明 幸好还有你 我的朋友 打来这个电话 还有我身旁这三个陪我玩儿麻将的朋友 哎 赶紧出牌快点儿 他们催我了 我现在正落着听呢 所以不能接你这个电话 我是五六筒 等待生命中的四七筒 咚 四筒 哎哎哎 胡了 T胡 给钱给钱

/123接电话/
ONE 我不能接电话 TWO 我有个好办法 THREE 将你要说的话精简一下 然后发短信吧 FOUR 怎么你还没挂 FIVE 我看着电话直犯傻 你的执着彻底感动我啦 我现在就来接电话啊

/红孩儿/
唐三藏 就知道你会给我打电话来 今儿是我红孩儿的生日 你都给我准备了什么礼物啊 是()啊还是矛台啊 是XO啊还是介绍女朋友啊 哈哈哈 咦 小东西的还反了你了 又烟又酒你还五(啊哈)毒俱全了你 我想教训人我也早不是一(哎呀)天两(两天)天了我跟你说 我看你小东西还敢在电话里跟我张(啊)牙舞(啊)爪 以前观音他们打我我不还手怎么了 我不还手那是迷惑他们呢儿子 想当年我也(你) 你你你你竟敢(打死你) 哎哟 哈哈哈 我打你屁股 行你等着 啊 炸弹 砰。。。。我告诉我妈去

/你快了吗/
你快了吗 我就快了吗 我就快手机没电了我跟你说 你快了吗 他快不了 他要快他早就接你电话了 那你快了吗 哎 我快疯掉了 我这不正找备用电池呢嘛 你快了吗 他快嘛呢 他那备用电池也是没电的 哈哈 干嘛呢你们怎么又唱上了 说你呢 拿那块肥皂硬往那个电视遥控器上塞什么呀你 哎 赶紧抢过来 哎张大夫 张大夫 给他们吃药了吗 病人又犯病了。。。

/波斯猫/
喵 波斯猫 我的手机没电 波斯猫 我的卡里没钱 波斯猫 既然好久没见 还不如请我吃个饭聊聊天 喵喵喵 最好是吃海鲜 喵喵喵 我最爱吃螃蟹 喵喵喵 如果没有意见 准备好我们现在就来接 喵。。。。

/ONLY YOU /
ONLY YOU 当当当当当 悟空 你终于想明白了 你肯给师父打来电话了吗 为师现在不接你的电话 是为了大家好 我一接 你要付四毛 我要付四毛 砰砰 你打我干什么 你真的要为师接吗 你要我接你说话嘛 你不说我怎么知道你要我接呢 你要我接我不会不接而不要我接我偏要接 我靠 I服了YOU 你看你又猴急猴急的嘛 是你给我打的电话嘛 你不要挂 我马上就来接 你闭嘴 哒哒哒哒。。。。。

/机主学中文/
你好请你等一等 机主正在学中文 你好请再等一等 机主学会了 噢。。。。。。

/别挂机/
你现在才打电话 正好是饭点儿啊 我为了等你电话一天没吃饭啦 别挂别挂 我现在就接电话 别挂别挂 我现在就接电话 别挂别挂 我现在就接电话 别挂别挂 我现在就接电话 。。。。啊哈哈哈哈

/新疆绕口令/
机主现在不说话嘛 因为在吃哈蜜瓜 机主一下子吃掉了三个 所以你就慢慢等着了吧 哎 朋友 教你一段新疆绕口令 你要说得象的嘛 机主就来接电话啦 准备好了吗 吃了吐鲁番的葡萄不接电话不着急 不吃吐鲁番的葡萄接个电话没人理 别吃吐鲁番的葡萄然后别发短信息 %¥%¥%¥%¥%¥%¥%¥% 记住了吗 娃哈哈 娃哈哈哈 每个人的脸上都乐开了花 娃哈哈 娃哈哈 每个人的脸上都乐开了花

/别别挂 /
请你别别挂 请稍等一下 机主现在手里有工作放不下 请你别别挂 请再等一下 希望你能多等些时间给他 请你别别挂 机主听见啦 他派我来 感谢你还再等他 请你先别挂 这就接通啦 接通以后 别再让他轻易挂断啦

/酒干了瓶卖我/
酒干了瓶卖我 酒干了瓶卖我 酒干了瓶卖我 你快把酒干了瓶子卖给我 多么浪费的年轻人啊 喝完酒瓶子到处乱扔 严重影响了公共卫生 也阻碍了资源的再生 你昏天又黑地 我着不起你这份儿急 你就这么点出息呀 以后()了你就爱唱戏。。。

/春天的信息/
春天 我打开手机 在想着现在 谁会让铃声响起 是你 我知道是你 打到我这里 让我一时无语 所以 我没按接听 你可否挂断 然后发短讯息 我会 将它珍藏在 我的手机里 因为这是你发给我的 春天的 信息

/南无摩托罗拉/
孙悟空 你欺师灭祖 长年拖欠话费 还敢打电话来 今天我要替天行道 让你停机 哎哎 观音姐姐 你闭嘴 哎哟 是我呀我是唐僧#¥¥ 我知道是你 贫僧·#¥ 你是够贫的你¥%¥ 唉哟 别打了 贫僧愿意为他交话费 什么  我是说贫僧愿意为徒儿补交话费 你待怎讲 这正是我佛慈悲的宽大胸怀啊 正所谓 我不入移动谁入移动 南无摩托罗拉 啪啪啪··

/鸳鸯火锅诺基亚/
唉哟我的妈呀 我手机掉火锅里啦 我算完了蛋了呀 刚刚新买的诺基亚 我赶紧捞起来了吧 上面挂着毛肚还有金针茹 你老就慢慢等着吧 等它干了咱才能再通话 唉呀 伙计 又掉啤酒里了 服务员 上餐巾纸 唉 你稍等啊 你正好在这儿把它先涮涮

/蜡笔小新个人简历/
大家好 这里是我的个人简历哟 我只说一次 好好听喔 我叫蜡笔小新 我的学历是幼儿园小班 嗜好就是爱和漂亮姐姐在一起 缺点就是太早熟了 最喜欢的运动是睡觉 最喜欢的零食是小雄饼干 最好的朋友 阿呆 正男 风间 哈 让我猜猜你是谁啊 咦 我的花呢 噢 在这里

/帅哥小强/(宝宝版)
喂 我是帅哥小强啊 前两天 我们老板跟我说 哎 小强 你怎么这么帅呢 告诉他 哪里哪里 我一点都不帅 没想到啊 他居然用砖头打我的头 噼¥#啪%# 他说我虚伪 所以我为了不挨打 就只好承认了%……¥#¥%·

/小猪乐乐诞生篇/
大家好 我是一只猪 一只手机小猪 初次见面 请多关照 我有一只可爱的名字 因为 妈妈在生我时候 她正在打麻将 我的猪妈妈特别喜欢打 就吧哒吧哒的打 打到清一色的时候 她饿得肚子咕嘟咕嘟叫 我一看见她乐 就很好奇呀 所以我就想出来看看 有什么事情那么高兴哩 于是我就来到了这个世界 所以妈生了我 还赢了钱 特别高兴 我就有了一个好听的名字 叫乐乐

/小猪乐乐之作诗篇/
哈喽 偶是手机小猪乐乐 最近我作了一首诗 妈说很有人生哲理 充满了矛盾与冲突 非常适合配乐诗朗诵 乐队老师请伴奏 在错的时间接通对的电话是一种遗憾 在对的时间接通错的电话是一声叹息 在对的时间接能对的电话是一生的幸福~~~~现在是什么时间 嘀~~ 又是什么样的电话 这次要不要接哩~~

/小猪乐乐之作诗篇二/
哈喽 偶是手机小猪乐乐 自从上次那首诗发表以后 反响很好 有很多人找我签名 于是 偶又做了一首诗 妈说 这次偶又进步了 乐队老师请伴奏 不是这首 乐队老师已经学会开玩笑喽 嗯嗯 就是这首 开始 我醉了 因为我快乐 我快乐 因为你想我 如果没有你 生活没法过 钱包没有钱 等待你支援 你就是我冬天里的棉袄 夏天里的鹅毛扇 完了 谢谢

/老头与手机/
很久很久以前有一个老头 年纪一大把了还喜欢赶潮流 有天进城看见人人手里拿块砖 老头看半天 那是啥砖哩 嘟~~忽然看见有个人拿砖往脸上拍 他嘻嘻哈哈说说笑笑感觉挺自在 老头明白了 他原来不是砖啊 他原来不是砖是个录音机啊 嘿嗦嘿嗦嘿 嘿嗦嘿嗦嘿 嘿嗦嘿嗦嘿  嘿嗦嘿嗦嘿

小猪乐乐之/可爱K歌的小猪/
哈喽 偶是手机小猪乐乐 最近我迷上了K歌 现在我正在卡啦OK 请勿打扰 你有事吗 你叫做啥 你不知道偶的电话没钱啦 偶不敢接偶不敢听 偶怕你说起来就没完没了的 你的心事偶全知道 偶的心事你怎么就不知道 好了 唱完了 偶刚刚请你免费听歌 不用谢 你是不是应该请偶吃饭哩 谢谢

/来我家干活/
你找我们家大人吧 他们现在没空 因为他们都在干活 你有什么急事啊 你你得给我买好吃的 我才去叫他们 哎呀 不行 我妈妈说了 不能要别人东西 那你还是来我们家干活吧 这样你就能找到我们家大人了

/约会中/(宝宝版)
你好 我现在在回家的途中 塞车 不方便接听你的电话 他骗你的 他在电影院门口呢 咳咳 本来就是 上午下班之前 他接了一个电话 说和美眉约好去看电影 真的 不骗你 咳咳咳 主人 你没事吧 怎么老咳嗽啊 哎 你别卸我电池啊 你别取我电池啊···

/谦虚的宝宝/
其实我没那么好 就是比其他女孩漂亮点儿 温柔一点儿 聪明一点儿 贤惠一点儿 懂事一点 大方一点 谦虚一点儿 嘿嘿

/替我交话费/
你所拨打的用户 话费余额已不足0.1元 无法与您正常通话请你在近日内 卖儿卖女卖大米 砸锅卖铁卖点血 卖房卖地卖老婆 替他把话费交了吧 啊喔

/手机小丽/
喂 你好 我是手机小丽啊 你找谁呀 是找我的主人吗 他现在没空 你可以留言 我会把你的话转告给他的 但是你得说慢点 我个儿小 记不住 预备 开始

/接还是不接是个问题/
接电话前 听首诗吧 陶冶一下情操 感悟一把人生吧 啊 天上飘着老大一块儿云 一个纯洁的声音从半空中响起 接吧接吧接个电话吧 啊哈 我的内心苦苦挣扎 接还是不接 这是个问题 接吧花钱儿 不接吧 闹心 砰 晴天一个霹雳 啊 这回省事儿了 电话给霹断了

/两只小蜜蜂/
两只小蜜蜂啊 飞到花从中啊 左飞飞 右飞飞 接呀 啊啊 接呀 嗯嗯 接呀 唔啊 你到底接还是不接呀 嗯 挺好玩儿的 再来一遍 两只小蜜蜂啊 飞到花从中啊 左飞飞 右飞飞 接呀 啊啊 接呀 嗯嗯 接呀 唔啊 你怎么还是不接啊 JJQQ 就是不接···

/我是个男人/
你要找谁呀 干嘛一上来就对我不那么礼貌呢 告诉你 我也有尊严的 别看我不起眼吧 我也比插座高啊 就说我是小孩吧 但我也是人呀 我还就告诉你 我还是个男人

/骗你是刚发生的事/
想你是件快乐的事 骗你是件开心的事 爱你是我永远要做的事 把你放在心上是我一直要做的事 不过 骗你是刚发生的事

/人是人 妖是妖/
喂 你好哇 哇 好久没有你这们的美眉给我打电话了 讨厌 谁说我是女的 哎呀 好久没有象你这样特别的男生给我打电话了 讨厌 干嘛说人家是男的 哇噻 好久没有象你这样的()给我打电话了 讨厌人就是人 妖就是妖 干嘛还()的 唉呀 救命呀 讨厌 好久没有给你这样可爱的()打电话了 啊·····

/接电话是有原则的/
哎 你好 打电话来了 我事先声明一下啊 我这个人是很有原则的 接电话按程序办事 第一步要把电话找到 第二步把电话的套套摘掉 第三步把电话的盖盖打开 嘿嘿 对了 我这个是翻盖的啊 第四步 看一下电话号码 第五步挂断 对不起 你拨打的用户已挂机 第六步 找一个公家的电话给你打过去哈 你稍微等一下下哈

/我有一句话/
嘿 哥们儿你来电话 影响我的工作你很不象话 今儿我正好有一句话 我要跟你讲你可不要挂 你知道哥们儿我长得有点帅吧 兜里有点钱我脾气也不坏吧 总的来说这个人是要啥啥不赖吧 咋就没个姑娘啥的跟我谈恋爱呀 一天到晚辛勤工作还得学文化 我是没有时间没有机会跟你俩说会儿话 只要你身边认识姑娘正好没有嫁 你可赶紧介绍给我 千万不要挂 流氓

/喂喂唱/
喂喂 我现没接电话请你稍等一下下下下下下下下下。。。喂喂
如果你不着急请你再等一会儿会会会会。。。。。。喂喂怎么还没接电话估计自己很忙忙忙忙忙忙。。。。。。喂喂估计现在有事儿请你稍后再拨拨拨。。。。。喂喂我还没接电话请你稍等一下下下下下下下。。。。。喂喂如果你不着急请你再等一会儿会会会会。。。。。

/水果健身/
我现在不能接电话因为我在吃水果等我补充完了能量再接你的电话吧  吃了苹果吃香蕉呀吃了香蕉吃菠萝 吃了菠萝吃葡萄呀最后再捡个西瓜 加油加油大家一起多吃水果多运动把身体里的肥肥肉统统减去了吧 全国人民努力吧全民健身重要啊 一切为了2008大家奋斗努力吧

最近在浏览一些Wordpress博客时发现人家的“页面”功能做的貌似和我的显示效果不一样,从网上查了一下,说可以使用模板,即自己复制page.php模板文件后,进行修改和制作后,重命名,并且上传到模板文件夹下,然后在后台“页面”里选择刚才新上传的模板即可。但是我操作了一下,发现在页面编辑里面根本就没有选择模板这一项,倒是在“快速编辑”中有,但是里面只有“默认”这一个选项。

又是在网上一阵搜索,发现貌似2.6版本后已经没有这个选项,但是可以通过修改模板文件名来实现。比如说,我的留言板的别名写的是guestbook,那么我想用的模板文件名就需要改为“page-guestbook.php”,这样博客就会自动使用这个模板文件啦。

今天C++学的指针,之前C语言课上讲过指针,但是当时几乎就没怎么深讲。今天讲的内容甚是让人头晕啊,回来后我在自己机器上把书上的示例程序修改了一下,仔细来看看指针。下面的就是我的指针学习程序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//      Copyright 2011 ETY001 <[email protected]>
// Website:akawa.ink
#include <iostream>
using namespace std;
int main()
{
static char t[2][3][5]={"abcd","efgh","ijkl","mnop","qrst","uvwx"};
cout<<" t[i] "<<" &t[i] "<<endl;
cout<<"01::"<<t[0]<<" "<<&t[0]<<" <---t[0]"<<endl;
cout<<"02::"<<t[1]<<" "<<&t[1]<<" <---t[1]"<<endl;
cout<<"03::"<<t[0][0]<<" "<<&t[0][0]<<" <---t[0][0]"<<endl;
cout<<"04::"<<t[0][1]<<" "<<&t[0][1]<<" <---t[0][1]"<<endl;
cout<<"05::"<<t[0][2]<<" "<<&t[0][2]<<" <---t[0][2]"<<endl;
cout<<"06::"<<t[1][0]<<" "<<&t[1][0]<<" <---t[1][0]"<<endl;
cout<<"07::"<<t[1][1]<<" "<<&t[1][1]<<" <---t[1][1]"<<endl;
cout<<"08::"<<t[1][2]<<" "<<&t[1][2]<<" <---t[1][2]"<<endl;
cout<<"09::"<<t[0][0][0]<<" "<<&t[0][0][0]<<" <---t[0][0][0]"<<endl;
cout<<"10::"<<t[0][0][1]<<" "<<&t[0][0][1]<<" <---t[0][0][1]"<<endl;

cout<<"11::"<<t[0][1][0]<<" "<<&t[0][1][0]<<" <---t[0][1][0]"<<endl;
cout<<"12::"<<t[0][1][1]<<" "<<&t[0][1][1]<<" <---t[0][1][1]"<<endl;

cout<<"13::"<<t[0][2][0]<<" "<<&t[0][2][0]<<" <---t[0][2][0]"<<endl;
cout<<"14::"<<t[0][2][1]<<" "<<&t[0][2][1]<<" <---t[0][2][1]"<<endl;

cout<<"-----------------------------------"<<endl;
cout<<"1::"<<t<<" <--- t"<<endl;
cout<<"2::"<<t+1<<" <--- t+1"<<endl;
cout<<"3::"<<*t<<" <--- *t"<<endl;
cout<<"4::"<<*t+1<<" <--- *t+1"<<endl;
cout<<"5:"<<*(t+1)<<" <--- *(t+1)"<<endl;
cout<<"6:"<<*(*t+1)<<" <--- *(*t+1)"<<endl;
cout<<"7:"<<**t<<" <--- **t"<<endl;
cout<<"8:"<<***t<<" <---***t"<<endl;
cout<<"9:"<<**(t+1)<<" <---**(t+1)"<<endl;
return 0;
}

通过这个程序,对照着来看指针,就会看的比较明白。下面是程序的运行截图:

截图

从程序的运行结果中,我总结了以下几点:

1、直接输入数组名称的时候,数组名代表的是数组的入口第一个空间的地址,t和t[0],t[0][0]的地址都是一样的;
2、*t+1和&t[0][1]等价,*(t+1)和&t[1][0]等价;
3、对*t进行加1操作的时候,有时候是对t,也就是地址加一,结果是t对应的地址加上一个数据类型长度,而有时候则是对于*t所代表的值,也就是t地址所指向内存里的值进行加一(我不知道我这个理解对不对,希望高人指点,我在这里感觉有点晕)。

暂时就总结这么多,另外,补充一点,在编译过程中曾经出现错误提示,说cout没有定义,从网上搜索了一下,了解到以下情况:

<iostream>和<iostream.h>格式不一样  前者没有后缀,实际上,在你的编译器include文件夹里面可以看到,二者是两个文件,打开文件就会发现,里面的代码是不一样的。 后缀为.h的头文件c++标准已经明确提出不支持了,早些的实现将标准库功能定义在全局空间里,声明在带.h后缀的头文件里,c++标准为了和C区别开,也为了正确使用命名空间,规定头文件不使用后缀.h。 因 此,当使用<iostream.h>时,相当于在c中调用库函数,使用的是全局命名空间,也就是早期的c++实现;当使用< iostream>的时候,该头文件没有定义全局命名空间,必须使用namespace std;这样才能正确使用cout。
解决方案一就是在头部加上
1
using namespace std;

,就像上面我的程序那样;
方案二就是把每个cout改为std::cout。

想知道更多,请看百度百科的namespace词条。

今天偶然的去我的GoogleAdsense账户上查看了一下,居然发现我的帐户上破0拉,哈哈,截个图留念一下。话说这是我从今年1月20日(/2011/01/20/add-google-adsense.html)正式开通的Adsense,到现在为止也就2000多次的显示,大家不要笑话阿~

由于最近服务器经常不给力,打开个页面居然要10s以上,有时候甚至到了20s,再忍耐了将近2个星期后,我不得不重新买了一个新的空间,并进行了调换。不过调换的过程也是痛苦的,在原空间的数据备份包下载速度几乎为0,我这还是用的迅雷离线下载,下了一个通宵才搞回来。

话说还是cpanel面板给力,linux服务器给力,一切调试配置起来都是那么的轻松。

另外,DM博客开通了自己的个人微博,用来用一句话记录生活,毕竟有时候没有那么多要说的,地址是:http://t.domyself.me,在页面的右上角也有连接。

今天上C++的第一堂实验课,老师为了了解一下我们之前学的C语言怎么样,出了一到程序题,让我们编一下。题目很简单就是给定一元二次方程ax^2+bx+c=0的三个系数,然后给出结果,并能够循环执行,主函数只负责输入参数,要至少有一个函数,本人很快就理清思路开始编写,很快写完了,并且编译了,下面的就是我的第一遍源代码(VC编译环境):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <stdio.h>
#include <math.h>
void charge(float a,float b,float c); //判断过程
void runorstop(); //是否继续运行
int run = 1; //继续运行的标志,1为继续运行,0为停止运行
void main()
{
while(run == 1)
{
float a,b,c;
printf("请输入a\n");
scanf("%f",&a);
printf("请输入b\n");
scanf("%f",&b);
printf("请输入c\n");
scanf("%f",&c);
charge(a,b,c);//进行运算
}
}
void runorstop()
{
printf("是否还要继续运行程序,“是”请输入“1”,“否”请输入“0”\n");
scanf("%d",&run);
}
void charge(float a,float b,float c)
{
float x1,x2;
float d; //daite
if(a == 0)
{
if(b == 0)
{
if(c == 0)
{
printf("方程有无穷个解!\n\n");
runorstop();
}
else
{
printf("a,b同时为0,方程错误!");
runorstop();
}
}
else
{
x1 = -c/b;
printf("方程的解为 x = %f",x1);
runorstop();
}
}
else
{
d = b*b - 4*a*c;
if(d>0)
{
x1 = (-b+sqrt(d))/(2*a);
x2 = (-b-sqrt(d))/(2*a);
printf("方程的两个根分别是:\n");
printf("x1 = %f , x2 = %f\n",x1,x2);
runorstop();
}
if(d=0)// 《《---这里就是错误的出现的地方
{
x1=-b/(2*a);
printf("方程有两个相同的根:%f\n\n",x1);
runorstop();
}
if(d<0)
{
printf("方程没有实数解!\n\n");
runorstop();
}
}
}

但是在运行的时候,发现输入完a,b,c三个数据后,程序不停的出现 【是否还要继续运行程序,“是”请输入“1”,“否”请输入“0”】 这个提示信息,看来可能是while循环导致的不停的循环,先注释掉,然后再运行,输入完三个数后什么也没显示,程序就结束了。

我前前后后看了好几遍也没找到问题,第一次猜测是数据输入有些问题,于是在第16行之后加了一行printf输出一下a,b,c三个值,编译运行,成功输出,证明输入正确。于是又猜测可能是数据没有被带入到函数中去,于是又在28行后面插入输出语句进行测试(这里注意,一定要把printf放到后面,不能放到27或者28行前面,因为27,28行是声明的局部变量,局部变量的声明必须要放在这个函数的头部,这是老师说的)。测试结果正常,证明数据已经能进入函数。由于我输入测试的数据,应该进入68行的那个花括号,所以就在那附近检查,终于发现了问题,原来是一时打字疏忽,把62行的判断相等双等号打成了赋值单等号。这样一来,就成了把0赋值给d,而if(0)肯定不执行花括号里的内容,所以程序就跳过了所有的if,结果就是什么都不会显示。于是我想到了,如果当时使用了else的话,那么问题很快就能找到,因为一个判断不正确,他会跳转到else的花括号,这样就等于所以了检查范围。既然找到了问题,那么把之前注释掉的while循环改过来,然后把=加上,编译运行成功了。

附:由于机房使用的是VC,而我现在写这篇文章的时候是在我的本本的ubuntu系统下,于是又出现了点小插曲,就是sqar()函数在编译时,提示错误信息:

1
2
3
4
/tmp/ccszYPUG.o: In function `charge':
1.c:(.text+0x1a6): undefined reference to `sqrt'
1.c:(.text+0x1cc): undefined reference to `sqrt'
collect2: ld returned 1 exit status

我在网上搜索了一下,找到了下面的这个资料,先收了,以备后用:

1
2
3
4
5
6
7
8
9
10
-l参数和-L参数
-l参数就是用来指定程序要链接的库,-l参数紧接着就是库名,那么库名跟真正的库文件名有什么关系呢?就拿数学库来说,他的库名是m,他的库文件名是libm.so,很容易看出,把库文件名的头lib和尾.so去掉就是库名了
好了现在我们知道怎么得到库名,当我们自已要用到一个第三方提供的库名字libtest.so,那么我们只要把libtest.so拷贝到/usr/lib里,编译时加上-ltest参数,我们就能用上libtest.so库了(当然要用libtest.so库里的函数,我们还需要与libtest.so配套的头文件)
放在/lib和/usr/lib和/usr/local/lib里的库直接用-l参数就能链接了,但如果库文件没放在这三个目录里,而是放在其他目录里,这时我们只用-l参数的话,链接还是会出错,出错信息大概是:“/usr/bin/ld: cannot find -lxxx”,也就是链接程序ld在那3个目录里找不到libxxx.so,这时另外一个参数-L就派上用场了,比如常用的X11的库,它在/usr/X11R6/lib目录下,我们编译时就要用-L/usr/X11R6/lib -lX11参数,-L参数跟着的是库文件所在的目录名。再比如我们把libtest.so放在/aaa/bbb/ccc目录下,那链接参数就是-L/aaa/bbb/ccc -ltest
另外,大部分libxxxx.so只是一个链接,以RH9为例,比如libm.so它链接到/lib/libm.so.x,/lib/libm.so.6又链接到/lib/libm-2.3.2.so,
如果没有这样的链接,还是会出错,因为ld只会找libxxxx.so,所以如果你要用到xxxx库,而只有libxxxx.so.x或者libxxxx-x.x.x.so,做一个链接就可以了ln -s libxxxx-x.x.x.so libxxxx.so
手工来写链接参数总是很麻烦的,还好很多库开发包提供了生成链接参数的程序,名字一般叫xxxx-config,一般放在/usr/bin目录下,比如
gtk1.2的链接参数生成程序是gtk-config,执行gtk-config --libs就能得到以下输出"-L/usr/lib -L/usr/X11R6/lib -lgtk -lgdk -rdynamic
-lgmodule -lglib -ldl -lXi -lXext -lX11 -lm",这就是编译一个gtk1.2程序所需的gtk链接参数,xxx-config除了--libs参数外还有一个参数是--cflags用来生成头文件包含目录的,也就是-I参数,在下面我们将会讲到。你可以试试执行gtk-config --libs --cflags,看看输出结果
现在的问题就是怎样用这些输出结果了,最笨的方法就是复制粘贴或者照抄,聪明的办法是在编译命令行里加入这个`xxxx-config --libs --cflags`,比如编译一个gtk程序:gcc gtktest.c `gtk-config --libs --cflags`这样就差不多了。注意`不是单引号,而是1键左边那个键。

最后还是找到了,需要加-lm参数,编译指令如下:

1
gcc 1.c -o a -lm

这样就编译生成名字为a的程序了,但是运行的时候全是乱码,这个问题好解决,因为在VC下编写的源代码文件都是GBK格式的,只需要在ubuntu下面用leafpad打开源文件并且另存为UTF-8再编译运行就可以了。

0%