程序设计初步讲义.docx
- 文档编号:9185205
- 上传时间:2023-02-03
- 格式:DOCX
- 页数:60
- 大小:154.31KB
程序设计初步讲义.docx
《程序设计初步讲义.docx》由会员分享,可在线阅读,更多相关《程序设计初步讲义.docx(60页珍藏版)》请在冰豆网上搜索。
程序设计初步讲义
第3章程序设计初步
3.1算法初步及其描述方法
3.1.1算法初步
1.什么是算法
算法是为解决一个特定问题而采取的特定的有限的步骤。
广义地说,做任何事情都有算法,例如一张太极拳打法图解也可以看作是一个“太极拳算法”。
因此,算法概念不限于算术问题,而是具有更广泛的含义。
从计算机应用的角度来说,算法是指完成一个任务所需要的具体步骤和方法(解决问题的方案)。
也就是说给定初始状态或输入数据,经过计算机程序的有限次运算,能够得出所要求或期望的终止状态或输出数据。
【算法3.1】给定两个正整数p和q,求其最大公因数。
古希腊数学家欧几里德给出的算法:
步骤1:
如果p 步骤2: 求p/q的余数r。 步骤3: 如果r=0,则q就是所求的结果。 否则反复做如下工作: 令p=q,q=r,重新计算p和q的余数r,直到r=0为止,则q就是原来的两正整数的最大公因数。 算法常常含有重复的步骤和一些比较或逻辑判断。 如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题。 不同的算法可能用不同的时间、空间或效率来完成同样的任务。 一个算法的优劣可以用空间复杂度与时间复杂度来衡量。 从原则上说,有了算法,人们就可以借助纸、笔和算盘等工具直接求解问题了。 但如果问题比较复杂,计算步骤很多,则应通过编写计算机程序,使用计算机解决。 2.算法的特征 算法是在有限步骤内求解某一问题所使用的一组定义明确的规则。 通俗点说,就是计算机解题的过程。 在这个过程中,无论是形成解题思路还是编写程序,都是在实施某种算法。 前者是推理实现的算法,后者是操作实现的算法。 一个算法应该具有以下五个重要的特征: (1)有穷性: 一个算法必须保证执行有限步之后结束。 (2)确切性: 算法的每一步骤必须有确切的定义。 (3)输入: 一个算法有0个或多个输入,以刻画运算对象的初始情况,所谓0个输入是指算法本身定义了初始条件。 (4)输出: 一个算法有一个或多个输出,以反映对输入数据加工后的结果。 没有输出的算法是毫无意义的。 (5)可行性: 算法原则上能够精确地运行,而且人们用笔和纸做有限次运算后即可完成。 3.算法的类型和结构 (1)算法的类型 算法可分为两大类: 数值算法和非数值算法。 数值算法是为数学问题形成一个构造性解法的完备而确切的描述,并规定方法中仅允许使用加、减、乘、除等基本的算术运算。 非数值算法广泛应用在“数据处理”的场合。 需要对大量的信息(数据)进行加工处理,包括转换、分类、查找、排序和存储等。 常用的算法有穷举、递推、顺序查找和冒泡排序等。 (2)算法的结构 一个算法是由“结构”和“原操作”构成的。 原操作包括: 输入、输出、赋值和比较等。 算法的三种基本结构是: 顺序结构、分支结构和循环结构。 用这三种基本结构可以表示任意一个复杂的算法。 ①顺序结构 顺序结构是指通过安排操作的排列顺序来决定算法流程的结构。 在这种结构中,各个操作是依次执行的。 顺序结构是由若干个依次执行的处理块组成,这是任何一个算法都离不开的基本主体结构。 ②分支结构 在绝大多数情况下,算法不会按部就班地从第一条操作执行到最后一条操作,往往由特定的条件决定执行哪个操作,这就是分支结构。 分支结构是以条件或情况的判断为起始点,它是人脑判断思维活动的抽象。 最基本的分支结构是二分支结构,根据判断逻辑是否成立而决定选择哪一边的处理块去执行。 ③循环结构 循环结构是指在算法设计中,从某处开始有规律地反复执行某一处理块,这个处理块称为循环体。 循环体的执行次数由一个控制循环条件决定。 满足条件反复做,不满足则停止。 3.1.2算法的描述工具 设计一个算法可以根据问题的不同需要用某种语言符号来描述。 目前最常用的几种算法描述工具有: 自然语言、流程图、N-S图、伪代码等。 1.自然语言 自然语言就是人们日常使用的语言,可以是中文、英文等。 用自然语言表示的算法通俗易懂,但一般篇幅较冗长,表达上不易准确,易引起理解上的“歧义性”(即对同一段文字,不同的人会有不同的理解)。 【算法3.2】输入3个数,求其最大数。 分析: 该算法可以使用分支结构表示。 设num1,num2,num3存放3个数,max存放其最大值。 为求其最大数,只要对3个数进行比较,可按如下步骤去做: S1: 输入3个数num1,num2,num3; S2: 先把第1个数num1的值赋给max; S3: 将num2与max比较,如果num2>max,则把num2的值赋给max,否则,不做任何事情。 S4: 将num3与max比较,如果num3>max,则把num3的值赋给max,否则,不做任何事情。 S5: 输出max的值,即最大值。 【算法3.3】求1+2+3+…+100。 分析: 该算法可以使用循环结构表示。 设n存放1到100之间的整数,sum存放1到100的和,即sum=1+2+3+…+100,可按如下步骤去做: S1: 进行初始化,1=>n,0=>sum; S2: sum+n=>sum; S3: n+1=>n; S4: 进行判断,n是否小于等于100,如果条件为真,则返回S2,否则执行S5; S5: 输出sum的值。 2.流程图 流程图是用一组规定的图形符号、流程线和文字说明来表示算法,它直观形象,易于理解。 流程图的特点是用“流线”给算法执行中的每一个步骤指定了逻辑上的顺序,因此能把程序执行的控制流表达得十分清楚。 但如果使用不当会使程序的流程出现缠绕,不利于结构化程序设计的实施。 流程图符号见图3-1。 图3-1 流程图符号 【算法3.4】用流程图描述算法3.2(如图3-2)。 【算法3.5】用流程图描述算法3.3(如图3-3)。 3.N-S图 N-S图也是描述算法的常用工具。 与流程图相比,N-S图完全去掉了流程图中的流线和箭头,因此能用N-S图表示的算法,必是结构化的算法。 图3-4N-S图的三种基本结构 图3-2 图3-3 【算法3.6】用N-S图描述算法3.2(如图3-5)。 【算法3.7】用N-S图描述算法3.3(如图3-6)。 4.伪代码 伪代码是一种算法描述语言,使用伪代码的目的是为了使被描述的算法可以容易地以任何一种编程语言实现。 因此,伪代码必须结构清晰,代码简单,可读性好,并且类似自然语言。 【算法3.8】用伪代码描述算法3.2。 INPUTnum1,num2,num3 num1=>max IFnum2>maxTHENnum2=>max IFnum3>maxTHENnum3=>max PRINTmax 图3-6 图3-5 【算法3.9】用伪代码描述算法3.3。 1=>n,0=>sum while(n<=100) {sum+n=>sum; n+1=>n; } printsum 3.1.3算法和程序设计 前面介绍了如何描述算法,但计算机是无法识别流程图和伪代码的,只有用计算机语言编写的程序,经编译成目标程序后,才能被计算机执行。 因此,用任何方法描述的算法,还得要将它转化成计算机语言程序。 程序设计是人关于现实问题求解的思维活动的“代码化”过程,是用计算机语言作为工具进行的创造性劳动。 编程序的一个主要内容就是如何将解决应用问题所使用的算法用程序设计语言来描述。 1.程序设计的一般步骤 (1)分析问题 根据用户的具体要求,进行需求分析、数据及处理分析、可行性分析、运行环境分析。 然后在分析的基础上,将实际问题抽象化,建立相应的数学模型并确定解决方案。 读者在初学程序设计的时候,教科书中的例题都比较简单,从这些简单的例题中读者很难体会到分析问题的作用。 而且题目本身往往已经对需要解决的问题做了清楚准确的描述。 但尽管如此,我们也不应直接开始编程,而应该首先进行问题分析。 (2)确定算法 根据选取的数学模型和确定的方案,设计出具体的操作步骤,并可以通过流程图等描述算法的工具将确定的算法清晰、直观的表示出来。 (3)编写程序 选用合适的开发平台和程序设计语言,将算法按所选语言的规则描述出来,即形成程序设计语言编制的源程序。 (4)调试运行程序 对编写好的程序进行试运行和检验,发现问题立即对程序进行修改,然后再试运行和检验,直至得出正确的结果。 (5)建立文档资料 整理分析计算结果,并建立相应的文档资料(程序技术说明书、用户使用说明书等),以便维护和修改。 2.结构化程序设计方法 结构化的程序设计方法的要点如下: (1)程序的质量标准是“清晰第一,效率第二”。 (2)程序的设计采用“自顶向下,逐步求精,模块化设计,结构化编程”的方法。 (3)程序的结构仅由顺序、分支、循环三种基本结构的组合、嵌套而成,且满足: ·每个程序模块只有一个入口和一个出口; ·没有死语句(永远执行不到的语句); ·没有死循环(永远不能终止的循环); (4)程序的书写必须按一定的规范和格式进行(参见附录部分)。 (5)程序的设计风格要以好的可读性为标准,力求外观美观、结构流畅、语句简洁。 3.2基本计算 3.2.1数据类型 在C++中,数据具有不同的类型,类型定义了变量可存储的数值范围以及可进行的操作。 变量是用于内存中保存数据的,每个变量都必须有确定的数据类型,C++语言的数据类型如图3-7所示。 说明: ①基本数据类型前可以添加修饰符,以改变基本类型的意义,可用的修饰符有long、short、signed和unsigned四种,其中,unsigned和signed只用于修饰char和int,且signed修饰词可以省略。 当用unsigned修饰词时,后面的类型说明符可以省略。 另外,双精度型前可以加long修饰符。 基本的数据类型及其表示范围,可参见表3-1。 ②当多种类型的数据进行混合运算时,往往需要进行类型转换,将它们转换为相同的类型,即较低类型转换为较高类型,然后再参加运算,转换规则如图3-8。 注: 其中,type表示一种非void的数据类型。 图3-7C++数据类型 表3-1基本的数据类型及其表示范围 类型名 类型 字节 表示范围 char 字符型 1 -128~127 unsignedchar 无符号字符型 1 0~255 int 整型 4 -2,147,483,648~2,147,483,647 unsignedint 无符号整型 4 0~4,294,967,295 short 短整型 2 -32,768~32,767 unsignedshort 无符号短整型 2 0~65,535 long 长整型 4 -2,147,483,648~2,147,483,647 unsignedlong 无符号长整型 4 0~4,294,967,295 float 浮点型 4 3.4E+/-38(7位有效数字) double 双精度型 8 1.7E+/-308(15位有效数字) longdouble 长双精度型 10 1.2E+/-4932(19位有效数字) 图3-8 转换规则 图中横向的箭头表示必须的转换,如两个float型数参加运算,虽然它们类型相同,但仍要先转换成double型再进行运算,结果亦为double型。 纵向箭头表示当运算符两边的操作数为不同类型时的转换,如一个long型数据与一个int型数据一起运算,需要先将int型数据转换为long型,然后两者再进行运算,结果为long型。 所有这些转换都是由系统自动进行的,因此也称为隐式转换。 程序3-1类型转换程序 #include usingnamespacestd; intmain(void) { chara='x'; intb=3; intf=2; floatc=2.5678; doubled=5.2345; longe=32L; cout< return0; } ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 下面我们来分析一下这段程序: (1)进行d/c运算时,要将c转换成double型,运算的中间结果为double型; (2)进行e*f运算时,将f转换为long型,运算的中间结果为long型; (3)进行a-b运算时,将a转换为int型,运算的中间结果为int型; (4)当(3)的中间结果与 (1)的中间结果运算时,将(3)的中间结果转换为double型,运算的中间结果为double型; (5)当(4)的中间结果与 (2)的中间结果运算时,将 (2)的中间结果转换为double型,得出最后结果。 程序最后的运行结果为: 55.0385 程序所处理的数据不仅分为不同的类型,而且每种类型的数据还有常量和变量之分。 接下来,我们详细讨论各种基本类型的数据。 3.2.2变量 在程序执行过程中其值可以变化的量称为变量。 变量是需要用名字来标识的,其命名规则与标识符相同。 为了提高程序的可读性,给变量命名时,应该注意使用有意义的名字,以帮助描述变量所保存的值。 例如: 要用一个变量保存工资总额,可以使用total_payroll,也可以使用XYZ作变量名,它们都是合法的名字。 但使用前者比使用后者就更好,因为从变量名就能大致知道它保存了什么样的值,便于使用。 在使用一个变量之前,必须先定义。 变量的定义的一般格式如下: 数据类型变量名1[=初始值1],变量名2[=初始值2],...; “数据类型”是指C++有效的数据类型,如int、double、long等。 方括号中的内容是可选的,它是在变量定义时给变量赋初值。 下面是几个变量定义的实例: longn;//定义了一个长整型变量n,未赋初值 doublea,b=0.5;//定义双精度型变量a、b,a未赋初值,b的初值为0.5 下面是一个使用变量的程序实例。 程序3-2 #include usingnamespacestd; intmain(void) { intworkDays=5; //定义了一个整型变量workDays,并初始化为5,表示一周的工作天数。 floatworkHours,payRate,weeklyPay; //定义了三个实型变量,分别表示每天工作的小时数、每小时应支付的薪水及每周应支付的薪水。 workHours=7.5;payRate=38.55; //两个赋值语句。 7.5赋给变量workHours,38.55赋给变量payRate。 weeklyPay=workDays*workHours*payRate; //计算每周的工资,即三个变量workDays、workHours、payRate的积,*是乘运算符,结果保存在变量weeklyPay变量中。 cout<<"WeeklyPay="< //输出字符串"WeeklyPay="、变量weeklyPay的值和换行符。 return0; } ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 本程序的运行结果如下: WeeklyPay=1445.63 注意: 我们定义一个变量时,如果没有给它赋初值,它的值是不定的。 例如,在上面的第四行执行前,weeklyPay的值是不定的。 因此,变量第一次赋值称之为初始化,变量在使用之前应当先初始化。 下面分别介绍各种类型的变量。 1.整型 整型变量可用short、int、long定义,可以表示正整数、负整数和零。 缺省的情况下,整型变量假定为有符号的,但是,使用unsigned关键字,也可以把整型变量定义为无符号的。 整型是常用的一种数据类型,但是,它的大小是不固定的。 整数能存储的最大值是由计算机给它分配的存储空间的大小决定的,而整数所占的存储空间因不同的计算机而异。 当一个整数存储在计算机中时,左起第一位叫做第0位,即符号位,它用来表示该数是正数或负数。 如果是负数,符号位被置1,正数则为0。 例如,某种计算机可能用16位(两个字节)来存储一个整数,能表示的整数范围是-32768~32767。 如图3-9。 图3-9整型数据的存储 2.实型 实型变量分为单精度(float)型、双精度(double)型和长双精度(longdouble)型三类。 有关规定见表3-2。 表3-2实型数据 类型 比特数 有效数字 数值范围 float 32 6~7 -3.4×10-38~3.4×1038 double 64 15~16 -1.7×10-308~1.7×10308 longdouble 128 18~19 -1.2×10-4932~1.2×104932 一个实型数据一般在内存中占4个字节(32位)。 与整型数据的存储方式不同,实型数据是按照指数形式存储的。 系统把一个实型数据分成小数部分和指数部分分别存放,小数部分采用规范化的指数方式表示。 实数3.14159在内存中的存放形式如图3.10示意。 图3-10实型数据的存储 3.字符型 字符变量用char定义,表示用单引号括起来的一个字符,如'a','D','? ','$'等。 另外,还有一些字符是不可显示字符,也无法通过键盘输入,例如响铃、换行、制表符、回车等。 这样的字符变量该如何写到程序中呢? C++提供一种称为转义序列的表示方法来表示这些字符,表3-3列出了C++预定义的转义序列。 表3-3C++预定义的转义序列 字符常量形式 ASCII码 含义 \a 07 响铃 \n 0A 换行 \t 09 水平制表符 \v 0B 垂直制表符 \b 08 退格 \r 0D 回车 \\ 5C 字符“\” \” 22 双引号 \’ 27 单引号 一个字符变量仅占用一个字节,存放该字符的ASCII码,如图3-11所示。 例如: 字符'A'的ASCII码为65,字符'a'的ASCII码为97。 象整型数一样,字符变量也可被指定为signed或unsigned。 一个有符号字符变量可以保存-128~127之间的整数,而一个无符号字符变量可以保存0~255之间的整数,它们均可用于表示小整数,象整型数一样赋值,例如: signedcharoffset=-88; unsignedcharrow=2,column=26; 图3-11 字符型数据的存储 C++语言把字符型变量当作整型量一样使用,下面举例说明: 程序3-3 #include usingnamespacestd; intmain(void) { charc1='a'; charc2='b'; charc3,c4; c3=c1-('a'-'A'); c4=c2-('a'-'A'); cout< return0; } ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 运行结果为: AB 程序中的'a'-'A'是大小写字母之间的差值,其值为32。 所以我们也可以把程序写成: c3=c1-32; c4=c2-32; 如果我们想看一看c3、c4中到底存储的值是多少,可以这样: cout<<(int)c3<<(int)c4< 其运行结果为: 6566 注意: 在内存中,字符数据以ASCII码存储,即以整数表示,因此,'0'和0是不同的。 4.布尔型 布尔类型变量用bool定义,其值为true或false,true和false都是C++的关键字。 整型值也可赋给bool变量,但会被隐式转换成true或false。 转换规则如下: 整型值非0时,转换为true,整型值为0时,转换为false。 同样,布尔值也可赋值给整型变量,但要进行隐式转换,转换规则为: 布尔值为true时,转换为1,布尔值为false时,转换为0。 所有的条件表达式返回类型都是bool型,比如n! =0(! =是“不等于”运算符,我们在本章后面要介绍)根据不同的n,返回true或false。 3.2.3常量 常量就是在程序运行过程中其值不发生变化的量。 常量可分为直接常量与符号常量。 直接常量就是平常我们所说的常数,例如: 'r'为字符型直接常量,3.1415926为双精度直接常量。 符号常量就是用一个标识符代表某个常量。 符号常量可用关键字const声明,其格式如下: const数据类型 常量名=常数值; 例如: constinta=1234;//定义a为整型常量,其值为1234。 constcharb='a';//定义b为字符型常量,其值为'a'。 在程序设计中,尽量使用符号常量来代替常数,这是一种好的编程习惯,这样可以增加程序的可读性、可维护性。 例如,在数值计算中,我们会经常遇到一些常量,比如圆周率,如果把它定义成符号常量,当需要更改常量值的时候,只需要更改符号常量的定义语句即可。 也可以使用预处理语句定义符号常量,例如: #definePI3.14159 定义符号常量PI,然后在程序中使用PI,跟使用常数3.14159的效果是一样的。 编译器在编译时,把符号PI替换成3.14159,当需要修改PI的值时,只需要修改上面的语句即可。 但是我们不推荐这样做,因为在编译时使用常数替代了所有的预定义符号,这样在代码中相应位置实际都是常数。 程序中过多的常数会导致程序代码量变大,而且在多个源文件中定义了同样的符号,会产生符号重定义的问题。 由于大部分内容在变量的相关内容中介绍了,下面简单介绍各种类型的常量。 1.整型常量 整型常量即以文字形式出现的整数,包括正整数、负整数和零。 一个整型常量,例如2007,总是被假定为int类型,除非有L或l后缀,才被处理为longint类型。 例如2007L,2007l。 同样,一个整型数也可以加U或u后缀,指定为unsigned类型。 例如2007U,2007u。 整型常量的表示形式有10进制、8进制和16进制。 如果一个整型数有前缀0,则表示是8进制数,有前缀0x或0X,表示是16进制数。 例如: 92(十进制),0134(8进制),0x5C(16进制)。 其中,8进制数只能使用数字0~7,16进制数可用0~9及A~F(或a~f)表示。 2.实型常量 实型常量即以文字形式出现的实数,实数有一般形式和指数形式两种表示形式。 一般形式: 例如,12.5,-12.5等。 指数形式: 例如,0.345E+2表示0.345×102,其中字母E可以大写或小写。 一个实型数,如0.06总是假定为double型,除非有F或f后缀,才被处理为float型。 若有L或l后缀,则被处理为longdouble型。 3.字符型常量 字符常量可以表示用一对单引号括起来的普通字符及转义字符(转义序列)。 4.字符串常量 字
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 程序设计 初步 讲义
![提示](https://static.bdocx.com/images/bang_tan.gif)