编程及C/C++初学者 FAQ
本文原为本人在论坛所发若干帖,意在集中解决新手学习C/C++语言时将遭遇到的各类问题,网友反馈情况良好,集合修订后作为个人作品贴于此处。
本贴主要分析概念原理和解决方案,不讨论具体程序语法,立足于让初学者能运行起第一个程序。其他事宜如解释入门语法等本文基本不涉及。
本文依照 创作公用约定(署名-非派生作品-非商业用途) 发布。作者(即本人)无更新计划,请勿与作者联系。
联系方式:
[email protected]
=========================================分割线================================
目 录
一、开始之前
FAQ 那是什么
为何有这篇FAQ
编程为何物
如果这就是编程,那语言是怎么回事
我为啥要学编程
听说编程很难,是真的么,那我能学会吗?
我真的可以么
还一定要有台电脑么
好吧你说服我了,我打算开始,该怎么做
那么,下一步怎么干
我碰到问题了,谁能帮我
我能看懂别人的程序,但自己做就觉得无从下手,怎么会这样
我英语\XX不会,咋办
关于态度、情绪和其他
二、选择C/C++语言
C语言是什么
C++语言是什么
为何要选择纯C
C/C++语言和其他语言有什么关系
我为什么要学C/C++语言
Python语言 作者的另一推荐
三、一些重要的概念-----计算机原理
编程的对象是什么————计算机
程序到底是怎么回事————是操作而不是结果
为什么要编程————因为机器的特点
你们老是提到编译器,那是什么-----代码翻译机
给我解释下啥叫编程语言————各路江湖武功
语言之后要确定的事情------操作系统和平台
编程时什么东西最重要----源代码
我的程序和一般的程序不一样,什么原因————控制台和图形界面的差异
好像不能建立一个单独的文件来编译————工程和项目的问题
难道一切都要从头干起————函数、API、类、控件、开发包与软件复用
关于图形库的补充说明--------可选择的图形库
四、教材、习题和示例
能推荐几本好书么
首先是纯C的教材
然后是C++的教材
接下来是Windows编程
Unix/Linux/BSD系统
数据结构和算法
各种图形以及其它库
软件工程思想
找书的诀窍
光看书似乎不解决问题,难道要做题
OJ是什么
哪里有可用的OJ
哪里有代码示例可看
五、选择编译器
有哪些编译器可用
还有些可以配合编译器的开发环境
他们在哪里
怎么安装他们----特别解释 MingW版GCC的安装
六、TC下常见的问题解决
用TC创建第一个程序
TC的库路径设置
TC下的图形编程设置
我的程序在TC下可以编译,在VC/GCC下为什么出错
七、其它编译器问题
用VC创建程序
用DEV-CPP创建程序
用MingW创建程序
用Lcc-win32创建程序
八、结束语
程序员成长的六个阶段
=========================================分割线================================
一、开始之前
FAQ 那是什么
FAQ就是Frequently Asked Questions,也就是常见问题解答。这玩意儿通常是一些所谓的高手或者前辈为了节省回答新手的大量简单重复问题所耗费的时间精力而采用的一种偷懒手法。一旦完成,高手只要一努嘴,“看FAQ去”就万事大吉了。实在是居家旅行杀人越货之必备良药,因此在各大论坛已经有大泛滥的趋势。
本篇FAQ为学习C语言、C++语言的大量新手编写,重点是如何运行起第一个程序,不涉及语法、数据结构和算法等内容。如果你已经通过计算机二级或水平相似的考试,甚至你是职业选手或是大师级的人物,就不必再往下看了。同时,本FAQ只讨论C/C++语言,其他语言如Java VB python等均不涉及,虽然阅读本文前四章节也会对学习这些语言有所帮助,但深入学习还是请阅读这些语言的专门教材。
为何有这篇FAQ
本文是为那些对编程新手所准备的,如果你自认已经不是新手,那么请离开把时间放到更有用的地方。如果你是那种对编程一无所知,迫切想知道他是怎么回事,或者仅仅编写了几个小程序,却遇到一大堆问题,而在论坛或是其它地方又得不到帮助,但心中又有雄心壮志想要做绝世高手顶尖黑客或者想要以程序为生的入门级新人,那么你恰好是本文的服务对象,请详细阅读以下的文字,我想应该会对你有所帮助。而且请你了解,本文的这部分内容所要介绍的是那些普遍性的概念,与具体任何一种语言都无关。
正如我们所知,市场上充斥着无数的编程教材,同时可以肯定的是,目前已经面世的教材(包括正式出版物和网络上的教程),穷一人一生之力是看不完的。在这些书中,有大量的垃圾书,大量的平庸之作,还有少量的精品。而即使是这少量的精品,也不可能看全。既然书这么多,我为什么那么闲还要来写一篇呢,有这时间,我还能多画几张效果图挣俩钱花呢。
情况是这样的,市场上的书虽多,但其中几乎没有几本是面向初学者的。我所指的初学者,是指从来没有编写过程序,甚至是连编程二字都没有听说过的人。这样的书是如此之少,以至于要去购买或是阅读到他们都是很困难的事。在我个人的学习生涯中我认识到很多编程教材有个糟糕的倾向。他们要么是一下子告诉你所有的事,好像你能在千分之一秒中突然从菜鸟变成好手,要么就是认为有些事你早就应该知道,拿你当熟手看,导致你有一种赤身裸体被抛弃于猛兽横行的非洲旷野的感觉。你还没有穿上衣服走出帐篷,连刀子都没有摸过,他们就试图告诉你草原上有多少可以捕获的猎物以及他们的位置,告诉你几百种武器和毒药的使用秘籍,告诉你两百条以上的陷阱安放要领。你没有经过丝毫的练习,甚至还没有杀死过一只刚出壳的小鸡,他们就要你独自去捕猎数十头饥饿的狮子。这种看似荒谬的情况从过去持续到今天,至今仍然存在。这并不是说那些写教材的朋友都是傻瓜,这件事当然有它的原因,因为他们面向的读者是程序员。程序员就象是猎人,他们更换语言就像猎人更换武器一样,不管他使用哪一种武器,捕猎的基本原理没有变化,变化的只是武器的使用方法。对一个成熟的猎人而言,再强调基本原理就没有必要,所以教材们对人所共知的一些事也就避而不提。一个成熟的猎人,她心中的捕猎知识是浑然一体的,武器的选择,野兽的习性,陷阱的安放,怎样做和为什么这样做都结合在一起,没有哪一部分可以独立出来,一部分一部分的教给别人是极度困难的的,要教就只能混杂在一起。程序员的情况类似,知识体系是完整系统的,谈到一个问题总会牵扯到另一个,最后的结果就是别人总是希望并想当然的认为你可以一口吃成一个胖子。
这样的后果就是,一些很明显的事情,老手认为那是你应该知道的因而不予回答,而新人却发现没有任何地方可以找到解释,也不知道该到哪里去找答案。(不懂得如何找答案也是新人的特点之一)。有一个典型例子与这种情况很类似,鼠标,我们已经习以为常并且很熟练地使用着,但是很多第一次接触电脑的人那却是完全摸不着头脑的东西。在各地的论坛里,总有大量的新人提出诸如“学C++好还是VC,VC++好?”“C++也可以编窗口程序吗?”这样的毫无常识的问题。我的FAQ就是为了来一次性解决这种问题的。
编程为何物
编程就是编制程序。程序是让计算机发挥功能的命令的集合。程序有两种形式,让计算机真正执行的是电脉冲形式,叫机器码,程序员编制的通常是文本形式,叫源代码。使用一个称为编译器的工具,可以把源代码转变为机器码。而编程就是产生那些源代码的工作。这个工作类似于谱曲、编菜谱、写工作手册。我们知道,谱曲并不是一蹴而就的,往往需要反复的修改,直到最后满意为止,编程也是一样,接近工作时间的30%是完成粗制成品,剩下的70%时间是在不断的修改,这是相当枯燥和乏味的。有志于投身编程的朋友们,不要忘记这一点。
如果这就是编程,那语言是怎么回事
文本形式的源代码,其实有些规定的。就像我们和老美用英语交流。首先你得说英文单词,不能冒法语词汇日文假名出来,其次你得按语法讲话,不能一个个单词往外蹦。程序也同样有词汇和语法上的一些规定,这些规定就构成一门语言。显然任何一门编程语言都是人造语言。人造的东西,因发明人的想法而不同,就形成了不同的语言。
我为啥要学编程
这个问题有两层意思。首先是编程为啥要学,很简单,因为这玩意不是生来就会,就像木匠活一样属于一门手艺,自然要通过学习才能掌握。你怎么也得花上几年来学英语不是。
第二层涵义才是重点,为啥我要学它。答案因人而异。有人为了上学有人为了考试,有人为了求职挣钱,还有人就是吃饱撑没事做自虐。什么为了开发智力啊证明自己啊寻找成就感啊,那都属于自虐,在下便属于自虐一族。没啥说的,确定你的目的,也许只是好奇想接触下啥是编程,也许是有课业的任务,也许是想以后靠他找工作,或者是羡慕那些黑客。总之,想继续深入的,往下看,没信心的趁早走人,外面帅哥美女多的是,不要浪费大好时光青春年华在一台破机器上,ok?
听说编程很难,是真的么,那我能学会吗?
你觉得说中文难么?你能流利的说普通话是不是。但是你知道么,汉语是世界上最难学习掌握的语言。稍后我会介绍计算机的特征,你就会明白知道基本上编程这件事的难度等价于指挥IQ<20的壮汉。任何一种计算机语言的难度都不会超过英语,更比不上汉语。那么你认为你能不能学会编程呢。
请记住学会和学好是两个层次,就像中学生作文和报刊出版物之间的差异。达到学会那个程度,只要有小学三年级的知识基础就可以开始了,也就是识字就行。而如果要学好,那需要初高中毕业的文化水准,也就是应该略懂英文和解析几何。当然还有更高的技术层次,比如在相当于职业作家的水平上,你将被称为专业程序员。而如果你被称为大师,那就是诺贝尔文学奖。抵达那个程度需要付出艰苦的努力,至于怎么达到,不在本FAQ讨论之列。
我真的可以么
如果你已经看完前面的部分到达这里,显然你是确实想要学习编程的新手。不论你是为了什么目的来学习,在看了我上面的话之后是不是很有信心呢,不过我要打击你一下,不是谁都学得好编程的。人人学开车,但不是谁都能上赛道,舒马赫更是只有那么一个。
就像有些惊险刺激的游乐设施禁止高血压心脏病患者参与一样,编程作为一项耗费智力和体力的活动,对参与者也有一定的要求,先来看看吧,满足这些条件,你就可以放心大胆的开始。
先说体质要求。太祖说:身体是革命的本钱。健康的身体对编程大有益处,但并不是说残疾人就不能参与。就目前的技术水平,除了脑瘫和目盲这两项,其他的肢体残缺根本不妨碍。霍金先生在这样严重的情况下还能持续研究的事实,还不够激励你么。
紧随其后的是足够的精力和时间。Dear friend,只要你能静坐20分钟安静的看完这篇FAQ,你的体能就达标了。如果你想告诉我,你能够一天在电脑前连续操作18小时以上,我要说的是,年轻人,虽然你很威猛,但请注意保养身体。只要每天您能抽出30分钟来学习,那你的时间也合格了。当然有更多时间确实会更好,不过也没必要每天12小时,编程并不是世界上最重要的事,我们还有别的事要做(这是对非职业选手说的)。必须认识到,学习编程重要的是持之以恒,而不是依靠爆发力,每天半小时比一周一次6小时效果好的多。
第三个要求是你要略微懂一点计算机。不错,只要略懂就可以了。因为这正是本文的主要目的:向略懂计算机的人介绍编程。那么,怎么才算略懂呢。
如果你能够前往这几个网站并浏览:www.google.com www.acm.org 和www.csdn.net,那么你的水平已经超过我的想象,完全能胜任接下来的学习。不用现在就前往,你知道怎样操作就可以了。
如果你还不会上网,没事。你会不会打字,不需要打得很快,也不需要会打中文,只要你能把键盘上的26个字母和十个数字挨个输入一遍我就认为你已经通过。然后,对于Windows用户,你能不能打开记事本程序,在里面打几个字并且存成一个文件。如果你说能,OK,你合格了。
你还不会打字或是不会用记事本?这样的话,你最好还是先学一学基本操作,否则本文对于你实在是毫无用处。
你找不到记事本程序,请让您边上的人指导一下,可能你还没有安装这个程序。有可能您不是Windows用户,联系给你装机的人或公司,或是你们的网管,让她给你可用的文本编辑器,通常会是vi或Emacs,当然也可能是别的,只要你会编辑并存储一个文件,就可以了。
你连电脑都没见过??@#$%^&*!!!! 这样的话,本教程对你根本没有用处,你还是看见过电脑以后再来阅读本教程吧。
最后一点,你需要有顽强的毅力。编程并不象你想象的那样轻松,不是野餐和聚会。尤其是对于职业程序员都应掌握的C++,她可以用两句话来形容:三年不开张,开张吃三年。千万记住,C++被称为是真正的程序员使用的语言不是没有理由的,她的复杂度和性能超出你的想象。有无数的编程新手,在第一个月不到就放弃了,你最好确定你不是他们中的一员。毅力没有尺子可以来度量,在这里我只能先祝愿各位读者都能坚持到最后。
还一定要有台电脑么
不幸的是,到目前为止,是的。在老年时期,贝多芬可以凭空作曲而不依靠钢琴之类的东西。但几乎没有哪个程序员不依靠电脑而只在大脑里编写,尤其是开始学习的阶段。
作为编程的另一方面,一台合适的计算机也是不可缺少的。用各种语言所编写的程序被运行在各种各样的机器和设备上,从掌上设备到巨型服务器,从台式电脑到微波炉,所有能够自动运行的地方都有程序的身影。但是很遗憾,并不是只要能够运行的设备就可以用来进行编程的,这就像虽然可能洗衣机也能发出悦耳的声音,但你不能指望用洗衣机来录制流行歌曲(嗯,也许SONY有这样的产品,我保留意见)。我们主要还是用个人电脑来学习编程。目前大部分语言,所需要的电脑并不如你想象的那样高级(.net系列不在我们的讨论之列,他的集成环境对系统要求很高)。就我所知,即使是主频只有30MHz,640K的内存,也是可以用来编写小规模C/C++程序的,只不过感觉不是那么畅快而已。当然作为学习,我们还是需要有比较称手的设备。不错,最重要的就是称手两个字,所谓称手,就是不会由于设备的问题,妨碍你的思考,不需要高速的处理器,也不需要巨大的显示器,更不需要海量的硬盘,只要称手。编程不是豪华海上旅游,而是修行。修行不需要五星级饭店,但也要有破屋以遮风雨,否则感冒发烧了,怎样来修行呢。那么还是来谈一谈电脑的要求吧。
只要你的电脑能运行DOS,就及格了。如果能够比较好的运行Windows 98操作系统(说实话,98死机是免不了的,只要不常死机就可以),硬件上就达到80分的要求了,如果能运行Windows 2000的话,那已经是满分了。如果比这还高档,那简直好的超出想象,甚至可以参加奥运拿金牌去。满分的那种设备,能够流畅运行.net环境的,在2008年1月份,全新的低于人民币一千元,二手设备甚至三百元不到。如果你实在囊中羞涩,可以考虑到毕业前夕的大学去碰碰运气,也许能遇到大肆的前辈们送你一台。在你看到本FAQ的时候,去任何一个电脑商场,随便购买一台,都可以符合要求。在下强烈建议你买一台自己的设备,那种自由是公共机房无法给予的。当然你执意要去机房的话,我也不反对。但你能看到这份教材,就连一台能运行win2000的机器都弄不到吗,怎么说现在也已经是双核时代了。
我希望你的机器上装着以下操作系统之一:Windows 2000, FreeBSD, Windows XP, Windows98, Linux ,MS-DOS或任何厂商的UNIX。我强烈推荐使用WindowsXP+SP2和FreeBSD这两个系统进行学习,本文中所有的程序在这两个系统都可以顺利运行通过,我将详细介绍在这两个系统下的设置,这对新手尤其重要。当然我也没有忘记其它系统的兄弟,相应的设置也不会遗漏。我没有提到Mac OS系列是因为我对她还不熟悉,但我不反对你拥有她。如果你的机器没有以上任何一个操作系统,请联系提供给你机器的人,如果不是你的机器忘记安装操作系统的话,那她极有可能是军方的机密设备,总之你小心为妙。
软件方面,依据不同的语言需要安装不同的软件。
如果学习C/C++。使用FreeBSD,Linux,Solias等UNIX系统的,推荐安装GCC,该程序是默认被安装的,总在系统的某处,初学者不必考虑版本问题。使用Microsoft操作系统的,建议使用VC 6.0或VC2005/2008,或者GCC的windows移植版。由于版权问题,如果不想破费的话, VC6要用VC2005的免费学习版来代替,BCB的命令行编译版和GCC的Win32版本来就都是免费的。GCC的Win32版有Dev-cpp,MinGW等不同发行形式。
其他语言都要按照相关的资料安装和设置。比如本文作者偏爱的Python语言,那是非常的方便,只要去python的主页直接下载对应不同平台的可执行包既可。
这些编译器怎样安装和设置我会在随后的章节里详细说明。毕竟,好多人的学习热情就是被这样的细节所消耗掉的。
除此之外,拥有以下两件法宝将使您如虎添翼。
一:一个被大家称作高手的喜欢玩计算机的人,这种人通常被叫做黑客或者极客。拥有他(她),你在遇到问题的时候,可以求他帮忙。记得给他点好处,吃个饭什么的。
二:便捷的Internet连接。可以上网意味着你可以干很多事,譬如可以和线上的高手(譬如我)即时联系,到论坛和usenet寻求帮助等等。这在有时是极有价值的。
好了,不要着急,还有一点点准备工作我们就可以出发了。
好吧你说服我了,我打算开始,该怎么做
首先确保你的健康状况和基本计算机操作水平,我上面说过的机器也已经找好了吧,从来没听说谁没有电脑就能学习编程的(以后科技进步到人机合一的程度,也许可以实现)。如果能有网络连接,那简直达到了完美的境界。
没人可以无师自通,天才也不行。所以你要做的第一件事是找一本好的入门教材,最好是经典作品。反复地看教材,要牢记一点,你所提出的大部分问题,教材上都有解释,只是你没有认真看而已。反复地阅读,直到你觉得你已经可以编写出那本教材了,才可以丢弃他。教材比老师好的理由之一是,你可以带教材上厕所去卧室,而老师不行。当然,老师也有比教材优越的地方,那就是他可以给你解释教材上没有的问题。但记住老师也是人,你不动脑子就去找他,他会厌烦的。不要鄙视你的老师,即使他其它方面不如你,至少在编程这件事上他能做你的老师就是他比你强的硬道理。
你以为光看语法书和背诵单词而不练嘴就能说好英语么,显然不对。编程也是,熟能生巧在任何地方都是一样的。首先看懂教材上的那些例子,确保看懂之后,按着他的思路把它默写出来,当你尝试过就会知道看懂和默写是两个完全不同的程度。然后就可以做书后面的习题,独立想,不要看答案或提示。等到整本书后面的习题你都能做对的时候,你就算入门了。然后去找等级考试二级三级的题目来做,等到也可以准确无误的时候,恭喜你,C语言(或者其他语言)可以算是通过了。如果你的目的是去考试,现在就出发吧。但如果你想要以编程谋生,sorry,你还欠火候。这其中的差别就相当于大学英语四级作文和畅销英文小说之间的差异。
那么下一步怎么干
只需要考试的朋友,不需要看这一段。想谋生或自虐的这边请。
通过C语言(或者其它语言)考试只是编程的第一步而已。你掌握了大量的单词并且熟悉语法还不能让你写出优美的英语小说。你要学习修辞手法、谋篇布局这类文学技巧,也需要掌握历史典故、谚语俗话和文化背景这些文字外的东西,如果要畅销,还需要超凡的主题生动的故事跌宕的情节。编程圈子里有和这些类似的玩意儿。
算法和数据结构就是程序里的修辞手法谋篇布局。人类编程虽然不过几十年,但运用程序所解决的问题,已经覆盖世界的每个角落各个方面。各种各样的问题,被前辈的大师提炼归纳。有些人们直接找出了解决的方法,有些人们找到了寻找解决方法的途径,还有些人们索性证明了在现阶段是不可能解决的。这些解决方案就被统称为算法。学习算法就是学习前人的智慧,少走弯路。连牛顿爵士都是站在巨人的肩膀上,除非你自觉比老牛还牛,凭空就能解决别人十几年才想清楚的问题,那我也无话可说。
学算法很简单,也是找教材,做习题。教材容易找,但新手往往找不到合适的习题。我的建议是,在完成教材上的所有习题之后,可以去找编程竞赛的练习题来做,也就是所谓的OnlineJudge,我会在后续深入讨论这个东西。
相当于历史典故、谚语俗话、文化背景的东西,就是各个编译器和平台上的接口和库了。假设现在有个程序要读写文件,不要误认为你需要亲自写个程序去控制硬盘的磁头伸缩,或者是光驱的透镜移动或者是U盘的地址定位。除非你是想做个window或者Linux那样的操作系统(那样的兄弟会来看这篇FAQ还真是奇迹),否则所有包括文件操作、网络通讯、人机界面(键鼠屏打印机)这些,都是由操作系统提供的现成模块,只等着你来使用。这些模块通常称为应用程序接口,不同的操作系统提供的不一样。在接口的基础上,很多编译器和程序员做了进一步的包装形成了库,你可以比直接使用接口更方便地使用这些库而达到同样的功能。
由于系统的不一致,编译器的不同,所以在学库之前,先要确定你所要工作的平台和环境,还有应用方向。Windows下编游戏和Linux下做数据库用的库是大相径庭的。然后就是同样的一套步骤,找教材,做练习。这个教材通常就是官方文档,windows下最好最全的就是MSDN,Unix/Linux平台有大量的文档,分布于man页和各种手册上,其他平台自行搜索。可以去找习题,但更好的方案是去找一个实际的小型应用,在使用中学习效果无与伦比。编写一个QQ或者BT,绝对能让你对网络操作部分了如指掌。在这个阶段,你已经可以写出实用的程序了,为什么还要执着于做题呢。
优秀的文学作品有个共同的特征,他们虽然立足于不同的本民族文化,但却关心全人类共通的思想感情,体现着终极的人文关怀,我们都会为奥塞罗流泪不是么。优秀的程序虽然应用方向不同平台各异,但他们一定完全符合计算机原理,用最合理的数学模型来展现。如果你想成为合格的程序员,计算机原理和相关的数学知识是一定要补习的理论课。
除了看书和做题之外,还有一个内容不可缺少,就是阅读别人的程序。没有哪个作家不大量阅读别人的作品,同样你也可以从别人的代码中吸取营养。代码就是程序的全部,是真实的实现方法,一切都在代码中,甚至有时长篇累牍的说明还不如几行代码清晰明白。今天的程序员是幸运的,开源运动的发展使得他们能够无偿而方便地得到世界上最优秀的并且是实际运作中的代码,几乎遍布任何应用领域。只要你有心,可以找到任何想要的代码。但读代码也是辛苦的事,请阅读和你水平相当的代码,差距太大将会是严重的身心打击。
学习库和学习算法可以同时进行,在你完成这两个阶段的时候,你已经是一个合格甚至是优秀的程序员了。
超凡的主题跌宕的情节,这个东西其实就是你的程序的应用方向。如果说前面都是练习的话,这就是你自主创新的时候到了。很多人都只是在老板的安排下为了工资而被动做些既不喜欢又没有价值的流水线产品,少数人才有机会做自己喜欢的东西。想想看,QQ、3DMAX、WOW、IE、Apache甚至Windows都是多么知名的程序,有朝一日你的程序将会和他们一样知名。不过我还是不得不给你泼冷水,这需要不懈的努力、敏锐的眼光和少量的运气,只有极少数的程序员能做到这一点。不过,有梦想才能不断前进,不是么。
我碰到问题了,谁能帮我
郑钧说,记得没人会同情你,我亲爱的兄弟。这真是至理名言。编程这件事,基本上是不能指望有人帮你的。
当你遇到编程遇到问题,首先应该是去看编译器提供的信息。它可是最直接的来源,相当于案发现场,从没听说刑警不看尸检报告就直接破案的。现代的编译器已经不止编译那么简单,编译本身就能送出大量的提示,调试功能更是强大到可以让你检视程序运行的每一步都发生了什么变化,只要你能看懂。机器的问题,就应该用机器来解决,而不是用人的肉眼去检查。
然后就去查教材和文档。手边的教材能解决70%以上的问题,如果还不够,上网去查。如果找不到,请记住有个东西叫搜索引擎,国内最著名的两个,google baidu。99%的问题可以得到解决。
如果你有老师,可以试着向他请教。不要抱太大的希望,虽然他收你学费,但他也不是万能的。
如果还是不行,确认你已经努力过而没有答案,那么你可以考虑提问,去论坛、新闻组或者群,都可以提问。
在你确定要提问之前,请先阅读这篇文章《提问的智慧》
http://www.chinaunix.net/jh/29/8675.html
http://www.vcgood.com/bbs/forum_posts.asp?TID=1581&PN=1&TPN=1
这个也行,《提问的智慧 图片版》
http://bbs.chinaunix.net/viewthread.php?tid=750796&extra=page%3D1
http://www.vcgood.com/bbs/forum_posts.asp?TID=1573&PN=1&TPN=1
我能看懂别人的程序,但自己做就觉得无从下手,怎么会这样
正如你所知道,刚开始学习的时候,我们总会作一些习题,等到后来涉及实际的应用程序,我们也可以把它们都看成是大型的习题。这个问题就变成了,为什么你能看懂别人的解题程序,而自己写不出来。这个问题其实每个刚开始学习编程的人都会遇到,你所见到的各位达人大牛都曾经有过这段经历。所以不要为这种情况而怀疑自己的能力。
为什么会有这样的情况出现呢,因为思维模式。
在小学的数学教材里,有一种题型,叫应用题。他会给出很多生活中的场景,然后让你用数学知识来解决。在解这种题时,其实分为三个步骤,首先是要提取出数理模型,比如常见的追击相遇这类问题,就要使用速度时间模型,然后把这个模型数学化,找出各个变量之间的关系,确定已知量和未知量,形成可求解的方程,最后求解。
编程的情况与此类似。首先要建立一个抽象描述模型,然后建立数学表达,接下来略有不同,不是亲自求解,而是给出求解的方法,也就是算法,最后把算法转化为程序。而新人通常之所以会卡壳,是由于这个流程中有两个难关。建立模型不是问题,数学表达也不难,但找出算法却是非常艰难的事情,即使找到正确的算法,要把它写成正确的代码也不容易。新人常说我在学习XX语言,XX语言真复杂啊。其实学习语言本身只能保证你在最后一步,也就是翻译代码那里少出错误,即使你顺利的学习了一万种语言,你也会觉得编程很难,如果你没有学习算法的话。
让我们找个具体的例子来说明,假设现在有个题目要找N个正整数中的最大值。显然这个题目模型很清楚,本身就是数学问题,也不需要数学表达了。接下来就是解法,新手这时就卡在这个地方了。
刚接手这个题目,很多人就会想用一种类似人类的快捷操作,比如三个数,瞥一眼就可以找出最大值,四个数也毫无问题,甚至十个数也是一下子。这时我问你,你怎么把这个瞥一眼的动作表示成程序,另外如果N大于10000怎么办。哑口无言。原因是,人类的头脑过于聪明,可以同时处理很多事务,也就是可以并行处理一定量的数据(当然大规模数据就要另外对待)。而计算机,很遗憾,没有这种能力。有人要和我抬杠,现在不是有多处理器多核多线程等各种各样的并行处理的计算机了么。我要告诉你,那些都是不同层次的概念。目前这个时代的计算机,在出现革命性的变化之前,从CPU指令的层次来说,都是单线程单参数工作的。再说明白一点,这些机器任何时候只能一次处理两个数,而且其中一个还必须已经在CPU内部了,任何N>=3个数相加都必须转化成持续的两个数相加,就是先把第一个第二个加起来得到结果之后,才能和第三个相加,照此重复求得所有的和。这时目前的科技无法改变的铁律。
这个时候我要请你记住一个重要的思想:编程中任何问题都要分解到足够小,小到机器可以一次解决的程度。回到刚才的那个题目:寻找N个正整数中的最大值。我们知道直接解决是不可能的。而按照刚才讲过的铁律,我们知道直接找到两个数中的最大值是一次可以做到的。怎样从2个扩展到N个呢。这里就是算法的天下了。一种很常见的想法是,完全可以从两个中找出最大值,再让他和接下来的一个比较,这就是N=3的情况,再把三个中的最大值和第四个比较,这就解决了N=4,以此类推,我们似乎找到了通用的算法,是的,找到前N-1个中的最大值,然后与第N个比较。不要怀疑,这个算法方向是正确的。接下来就是把它细化使他能变成代码。你注意到,首先要设法从1增加到N,而且每次前进一步都要做类似的操作。显然用一个循环来实现。每一次循环中,都需要将保留的最大值和当前的这第n个数比较,如果最大值比他大,那就保留,否则就要把最大值替换成新的。这就是条件语句的作用了。写完这个循环之后,还有些小细节,比如这个最大值在于第一个数比较之前应该是多少呢,太大的话,可能会比整个数列的数都大,这就会出问题,常用的做法是,就让他等于第一个数。然后包括读入那N个数,输出这个最大值这些琐碎的细节就属于收尾工作了,没什么可多谈的。
当然,即使是这样的小题,也不仅这一种算法。你记不记得有一种叫做单淘汰赛的机制,最后顶点的就是最大值。用在这个地方正合适。不过,如果要把这个淘汰赛算法实现成程序的话,如何实现分组,如何表达这个淘汰过程和取出顶点的值,正是算法描述里要解决的。这个就是排序里很有名的最大堆排序。一旦算法描述齐备,程序编写不过是打字校对的工作。
现在你明白本节讨论的情况的实质在哪里了吧,是的,是算法。为什么你可以看懂别人的程序呢,因为他的算法隐含在程序中已经被实现了。就像你读一段高明小说家的风景人物描写,总能在眼前浮现出那幅画面。但轮到自己写,却描绘不出那样的画面。一方面是因为你胸无成竹,不知道怎样找到可实现的算法,另一方面是即使你找到了算法,也是爱你在心口难开,也不清楚怎样去表达他。
算法总是从问题出发,通过一定的模式,逐渐细化再细化,直到可以直接转成程序。新手很难一下子领会怎样的算法是可以实现的。但好在新手接触的问题不是很难,算法通常很清楚明白,所以重点先要解决后面那个表达的问题。这就是为什么我建议各位默写教材上的例题程序的原因。很显然对于那些例题,只要你用心看过就会领会他的算法。那么,你再默写一遍,即使和他的原程序样子不一样,也总算是把这个算法表达出来了。反复这样练习,这个表达问题不就解决了么。而且在这个过程中,至少你学到了一个算法。基于此原则,任何你遇到的可以看懂的例程,我都建议你默写它。尤其是例如等级考试的题库的标准答案那样的东西,以及开源的精品代码。
我英语\XX不行,咋办
无法回避的事实,今日世界中的信息技术,绝大部分是欧美人的发明,更明白地说,是美国人的功劳。顺理成章的,各种资料文档技术手册,尤其是记载最新技术的,都是用美国通用语也就是英语撰写的。可能在其他领域不懂英语没有什么问题,但在IT业,不懂英语就是无法掌握最先进的技术,基本等于没有出头之日。
话说回来,不是说你一定要有个托福雅思的高分才能去学编程的。就编程本身而言。他所需要的英语水平不过是死记硬背三五个单词而已。你在看好莱坞大片时,一部片子下来总能记住主角和主要配角的名字吧,C语言全部关键字一共32个,而其中有6到7个的使用率超过78%。这样你还有什么可担心的。但是,要想成为高手,阅读大量的相关资料是免不了的,这个时候,英语就显出它的重要性了。
刚才谈过算法。前辈们已经总结出很多算法和产生算法的方法,我们可以直接学习。如果你积极进取,总有一天,你会发现有需要自己开创新的算法的时候。这个时候,数学功底会帮你很大的忙。也许只是数学工具在起作用,但更有可能是你的大脑受过的数学思想训练在帮助你。总之,为了前途着想,提高数学素养是没错的。这不是说多背数学公式和多做数学题,而是指一种数学的思维方式。
看不懂英语,那编程还有什么前途。数学不行,成为大师的希望不大了。不能上网,你完蛋一半。没有机器,难道要我买给你。指法不行,练去。
记得没人会同情你,我亲爱的兄弟。不会就去学吧,没有什么是不可跨越的障碍。
请记住这段话:在信息时代,任何主观障碍都不存在。如果你要研发什么新技术的话,只需要一台便宜的二手电脑、一张linux光盘和一个上网账号,再加上为之献身的决心,你就可以达到想要的任何编程深度。这话是一位大牛说的,那是谁,回想一下提问的智慧,然后自己上线查。
关于态度、情绪和其他
和技术无关,关于学习态度和方法的一些提示。
《循序渐进学编程 》
http://www.vcgood.com/bbs/forum_posts.asp?TID=1353&PN=2
《一个程序员给初学编程人的建议》
http://www.vcgood.com/bbs/forum_posts.asp?TID=265&PN=1
《 c语言学习经验--请不要做浮躁的人》
http://www.vcgood.com/bbs/forum_posts.asp?TID=1359&PN=2
《成为软件高手的几个忌讳》
http://www.vcgood.com/bbs/forum_posts.asp?TID=155&PN=8
《程序员四大忌》
http://www.vcgood.com/bbs/forum_posts.asp?TID=174&PN=8
=========================================分割线================================
二、选择C/C++语言
C语言是什么
C语言是一种计算机编程语言。语言是什么,请查阅上面的内容。
1970年前后,AT&T 贝尔实验室的 Ken Thompson根据BCPL语言设计出较先进的并取名为 B的语言,之后Dennis Ritchie在此基础上设计发明了C语言, 并首次在UNIX操作系统的 DEC PDP-11 计算机上使用。随后,C语言和UNIX操作系统一起,攻占了计算机世界的大片领地。
在发展的过程中,出现了许多略有差别的C语言版本。1989年,美国国家标准研究所(ANSI)为C 语言制定了一套ANSI标准, 成为现行的C语言标准,就是所谓的C89。当然经过10年的发展,在C89的基础上又颁布了C99标准。现在流行的大部分编译器完全支持C89,部分编译器完全支持C99。对于初学者来说,掌握经典的C89即可。
C++语言是什么
C++和C的关系非比寻常。1979年,当Bjarne Stroustrup在新泽西州的Murray Hill实验室工作时,发明了C++。Stroustrup 最初把这种新语言称为“带类的C”,1983年,改名为C++。C++通过增加面向对象的特性扩充了C。因为C++产生在C的基础之上,因此它包括了C所有的特征、属性和优点。在这个意义上,你可以认为C++是C语言的进化,这个进化的原因是复杂性(complexity)。一旦一个程序的代码超过25 000~100 000行,就很难从总体上把握它的复杂性了。C++突破了这个限制,帮助程序员理解并且管理更大的程序。
当然今天的C++已经不只是C的进化那么简单,他还包含了其它很多很多的新内容,它是如此的复杂以至于你要花上几倍于学习C的时间来学习他。但由于他和C的历史渊源,所有支持C++的编译器都能支持C。因此他俩也就被合称为C/C++语言。
C++对于C的进化着重体现在规模上,几乎C++的所有新特性,都是为大规模编程服务的。如果说C语言编程是单兵小组作战的话,C++编程就是集团军运动。
为何要选择纯C
在某些时候,我们不得不只使用C语言而不是C++,这种情况称为纯C编程。最常见是因为以下两个原因:
C++的语法很复杂,所以C++的编译器很难制作。因此在很多平台上没有现成的C++编译器,而C编译器因为足够简单,几乎到处都有,这时就只能用纯C。实际上最初的C++编译器也是用C语言来实现的。
仍然是因为C++很复杂,为了实现很多特性,做出的程序往往比用C做的类似功能程序体积要大很多,在程序的空间和时间要求比较高的时候,也只好选择纯C。
上面两种情况经常共同出现,实例之一就是嵌入式设备。各种单片机往往没有足够的内存和处理器能力,在上面实现C++编译器也比较困难,因此往往是纯C开发,而非C++。
C/C++语言和其他语言有什么关系
java 只要用一句话就可以概括,它是一种简化了的跨平台的C++语言。掌握了C++的人,学习java几乎是轻而易举。
basic pascal delphi(其实是objectPascal) perl python 还有其他诸如此类的语言,或者与c处于同一档次,或者与C++处于一个水平,学过C/C++之后,再去学习他们是很容易的事。作者个人比较偏爱和看好python,它的很多特性使他极有前途。
lisp Scheme是和C的思维方式完全不同的一类,被称为函数式编程语言,在人工智能等领域有奇妙的应用。有兴趣的朋友可以去领略,如果你要成为一个大师,至少要学习其中的一种。
我为什么要学C/C++语言
考试的人不用讨论这个问题,他们没有选择。如果我们有选择,为什么我们学习C语言而不是别的。
首先因为C本身是非常优秀的,他是世界上最伟大的编程语言之一。许多人认为C语言的产生标志着现代计算机语言时代的开始。它成功地综合处理了长期困扰早期语言的矛盾属性。C语言是功能强大、高效的结构化语言,简单易学,而且它还包括一个无形的方面:它是程序员自己的语言。它的设计、实现、开发由真正的从事编程工作的程序员来完成,反映了现实编程工作的方法。它的特性经由实际运用该语言的人们不断去提炼、测试、思考、再思考,使得C语言成为程序员们喜欢使用的语言。
在编程规模越来越大的今天,用C往往会遭遇协作型的问题,而C++在保持了C的高效的同时,实现了大规模协作的可能,因而成为了真正工业化的语言。
C/C++的优秀,使得他是主流的,在20世纪70年代末和80年代初,C成为了主流的计算机编程语言,至今仍被广泛使用。今天几乎所有的操作系统、大部分的(大于70%)的应用软件,90%以上的大型游戏都是用C/C++编写的。在对运行速度和资源占用有严格要求的领域,比如游戏、即时控制、嵌入系统,基本都是C语言内嵌汇编语言的天下。今天只有一种语言的性能比C强,那就是汇编,优化过的C程序的速度大约是汇编的95%-98%。但汇编基本不是常人用的。所以实际上C就是最快的语言。
主流的就意味着资料丰富。不论是编程时所需要的文档,还是学习的示例代码,甚至是平台提供的接口和库,C/C++语言版本都是最丰富的。业界的算法研究理论研讨,大部分都是C/C++语言,开源代码的78%以上是C/C++.任何一家硬件软件公司,当他开发一款能够编程的设备或是软件,必然会提供C语言的接口函数。其他的语言,就不一定有这样的好处了。不论是计算机图形学、加密解密还是计算机编程的其他领域,C/C++简直就是编程界的普通话。根据 International Data Corporation 的统计,C/C++ 是全球开发者使用最多的编程语言。如果确实要投身编程界,不懂C/C++的话,根本就是Mission Impossible。
如果你还不明白,我只需举一个小例子。假设你现在有机会去学习一门外语,投入时间差不多,你会选择学习英语呢,还是斯瓦希里语呢。(斯瓦希里语流行于非洲东部,为肯尼亚坦桑尼亚等国的官方语种)
当然,并不是说其他语言不值得学习,存在即是合理,今天存在的各种语言,当然都有它存在的价值,多学一点没有坏处。没有人禁止你在学会英语的基础上再学习法语日语等等。况且为了找工作等现实原因,学习其他语言也是非常正常和必要的。无论过去、现在还是将来,天底下不存在哪一门语言非学不可才能成为高手,思想最重要,“不会XXX语言不算真正的高手”之类的言论实在无聊之至。学C/C++,主要还是通过他学习编程思想。真正的武林高手,难道会局限于手里的那把大剑吗。
但我们还是强烈建议初学者从C语言开始,因为除了上面所提的好处,C语言还足够的简单。初学者或许会觉得C很难,但请记住,那些是编程之难,不是C之难。当你学过三种以上语言的时候,就会越发体会到C的简单。
Python语言 作者的另一推荐
虽然如上所述,C/C++语言有如此之多的好处,但他也不是完美无缺的,第一个致命弱点是复杂性。为了应付千奇百怪的需求,C++提供了很多奇妙的语法从而实现了各种现代编程特性,这就使得C++变得异常复杂。可以充分体现这个情况的一个事实就是,迄今为止,还没有哪个C++的编译器是100%完全实现C++官方标准的。如果有一个程序员对你夸口说他已经彻底掌握了C++的话,你基本可以断定他接触C++还没超过半年。幸好C语言还没有复杂性的困扰。但是开发效率也是C/C++的致命伤。因为过于接近硬件底层,C/C++程序在运行时几乎可以调动一切资源,取得最高的性能。但与此同时,C/C++程序员必须小心维护程序的运行状态,稍有不慎,轻则文件丢失内存泄露,重则死机甚至导致整个系统软硬件崩溃也是有可能的。所谓高收益必与高风险相伴就是这个道理。这就使得开发时必须小心谨慎,开发效率也就提不上去。
对于性能要求极高的程序,比如要求大量高速3D计算的计算机游戏、密集科学计算的工程软件、同时应付巨量用户的网页和数据库服务器,使用C++是当仁不让的选择。但是对于很多应用来说,些许的延迟是可以忍受的。举例来说,在某个工程中想要得到圆周率的后十万位,如果此时我们不在乎0.25秒和1.25秒运算时间之间的差别的话,就可以选择开发效率极高,而计算速度相对较慢的其他语言来实现。
在所有这些其他语言中,本文作者强烈推荐的是 Python语言。
由创始人Guido van Rossum在1989年圣诞节期间创造出来的Python语言,是一种面向对象的解释性的计算机程序设计语言,也是一种功能强大而完善的通用型语言,已经具有十多年的发展历史,成熟且稳定。Python 具有脚本语言中最丰富和强大的类库,足以支持绝大多数日常应用。这种语言具有非常简捷而清晰的语法特点,适合完成各种高层任务,几乎可以在所有的操作系统中运行。
Python语言有两大关键特点。首先他被称为是一门清晰的语言。因为它的作者在设计它的时候,总的指导思想是,对于一个特定的问题,只要有一种最好的方法来解决就好了。这在由Tim Peters写的python格言(称为The Zen of Python)里面表述为:There should be one-- and preferably only one --obvious way to do it。这正好和Perl语言(另一种功能类似的高级动态语言)的中心思想TMTOWTDI(There's More Than One Way To Do It)完全相反。Python语言是一种清晰的语言的另一个意思是,它的作者有意的设计限制性很强的语法,使得不好的编程习惯(例如if语句的下一行不向右缩进)都不能通过编译。这样有意的强制程序员养成良好的编程习惯。简单来说,几乎所有的python程序看起来都是一个样子的,而相对的,人们说,到哪里去找一段随机字符,读一段perl程序就行。
第二个特点是他被称为胶水语言。哦,这可不是说他会把你的手指给粘住。他的意思是他可以象胶水一样,把用其他语言制作的模块拼合起来。很多人是这样用python语言制作大型程序的:他们先用python做出一个可用的程序,再把其中最影响性能的部分用C/C++语言重新写成模块(在已经满足要求的时候,根本就无需替换)。不用担心配合的问题,python的可扩充性完全可以胜任要求。可扩充性可说是Python作为一种编程语言的特色。新的内置模块(module)可以用C/C++或其他语言写成。同时也可为现成的C/C++或其他语言模块加上Python的接口。这样一来,我们既能充分享受到python快速开发带来的效率,又能够实现足够强大的性能。
再加上设计极为出色的三大内置数据类型:异构列表、元组、字典和从函数式语言学来的列表解析、对象自省、方法动态生成等突出特性,使得它的功能变得极为强大的同时程序又相当简洁。想想看,你能在C程序运行的同时,改变自身的代码让他再次以另一面貌运行么,python就可以轻松地做到。同样的功能,用python实现所需的语句仅仅是C的十分之一到二十分之一,而开发(包括调试)所需要的时间更可能只需要百分之一。
Python在编程领域的占有率一直处于稳步上升之中,根据2007年末最新的统计数据,Python排名第七。前六名分别是Java,C,VB,C++,PHP和Perl. 作为一个很年轻的语言,Python的位置已经相当令人振奋了。随着微软将Python纳入.Net 平台(官方行为),相信Python的将来会更加强劲发展。Python 很可能会成为.Net平台快速开发的主流语言。欲了解这方面情况,请参考Iron Python的相关信息。
著名的搜索引擎 Google 大量使用Python,NASA等大站也在用。更加令人吃惊的是,在Nokia智能手机所采用的Symbian操作系统上,Python成为继C++,Java之后的第三个编程语言!可见Python的影响力之巨大。
作者个人的观点是,Python语言是少有的一种可以称得上即简单又功能强大的编程语言。对于工程师会计师这类非职业程序员(本人就是),在平时需要某种语言来编写程序解决一些小问题的时候(例如做个土方计算,分析某种投资的收益,批处理一些文件的改名压缩之类),python是比C语言更好的选择。即使对职业程序员,python也是称手的工具。总之,python就是手边的语言。
=========================================分割线================================
三、其它一些重要的概念—计算机原理
编程的对象是什么————计算机
如果你看到的这篇文章是电子版的话,你眼前的东西就是计算机,也就是俗称电脑的东西。这样的说法对普通用户来说是已经足够了,但是电气工程师认为一堆电路板、缆线、马达、和机壳的组合才算,联想的销售人员认为他们卖的那些方块才是计算机,而中央军委的人大概觉得银河5才能称得上。程序员的看法和他们并不完全相同。程序员看来,只要能自动计算的东西,就是计算机。这个说法的重点在于自动和计算这两个词。广义的计算是指能对外界的某种输入做出反应,不一定就是数学运算。比如电梯就可以对按键做出反应,所以她也是能计算的。自动是说计算是通过自身的运作来完成的,不需外界干预。在有电的时候,电梯就可以自动运行,这样看来电梯也是计算机。算盘虽然能计算,但不是自动完成的,如果把打算盘的人一起算上,那就是不错的计算机了。使用指纹或虹模的智能锁、秦始皇陵里的机关和自动钢琴似乎也都是一种计算机。情况确实是这样,计算无处不在,计算机也无处不在。如果你有兴趣的话,可以把我们的世界看作一台巨大的计算机,然后就觉得我们是生活在Matrix里,不过打住,我现在没兴趣和你讨论哲学问题。通常在实际编程中,程序员只考虑现代数字电子计算机,也就是使用电能为动力,在运算时以电子电路和逻辑代数为基础的计算机。他们用途广泛,种类也是极其繁多,手机、PC、服务器是比较常见的样子,电梯、收银台、智能门禁则是各种隐藏的版本。虽然设备的外在形式千变万化,但现代电子计算机的基本原理和体系结构并没有太大的变化,这体系结构的问题我们会在以后详细讨论。就本文的读者—新手程序员而言,回答什么是计算机这一问题,请回头看本段的第一句话。
程序到底是怎么回事————是操作而不是结果
计算机本身什么也做不了,必须依靠程序来指挥他做事。程序就是操作流程的顺序,或者说是顺序排列的多个操作过程,他是方法的描述。
有一次我的朋友王二老板要做家具,这可是他的老本行。他先把原木分割成木条木板,再把木条木板弯曲到指定的形状,然后把他们放置到适当的位置,接着设法固定他们,最后雕花抛光和上漆,一张漂亮的摇椅就做好了。这整个的流程如果记录下来,就是一个程序。任何程序都有三个要素,执行者、操作对象(也称为资源)和操作方法(指令)。在做家具这个程序里,王二就是执行者,木头就是他所对付的资源,在指令的持续作用下,木头(资源)的状态(如形状大小、颜色位置等)不断发生变化。最后,在程序结束时,木头变成了家具。
电脑程序和上面一样,是方法的描述。只是这些程序的执行者不再是人,而是CPU,命令也变成了CPU的指令(无法想象怎么给CPU下“吃口菜”的指令),而资源则是CPU可以改变其状态的东西,通常是内存,当然端口硬盘等等也是,不过一般应用程序都只使用内存就可以完成工作。
有一点要注意,CPU其实并不知道自己在做什么,是程序在指挥CPU的运作。这一点比较难理解,让我举例说明。来看一个算盘的计算,要使用算盘,只需要一件东西:口诀。记熟口诀(当然还有它对应的操作),就可以用算盘计算。在这个用算盘计算的过程里,口诀就是程序,指导着计算过程。算盘自身并不知道自己在计算,他只产生了物理上的一些变化(算珠位置的变化),做珠算的人同样也不需要知道,他只需要按照口诀调整算珠的位置。当程序结束的时候,算珠必定会处在某个位置上,这个位置的状态可以按照某种约定被读出,被读成某个数值,比如下面4个算珠全都在中档而上面的珠子没有落下的状态就是4。
操作和储存状态的设备并不需要知道状态是怎么转换成信息的,转换由阅读者来完成。显示器在显示图像的时候,总是这样进行:
坐标(1,1)黑色、坐标(1,2)白色、坐标(1,3)白色、坐标(1,4)白色、坐标(1,5)白色、(1,6)白色、(1,7)白色、(1,8)白色、(1,9)白色、(1,10)黑色……(2,1)黑色、(2,2)黑色、(2,3)黑色、(2,4)白色、、(2,5)白色、(2,6)白色、(2,7)白色、(2,8)白色、(2,9)白色、(2,10)黑色…………虽然显示器只是在适当的坐标显示黑色或是白色,但我们却在显示器上看到了文字、图片和动画,你不会认为显示器知道这些是鸟山明的漫画吧。
计算机也是一样。比如计算圆周率的程序,CPU只是不断地对某一块内存进行操作,当程序结束的时候,这块内存恰好处在某种特殊的状态。而按照事先的约定,这个状态在被读出来的时候,它正好和圆周率相同。于是我们说,算出了圆周率,其实CPU只是在那里象手指头一样拨动内存的算珠而已。这种算珠极其简单,他只有两个位置,0和1,拨动它也很方便,电流就可以,但这种算珠实在太多,使得他们能组合起来表示很复杂的信息,就象只有黑白两色的屏幕点当数量足够多的时候,就可以用来表现有趣的漫画。
所以程序代表人期望电脑能做的事(注意不是电脑要做的事,这一直混淆着许多人),当人需要做这些事时,人提供指令,再给出某些资源以期电脑能对其做正确的改变。程序只是方法的描述,本身是不能发生任何效用的,直到它被执行,人为给定它一块内存,告诉它计算结果的精度及计算结果的存放位置后,他通过控制CPU才改变人为给定的这块内存的状态以表现出计算结果。
通常,我们把计算机的物理实体部分称为硬件包括电路板、机箱、键盘鼠标等,而把不可见的非实体部分称为软件,软件大体就是程序和主要由程序产生的数据。广义的说,乐谱、菜谱、工作手册、仪器的操作说明也是某种程序,我们不妨称之为类程序。
为什么要编程————因为机器的特点
编程这件事存在,完全是迫不得已。人们发明了计算机,想让它做事。但机器有三大特点,使得如果要让机器做事,完全不像吩咐人那么简单。
第一个特点就是机器很傻。很多人希望自己像计算机一样聪明,我说如果那样你就完了。举例来说,从三个数里选出最大最小值,人类可以一眼就看出,但机器只能先从两个里找出最大的,在把这个最大的和第三个比较,然后再这样重复一遍找出最小值。如果是四五个数,机器也是这样反复操作(我想这个例子我已经讲过了)。这就类似工地上搬砖,人类的做法一次搬很多很多砖,用推车或者别的把砖码得高高地然后运到目的地。计算机的做法是每趟只搬一块砖,你没看错,每趟一块。
那为什么计算机这么厉害呢,因为他的第二个特点,快而不乱。机器可以不知疲倦地用同一方法,重复重复再重复地做某件事,而且每次重复都相当的快。这一点是人类做不到的,让一个人搬一堆砖,也许没什么问题,但是一车砖就会让人疲惫不堪,如果有一轮船的砖,想必大多数人想都不想就放弃了,即使有坚持去做的人,他的动作质量也只会越来越差。但机器不同,他搬砖不是每趟一块么,但他每趟来回的时间很短,比如低于0.00……001秒,不管砖头有多少,十万块也好十亿块也罢,按同一方法处理,既没有差别也不会厌烦直到全部处理完。从总体来比较结果,机器就比人强了。还是以选最大最小数为例,人可以用肉眼检视三四个数,但超过100个数就要用其他的方法。对机器来说,三个和三万个数只是重复次数的差别。单调快速的重复,这就是机器的诀窍。
更重要的一点,机器和我们言语不通。就是说,我们不可能一抬手一挑眉毛就吩咐他做事。不要和我抬杠说你可以用鼠标画圈让机器做事,也可以声控。那都已经不是纯粹的机器了。机器和我们处在一个不同的感知空间,所以他不能理解我们的话语。我们要命令他,必须用他能够理解的形式。从根本来说,就是电脉冲。
基于这三个特点,要让机器做事情,就必须让把我们的要求转化成最简单适于重复的命令集合,而且是电脉冲形式。比如我们要让机器在屏幕上显示一幅图,首先我们要把这幅图分解成很多很多的小方格,也就是所谓像素,每个像素只有一个颜色,每个颜色都用一个很长的数字表示,然后所有这些数字转化成内存里的电平信号,再用另外的电路信号来一个个的把这些电平送到显像电路。所有这些电平和信号的集合就是程序。而编程,就是制造这些程序的工作。
也许有一天,我们不再需要编程序,程序员这个职业也不复存在。不过我想如果那天到来,那就是机器已经能完全理解人类的语言和思想的时代了。在肉眼所及的范围里,似乎还看不到呢。
你们老是提到编译器,那是什么-----代码翻译机
这个问题经常被问到,我在前面的文字略微解释了一下。不过我不介意再解释一次。
是的,我刚刚说过,程序其实是电脉冲形式的指令的集合。对机器这是绝对正确的。但你认为人类可以直接操作电脉冲么,当然不能。所以最早的时候,程序员们是通过反复的拨动开关或者插拔插头来做这件事的,就像老电影里的电话接线员和发报员。后来技术进化了,人们可以把脉冲信号设置在打了孔的纸带上,然后让纸带穿过有灯管的感应器,有孔电路就通,没有就是断,由纸带机实现了在电脉冲和纸带之间转换。老电影里的工程师们经常拿起一条长长的纸带来阅读。真是高深莫测啊。不过即使这样,要理解程序还是很困难,更别说阅读编写和修改了,人毕竟不是机器。其实人们最习惯用来表达思想的方法是文字,于是人们设想能否直接写出文字形式的程序。通过不懈的工作,这个目标实现了。今天人们可以写出文本形式的称为源代码的程序,然后再利用特定的工具把代码转换成机器能理解的电脉冲形式,也就是目标程序。这种转换工具就叫做编译器,作用相当于翻译,以前是纯粹的机电设备,到了现代他也成了程序的一种。
从某个角度来说,其实没有任何人能被称为程序员,编译器才是真正的程序制造者。人所制造的只是源代码。从这个角度往下想的话,其实是程序在制造程序,换言之,程序在借助人类之手自我进化。
在这里顺便讲解下编译和解释的差别。编译器的工作本质上类同于翻译,而我们知道其实翻译有口译和笔译两种工作模式。程序员写完所有的源代码,由编译器一次性转为可执行文件留待以后执行,这种类似笔译的模式我们称为编译。程序员每次输入一行或数行代码,编译器马上把他转换并执行,并等待程序员的后续输入,这种类似即时口译的方式就称为解释,此时编译器就被叫作解释器。C/C++ pascal等语言是编译型的,perl python等语言就是解释型的,java语言很特殊,他先编译成一种中间代码,然后在不同的机器上边解释边执行,这样就能实现跨平台运行,成为半编译模式。微软的.net也是这种机理。现代的新型解释性语言很多都是半编译的,兼顾了运行效率和跨平台性。一般来说,编译型要比解释型的运行效率高些,因为不需要等待程序员的输入,也便于系统优化,但解释型在编程的时候容易排错,界面友好,而且通常程序编写比较方便。不管用哪种语言编程,你总需要一个编译/解释器。
现代的编译器,往往不止是编译器,他还会包含有着色和搜索等功能的代码编辑器,支持单步调试并行调试的调试器,能够读入文件的多个版本并进行比较分析的版本控制,编辑图标等的资源编辑器,在大型项目中用于统一协调的项目管理,和用于自动化代码生成的向导工具等等。这样的编译器,我们就称它为集成开发环境(IDE : Integrated development environment ),最著名的代表就是微软的VisualStudio系列。
给我解释下啥叫编程语言————各路江湖武功
菜谱、仪器的操作说明可以用法语来写、也可以用中文来写,不影响实质效果。因为人类生存在同一个四维物理时空中,具有相同或类似的感知。虽然人类的语言五花八门,但都可以通过翻译得到正解。仪器操作说明、一般的菜谱,所描述的都是人类世界的事物,人类可以理解,因此它们可以用人类的语言来描述。但计算机程序显然与菜谱有不同,他是指挥计算机用的。首先CPU所能感受到的物理空间和与人类的感受严重不同,很多概念根本无法传达,其次没有大脑的计算机并不懂得人类的语言,何况人类的语言并不那么完美,很多事不能精确的描述,所以人类的语言不论英语还是中文都不能胜任这个任务。这个情况和音乐有点类似,解决方案是发明一种人造语言专门用于这个领域。比如五线谱就是一种专门的供音乐使用的人造语言(简谱也是,不过那是国人的自创,有点地方话的味道)。于是就有一些专门的纯粹用于计算机的语言被创造出来。
其中最早的一种基于电路原理,直接用0和1来表示电路的开关通断,不断的拨动开关,就形成了程序。这种语言就是机器语言,它可以直接被计算机听懂,但遗憾的是,人类虽然可以看懂这种语言,但它不符合我们通常的交流习惯,很难被人所阅读,更不要说修改了。
后来人们提出这样一个方案,我们可以先按某种方法和规则,生成一个我们能看懂的指令序列(就是源代码),再通过某个转化的工具(就是编译器),把它变成机器可以运行的指令(也就是可执行程序)。这个我们能看懂的指令序列的规则的总和(也就是词汇和语法),就是我们通常说的计算机语言,为了和机器语言相区别,被称为高级语言。相应的规则,被称为语法。由于语法和词汇的不同,常见的语言有很多种,本文将介绍的就是C/C++语言,其他著名语言有BASIC、Pascal、JAVA、COBOL、 Python、汇编等等,他们各有所长,在不同的领域发挥着作用。但由于计算机的体系结构大致相同,这些语言也大同小异,具有共通之处。这情况很好理解,通常真实世界的拳法看起来都有点相似,只有漫画这类幻想作品里才会有手脚飞出或者口吐火焰眼下喷水这种怪异的事情发生。这个编程语言的共通之处也就是我前面讲过的算法和数据结构、平台和库这类东西。由于历史原因,大部分计算机语言借用了部分英语的词汇作为基本词汇,但绝不是说必须先学英语才能学习编程。如果只因为那几个屈指可数的英文单词而放弃学习编程,我只能说这样的人乘早离开为好。
顺便提一句,本文作者(也就是我),一向认为那个叫易语言的中文编程语言是个不折不扣的笑话。理由很简单,其他流行的语言都有自己的独到之处,就像武当剑少林拳打狗棒一样在江湖上占有一席之地,而这个语言除了有几个中文标识符之外,一无所长。而这几个中文标识符也不过是使用了文本替换的方式把C语言的几个特定词汇换成了意思相对应的中文而已。任何一个文本编辑器都可以做到这一点。形象的表现一下,这就是有个猥琐的家伙特地身穿全套阿拉伯长袍练了整路正宗少林长拳然后大声叫嚷这就是他发明的具有民族特色的中东石油大亨拳。
语言之后要确定的事情------操作系统和平台
在众多的程序里,有一大类特殊的程序,他们就叫操作系统。操作系统是最基础的程序,他让计算机运行起来,所有的硬件都做好准备,接受别的程序给予的指令。相对的,其他程序就叫应用程序。操作系统和应用程序的关系,就象人的基本意识和数学水平一样。想让一个连基本意识都没了的人(植物人)参加数学高考,看来你和我都疯了。一般的计算机都是硬件、操作系统和应用程序相互分离的,需要的时候分别安装。有些特殊的设备直接把操作系统做在硬件里,比如各种电子游戏机,可以开机,但是要有游戏光盘或游戏卡才能玩,还有些计算机把操作系统和应用程序都做在一起,放在机器内部,前几年很流行的俄罗斯方块掌上游戏机和电子宠物就是这样的设备。但总体而言,没有操作系统的计算机,就像没有灵魂的身体,是无法动弹的。这种情形,回想一下你那只进了水彻底完蛋了的手机就明白了。
编写操作系统要比通常想象的困难的多,它涉及到大量的背景知识和底层操作。所有连本篇FAQ都还不能消化的新学者应该完全打消诸如自己制作操作系统的念头,有实力之后再来尝试也不迟。
提供给钢琴和手风琴的乐谱并不是完全一样的,这是一种共识。为什么,因为这是两种不同的乐器。同样,在这个世界上有很多种的计算机,他们相互之间的差别也很大。每一种计算机都需要操作系统,而某一款计算机可能有好几种操作系统可以使用,就象黄种人可以说中文,也可以说日语。特定的计算机和特定的操作系统的组合,就被称为平台。就像钢琴曲不是给京韵大鼓使用的,对印度土著说中国成语也不会有什么好效果,编程通常都要针对某种平台来做。有一些高级语言号称能够跨平台,也就是可以在很多平台上运行,但作者认为那样多少会有性能上的损失或者意想不到的问题出现,所谓有得必有失就是这个了。
就像我在前面谈到库的时候已经提到过,如果你想要在编程上面有所成就,你不得不选定一个平台深入地钻研。个人认为,初学者不适宜同时在两个完全性质不同的平台上学习,不同的特性绝对会把你搞晕,在你确认掌握了一个之后再学习另一个,相互借鉴的作用才能体现出来。
编程时什么东西最重要----源代码
按照一般编程语言的规则编写的程序通常都是文字形式的,虽然还不能直接执行,但可以转换成可执行的程序,它是真正程序的源头,于是被称为源代码。编程的主要工作就是在制造源代码。由于源代码几乎人人都能看懂,而源代码又可以生成真正的程序,所以取得了源代码,就相当于取得了程序的一切,包括程序本身和程序背后的思想。基于此,大型软件公司要把他们的源代码严密的保护起来,而开源组织的第一条规则就是开放源代码。而作为初学者的你,请妥善保管你所写下的每一段源代码,这都是你积累的财富。
我的程序和一般的程序不一样,什么原因----控制台和图形界面
当你开始照书上的例子编写第一个C程序时,很快就会问出这个问题。回想平时见到的那些程序,他们通常都有标题栏,有菜单和工具栏,可以用鼠标在上面点来点去好像还有很多别的功能。可是这个程序似乎完全不同,难道出了什么问题。其实没有问题,这是一个控制台程序。
世界上有各种各样的程序。几乎所有的程序都要和用户交流,接受用户的输入,送出运行的结果,但他们接受和送出的方式是不一样的。程序与用户交流的方式被称为界面,还记得早期科幻电影里那种出现在计算机屏幕上可以和人对话的巨大人脸吗,那就是界面的一种。事实上这种界面到现在还没有实现,人类的想象力总是能超前实际技术很多。
界面有好多种。有些程序不需要界面,因为他们根本不和用户交流,他们和其它的程序交流,你可以叫他无界面,典型的例子就是驱动程序,你什么时候见过驱动程序运行的样子。现在常见的windows下的程序所使用的则称为图形用户界面(GUI:Graphics User Interface)。简单来说,就是所有的输入和输出都使用图形的方式。他接受用户图形化的输入,譬如用户用定位设备(鼠标、轨迹球、手写板)输入坐标、绘图,把程序的输出反映在可以显示图形的设备上,譬如显示器、打印机、头戴式监视器,通常这种程序会提供菜单、工具条等方式而极大地方便用户。这种程序直观明了,一般用户能很容易的掌握使用,只需要点击就可以完成大部分的任务。魔兽世界和WORD就是典型的GUI程序。
但其实图形界面的编程是相当复杂的。你能想象其实每次你都要画出显示器上所有的东西,窗口移动缩放时,你需要重画窗口里的每一样东西,在多窗口并存的时候,如果你的窗口被别人的窗口挡住了一部分(这是很常见的情况),你需要控制窗口上哪部分被显示、哪些被遮挡,鼠标移动的时候,你需要把被鼠标遮住的部分盖住,并重画鼠标,当鼠标点击时,你需要判断鼠标的位置,还要判断这个点击是你的程序的,还是别人的,当鼠标点击到菜单的时候,你要确定是菜单还是按钮,是哪个菜单项,然后执行相应的操作。所有这些情况,都必须解决。有些,操作系统可以帮你解决,但你要知道怎样才能让他帮你做,还有些就必须你自己想办法,种种问题使得图形界面的编程变得异常复杂。由于处理图形的需要,图形界面对硬件的要求也比较高。画面绚丽的3D游戏,远比记事本程序对系统的要求要高的多。虽然现代的计算机早已能够满足这些要求,但早期的计算机并不是这样强大的。
所以,在早期(也不远,大约是6、70年代)的时候,程序的界面并不是图形,而是字符的。用户在键盘上输入文字,比如dir,系统找到相对应的命令,然后执行,执行的结果也是以一行行文字的形式输出在可以输出文字的设备上(当然也主要是显示器),用户阅读文字,进行下一步的操作。现代的一些科幻片,在表现黑客侵入或者是操作高级设备(比如美国国防部的核武器系统)时,往往出现操作员在啪啪啪啪快速打字,然后突然一回车,就大功告成的场景,很少会出现卡通化的菜单和工具栏。想想黑客帝国的那个接线员,你见过他什么时候抓着鼠标吗。这种方式就叫命令行界面(Command Line Interface),由于操作员通常是坐在一个操作台前,而这个操作台确实可以控制整个系统,所以也被称为控制台界面(Console Interface)。控制台下运行的程序,就是控制台程序,运行控制台程序的系统,就叫控制台环境。
控制台看起来很高级,很酷很眩,黑客们操作的时候也显得很高深。其实反倒是比较容易编程实现的。因为你只要处理和输出字符就可以,系统自然会把字符放在屏幕上适当的位置。你不用去管字体大小颜色这些事,更别说窗口菜单鼠标这些不存在的东西,只要把注意力全部放在程序的功能上。电脑系统也不用消耗资源来画图,系统自然比较高效。所以,命令行界面一出现,就得到了广泛的应用,他的历史可比图形界面古老多了。和GUI程序比起来,命令行的程序通常很难看,操作也不直观。但由于它的高效和快捷,命令行方式的程序迄今仍然在使用,在很多时候,人们宁可使用命令行的程序来完成某些工作。在现代,FreeBSD、Linux和其它的UNIX系统,默认都是控制台环境,DOS就是一个标准的控制台环境,windows系列操作系统,也提供了控制台环境。而很多的GUI程序,借鉴控制台方式,仍然保留有直接使用键盘操作的方法。比如魔兽争霸,几乎每个命令都有快捷键的以加速操作。
实际上,很多系统管理员更偏爱控制台程序,除了他比图形化程序更高效之外还有一个原因。同样要增加实现一个选项,控制台只要增加一个输入字符作为开关,而图形界面至少需要增加一个按钮,想想看,屏幕上是可以增加的按钮多还是可以增加的字符数多呢。所以控制台程序往往更能实现纷繁复杂的功能,只要你记得住指令。
让我们打开在Windows下打开一个控制台环境并使用几个控制台程序感受一下。至于其它的操作系统,基本上本身就是控制台环境。就不需要演示了。假如你使用的是Windows2000或Windows XP,点击开始,找到程序->附件,在里面有一个叫“命令提示符”的快捷方式,点击运行他。如果是Windows 98,在程序组里设法找到一个叫MS-DOS方式的快捷方式,运行它。
你是不是看到了一个窗口,没有菜单,没有工具栏,只有标题栏和最大最小化的按钮,这就是win2000下的控制台环境,在这里就可以运行控制台程序。现在,输入"dir",然后回车。你看到了输出吧。这就是控制台程序的运行了。只要输入命令再回车,就可以运行了。再来运行一个,time。再来一个,ipconfig。最后再来一个,help。他给出了当前系统提供的各种命令,你可以看着提示分别试一试。其实不止可以运行这些,试试 notepad,你发现了什么。explorer,calc,cdplayer,freecell等等都是可以这样运行的哦。
玩够了,好吧,输入exit,再回车。控制台环境就被关闭了。
控制台程序容易编写,易于理解,所以对于初学者,控制台程序是理想的选择。本教程以后的部分所讲的程序,在没有特别说明的情况下,都是控制台程序。在学会了控制台程序的基础上,再转到窗口程序就比较轻松了。
好像不能建立一个单独的文件来编译
————工程和项目的问题
有一件很明显的事情是,当软件项目变得很大的时候,仅仅使用一个文件来完成所有的内容是不现实的。以《魔兽世界》这款游戏为例,游戏中需要声音、动画、图片这样的素材,也需要地图编辑、人工智能、光影渲染这些不同的模块,在制作的时候,需要有不同的部门完成不同的工作,工作中所使用的文件和工具都不相同,不可能生成同一个文件。这时,就存在一个协调的问题。因此,对于流行大型的开发工具来说,他们不是以单个文件为单位进行处理的,而是以项目为单位。一个开发项目包含一个到几个工程,每个工程都包含有大批的文件,有源代码,有程序所使用的图片音乐等资源,还有编译时需要纪录的各种参数。每次编译都要完全编译整个工程(当然在优化状态可以只考虑更新变动的部分)。即使源代码只有一个非常小的文件,也必须为它生成一个工程才可编译。
显然工程对于类似魔兽世界这样的大型项目的编写是十分必要的,但在新手练习的小程序上,使用工程就象你只想在家给你的小狗搭个窝,却拉来了整个中国长江三峡工程开发总公司,实在有点小题大做。而且,以后我们要编写很多这样的小程序,如果每一个都兴建工程,那会生成多少垃圾文件啊。所以,我们需要一种只编译单独文件的方法。幸运的是,不论哪种开发工具,他们都提供了这样的方法。虽然这种方法通常不会在菜单上直接出现,但他确实是常用的和正确的方法。
难道一切都要从头干起
————函数、API、类、控件、开发包与软件复用
还有件事也很明显,随着工程项目的越来越浩大,每一次都从零开始编写一个项目是不经济也是不现实的。我们注意到,不论是程序还是源代码,都有以下两个特性。第一,他们都是人类智慧的成果,每一行源代码都凝聚了程序员的聪明才智,花费了开发者的时间和金钱。第二:几乎每一行源代码本身都可以毫不费力的零成本的被复制到另一处,另一个代码块、另一个程序甚至另一个项目。基于这样的特性我们认识到,如果能够重复利用已经编写过的程序和源代码,尤其是那些在使用中已经被证明强壮而正确高效的程序,就能够节约巨大的人力物力财力时间。即使只能使用其中的一小部分,也是了不起的成就。这就叫做软件复用。从编程出现的第一天起,人们就意识到这一点,并为实现软件复用而努力。软件复用最重要的好处就是能够让程序员不再把有限的智慧放到早已解决过的问题上,而是投身新的问题,也就是:不要再重复发明轮子。开放源代码的一个重要理由就是为了软件复用。
软件复用的一个行之有效的方法是使用函数。所谓函数,就是把一些具有固定功能的代码段组合在一起,并给予一个名字。在需要这些功能的时候,只要在适当的地方填入函数的名字。在编程时使用函数而不是纯粹手工打造,就像在盖楼时使用砖块而不是用粘土堆砌,是不小的进步。盖楼时使用的砖块,既可以自己制造,也可以到市场上去购买。购买来的砖块,虽然有某些差异,但总是遵循某些共同特性。这些砖块虽然总是一块块地使用,但总是一车车的大量购买。函数也一样,市场上总是有专业公司提供函数出售,他们出售的函数按照功能聚集在一起,成为函数库。虽然不同公司的函数库可能具有相同的名字和功能,但内部是怎样完成的却不尽相同。大部分现代编程语言,在规定了语言本身的语法和词汇(当然其中也包括了函数的使用方法)的同时,还会规定一个函数库。这个函数库只规定了每个函数的名称和用途。至于函数的具体实现方案,有的是由语言本身直接定义,有的是由实现该语言的编译器的厂商提供。而使用这种语言的用户,只要在需要的时候使用,而不用去管函数库内部的问题,大大提高了效率。这个库就叫做标准函数库。通常,现成的函数库都是经过了大量的检验证明是高效而强健的,要比自己徒手打造的函数好用的多,所以在可能的情况下,要充分使用已有的函数库,尤其是标准函数库。C语言之所以如此强大,原因之一就是它有一个强大完备的标准函数库。而C语言之所以如此难学,原因之一也是在于它有一个强大完备的标准函数库。
软件通常是运行在操作系统下。从软件复用的角度看,操作系统如果能提供某些通用的服务,程序就可以集中注意力做自己的事。这些服务包括文件读写、设备操作、网络通讯、窗口绘制等等。否则,程序就会把大把的精力浪费在这些基础工作上。幸运的是,几乎所有的现代操作系统都提供了这样的服务。这些服务以函数的形式出现,在程序使用这些服务,就象使用函数一样。这些函数形式的系统服务,就叫做应用程序接口(Application Program Interface),即API。遗憾的是,不同的操作系统,提供的API通常是不同的。使用某个操作系统的API而编写的程序,搬动到另一操作系统时,由于API不能相互对应,也就不能运行了。这就是编程要针对平台的原因了。
有时候,有些大型程序,比如Autodesk公司的AutoCAD,当你对他的某些功能不满或是感到有改进的必要时,它提供了编程改变的可能,相对于第一次开发来说这就叫二次开发。二次开发时,原始程序所提供的那些服务也被称为API。
使用砖块盖楼确实很方便,但如果能使用预制板,那就更方便了。比函数更高一级的可以复用的程序模块叫做类。类的使用比函数复杂,但是它可以更广泛的复用,是更高级的软件复用形式。类,同样可以聚集成类库。能够使用类的语言,就会规定标准类库。C++比C更强大,更难学,就是因为,C++除了具有C所有的函数库之外,还有一个完整强大的标准类库。
在类库当中,有一种很特殊的类,称为控件(control)。控件在快速的窗口程序开发中特别有用。它可以实现拖放式的编程。举例来说,想要编写一个有一个按钮的窗口程序。那么只要先创建一个窗口程序的工程,这个工程会自带一个窗口控件,而且直接显示在工作区里,然后再用鼠标把按钮控件从控件板上拖到窗口里需要的位置,按钮就摆放好了。至于按钮的功能,就需要程序员来编程实现。将来编译运行之后,程序的外观就和设计的外观一模一样。控件极大的提高了编程效率,但因为它需要自动生成某些代码,所以需要编辑环境的支持,支持控件的编辑环境总体来说比较少。控件的总和,就是控件库。
所有这些,函数、API、类乃至控件,开发必备,就象旅行时必需携带的行李一样,于是被统称为开发包(SDK : Software Development Kit)。最著名的SDK就是windows提供的Win32SDK了。有些开发包是编译器自带的,如标准库等等。有些包是第三方厂商提供的,比如微软的DirectX系列开发包专为游戏编程所设计。所有开发包都需要集成开发环境(内带编译器)的支持,有的要编译器提供内部实现,有的要编译器给于连接,有的要编译器生成代码。不同的编译器提供的方式不太相同,这就造成了编译器之间的差异,有时,甚至导致某个开发包不能在某款编译器上使用。
为了进一步提高程序员的工作效率,很多集成开发环境还发明了另一些方法,相当于直接用一间间的房子叠在一起做成居民楼,你几乎只要刷刷外墙漆,就可以完成了,这被称为应用程序框架。可惜,不同的厂商的方法根本不同,这进一步扩大了集成开发环境之间的差异。
不管未来怎样,至少现在,编程的规模变得越来越大,也越来越需要更多人的智慧。每个人的智慧都是有限的,不应该被浪费,充分使用每个人的智慧,才能取得成功。软件复用就是整合所有人智慧的方式之一。从你编程的第一天开始,请牢牢记住:软件复用。要复用,复用,再复用。
关于图形库的补充说明
--------可选择的图形库
黑客们很偏爱控制台,但对于用户来说,图形界面是他们更熟悉的。我们也喜欢编写GUI程序,因为那看起来确实更友好也更有成就感。那么,怎样才能编写GUI,需要什么东西呢。
答案是:图形库。每一个操作系统,都会提供一套API(不理解的请回头看上面一小节),如果该系统支持GUI,那么它的API中就会有一个图形子系统和窗口管理子系统。其中图形子系统包括了基本图形元素的绘制,比如画点线面、显示文字图片和上色渲染等等,窗口管理子系统首先会包含图形子系统,再增加上包括窗口和窗口元件的绘制、窗口的遮盖、移动调整,以及鼠标点击这类事件的传递处理等等这些内容。在Windows下,图形子系统就叫GDI(Graphics Device Interface)。其他平台也有类似的接口,在TC下可以通过扩展的graphic.h来实现画图,不过窗口的支持要另行实现。此外,为了应对3D绘图在速度和效果上的需求,有专门的3D加速图形库被开发出来,最著名的就是DirectX和OpenGL。其中前者只能用于Win平台,但除了图形之外还整合其他很多功能,用他搞出了大量的windows游戏。后者跨平台,能在从家用到大型商务等各方面使用而且性能卓越,无数的好莱坞电影都是用OpenGL渲染生成的。
但是即使有图形库窗口管理库,GUI编程仍然是相当的繁琐。首先是要完成某个工作必须填写大量按部就班的代码,而且这些代码在程序内部和各个程序之间重复着。这提示人们应该在图形库的基础上作进一步的抽象。简单来说就是要在画点画线函数的基础上做出画二次曲线画立方体的模块。幸运的是,这些工作已经有人完成了,而且是不止一套。
这些东西按照功能强弱,有的叫图形用户界面库,有的则叫应用程序框架。在windows下,使用VC的人 可以选择MFC ATL,使用Delphi和BCB的,可以用VCL,至于VB,它本身就是和图形库捆绑在一起。如果你选择.net阵营,.net framework 就是你最好的选择。
如果你希望程序不止在windows使用,那么跨平台的QT GTK+ wxWindow 都是你的好选择。他们在保证效率的同时,适当抽象,抚平了底层操作系统的差异。
对于学习C++的人来说,上述库都是可以用的。但如果你是C语言死忠,就我的认知,可以直接用API,否则只有一个选择:GTK+。实体书比较少,相关资料推荐去线上查。
=========================================分割线================================
四、教材、习题和示例
能推荐几本好书么
当然,FAQ的目的之一就是这个。我将分别介绍纯C、C++以及widows编程、数据结构算法以及图形库等等的教材。市场上这些主题中任意一个的教材都是汗牛充栋,读都读不完。不过很显然,大家都公认的经典,也只是那么寥寥数本而已。下面推荐的都是这样的著作,当然总是有好作品在不断推出,我这里不可能把他们都列举出来,你可以用自己的犀利的目光把他们挑出来。
首先是纯C的教材
第一本:H.M.Deitel和P.J.Deitel的《C HOW TO PROGRAM》(C程序设计教程)。
作者是父子,从事语言教材的编写合计超过40年,本书被美国众多高校选用为教材,既可入门也可翻阅,甚好。本FAQ作者认为如果你只打算看一本的话,那就选他好了。
第二本:Brian W.Kernighan和Dennis M.Ritchie 的《The C Programming Language 》(C程序设计语言)。
此书简称K&R,由C语言的创建者撰写,是全球销售最多的C语言教材,其品质不容置疑。不过不适合入门,适于在入门之后巩固提高。实体书有原版和译本购买,电子版英文较多。
第三本:谭浩强的《C程序设计》。
优点在于,面向中国学生,语言易于理解,而且全书篇幅小,看过的人多,容易找到人请教。但是各方面的概念不深入,浅尝辄止,实际上还有些小错误,不是很严谨。因此适合第一次入门学习,例题做完基本就可以抛弃了。有实体书和电子版下载。同时配套有习题集和习题解答,适合自学。
第四本:王大刚先生的《C语言编程宝典》。
质量不错,与老谭的书一样非常适合中国学生,而且对于TC的图形编程讲解非常透彻。本人没有发现实体书,可能只发布在网络上,在VCgood论坛有转载:
http://www.vcgood.com/bbs/forum_posts.asp?TID=1560&PN=2
http://book.chinaz.com/C/C/index.html
第五本:无名作者的《C语言初学者入门讲座》
VCgood论坛转载,作者未知,质量同上一本。http://www.vcgood.com/bbs/forum_posts.asp?TID=1294&PN=4
第六本:Kenneth A.Reek 的《C和指针》
进阶读物,把指针一章演绎为一本书可见其技术精度。指针是C的灵魂,能领会本书中的理念,才能算是真正明白了C指针的奥妙,才算懂得了C。
第七本:Andrew Koenig 的 《C陷阱与缺陷》
进阶读物,在认真读完上面的入门书之前,暂勿阅读。本书畅销14年历久不衰,足证品质。
最后一本:ISO C89规范/C99规范
一切关于C语言的疑问,只有一件东西最权威,那就是ISO的规范。但这不是正式出版物,是类似法律文本的技术说明,而且只有英文版。新手阅读,提防吐血而亡。
然后是C++的教材
C++比C复杂的多,所以教材也就纷繁芜杂。既有综合性入门性的,也有专项深入的,阅读要循序渐进,以下分阶段介绍(以下文字有部分引用自他人评介)。
首先是毫无基础的时候,先要初步掌握语法并形成编程的概念
level 0:
H.M.Deitel和P.J.Deitel的《 C++ How to Program 》(C++大学教程)。
又是这对父子。有很多号称C++入门的书,但经我的观察,如果要选择能推荐给毫无编程概念的新手用的书,这本算是佼佼者了。此父子的《C程序设计教程》我已推荐了。
仍然是K&R,Brian W.Kernighan和Dennis M.Ritchie 的《The C Programming Language》(C程序设计语言)。
尽管C++之父亲口说,最好把C++看作一门新语言来学习,但我个人认为,一开始学习C至少有两大好处。相比C++,C还是非常简单的,易于掌握,避免你过早陷入C++的语法泥潭。同时,学C能让你对计算机的底层运行有所认识,建立良好的概念。
钱能的《C++程序设计教程》
国内C++教材中较好的一本,作者是教师,总结多年教学实践的经验写成的,比较适合国内学生。
PS:老谭也有一本C++教材,在此就不太推荐了,它完全是用C的思维来看C++。
当读者有一定c/c++基础
推荐的阅读顺序:
level 1
从Stanley B.lippman著 侯捷 译的《essential c++》开始,短小精悍,可以对c++能进一步了解其特性。Stanley B.Lippman的职业是提供关于C++和面向对象的训练、咨询、设计和指导。他也是Bjarne Stroustrup领导的Bell实验室Foundation项目的成员之一,负责C++程序设计环境中的对象模型部分。简单说,他是C++的创建者之一。
以Stanley B.Lippman,Josee LaJoie,Barbara E.Moo的《c++ primer》作字典和课外读物,因为太厚不可能一口气看完,当然你也可以用它作为主力教材。Lippman说过了,Josee LaJoie是C++标准委员会原负责人,Barbara E.Moo 是独立咨询顾问,参与了第一个使用C++编写的商业产品的开发,领导了公司中第一个C++编译器项目。
C++之父Bjarne Stroustrup的《the c++ programming language》,简称BS的TCPL,全面而深入的书,缺点也是太厚。
这个阶段 也可以延用前阶段Detiel父子的教材。
level 2 这个阶段就要养成好习惯
然后从Scott Meyers的《effective c++》开始转职,这是圣经,请遵守10诫,要经常看,没事就拿来翻翻
接着是 Herb Sutter的《exceptional c++》。此人是C++标准委员会的主席,主席说话,谁有异议。
顺下来就是Scott Meyers的《more effective c++》和Herb Sutter的《more exceptional c++》,请熟读并牢记各条款
level 3 这个阶段 把C++的类搞透
Stanley B.lippman的《insied the c++ object model》(深度探索C++对象模型)看过后如一缕清风扫去一直以来你对语言的疑惑,你终于能明白compiler到底都背着你做了些什么了,这本书要细细回味,比较难啃,最好反复看几遍,加深印象。
看完上一本之后,这本Bjarne Stroustrup的《The design and evolution of c++》(C++的设计与演化)会重演一次当年C++他爹在设计整个语言过程中的历程。
Stephen C. Dewhurst的《C++ Gotchas: Avoiding Common Problems in Coding and Design》(C++程序设计陷阱)会帮你在设计层面避免错误。
level 4 这个阶段深入STL吧
Nicolai M.Josuttis的《the c++ standard library》(C++标准程序库—自修教程与参考手册) 是stl的字典,什么都可以查得到。
Scott Meyers的《effective stl》,它和圣经一样是你日常行为的规范。发现没有,Scott Meyers先生一直在搞effective系列。
Matthew H. Austern的《generic programming and the stl》(泛型编程与STL)让你从OO(面向对象)向GP(泛型编程)转变。
光用不行,我们还有必要了解stl的工作原理,那么侯捷的 《stl源码剖析》会解决你所有的困惑。
level 5 彻底掌握模版泛型编程
对于c++无非是OO和GP,想进一步提升OO,Herb Sutter的《exeptional c++ style》是一本主席这么多年的经验之谈,是很长esp的。
一位stl高手是不能不去了解template的,《c++ template》是一本百科全书,足够你看完后对于GP游刃有余。
Andrei Alexandrescu的《modern c++ design》是太过聪明的人写给明眼人看的。
level 6
这个时候,对于C++语法本身,你应该是已经到了随心所欲的境界,你所要练习的大概就是大规模的C++程序的设计以及一些通用的高效库的使用,以及为什么要这样做的理由。
所以,《C++ 输入输出流及本地化》《C++ Network Programming》《大规模C++程序设计》是你需要的。
同时,C++教材中的异类:Barbara E.Moo和Andrew Koenig的《Ruminations On C++》(C++ 沉思录)是值得你一看的,他集中反映了C++的关键思想和编程技术,说明了C++是什么样的以及能够做些什么,不仅告诉你如何编程,还告诉你为什么要这样编程。本书曾出现在众多的C++专家推荐书目中。
和C一样,同样有最后一本书
ISO+IEC+14882-1998 C++规范。这可不是宝典圣经,这就是C++的法律,一切疑问以此为准到此打住。不过,有个脚注,某些具体情况取决于编译器实现。
接下来是Windows编程
至少在国内来说,Windows环境下的编程还是很有市场的。
第一本书:Charles Petzold 的 《Programming Windows》(Windows程序设计)。
如果说,在windows编程领域只能翻阅一本书的话,那就是他了。《Windows程序设计》由微软出版社在1988年首次出版,后来被认为是这方面最好的导论性读本。在1994年5月,Petzold作为仅有的七个人之一(并且是唯一的作家)被《Windows Magezine》和Microsoft公司授予Windows Pioneer奖,以表彰他对Microsoft Windows的成功做出的贡献。这本书经典到这个程度,以至对于Windows程序员来说,“从Chares 的(Window程序设计)一书中寻找答案。”几乎成了一句至理名言。
你可以在这个地方观看到他的外观,http://www.charlespetzold.com/pw5/,国内书店有售,电子版则需要仔细搜索。
第二本:Jeffrey Richter 的《ProgrammingApplicationsforMicrosoftWindows》(Windows核心编程)和《Advanced Windows》(Windows 高级编程指南)
和上面这本书难分伯仲。这么说吧,你读了之后就会后悔,后悔为什么没有早点读他。建议先看高级,再看核心。
个人认为除非windows发生革命性的变化,否则看完这三本书,足以应付通常的Windows编程。
上面三本书介绍的是直接使用WindowsAPI实现应用,总的来说那是一种很基础但很繁琐的方式。Windows下有很多的编程库可以使用,VC和BCB都自备了优良的库。
在VC来说,存在版本的差异,如果是6.0版本,那么你基本只有MFC这一种选择,但对于2002以后的版本,包括新推出的2008,MFC、ATL、.net都不错。
对于MFC。
要学会怎么用,可以看一下这几本:
微软出版社授权的中文版系列书 由David J.Kruglinski,Scot Wingo,George Shepherd写的《Programming Visual C++ 6.0 技术内幕(第5版)》,经典的“Visual C++技术内幕”的第5版。
清华大学出版社出版 杨永国 的《Visual C++ 6.0实用教程(第2版) 》,这本不是那么经典,同类多得很,但好处是便宜,而且能够买到,有些书已经买不到了。
如果想知道MFC的原理,侯俊杰先生的《深入浅出MFC 》(Dessecting MFC)就值得你仔细阅读。
对于VC2002--2008中的.net,单独讲授的似乎目前还没有像《Windows程序设计》那样经典的书出现,毕竟.net出现的时间也不长。但把.net MFC ATL等综合在一起讲的,倒还是有一些。
由H.M.Deitel,P.J.Deitel,J.P.Liperi和C.H.Yaeger共同编写的《Visual C++.NET:How To Program 》(Visual C++.NET大学教程)品质算是上乘。还记得Deitel这对父子作者么,在chinapub上可以看到父子俩合著的教材有47套之多,而且个个畅销,我觉得他们俨然就是美国的谭浩强,只是水平高出不少。
George Shepherd,David Kruglinski 的 《Visual C++ .NET技术内幕(第6版)》,就是上面那本书的.net升级。
IVOR HORTON的《VISUAL C++ 2005入门经典》也可一看。
BCB在版本6以前用的是著名的VCL库,BCBX另起炉灶,用的是wxWidgets库。由于对BC,作者自己涉猎不多,所以这两套库的教材,请大家自行查找。
就像C++和C的规范文件一样,Windows编程中,也有一件类似万宝全书的神物,那就是Microsoft自己推出的MSDN。
MSDN是Microsoft Software Developer Network的简称。这是微软的针对开发者的开发计划。你可以在http://msdn.microsoft.com看到有关软件开发的资料。在VisualStudio中包括MSDN Library的光盘,其中包括VisualStudio的帮助文件和许多与开发相关的技术文献。MSDN Library每个季度更新一次,可以向微软订阅更新光盘,不过价格不便宜。
MSDN就是微软的技术大全,所有微软的软件系统的开发的已公开资料,都在上面。如果在那里也无法找到答案,那你只能想办法咨询微软的内部工程师求得隐藏秘籍。不要妄想能够完全阅读它,3G容量的文档(大部分是文本,不是图片和视频),实在太过巨大了。
Unix/Linux/BSD系统
相对于Windows,在UNIX下编程获得相关文档要方便很多。由于历史原因,能够看到的教材基本上都经受了考验,几乎个个都是经典,不象Win下有鱼龙混杂泥沙俱下的现象。
三本可以替换的入门书,任选其一即可:
Bruce Molay的《Understanding Unix/Linux Programming A Guide to Theory and Practice》(Unix/Linux编程实践教程)应该是你的第一本书。一句话,大家都说好。
Kay A.Robbins(美), Steve Robbin(美)的《UNIX Systems Programming》(UNIX系统编程)。他是一本介绍UNIX系统的工作原理以及学习UNIX系统程序编写方法的经典教材,一本程序员不可多得的案头必备参考书。
Neil Matthew(英),Richard Stones的《Beginning Linux Programming》(Linux程序设计)。本书是Linux程序设计领域的经典名著,以筒单易懂、内容全面和示例丰富而受到广泛好评。
随后,以下几本书排名不分先后,分属不同方面,想深入的伙计建议都看:
W.Richard Stevens, Stephen A.Rago的《Advanced Programming in the UNIX Environment》(UNIX环境高级编程)
W.Richard Stevens,Bill Fenner, Andrew M. Rudoff,Richard W.Stevens的《Unix Network Programming》(UNIX网络编程),注意这套书是三卷本。
宋宝华 的《Linux设备驱动开发详解》。一本介绍Linux设备驱动开发理论、框架与实例的书,是作者多年Linux设备驱动开发从业经验的总结。能够在众多海外强手的教材阵中脱颖而出,足见作者的实力。
Robert Love 的《Linux Kernel Development》(Linux内核设计与实现)。内核相关概念及如何使用内核介绍的非常到位,全书偏应用,主要强调如何用,以及为了用而需要了解的内核实现。
Daniel P. Bovet和Marco Cesati 的《Understanding the Linux Kernel》(深入理解Linux内核),分析内核代码几乎无出其右者。
John Lions(澳)的《Lion'Cornmentary on UNIX 6th Edition With Source Code》(莱昂氏UNIX源代码分析) 。本书由上下两篇组成。上篇为UNIX版本6的源代码,下篇是莱昂先生对UNIX操作系统版本6源代码的详细分析。本书语言简洁透彻,曾作为未公开出版物在黑客界广泛流传了二十多年。现在MIT的操作系统的研究生课程里面依然采用的是这本书,unixV6的代码量小,门槛比动辄数百万行的linux更适合初学者。绝对是神作,很难买到这本书,所以如果遇上要毫不犹豫弄到手。
和MSDN类似,Unix/Linux/BSD下也有一个文档大全似的东西,而且只要一个命令就能打开他。他就是所有Unix系统都会自带的man page,完整安装的情况下,他已经存在系统中,更重要的是,他是免费的,相对照的MSDN宇宙版至少需要几百美元。
最后,在UNIX下无论如何都必须翻阅的教材是由公认的Unix编程大师、开源运动领袖人物之一Eric S. Raymond亲自撰写的《The Art of Unix Programming 》(UNIX 编程艺术),这本书著名到他有个专用缩写: TAOUP。他不是在技术层面讨论问题,而是从哲学角度来讨论UNIX编程,从而把编程上升到了艺术的高度。
数据结构和算法
数据结构就是在机器里组织数据的方法,而算法就是解决某个问题的总思路。数据结构和算法有两个层次,一开始的时候,它是语言相关的,尤其是对于数据结构来说,因此C和C++的教材要分开。后来在算法的层面,他就只是一种思想,也就和语言无关了。
清华教授严蔚敏和广东工业大学教授吴伟民的《数据结构(C语言版)》,这是清华计算机系的标准教材,还有什么要补充的么。
清华教授殷人昆的《数据结构(用面向对象方法与C++描述)》,也是清华的教材。
Mark Allen Weiss的《Data Structures and Algorithm Analysis in C》(数据结构与算法分析--C语言描述)和《Data Structures and Algorithm Analysis in C++》(数据结构与算法分析--C++语言描述)。数据结构和算法分析的经典教材。
之后就可以看深入一点的东西了:
王晓东的《算法设计与分析》。国内本科教材,书写得不错。
M.H.Alsuwaiyel(沙特)的 《Algorithms Design Techniques and Analysis》(算法设计技巧与分析)。本书结构简明,内容丰富,适合于作为计算机学科以及相关学科算法课程的教材和参考书,尤其适宜于学过数据结构和离散数学课程之后的算法课教材。同时也可作为从事算法研究的一本好的入门书。
Thomas H.Cormen, Charles E.Leiserson的《Introduction to Algorithms》(算法导论)。这是麻省理工学院计算机系的算法教材,已经成为世界范围内广泛使用的大学教材和专业人员的标准参考书。
经典中的经典,每一个想要掌握算法精髓的人都必须看的书,算法书中的圣经,他就是:
大师中的大师 Donald E.Knuth的《Art of Computer Programming》(计算机程序设计艺术)。
Donald E. Knuth(唐纳德 E. 克努特,中文名高德纳)是算法和程序设计技术的先驱者、计算机排版系统TEX和METAFONT的发明者,他因这些成就以及大量富于创造力和具有深远影响的著作(19部书,160篇论文)而誉满全球。这么说吧,目前你所能听说过或者还活着的那些计算机软件大牛,没有哪个不直接或间接的受过Knuth的教导。他强悍的程度只用一件小事就可以说明,在撰写这套《计算机程序设计艺术》的过程中,由于感到原有排版系统的不足,他特地重新制作了一套新的计算机排版系统,这套称为TEX的东西目前已经是出版界的标准系统。
《计算机程序设计艺术》这套关于算法分析的多卷论著已经长期被公认为经典计算机科学的定义性描述。迄今已出版的完整的三卷已经组成了程序设计理论和实践的惟一的珍贵资源,无数读者都赞扬Knuth的著作对个人的深远影响,科学家们为他的分析的美丽和优雅所惊叹,而从事实践的程序员已经成功地将他的“菜谱式”的解应用到日常问题上,所有人都由于Knuth在书中表现出的博学、清晰、精确和高度幽默而对他无比敬仰。微软的盖茨曾经说:如果你能完成他书中50%的习题,请尽管给他寄简历。(事实上,用盖茨来衬托Knuth简直是对Knuth先生的侮辱)
此书原定计划为七卷。目前已出版四卷,作者还在撰写后续部分。已出版的分别为:
第1卷 基本算法 Volume 1: Fundamental Algorithms
第2卷 半数值算法 Volume 2: Seminumerical Algorithms
第3卷 排序与查找 Volume 3: Sorting and Searching
第4卷 组合算法 包括:
第4卷 第0册 组合数学和布尔函数 Introduction to Combinatorial Algorithms and Boolean Functions
第4卷 第1册 尚未出版
第4卷 第2册 生成所有元组和排列 Volume 4, Fascicle 2: Generating All Tuples and Permutations
第4卷 第3册 生成所有组合和分划 Volume 4, Fascicle 3: Generating All Combinations and Partitions
第4卷.第4册 生成所有树 Volume 4,Fascicle 4: Generating All Trees History of Combinatorial Generation
各种图形以及其它库
图形库,著名的有两个:OpenGL和DirectX。
OpenGL(“Open Graphics Library”)是一个性能卓越的三维图形标准,是图形硬件的软件接口。他是在SGI等多家世界闻名的计算机公司的倡导下,以SGI的GL三维图形库为基础制定的一个通用共享的开放式三维图形标准,具有使用简便、效率高、便于移植、性能卓越等特点,独立于窗口系统和操作系统,以它为基础开发的应用程序可以十分方便地在各种平台间移植。目前包括Microsoft、SGI、IBM、DEC、SUN、HP等大公司都采用了OpenGL做为三维图形标准,许多软件厂商也纷纷以OpenGL为基础开发出自己的产品,其中比较著名的产品包括动画制作软件Soft Image和3D Studio MAX、仿真软件Open Inventor、VR软件World Tool Kit、CAM软件ProEngineer、GIS软ARC/INFO等等。包括迪斯尼梦工厂等好莱坞厂商的大批电脑特效程序都是使用的OpenGL库。
OpenGL有两大经典教材:
OpenGL体系结构审核委员会,Dave Shreiner, Mason Woo, Jackie Neider, Tom Davis 联合撰写的《OpenGL Programming Guide: The Official Guide to Learning OpenGL》(OpenGL编程指南),此书因封面为红色,被大家爱称为“红宝书”。
Richard S Wright和Benjamin Lipchak的《OpenGL SuperBible》(OpenGL超级宝典),是另一本合适的入门教材。
OpenGL结构评审委员会的《OpenGL Reference Manual》(OpenGL 参考手册),就和他的名字一样,它是一本文档大全,和“红宝书”相对应,他被称为“蓝宝书” 。
按照前辈的经验,有红蓝两宝书足矣。不过,OpenGL社区的实力雄厚的很,好为人师的大牛也不少。有一位昵称NeHe的大牛,他在自己的网站上放了一整套完整的OpenGl教程,实例教学讲解清晰,而且会跟随OpenGL的发展在随时更新,更重要的是,除了C/C++的标准例程之外,他的例程还几乎涵盖世界上的所有语言,如果想用自己喜欢的独特语言,可以参考页面最下方的联接。NeHe的教程在http://nehe.gamedev.net/。同时,Nate Robin的例子对你理解OpenGL很有帮助。http://www.gamedev.net/reference/articles/article839.asp。
OpenGL最权威的资料在他的官方网站 http://www.OpenGL.org的Documentation中,可以下载到官方教程和例子程序。
DirectX是微软提供的一种应用程序接口(Application Interface)。简单的说它是一个提高系统性能的辅助加速软件。"Direct"的意思是"直接的",而"X"则意味着"无限"。事实上它是一个.dll(动态连接库Dynamic link library)的文件集合。通过这些动态连接库文件,开发者们可以在不考虑设备差异的情况下访问硬件最底层。这项特性使程序员从无尽的硬件驱动程序中解脱了出来。DirectX同时封装了一些COM(Component Object Model)对象,这些 COM 对象为访问系统硬件提供了一个主要的接口。DirectX是一种游戏开发利器,Windows下的大量游戏在制作时都用到了它。DirectX包括很多组件,他们按功能划分为:DirectDraw,Direct3D,DirectMusic,DirectSound,DirectShow,DirectPlay,DirectInput,DirectSetup and AutoPlay等等。
在DirectX中最重要并且最具有代表性的是Direct3D和DirectDraw(在DirectX7.0之后被合并进了Direct3D),它的主要功能就是3D图形。Direct3D和OpenGL处于竞争关系,很难评论他们孰优孰劣。OpenGL专攻图形,而且适用众多平台。而DirectX可以在Win平台下获得多样的服务,而不止是图形。
如果你想学习如何使用DirectX,那么必须得掌握BASIC或Delphi或C++/C#等语言中的一种,纯C是不行的。同时,掌握Win32编程技术以及一些其他相关的知识也是必需的。
Frank D.Luna的《DirectX 9.0 3D游戏开发编程基础 》可以作为你的入门书。DierctX合适的入门书其实很多,重点是要注意版本要跟上最新的DircetX才行。
微软的东西,最标准的教材就是MSDN。想深入学习DirectX,就去翻阅MSDN好了。而且,那里也有不错的入门资料。
OpenGL和DirectX的最新进展往往是由显卡厂商作出的,经常去Nvidia和ATI的主页上去关注最新技术是个好选择。
其他库,比如用于构建窗口程序框架的GTK、QT、wxWidgets等,用于科学计算的Blitz、CGAL,网络通讯的ACE,加解密用的Crypto++,测试用的CppUnit,XML用的xml4c、XMLBooster、Xerces c++,当然也少不了即将加入标准库的Boost,这些库由于在不断的发展进化中,实体出版物相对较少,但他们自带的电子文档和相关主站上的资料通常足以满足需求。请记住,既然这些库的作者把他们发布给大家用,他当然要给齐资料让我们知道怎么用才行。
软件工程思想
当软件膨胀到一定程度,它就不是一个人能搞定的了。这个时候,就要像建筑上对待一个大型工程项目一样,通过有效的组织管理来进行软件生产。这种思想就叫软件工程。而实际上,即使是个人开发者,在初窥编程门径之后,也建议学习软件工程,从而培养起好的编程习惯便于将来的集体合作。所谓好习惯的养成是很难的而改掉坏习惯就更难,所以千万不要养成坏习惯。
林锐、韩永泉的《高质量程序设计指南--C++/C语言》会让你大吃一惊,原来你原先的编程习惯就有这么多的漏洞。
Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides的《Design Patterns:Elements of Reusable Object-Oriented software》(设计模式:可复用面向对象软件的基础),这是软件复用的权威教材,不过似乎要有很久编程经验之后才能领会。
Andrei Alexandrescu 著 侯捷 译的 《Modern C++ Design Generic Programming and Design Patterns Applied 》(C++设计新思维——泛型编程与设计模式之应用)是从实例上演示设计模式的。
Martin Fowler著 侯捷 译的 《Refactoring: Improving the Design of Existing Code》(重构:改善既有代码的设计),与巨著《设计模式》并称"软工双雄",全美销量超过100000册,亚马逊书店五星书。
Ian Sommerville的《Software Engineering》(软件工程)直接以软件工程为名的书,猜猜也知道有多强,此书已经再版8次。
Frederick P.Brooks的《The Mythical Man-Month: The Essays on Software Engineering》(人月神话)。出版于1975年的《人月神话》是软件开发方面的经典作品。在软件领域,很少能有像《人月神话》一样具有深远影响力并且畅销不衰的著作。Brooks博士为人们管理复杂项目提供了最具洞察力的见解,既有很多发人深省的观点,又有大量软件工程的实践。32年后的今天,他的思想仍然引领我们。他是和《计算机程序设计艺术》一样经典的著作。
找书的诀窍
可能有一天你会踏入一个别的编程领域,比如人工智能、加解密和密码学、网络与通讯、嵌入式等等,我并没有在这里列出书单,又或者你打算自己找些书。有什么能快速找到好书的技巧么,除了在线上论坛新闻组等地方寻找别人的推荐评价,在老师和前辈师兄师姐那里咨询之外,还有一个极为简洁的方法,那就是去找著名大学的计算机教材。声名在外的麻省理工、加州伯克利和清华,他们的教授们的眼光绝对是你可以信任的。买书时参看出版社也是个好办法,国内的清华大学出版社、机械工业出版社、电子工业出版社、人民邮电出版社四家出好书的机会很高,不过有时翻译质量是个问题。国外的O'Reilly可以说是最专业的计算机图书出版商,他出的没有不是经典的。此外Addison Wesley、Microsoft Press、 Pearson几家也尽是出猛书的地方。这个经验可不止是适用于编程哦。
光看书似乎不解决问题,难道要做题
当然要做题,而且做题也要循序渐进。
首先是教材正文中的示例,然后是书后的练习题。
第二步可以做国家等级考试二级三级的C语言题。在线上可以找到,大量二级题库。三级题推荐南开的三级100题。此外VCgood群的共享文件中也有一些这一难度的题目。
正如前面讲过,当第二步的题目都做完后,语法已经不是问题,应该开始学习数据结构和算法。这个方面的练习题可以去各大OJ。OJ是什么,请看下一节。
OJ是什么
OJ是OnlineJudge的缩写。OnlineJudge是一种在线裁判系统。她可以对程序原代码进行编译和执行,并通过预先设计的测试数据来检验程序原代码的正确性。
首先,他是一个在线的题库,有很多习题,你可以任选其中之一来解答。然后,系统的编译器能够编译执行你所提交的代码。如果编译通过,针对每个题目,系统将使用自带的多组测试数据检验你的程序,如果程序都能得到正确的输出,那么你顺利地解决了这个问题。最后,系统还能对所有参与答题的用户进行统计和排名。
OJ的题目大部分是关于算法的。题目的输入输出通常是命令行方式,而非图形界面。也就是说,要关注的不是平台的兼容性、文件的格式抑或窗口的布置这种无关紧要的细节,而是问题本身的逻辑实现。一个用户提交的程序在Online Judge系统下执行时将受到比较严格的限制,包括运行时间限制,内存使用限制和安全限制等。用户程序执行的结果将被Online Judge系统捕捉并保存,然后再转交给一个裁判程序。该裁判程序或者比较用户程序的输出数据和标准输出样例的差别,或者检验用户程序的输出数据是否满足一定的逻辑条件。最后系统返回给用户一个状态,通过、错误、超时、溢出或是无法编译。
Online Judge系统来自ACM和IOI大赛。由美国计算机协会(ACM Association for Computing Machinery)发起和组织的ACM国际大学生程序设计竞赛(简称ACM/ICPC)是目前世界上规模最大的计算机学科赛事。IOI则是国际信息学奥林匹克竞赛,和数学奥林匹克竞赛一样著名。Online Judge系统是IOI或ACM的训练题库,同时也是ACM和IOI的评分系统。
哪里有可用的OJ
以下几个OJ都很不错,请随意进入。也可以自行搜索,国内很多学校的OJ正在热火朝天的建设中,有的甚至直接作为了考试用系统。
Vijos http://www.vijos.cn/
内容丰富、分类清晰明了的中文在线评测题库。题量适中(目前大约400题左右),难度面向初学者和中学生,尤为重要的是,界面和题目都是中文的。
USACO http://ace.delos.com/usacogate/
全美计算机奥林匹克竞赛(USACO)的训练网站,特点是做完一关才能继续往下做,与通常的OJ不同的是测试数据可以看到,并且做对后可以看标准解答(包括分析),所以如果大家刚开始的时候在上面那些OJ上总WA却找不到原因的话,可以试着来这里做做,看看测试数据一般是从什么地方阴你的。此外,虽然都是英文题目,但在国内有人做了翻译,有全部题目的中文译本,搜索即可。
这两个强烈推荐新手前往。
浙江大学的Online Judge http://acm.zju.edu.cn/
国内最早也是最有名气的OJ,有很多高手在上面做题。特点是数据比较刁钻,经常会有你想不到的边界数据,很能考验思维的全面性。
北京大学的Online Judge http://acm.pku.edu.cn/
建立较ZOJ晚一些,但题目加得很快,现在题数和ZOJ不相上下,特点是举行在线比赛比较多,有报告称数据比ZOJ上的要弱,有时候同样的题同样的程序,在ZOJ上WA(wrong answer),在POJ上就能AC(accomplished)
这两个可以说是国内顶级水平了。
西班牙的Universidad de Valladolid http://acm.uva.es/
世界上最大最有名的OJ,题目巨多而且巨杂,数据也很刁钻,全世界的顶尖高手都在上面。据说如果你能在UVA上AC一千道题以上,就尽管向IBM、微软什么的发简历吧,绝对不会让你失望的。
俄罗斯乌拉尔大学 http://acm.timus.ru/
也是一个老牌的OJ,题目不多,但题题经典。
有实力的朋友,尽量去国外的OJ为国争光吧。那上面中国大陆选手的排名可不怎么靠前哦。
另外几个可以尝试,但不保证服务器总是开机的站
myOJ http://myoj.kuye.cn/
建站人员自称是专为中学生OI选手训练使用,由中学生和中学教师共同开发的,也是给中学生和中学教师使用的。优点是题目难度较低,而且题目都是中文版易于阅读。
浙江大学宁波理工学院 http://acm.nit.net.cn/
也是适合新手的OJ,题目难度由低到高不等。中文题不少。
同济大学的OJ http://acm.tongji.edu.cn/ 大部分是中文题。
南开大学的OJ http://acm.nankai.edu.cn 界面友好,部分中文题
天津大学的OJ http://oi.tju.edu.cn/ 界面题目皆中文
杭州电子科技大的 http://acm.hdu.edu.cn/
武汉大学的 http://acm.whu.edu.cn/noah/
这几所大学的题目难度相近,甚至有好多是相互借用的,难度等级要比北大和浙大的低一些。
一个人孤单做题的滋味是很郁闷的,尤其是当你确实绞尽脑汁也搞不定的时候。幸好线上还是有很多同样在做题的朋友,他们通常会在论坛BBS之类的地方集中讨论解题心得,甚至有可用的答案。建议用OI (Olyimpiad in Informatives 信息学奥林匹克)为关键字搜索。请不要用答案代码直接提交哦。
哪里有代码示例可看
这个可以自己google或baidu。
如果你已经能够做一些OJ的题了,那么可以考虑看一些开源软件的代码。http://sourceforge.net/ 是全球最大的开源软件集中地,确定一个应用主题上去找就会有收获。不过说实话,从OJ到项目是很大的跨越,所以要找到适合自己的项目来看是不容易的。个人的建议是,找一些知名的又比较小规模的项目,然后找他的早期版本的代码,会比较清晰,比如 vim1.0/2.0 lua1.0 apache1.0这种。
=========================================分割线================================
五、选择编译器
有哪些编译器可用
一般国内学习有以下几款可以用:TC VC GCC LCC-Win32,以下分别介绍。
TC 是Borland公司出品的Turbo C的简称,运行于DOS平台,win下可在控制台下使用。国内常用2.0版作为学习和考试的平台,为于1989年发布的产品,距今大约20年。另有3.0版本也可以使用,3.0比2.0多了C++语言支持。Turbo C 提供了两种编译环境:一种是类似于UNIX环境的命令行,包含一个TCC编译器和一个MAKE实用程序;一种是集成开发环境,由编辑器、编译器、MAKE实用程序和RUN实用程序,还有一个调试器组成。
TC2 具有编译速度快、代码优化效率高等优点,所以在当时深受喜爱。但由于DOS环境已经不是应用主流,所以TC基本不能用来作为软件开发平台。在今天由于TC对系统要求低,操作简便容易上手,他仍然是新手学习C语言的入门编译器之一。传闻Borland已在2002年放开TC的所有权,如果属实,那么使用Tc不再存在任何法律问题。
VC 指的是Microsoft公司的集成开发工具套装VisualStudio中的C/C++语言集成开发环境Visual C++。
目前可以使用的版本有VC6.0,和2005(即VC8)。VC2002/2003是过渡产品,可以不考虑。截至本文最后更新时,2008测试版已发行,2008正式版即将推出。
VC的编辑编译调试都可以在同一个窗口内完成,在Win下兼容性最好,代码效率高,被广泛用作Win下各类程序的开发,可以说是Win平台下的标准开发工具。使用VC意味着和微软同一阵营,文档有微软的官方文档MSDN作为最权威的参考,示例代码数量巨大,学习投资得到有效保护。纯粹学习和开发win本地应用可使用VC6,如果需要进行.net程序开发,就要用2005版。
VC系列的缺点有三:第一是体积庞大,VC6不包含MSDN容量为250M左右,包含则再加1G。VC2005不包含MSDN容量为2.7G,包含再加1.6G。第二是操作复杂学习门槛高,如果要在集成环境编译,必须建立工程和一批附属文件,同时还要熟悉集成环境的使用。第三:VC是有版权的软件。按照法律规定不付费购买是不可以使用VC的,因教学目的可以免费使用,但不能用于商业活动(不过显然国内的兄弟根本不理会这一套)。
VC6有一点要补充说明,VC6是没有中文版的。你所看到的中文版是某些人汉化的结果。虽然简洁明快,但在有些时候会出现莫名其妙的问题,还是直接使用英文版为好。
VC2005分为好几个版本,其中有一套叫做Express版的值得一提。他是微软送出的免费版,专门提供给学生和爱好者使用,功能上有删节,主要是图形界面和大量的工业用库和工具被裁减,而且基本只能在命令行编译。不过对于学习C/C++语言本身是完全足够的。如果有版权顾虑,可以用它。
GCC GNU Compiler Collection 也即是 GNU 编译器家族。
GCC是开源软件,是自由软件的旗舰项目,是可以在多种硬体平台上编译出可执行程序的超级编译器,其执行效率与一般的编译器相比平均效率要高20%~30%。
GCC 不仅仅能支持 C 语言,它还支持 Ada 语言、C++ 语言、Java 语言、Objective C 语言、Pascal 语言、COBOL语言,以及支持函数式编程和逻辑编程的 Mercury 语言等等等等。另一方面,说到 GCC 对于各种硬件平台的支持,概括起来就是一句话:无所不在。几乎所有有点实际用途的硬件平台,甚至包括有些不那么有实际用途的硬件平台。
根本无需再用什么语言来描述GCC的优点。几乎所有的开源软件和自由软件都是使用GCC编译的。如果要评选世界上编译出程序最多的编译器,除了GCC没有谁能担当这个荣誉。GCC的卓越是不言而喻的,连微软的员工也在使用GCC,学习GCC就是和世界上最优秀的程序员并肩作战。
GCC最早是在Unix平台上开发的,所以在Solaris/Linux/BSD等Unix平台上是默认组件。通过黑客们的努力,GCC已经被移植到Windows平台,而且性能绝无缩水。Win平台下的GCC有两种形式,一种是集成开发环境的,典型的是DEV-CPP,另一种是纯粹编译器和命令行指令集合,以MingW项目为首。
GCC的缺点是对新手不友好,命令行编译方式需要学习才能彻底掌握。
LCC-Win32
这是个小巧的纯C集成开发环境,目前最高版本4.0,和上面三个编译器相比,它有很多明显的优势。
第一她很小巧,全部安装不过30M多,相比VS2005这种庞然大物,简直是迷你的不行。虽小却不缩水,他的确能够编译出Win下的可执行程序,这一点是同样小巧的TC做不到的。可以肯定地说他是Win平台下体积最小的C环境。第二他完全支持C99标准。VS2005基本不能支持C99标准,GCC可以支持C99,但需要适当的配置,而LCC-Win32原生支持,无需任何调节。第三点最关键,它是自由软件,也就是说,他和GCC一样可以免费使用,而且作出的程序也可以自由的销售。缺点是缺少中文文档,无中文版是使用上最大的不便。
还有其它一些编译器,比如Borland的C++编译器BCB系列其中包括免费BCB5命令行版,Intel的Intel CPP Compiler等。在《C++编译器推荐目录》一文中有一个收集的编译器列表,各位可以前往参观。Blog: http://blog.csdn.net/sunwhite 。编译器如此之多,在下就不一一介绍了。
还有些可以配合编译器的开发环境
上面提到的或者是编译器,或者是整合编译器的开发环境。实际上有时我们还用另一种形式,就是用一个开发环境再搭配一个已有的编译器。
首先是业界很有名的Eclipse,这个是由IBM公司开发的一款java的IDE。但由于他设计出色的插件机制,使得在安装了插件之后,他可以通常充当C/C++的IDE。不过,只是在编辑上提供了方便,如果要编译程序的话,就要配合GCC的编译器才行。其实安装插件和编译器之后,Eclipse可以充当C/C++ python perl等很多语言的IDE。
第二个是一个开源的C++IDE,名叫Code::Bblocks。开源、跨平台、代码提示、支持插件、支持代码折叠,配合GCC可以说是完美的IDE,性能与VS2005不相上下。唯一的问题是:自从2005年10月25日发布了1.0rc2版本之后,就没有新的更新了。按官方的说法是在内核部分作重大修改,不过这个时间也太长了些。
第三个应该是算一大类,就是配置好的文本编辑器。Editplus、VIM、Emacs,这三个编辑器非常有名,而他们的可配置型使得他们能够很方便的成为准IDE。尤其是Emacs,当Emacs设置完成的时候,程序员根本不必退出他,就可以完成编程的所有工作。Emacs被戏称为程序员的操作系统,意思是它不仅仅可以用来编程,他可以做一切事,只要配置完全。
他们在哪里
理论上来说,这个问题应该自行通过搜索引擎解决,但我们还是不厌其烦的提供帮助。
TC20可在众多编程入门论坛找到,在VCgood论坛的空间也可。http://www.programfan.com/showdown.asp?id=152 此处也有。
VS6和VS2005建议直接买盘,要找建议通过电驴或BT等工具。
此处也有VC6 http://soft.zt169.com/Software/Catalog130/1569.html
此地址为VS2005 http://soft.zt169.com/Software/Catalog152/5496.html
GCC的dev-cpp版本在此,http://www.bloodshed.net/devcpp.html
GCC的MingW版本在此 http://www.mingw.org/download.shtml
lcc-win32可在 http://www.cs.virginia.edu/~lcc-win32/ 找到,英语很简单,很容易找到下载点,下载之前要填个名字。且本论坛空间也有。
怎么安装他们
除了GCC之外,上面提到的其他编译器都是很容易安装的。他们或者是简单的压缩包,释放即可,或者是标准的windows安装程序,相信大家都很熟悉。GCC的安装别具一格,要特别提一提。
dev-cpp版本的GCC是标准的windows安装程序,但MingW版本不是。MingW版本的GCC继承了UNIX应用程序的风格,简单来说就是小工具的集合。MingW就像一大堆积木组成的,你需要哪个功能,就把哪个模块下载并复制到适当的位置,他就可以工作。
具体操作流程如下:(PS:软件中所提版本以页面上最新为准)
1.下载
到MinGW的主页下载各个组件的最新版本: http://www.mingw.org/download.shtml
以下几个组件是必须的
binutils 其中包括ld,as等编程需要的程序组
gcc-core C语言编译器
mingw32-make Make程序
mingw-runtime 其中包括编译程序的大部分头文件和库文件(不包括Win32API)
w32api 这个里面是Win32 API 的头文件和库文件
其他组件可以根据需要下载,反正多装不影响。作者机器上还有如下组件:
gcc-g++ C++编译器
gdb 调试器
mingw-insight 调试器的图形化界面
软件包都提供了源代码版(src)和二进制版(bin),下载二进制版本即可。
2.解压
下载后,全部解压缩到同一个目录中,比如 C:\MinGW目录中。如果存在重名现象,通常都是许可证等的文件,可以覆盖掉或者不复制。
因为这些程序包都是使用GNU的压缩工具生成的,所以文件名不是zip,通常是.tar.gz。你可以用WinRAR打开,此处作者推荐著名的工具 7-zip 。
3. 设置环境变量如下:(假设mingw安装在C:\MinGW,且注意GCC的版本,这里假设为3.4.5版)
PATH : C:\MinGW\bin; (如果安装过其他c++编译器,务必把你要使用的编译器路径放在最前面)
LIBRARY_PATH :C:\MinGW\lib
C_INCLUDE_PATH :C:\MinGW\include
CPLUS_INCLUDE_PATH:C:\MinGW\include\c++\3.4.5;C:\MinGW\include\c++\3.4.5\mingw32;
C:\MinGW\include\c++\3.4.5\backward;C:\MinGW\include
=========================================分割线================================
六、TC下常见的问题解决
用TC创建第一个程序
用TC编辑和编译都很方便。
首先是菜单 File->new,在编辑区也就是那一大块蓝色的地方输入你的代码,然后file->save,会提示输入文件名并保存在合适的路径。
选择菜单Complie->compile或者按快捷键Alt+F9,就可以编译你的程序。编译成功后可以用菜单Run->Run或者按快捷键Ctrl+F9可以运行它,如果发现画面一闪而过,可以用菜单window->user screen或者按快捷键Alt+F5来查看。
如果编译失败,通常会给出提示,并且光标会停在第一个出错点,请仔细阅读。如果你要寻求帮助,也最好把错误提示贴给大家看。反复修改,直到程序通过。
TC的库路径设置
使用TC会遇到的第一个问题是库的路径设置。
当新手第一次用TC学习C语言,他们信心满满地照着书上的例子输入代码(这个例子往往是HelloWorld),存盘,编译,希望能看到想象中的结果,但却惊讶的发现TC报错。能看明白TC说的是缺少文件的人已属不错,大部分是不知道问题发生在哪里。
排除输入错误这类问题之后,这种情况通常只剩下一个原因,那就是TC的库文件的路径设置错误,解决方式如下。
目前安装TC通常不是使用安装文件,而是用解压缩的方式放到硬盘上的。这种方式会释放出一个名为TC20或者TC30的目录,里面有全套文件,包括默认的运行参数。这个默认参数所记载的TC目录的位置通常是C:\TC20,这就是问题所在。如果你的TC确实在那个位置,万事大吉,可惜通常情况不是这样的。
动手解决之前,首先检查你目前TC所在的路径,确保路径经过的每一个目录的名字都不超过8个字符,也没有中文或其他语言的字符,就是说确保目录名称都是8个英文字符或数字。我假设你的TC安装在X:\foo\code\TC
然后打开你的TC,打开Options菜单,可以用鼠标点击,也可以按键盘的Alt+O。用方向键移动到Directories菜单,回车之后就能看到一个窗口,这就是设置的地方。
在第一个输入栏里写上X:\foo\code\TC\include,这是头文件所在的目录。
在第二个输入栏里写上X:\foo\code\TC\lib,这是库文件所在的目录。
第三个输入栏是输出文件的路径,也就是编译完成的程序所在的位置。第四个是TC启动时搜索源代码的路径。这两个路径你都可以设为你喜欢的位置。
然后就可以ok确认。请选择Options菜单下的save命令来保存,避免以后再次设置。
至此问题解决。再次编译程序就可以通过。
PS:使用安装文件方式安装不会出现这个问题,但我已经很少看到TC的安装包了。
TC下的图形编程设置
很奇怪我们的教材却乐此不疲地要求学生们练习TC下的编程,而且是图形编程。因为这实在是太落伍而没有实际价值的要求。当然作为图形编程的练习,因为他够简单,也就可以理解了。
这个部分最好的文档就是上面提到过的王大刚先生的教材,其中专门有一章图形函数,详细讲解了所有的问题和事项。http://www.cnread.net/cnread1/dnwl/cxsj/c/cyyb/041.htm
鉴于有很多人不习惯认真地看文档,而偏爱直接发言。他们即使看完文档也还是会提问为什么我的TC图形程序不能运行。我就再麻烦一点,先讲一下两个最有可能导致无法运行的原因。
第一:使用图形函数时要确保有显示器图形驱动程序*BGI, 同时将集成开发环境Options/Linker中的Graphics lib选为on, 只有这样才能保证正确使用图形函数。图形驱动程序由Turbo C出版商提供, 文件扩展名为.BGI。根据不同的图形适配器有不同的图形驱动程序,你可以在TC的安装目录下找到他们。
第二: 在屏幕作图之前, 必须根据显示器适配器种类将显示器设置成为某种图形模式, 在未设置图形模式之前, 所有图形函数均不能工作。设置屏幕为图形模式, 可用下列图形初始化函数:
void far initgraph(int far *gdriver, int far *gmode, char *path);
其中gdriver和gmode分别表示图形驱动器和模式, path是指图形驱动程序所在的目录路径。
典型用法是 initgraph(&gdriver, &gmode, "c:\\tc");
注意path应形如"c:\\tc的形式,使用两个 \ 来转义表示单个字符\
其他问题请自行查阅文档。
也可查阅此帖 http://www.vcgood.com/bbs/forum_posts.asp?TID=1188&PN=1
我的程序在TC下可以编译,在VC/GCC下为什么出错
很简单,如果程序只涉及C语言本身和标准库,那么在任何平台都是可以运行的。而你运行出错的那些程序一定是调用了TC平台特有的服务和函数。比如,上一节提到的TC下的图形函数,在VC中完全不被支持,由GDI系统取代了,在Unix下的GCC中也要调用其它的图形函数库。同样的还有TC下的内存驻留程序,调用中断(如int13h进行硬盘读写操作)的程序。但此类程序可以在TC中编译通过后,由Win提供模拟DOS环境运行。
这也是我们建议新手尽量少用TC作为开发平台的原因。
=========================================分割线================================
七、其它编译器问题
用VC创建第一个程序
用VC创建程序取决于你的编译方式。
如果你选择命令行编译,你可以用你喜欢的任意文本编辑器编辑源代码(通常我们就用VC的环境),保存为后缀为.c的文件。然后转到命令行,输入 cl ,回车。你应该看到这样的话:
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
usage: cl [ option... ] filename... [ /link linkoption... ]
这是VC的编译器程序 cl.exe在无输入时的结果。如果你没有看到cl的招呼,而是这样的一段话:
“'cl' 不是内部或外部命令,也不是可运行的程序或批处理文件。”
这说明你没有安装VC,或是你安装的VC存在某些错误。其实也不是什么严重的错误,就是程序没有设置路径。假设你的VC安装在 D:\vs60,那么在控制台输入 SET PATH=d:\vs60\VC98\Bin;%PATH% ,再运行VCVARS32.BAT就可以了。
假设你的程序在 E:\cppcode 名为 Demo.cpp 那么输入:
cl Demo.cpp
一切顺利的话,就是这样的文字:
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
demo.cpp
Microsoft (R) Incremental Linker Version 6.00.8168
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
/out:demo.exe
demo.obj
这是告诉你编译成功,编译出了一个名叫demo.exe的可执行文件。如果输入:
cl /Fea.exe demo.cpp
编译出的可执行文件就叫a.exe,这是用参数控制编译的过程和结果,以后常常会用到。现在可以键入 demo.exe(或是a.exe),运行程序。
这就是使用VC在控制台编译程序,是我个人推荐的编译方法。
如果你选择在集成环境中编译,那么要在VC中选择:
菜单->file->new->Projects->Win32 Console Application,输入你的程序名,选择路径,在之后的操作中选择An Empty Project,这样就新建了一个空的控制台工程。
然后再菜单 file->new->Files->C++ Source File,填上文件名。
然后你就可以在打开的编辑区中编辑。最后,单击工具栏上的 save all 按钮,以保存你所有的工作。编程是个体力活,经常保存你的成果是非常明智的。
要把他编译成可执行的程序。选择菜单 Build->Build Hello.exe,稍等片刻。你会看到在屏幕下方出现了一个新的窗口,上面会依次出现如下的文字:
Compiling...
Demo.cpp
Linking...
Hello.exe - 0 error(s), 0 warning(s)
如果看到以上文字,尤其是最后一句,表示程序顺利的编译成了可执行代码。
如果情况是类似这样:
Compiling...
Demo.cpp
E:\cppcode\Hello\Demo.cpp(8) : error C2143: syntax error : missing ';' before 'string'
Error executing cl.exe.
Hello.exe - 1 error(s), 0 warning(s)
这表示程序有错而无法通过编译,你需要寻找出错误并修改。对于本例,是输入错误,请检查大小写,标点符号和中英文状态。改正之后,重新保存文件,再次编译,以上过程要反复的进行,直到编译通过。
编译通过的程序就可以运行了。选择菜单 Build ->Execute Hello.exe。
如果一切顺利,你应该看到了运行的结果。一个黑底白字的窗口,上面有两排字:
Hello World!
Press any key to continue
其中第一句是程序运行的结果,第二句是操作系统告诉我们,随意按一个键,便可结束该程序。
VC下的入门教程 可参见此帖 http://www.vcgood.com/bbs/forum_posts.asp?TID=1214&PN=1
用DEV-CPP创建程序
使用DEV-CPP的操作类似于用VC在集成环境下创建,也是新建工程,输入代码,然后编译连接,最后运行。差别只在于菜单和快捷键的设置。总体来说,DEV-CPP的编译速度要比VC慢一些。
用MingW创建程序
用MingW操作类似于用VC在命令行下编译。不同之处是控制台的命令是gcc 。命令形式为:
gcc demo.cpp,在Win下默认输出文件为a.exe
MingW不自带编辑器,因此用户要自己选择合适的编辑器,通常我们推荐Editplus gvim和Emacs这三款。后两款功能强大到无以复加,但需要学习。
GCC的简单使用教程见以下几帖
http://www.vcgood.com/bbs/forum_posts.asp?TID=1197&PN=1
http://www.vcgood.com/bbs/forum_posts.asp?TID=517&PN=1
http://www.vcgood.com/bbs/forum_posts.asp?TID=340&PN=1
Vi编辑器的使用可参见此帖
http://www.vcgood.com/bbs/forum_posts.asp?TID=141&PN=2
用Lcc-win32创建程序
Lcc-win32的使用类似于dev-cpp,不同点是它的项目设置不在项目目录里的单独文件中,而是直接记录在注册表。
有关Lcc-win32的资料可以参考lcc-win32的使用说明 http://www.blogjava.net/bluesky/archive/2005/11/30/21919.aspx
=========================================分割线================================
八、结束语
程序员成长的六个阶段
著名程序员梁肇新先生在他的《编程高手箴言--高手是怎样练成的》一书中提出了程序员成长的六个阶段,你到达了哪一个阶段呢,又有信心到达哪个阶段呢。
一个程序员的成长可分为如下六个阶段。
第一阶段 :
此阶段主要是能熟练地使用某种语言。这就相当于练武中的套路和架式这些表面的东西。
第二阶段 :
此阶段能精通基于某种平台的接口(例如我们现在常用的Win 32的API函数)以及所对应语言的自身的库函数。到达这个阶段后,也就相当于可以进行真实散打对练了,可以真正地在实践中做些应用。
第三阶段 :
此阶段能深入地了解某个平台系统的底层,已经具有了初级的内功的能力,也就是“手中有剑,心中无剑”。
第四阶级 :
此阶段能直接在平台上进行比较深层次的开发。基本上,能达到这个层次就可以说是进入了高层次。这时进入了高级内功的修炼。比如能进行VxD或操作系统的内核的修改。
这时已经不再有语言的束缚,语言只是一种工具,即使要用自己不会的语言进行开发,也只是简单地熟悉一下,就手到擒来,完全不像是第一阶段的时候学习语言的那种情况。一般来说,从第三阶段过渡到第四阶段是比较困难的。为什么会难呢?这就是因为很多人的思想转变不过来。
第五阶级 :
此阶段就已经不再局限于简单的技术上的问题了,而是能从全局上把握和设计一个比较大的系统体系结构,从内核到外层界面。可以说是“手中无剑,心中有剑”。到了这个阶段以后,能对市面上的任何软件进行剖析,并能按自己的要求进行设计,就算是MS Word这样的大型软件,只要有充足的时间,也一定会设计出来。
第六阶级 :
此阶段也是最高的境界,达到“无招胜有招”。这时候,任何问题就纯粹变成了一个思路的问题,不是用什么代码就能表示的。也就是“手中无剑,心中也无剑”。此时,对于练功的人来说,他已不用再去学什么少林拳,只是在旁看一下少林拳的对战,就能把此拳拿来就用。这就是真正的大师级的人物。这时,Win 32或Linux在你眼里是没有什么差别的。
每一个阶段再向上发展时都要按一定的方法。第一、第二个阶段通过自学就可以完成,只要多用心去研究,耐心地去学习。
要想从第二个阶段过渡到第三个阶段,就要有一个好的学习环境。例如有一个高手带领或公司里有一个好的练手环境。经过二、三年的积累就能达到第三个阶段。但是,有些人到达第三个阶段后,常常就很难有境界上的突破了。他们这时会产生一种观念,认为软件无非如此,认为自己已无所不能。其实,这时如果遇到大的或难些的软件,他们往往还是无从下手。
现在我们国家大部分程序员都是在第二、三级之间。他们大多都是通过自学成才的,不过这样的程序员一般在软件公司也能独当一面,完成一些软件的模块。
但是,也还有一大堆处在第一阶段的程序员,他们一般就能玩玩VB,做程序时,去找一堆控件集成一个软件。
初级程序员和高级程序员的区别
一般对于一个问题,初级程序员和高级程序员考虑这个问题的方法绝对是不同的。比如,在初级程序员阶段时,他会觉得VB也能做出应用来,且看起来也不错。
但到了中级程序员时,他可能就不会选择VB了,可能会用MFC,这时,也能做出效果不错的程序。
到高级程序员时,他绝对不是首先选择以上工具,VB也好,VC也好,这些都不是他考虑的问题。这时考虑的绝对是什么才是具有最快效率、最稳定性能的解决问题的方法。
软件和别的产品不同。比如,在软件中要达到某个目标,有n种方法,但是在n种方法中,只有一种方法或两种方法是最好的,其他的都很次。所以,要做一个好的系统,是很需要耐心的。如果没有耐心,就不会有细活,有细活的东西才是好东西。我觉得做软件是这样,做任何事情也是这样的,一定要投入。
程序员到达最高境界的时候,想的就是“我就是程序,程序就是我”。这时候我要做一个软件,不会有自己主观的思路,而是以机器的思路来考虑问题,也就是说,就是以程序的思考方式来思考程序,而不是以我去设计程序的方式去思考程序。这一点如果不到比较高的层次是不能明白的。
你设计程序不就是你思考问题,然后按自己的思路去做程序吗?
其实不是的。在我设计这个程序的时候,相当于我“钻”入这个程序里面去了。这时候没有我自己的任何思维,我的所有思维都是这个程序,它这步该怎么走,下步该怎么走,它可能会出现什么情况。我动这个部分的时候,别的部分是否要干扰,也许会动一发而牵全身,它们之间是怎么相互影响的?
也只有到达这个境界,你的程序才能真正地写好,绝对不是做个什么可视化。可视化本身就是“我去设计这个程序”,而真正的程序高手是“我就是程序”,这两种方法绝对是不同的。比如,我要用VB去设计一个程序,和我本身就是一个程序的思维方式,是不一样的。别人也许觉得操作系统很深奥,很复杂,其实,如果你到达高手状态,你就是操作系统,你就能做任何程序。
对待软件要有一个全面的分析方法,光说理论是没有用的。如果你没有经过第一、第二、第三、第四这四个阶段,则永远到达不了高境界。因为空中楼阁的理论没有用,而这些必须是一步一步地去做出来。
一个高级程序员应该具备开放性思维,从里到外的所有的知识都能了解。然后,看到世界最新技术就能马上掌握,马上了解。实际上,技术到达最高的境界后,是没有分别的。任何东西都是相通的,只要你到达这个境界以后,什么问题一看就能明白,一看就能抓住最核心的问题,最根本的根本,而不会被其他的枝叶或表象所迷惑,做到这一步后才算比较成功。
从程序员本身来说,如果它到达这一步以后,他就已经形成了开阔的思维。他有这种开放性思维的话,他就能做战略决策,这对他将来做任何事情都有好处。事实上,会做程序后,就会有一种分析问题的方法,学会怎么样把问题的表象剖开,看到它的本质。这时你碰到任何具体的问题,只要给点时间,都能轻而易举地解决。实际上,对开发计算机软件来说,没有什么做不了的软件,所有的软件都能做,只是看你有没有时间,有没有耐心,有没有资金做支撑。
“我就是程序,程序就是我。” 梁肇新先生的这本 《编程高手箴言》这本书就是他自己十余年来编程经验的集结。全书通篇没有时髦的IT新名词或新思想,而是踏踏实实地对很多知识进行了深刻的剖析,这有助于为编程打下坚实的根基。只有这样,才能使开发者在飞速变化的软件领域里免于雾里看花,才能更快更深地认识许多新问题、新知识,也才能更从容地应对未来之挑战。相信这本书对广大程序员大有裨益,无论是从技术角度还是从职业生涯指导角度。
内容涵盖了从认识CPU、Windows运行机理、编程语言的运行机理,到代码的规范和风格、分析方法、调试方法和内核优化,内有作者对许多问题的认知过程和透彻的分析,以及优秀和精彩的编程经验。建议朋友们都设法弄来一看。
=========================================分割线================================