广彩网10第一部分基础编程(PartITheBasicProgramming函数应该返回一个整型值,进一步可以参见整型的细节(CH3.1)。一对花括号“”是表示main的函数体。在函数体中可以写上许多程序语句,以供执行。上面程序的函数体中只有一条输出语句,以分号结束。任何一条C++语句都是以分号结束的。“intmainO.”这种结构构成了C++的函数定义体,后面的花括号“”就是程序结束处。如果一个程序很大,那么就是在main函数体中有许多语句,这些语句可以是直接计算和赋值的语句,也可以是对其他函数的调用语句,如此,便可以使程序规模无限制地扩张。总之,运行到main函数体的“)”结束处,再大的程序也不得不结束。cout是标准输出设备的名称,“<<”是操作命令,指示将后面的数据(字串Helloworld.ln)送到显示器设备上去。字串中的“n”是控制字符,表示一个换行操作。C++在显示可见字符的同时,还接受一些指挥设备动作的控制字符。控制字符一且送到设备后,并不显示,而是做出一定的动作。控制字符在屏幕上不可见,程序是用可见字符堆积而成,C++用可见字符表示不可见的控制字符时,用“”和另一个字符的组合。std是“名空间”。程序中有若干名称,程序规模大起来后,难免会有名称冲突,就好像学校中遇到同名学生:A班中有张三,B班中也有张三,当A、B班在一起上课时,就有名冲突问题。解决的简单办法就是两个张三分别命名为:“A班的张三”,“B班的张三”。C++也是这样来解决问题的。为了防止程序员自己又命名一个cout而造成冲突,就特地对语言专门提供的标准设备名cout冠以前缀“std:”,表示“标准库中的cout”。1.4.3编程风格(ProgrammingStyle)程序的书写方式完全是人为的,不同的书写方式构成了程序设计的不同风格。C++的程序语法是以空格和换行(回车)来区分词法单位,以特定的字符来辨认语法的,如分号“,”表示语句的结束。程序设计格式的随意性,给程序设计风格带来了可塑性。例如,上述程序可以写成:include<iostream>intmain()(std::cout <<"helloworld.In";7程序设计风格应以可读性为准则,合理的紧凑性、模块整体性、对齐、锯齿型嵌套、注释都是形成特定风格的因素。本书将以一种独特的紧凑风格来展示程序代码。将上述程序以作者的风格写出,则为:1///myfirst.cpp//带标准输出的最小样本程序//m#include<iostream>/www.TopSage.com
www.TopSage.com
11第1章概述(Introduction)int main()(std::cout<<"helloworld.ln"J//aamm#include命令之后加一注释空行,表示程序的头部描述告一段落,对于简单的函数头部(包括花括号(),只占一行是简捷的。cout输出语句属于函数体的动作序列描述,所以嵌进二个空格(有的程序员空三个字符或更多)字符,表示与函数的从属关系。为了让程序表现出美感,又不至于语句前后内容含混不清、结构混乱,语句书写讲究疏密得当。高级程序员的程序风格,体现了极大的一贯性和艺术性。每个初学者必须要模仿某些编程风格,随着编程量的增加,对程序会感受多多,不知不觉地形成自已独特的风格。为了让程序能够工作,还要学习C++的创建工程和设置工程路径操作,详见《C++程序设计实验指导(第二版)》一书。如果第1章读完后,还没有办法运行这个简单的程序那么再往下读就是不明智的了,为什么?1.5程序与算法(Programs&Algorithms)1.5.1程序(Programs)程序从静态上说,是以某种语言为工具编制出来的动作序列,它表达了人的系统性思维。而从动态上说,它是一系列逐一执行的操作。既然要操作,便要受到操作主体(计算机)的制约。由于不同的主体其操作性能不同,即使同一个主体,在不同状态下执行同一个程序,也会表现出差异。所以,同一个程序,可以反复运行而结果一致,这是肯定的,但性能上的细微差异是完全正常的。计算机程序是用计算机语言所要求的规范描述出来的一系列动作,它表达了程序员要求计算机执行的操作。由于不同的计算机,其机器指令系统和速度有差异,表达数据的能力有差异,所以计算机在执行程序中,也会表现出差异。优秀的程序员尤其是C++程序员,对计算机的差异是十分敏感的,正因为意识到差异的存在,所以,他们追求的是各个抽象层次的编程,追求编程方法的实效性。这意味着所谓“学会计算机语言,看得懂语法,了解了语言的描述方法”,还是不够的,它和熟练运用计算机语言,能用语言高效、正确地描述问题、解决问题是有天壤之别的。学习计算机语言在于让计算机准确地执行程序,在于会用程序设计方法去实现动作序列的表达。它和学习其他语言一样,都需要一个充分的实践过程。要求程序符合语言规范的目的是使计算机能够理解程序并执行。C++语言也是一种语言规范,用C++语言编的程序,能够被C++编译器所识别,并最终被计算机所执行。1.5.2算法(Algorithms)由于程序的动作序列包含了对数据的存取访问和算术运算,特别是当今的计算机发展大量地需要数据处理,因此对数据的合理描述、组织、存放和读取,关系到程序运行的正www.TopSage.com
www.TopSage.com
12第一部分基础编程(PartITheBasicProgramming)确和高效。算法是求解特定问题的一组有限的操作序列。算法的描述也需要借助于专门的工具,如某种计算机语言。Knuth大师早就对算法下了权威的定义(参考文献[2]CH1.1)。算法毕竟有别于程序。1.目的性算法是有求解目的之动作序列,因此,算法必须有运算结果。而程序只是强调过程性也许是不能自行终止的操作序列。例如,操作系统程序随着计算机的开机而运行,随着关闭电源而停止运行,不是自行终结。2.抽象性算法离不开数据结构,而数据结构在具体的计算机上实现要受到表示范围的限制,所以,算法比具体的程序设计更超脱一些,也就是抽象层次要高一些,算法甚至不在乎用什么编程语言来描述,3.研究性算法许多时候用于理论研究,描述算法的目的是沟通人们的思想,而不是实现。所以,算法可以用伪编程语言来描述。算法描述也可能是不切实际的,例如,研究和描述典型的NP算法问题时(参考文献[3JCH8.3),就会远离实用。等到算法真正与程序代码对应起来的时候,可能就一定程度地牲了研究的价值。一旦用特定的计算机语言来描述算法,就使该算法成为特定计算机语言下的程序。更多的情况是,算法要靠程序实现来验证,即通过有限的数据,在有限的时间内,得出正确的结果,测试其资源占用与性能各项指标。1.5.3编程与结构(Programming&Structures)编程强调全方位,具体问题具体对待,低级编程和高级编程应采用不同的方法和不同的程序组织形式。编程总是与具体的编程语言捆绑,同一个问题用不同的编程语言来写,内容会完全不同。编程当然是为了解决计算问题,计算问题强调算法,程序设计也就是在一定抽象层次上的算法设计。这里的抽象层次应理解为数据的描述方式。当人类面临大量数据需要处理时,也就是许多编程问题含有大量纵横交错的数据时,人们便逐渐意识到数据组织与数据结构的重要性,意识到数据存在的形式必须脱离程序。1976年,计算机专家N.Wirth提出这样的经典公式:程序=算法+数据结构程序设计方法的变革是以简化编程和提高软件生产率为自的的,它不以牺牲程序的正确性和效率为代价。N.Wirth的观点,是强调编程中数据结构的描述应相对算法而独立。针对算法事实上与数据相分离,如果数据由数据结构来描述,算法就可以数据结构为依托,通过数据结构来访问数据,从而简化算法和提高逻辑清晰性。www.TopSage.com
www.TopSage.com
大网第1章概述(Introduction)从动态性上说,程序仍然是计算机中的过程运行体,即操作系统中的进程(参考文om献[4]】。它服从进程管理。从静态性上说,程序不再是单纯的过程体(操作序列)了,不再是单纯的算法了,而是算法和数据结构的有机组织。程序含有更多的数据组织描述,而数据组织描述又包含有一系列的操作。N.Wirth的公式意味着程序所反映的操作序列依赖于抽象层次更高的数据结构,而不是直接对应于单纯空间上的原始数据。因此在观念上,程序发生了变化,带来了设计方法的进化,改变了程序的静态描述形式,动态与静态不再对应了,机器运行的进程与人工编程的逻辑开始分离,这也标志着语言编译器越做越高级,从单纯直译进入到对程序结构的复杂分析与理解。1.6过程化程序设计(ProceduralProgramming)1.6.1基于过程的程序设计(Procedure-BasedProgramming)从程序设计方法的角度来说,程序的概念是组织成一定形式的操作序列。同一问题若组织成不同的操作序列,则反映了程序设计方法的不同。编程问题是从一大类科学计算的问题开始的。这些科学计算问题所描述的数据大多不是很复杂,因而,依赖于早些时候的C语言中的内置数据类型,以及在空间上的简单复合就可以完成。其相关的数据操作也多半是数据复制、数据赋值等简单操作。所以程序设计主要体现在算法上,编程就是解决算法如何设计的问题。当算法很大时,就考虑将它按功能划分。程序组织围绕算法的切分而展开。这一类问题一般都是小规模的问题,一般的程序设计语言也都可以胜任,如图1-2所示。intfloatdoubleintint*基本数据类型过程结构技图1-2过程化编程结构框架www.TopSage.com
www.TopSage.com
14第一部分基础编程(PartITheBasicProgramming)图中的过程结构是按照问题要求所编织的解或算法。它所使用的是语言中现成的基本数据类型。图中反映了这样一个事实:问题模型反映为过程结构模型,实际上就是功能模型。模型可以做得很精巧,但由于过程模块与数据的复杂关系没有清晰地分离出来,所以它一般都是“具体问题具体解决”,无法重复使用其中的“零部件”,而且问题变得庞大以后,其复杂性会无法收场。例1-1有一些日期数据,放在数据文件abc.txt中,这些日期的年、月、日数值加起来若等于15,则收集,然后按日期从小到大的顺序打印出来。如文件abc.txt中有:03-11-1203-08-0404-08-1102-07-06则输出:02年07月06日03年08月04日简单地看,可以把求解过程划分成三个部分:第一部分是输入数据,将读入的数据放在一个年月日的复合数据结构的数组(CH3.5)中:第二部分是处理日期数据,数据处理完后,放到另一个同类数组中;第三部分是输出处理,将数组中的数据按要求输出。由于处理日期数据的算法“比较复杂”(相对而言),所以把它划分为两个子部分,第一子部分是取年月日的数值,加起来判断其和等于15否。这部分工作要经历一个循环,对数组中的每个日期进行操作、比较,如果条件满足,就将其放入准备好的另一个数组中。第二子部分是对结果数组进行排序操作。它要经历至少两重循环,通过频繁地比较大小和交换操作,达到数据按从小到大存放在该数组的自的。其中大小比较是日期的大小比较先比较年,再比较月,最后比较日。这里编程所要考虑的数据处理量并不应该仅仅是样本数据文件提供的数据量。整个问题写成算法就是:第一层(总体结构)1.1输入(读入输入文件的数据放入数组一)1.2处理(读入数组一的数据,处理后放入数组二1.3输出(读入数组二的数据,输出到显示器上)第二层(数据处理)2.1滤数(读入数组一的数据,寻找符合条件的数放入数组二)2.2排序(对数组二的数据进行排序)画成图的形式如图1-3所示。图中实线箭头表示过程控制关系,或者称过程调用。虚线箭头表示数据流向,矩形框表示过程。数组一和数组二是根据基本数据类型建立起来的存放数据的容器,输入文件和显示器可以看作是系统提供的数据类型实体,通过简单的操作可以获得数据和输出结果。www.TopSage.com
www.TopSage.com