《C语言北工商课件.ppt》由会员分享,可在线阅读,更多相关《C语言北工商课件.ppt(83页珍藏版)》请在三一办公上搜索。
1、准备上课,主讲:李越辉,北京工商大学计算机学院,C语言程序设计,本讲主要介绍程序设计的一般方法、结构化程序设计思想以及三种结构化程序设计的基本结构顺序结构、选择结构和循环结构。,第三讲 逻辑思维与计算机解题,4,将实际问题抽象为逻辑关系枚举法解题思路关系与关系表达式程序的循环结构与分支结构,学 习 目 标,5,关系运算符与关系表达式人的思维到用计算机语言的表示枚举的概念与思路程序的控制结构,内 容 要 点,6,计算机强大的逻辑分析功能是由人通过程序赋给它的。一些逻辑问题必须转换成计算机能够看得懂的数学表达式和一定的程序指令。这一章我们通过例子来介绍如何将人对问题的思考转换为让计算机能解的数学表
2、达式,同时给出一些通常要用到的程序结构和C/C+语句。,引言,7,北京工商大学某班有四位同学中的一位做了好事,不留名,表扬信来了之后,班主任问这四位同学是谁做的好事。A说:不是我。B说:是C。C说:是D。D说:他胡说。已知三个人说的是真话,一个人说的是假话。现在要根据这些信息,找出做了好事的人。,【任务3.1】“谁做的好事”,8,为了解这道题,我们需要学习如何通过逻辑思维与判断解这类问题的思路。,解题思路,9,3.1 算朮运算符在C/C+中基本的算术运算符有五个,分别为 加+乘*减-除/求余%cout 21%4 endl;输出是1,首先介绍C语言中的运算功能,关系运算符有如下6个=大于等于 大
3、于=等于=小于等于 小于!=不等于,10,为了讲解关系运算符和关系表达式,先在机器上建立和运行下列程序。,3.2 关系运算符和关系表达式,11,/*/*程 序:3_0.cpp*/*功 能:为讲解关系运算而编*/*编制人:李越辉*/*时 间:2008年3月20日*/*,引例,12,#include void main()cout 2 的逻辑值是“2)=2 的逻辑值是“=2)“,1 为真“endl;cout“3=2 的逻辑值是“(3=2)“,0为假“endl;cout“3 2 的逻辑值是“(3 2)“,0为假“endl;cout“3=2 的逻辑值是“(3=2)“,0为假“endl;cout“3!=
4、2 的逻辑值是“(3!=2)“,1为真“endl;,13,3 2 的逻辑值是 1,1为真3=2 的逻辑值是 1,1为真3=2 的逻辑值是 0,0为假3 2 的逻辑值是 0,0为假3=2 的逻辑值是 0,0为假3!=2 的逻辑值是 1,1为真,程序运行结果是:,14,关系运算符 例如:变量 1 为 b,变量 2 为 c,关系运算符为。关系表达式为b c在程序中系统要测试由关系表达式所表示的关系是否成立,成立为真,不成立为假。关系表达式是有值的,这个值非 0 即 1,是布尔值。关系表达式成立,其值为 1。关系表达式不成立,其值为 0。上述性质在编写程序时用到,因此很重要。,关系表达式的一般格式,1
5、5,结合本题任务,可以将四个人说的四句话写成关系表达式。在声明变量时,我们让thisman表示要寻找的做了好事的人,定义它是字符变量。char thisman=;/定义字符变量并将其初始化为空 接着让“=”的含义为“是”,让“!=”的含义为“不是”。,使用关系表达式解决一些问题,16,利用关系表达式将四个人所说的话表示成下表,17,在C/C+中字符在存储单元中是以ASCII码的形式存放的。因此,用赋值语句thisman=A;与thisman=65;两者是等效的,在以thisman为标识的存储单元中存的是数字65。建议你用如下实验加以验证。,thisman 65地址xxxx,赋值语句设置初始值,
6、18,/*/*程 序:3_1.cpp*/*功 能:验证A和65是否相等*/*编制人:wuwh*/*时 间:2001年6月27日*/*#include/预编译命令void main()/主函数/主函数开始char thisman;/声明字符变量thisman,thisman=A;/thisman赋值为A/输出关系表达式“65=A”的值cout 65=A 关系表达式的值为(65=A),1为真。endl;/主函数结束,程序实例,19,结合任务3.1分析,A、B、C、D四个人,只有一位是做好事者。令做好事者为1,未做好事者为0,可以有如下4种状态(情况),3.3 枚举法的思路,20,这四种状态可简化写
7、成,显然第一种状态是假定A是做好事者,第二种状态是假定B是做好事者,。所谓枚举是按照者四种假定逐一地去测试四个人的话有几句是真话,如果不满足三句为真,就否定掉这一假定,换下一个状态再试。具体做法如下:,21,(1)假定让thisman=A代入四句话中,四个关系表达式的值的和为1,显然不是A做的好事,22,(2)假定让thisman=B代入四句话中,四个关系表达式的值的和为2,显然不是B做的好事,23,(3)假定让thisman=C代入四句话中,四个关系表达式的值的和为3,就是C做的好事,24,综上所述一个人一个人去试,就是枚举。从编写程序看,实现枚举最好用循环结构。这部分的程序写出如下:,fo
8、r(k=1;k=4;k=k+1)/计数型循环,循环的控制变量为k/循环体开始thisman=64+k;/产生被试者,依次为A,B,C,D/赋值给thismansum=(thisman!=A)/测试A的话是否为真+(thisman=C)/测试B的话是否为真+(thisman=D)/测试C的话是否为真+(thisman!=D);/测试D的话是否为真/循环体结束,25,for是计数型循环的标识符,圆括号括起的是三个表达式。其下的大括号括起的部分是循环体。for循环的结构如下:,26,for语句的格式为,for(表达式1;表达式2;表达式3)循环体(语句组),27,求解表达式1,置循环控制变量的初值测
9、试表达式2,测试是否未到循环控制变量的终值2-1 如果表达式2的值为真,则执行32-2 如果表达式2的值为假,则退出循环转5执行循环体语句组之后转4求解表达式3,让循环控制变量增值或减值,再转2执行for语句的下一条语句,for循环的执行过程如下:,C程序的控制结构(一),程序设计的一般方法结构化程序设计顺序结构if 语句switch语句,作业,回主页,程序的灵魂算法(一),一个程序应包括以下两方面内容:(1)对数据的描述。在程序中要指定数据的类型和数据的组织形式,即数据结构(data structure)。(2)对操作的描述。即操作步骤,也就是算法(algorithm)。数据是操作的对象,操
10、作的目的是对数据进行加工处理,以得到期望的结果。作为程序设计人员,必须认真考虑和设计数据结构和操作步骤(即算法)。因此,著名计算机科学家沃思(Nikiklaus Wirth)提出一个公式数据结构+算法=程序,程序的灵魂算法(二),实际上,一个程序除了以上两个主要要素之外,还应当采用结构化程序设计方法进行程序设计,并且用某一种计算机语言表示。因此,可以这样表示:程序=算法+数据结构+程序设计方法+语言工具和环境也就是说,以上4个方面是一个程序设计人员所应具备的知识。在设计一个程序时要综合运用这几方面的知识。在这4个方面中,算法是灵魂,数据结构是加工对象,语言是工具,编程需要采用合适的方法。算法是
11、解决“做什么”和“怎么做”的问题。程序中的操作语句,实际上就是算法的体现。显然,不了解算法就谈不上程序设计。,算 法 的 概 念(一),从事各种工作和活动,都必须事先想好进行的步骤,然后按部就班地进行,才能避免产生错乱。不要认为只有“计算”的问题才有算法。广义地说,为解决一个问题而采取的方法和步骤,就称为“算法”。对同一个问题,可以有不同的解题方法和步骤。方法有优劣之分。有的方法只需进行很少的步骤,而有些方法则需要较多的步骤。一般说,希望采用简单的和运算步骤少的方法。因此,为了有效地进行解题,不仅需要保证算法正确,还要考虑算法的质量,选择合适的算法。,算 法 的 概 念(二),例:判定2000
12、2500年中的每一年是否闰年,将结果输出。闰年的条件是:能被4整除,但不能被100整除的年份都是闰年,如1996年,2004年是闰年;能被100整除,又能被400整除的年份是闰年。如1600年、2000年是闰年。不符合这两个条件的年份不是闰年。算法可表示如下:设y 为被检测的年份。可采取以下步骤:S1:2000=yS2:y不能被4整除,则输出y“不是闰年”。然后转到S6,算 法 的 概 念(三),S3:若y能被4整除,不能被100整除,则输出y“是闰年”。然后转到S6S4:若y能被100整除,又能被400整除,输出y“是闰年”;否则输出“不是闰年”。然后转到S6S5:输出y“不是闰年”S6:y
13、+1=yS7:当y2500时,转S2继续执行,如y2500,算法停止。,算 法 的 概 念(四),在这个算法中,采取了多次判断。先判断y能否被4整除,如不能,则y必然不是闰年。如y 能被4整除,并不能马上决定它是否闰年,还要看它能否被100整除。如不能被100整除,则肯定是闰年(例如1996年)。如能被100整除,还不能判断它是否闰年,还要被400整除,如果能被400整除,则它是闰年,否则不是闰年。在这个算法中,每做一步,都分别分离出一些范围(巳能判定为闰年或非闰年),逐步缩小范围,使被判断的范围愈来愈小,直至执行S5时,只可能是非闰年。见图2.1示意。,算 法 的 特 性(一),一个算法应该
14、具有以下特点:1.有穷性一个算法应包含有限的操作步骤,而不能是无限的。事实上,“有穷性”往往指“在合理的范围之内”。究竟什么算“合理限度”,并无严格标准,由人们的常识和需要而定。2.确定性算法中的每一个步骤都应当是确定的,而不应当是含糊的、模棱两可的。,算 法 的 特 性(二),3.有零个或多个输入所谓输入是指在执行算法时需要从外界取得必要的信息。一个算法也可以没有输入。4.有一个或多个输出算法的目的是为了求解,“解”就是输出。没有输出的算法是没有意义的。5.有效性算法中的每一个步骤都应当能有效地执行,并得到确定的结果。,怎样表示一个算法,为了表示一个算法,可以用不同的方法。常用的有自然语言、
15、传统流程图、结构化流程图、伪代码、PAD图等。,用自然语言表示算法,用自然语言表示通俗易懂,但文字冗长,容易出现“歧义性”。自然语言表示的含义往往不太严格,要根据上下文才能判断其正确含义。此外,用自然语言描述包含分支和循环的算法,不很方便(如例2.5的算法)。因此,除了很简单的问题以外,一般不用自然语言描述算法。,用流程图表示算法(一),流程图是用一些图框表示各种操作。用图形表示算法,直观形象,易于理解。美国国家标准化协会ANSI(American National Standard Institute)规定了一些常用的流程图符号。其中菱形框的作用是对一个给定的条件进行判断,根据给定的条件是否
16、成立来决定如何执行其后的操作。它有一个入口,两个出口。连接点(小圆圈)是用于将画在不同地方的流程线连接起来。图中有两个以为标志的连接点(在连接点圈中写上“1”),它表示这两个点是互相连接在一起的。实际上它们是同一个点,只是画不下才分开来画。用连接点,可以避免流程线的交叉或过长,使流程图清晰。,用流程图表示算法(二),判定闰年的算法用流程图表示,传统流程图的弊端,传统的流程图用流程线指出各框的执行顺序,对流程线的使用没有严格限制。因此,使用者可以不受限制地使流程随意地转来转去,使流程图变得毫无规律。这种算法难以阅读,也难以修改,从而使算法的可靠性和可维护性难以保证。如果我们写出的算法能限制流程的
17、无规律任意转向,阅读起来就很方便。既然用基本结构的顺序组合可以表示任何复杂的算法结构,那么基本结构之间的流程线就属多余的了。,用N-S流程图表示算法(一),1973年美国学者I.Nassi和B.Shneiderman提出了一种新的流程图形式。在这种流程图中,完全去掉了带箭头的流程线。全部算法写在一个矩形框内,在该框内还可以包含其他的从属于它的框,或者说,由一些基本的框组成一个大的框。这种流程图又称N-S结构化流程图。这种流程图适于结构化程序设计,因而很受欢迎。N-S流程图用以下的流程图符号:,用N-S流程图表示算法(二),用伪代码表示算法(一),用传统的流程图和N-S图表示算法,直观易懂,但画
18、起来比较费事。因此,流程图适宜表示一 个算法,但在设计算法过程中使用不是很理想。为了设计算法时方便,常用一种称为伪代码(pseudo code)的工具。伪代码是用介于自然语言和计算机语言之间的文字和符号来描述算法。它如同一篇文章,自上而下地写下来。每一行(或几行)表示一个基本操作。它不用图形符号,因此书写方便、格式紧凑,也比较好懂,便于向计算机语言算法(即程序)过渡。,用伪代码表示算法(二),即计算机语言中具有的语句关键字用英文表示,其他的可用汉字表示。总之,以便于书写和阅读为原则。用伪代码写算法并无固定的、严格的语法规则,只要把意思表达清楚,并且书写的格式要写成清晰易读的形式。例求5!,用伪
19、代码表示的算法如下:BEGIN(算法开始)1=t2=iwhile iti+1=iprint tEND(算法结束),用伪代码表示算法(三),BEGIN(算法开始)2000=ywhile yyEND(算法结束),用伪代码表示算法(四),从以上例子可以看到:伪代码书写格式比较自由,容易表达出设计者的思想。用伪代码写的算法也很容易修改。用伪代码很容易写出结构化的算法。例如上面例子都是结构化的算法。但是用伪代码写算法不如流程图直观,可能会出现逻辑上的错误(例如循环或选择结构的范围搞错等)。以上介绍了常用的表示算法的几种方法,在程序设计中读者可以根据需要和习惯任意选用。软件专业人员一般习惯使用伪代码,考虑
20、到国内广大初学人员的情况,为便于理解,以后各章中主要采用形象化的N-S图表示算法。但是,对其他方法也应有所了解,以便在阅读其他书刊时不致发生困难。,用计算机语言表示算法,要完成一件工作,包括设计算法和实现算法两个部分。设计算法的目的是为了实现算法。因此,不仅要考虑如何设计一个算法,也要考虑如何实现一个算法;用计算机语言表示算法必须严格遵循所用语言的语法规则,这是和伪代码不同的。我们将前面介绍过的算法用C语言表示;用计算机语言表示的算法程序。,3.1 程序设计的一般方法,程序就是按照某种算法,在有限的步骤内对一些经过整理的、按照一定形式组织起来的有关联的数据(即数据结构)进行分析研究,得到期望的
21、结果的计算机可以执行的指令序列。所以,数据结构和算法是程序设计的主要因素。程序设计的一般方法可以概括为以下四个步骤:明确处理对象、选择算法画流程图编写程序调试程序,3.1 程序设计的一般方法,已知三角形三条边,求三角形的面积首先需要明确处理对象,选择适合的算法根据数据特点和取值范围,浮点型的数据可以很好地表示三角形的边长和面积。如果a、b、c符合两边之和大于第三边,则a、b、c可以组成三角形,其面积的算法可以使用海伦公式第二步画流程图。,3.1 程序设计的一般方法,不成立,成立,3.1 程序设计的一般方法,已知三角形三条边,求三角形的面积第三步根据流程图编写程序。选择一种计算机语言,按照流程图
22、用该计算机语言提供的语句体系编写源程序。第四步调试程序。对已经编写好的源程序进行上机调试,并验算结果。如果不正确,修改程序再调试,直到得到期望的结果。,3.2 结构化程序设计(一),结构化程序设计方法的基本思想是:任何程序都可用三种基本结构的组合来实现。这三种基本结构是:顺序结构、选择结构和循环结构。这三种结构都具有一个入口和一个出口。要求限制无条件转移语句(即goto语句)的使用,3.2 结构化程序设计(二),顺序结构:是按照书写顺序依次执行的。选择结构:是对给定的条件进行判断,再根据判断的结果决定执行哪一个分支。循环结构:是在给定条件成立时反复执行某段程序。,3.3 C语言的顺序结构(一)
23、,顺序结构是结构化程序设计的三种基本结构中最简单的。它可以独立存在,也可以出现在选择结构或循环结构中,整个程序都存在顺序结构。在顺序结构中,函数、一段程序或者语句是按照出现的先后顺序执行的。例 求ax2+bx+c=0方程的解。a、b、c由键盘输入,且b2-4ac0。,3.3 C语言的顺序结构(二),用伪代码表示算法:定义a、b、c、p、x1、x2用于存放方程的系数、中间变量和结果;输入a、b、c令p=sqrt(b*b-4*a*c)计算x1、x2:x1=(-b+p)/(2*a)x2=(-b-p)/(2*a)输出方程的根x1、x2,举一反三:画出实现“输入三个数a、b、c,输出平均值aver”的程
24、序的流程图和伪代码。,3.4 if 语句(一),选择结构是结构化程序的三种基本结构之一,用于根据给定条件的判断执行何种操作。C语言中的选择结构有两种:if语句和switch语句。if语句主要提供两个分支的选择,switch语句提供多分支的选择。下面我们先介绍最为常用的选择结构if语句。,3.4 if 语句(二),if 语句的基本形式,if(条件)语句1;else语句2;,3.4 if 语句(三),判断方程ax2+bx+c=0是否有实数解,其中a、b、c由键盘输入 分析:用伪代码表示算法:定义a、b、c、p用于存放方程的系数、中间变量;输入a、b、c令p=b*b-4*a*cif(p=0)输出方程
25、有实数解else 输出方程无实数解,由键盘输入系数a、b、c,判断方程ax2+bx+c=0是否有实数解,如果有则输出其解。(提示:需要用到复合语句),3.4 if 语句(四),当语句2为空时,else可以省略,if语句形式变换为:if(条件)语句;,例:由键盘输入x、y两个数,要求从大到小排序并输出。分析:关键技术:两个变量互换算法是:t=x;x=y;y=t;定义x、y、t用于存放输入的两个数和中间变量;输入x、y if(xy)t=x;x=y;y=t;输出x、y,#include void main()float x,y,t;scanf(“%f,%f”,3.4 if 语句(五),3.4 if
26、语句(六),当if语句中的语句1或语句2是一个含if语句的复合语句时,形成if语句的嵌套。形式一:当语句2是if语句结构if(条件1)语句1 else if(条件2)语句2 else 语句3形式二:当语句1是if语句结构if(条件1)if(条件2)语句1 else 语句2else 语句3,3.4 if 语句(七),3.4 if 语句(八),举一反三:试判断下列选择结构是否可以表示上例函数。if(x0)y=-1;if(x=0)y=0;else y=1;,/*/*程 序 名:3_4.cpp(分支程序示例)*/*作 者:李越辉*/*编制时间:2007年3月*/*主要功能:实现符号函数*/*#incl
27、ude/预编译命令void main()/主函数/主函数开始int x=0,y=0;/声明x,y为整型变量,初始化为0cout x;/从键盘输入整数送至x中if(x0)/如果x0,将1赋给yy=1;elseif(x=0)/如果x=0,将0赋给yy=0;elsey=-1;/否则(x0),将-1赋给ycout 当x=x 时,y=y endl;/输出x,y的值/主函数结束,3.4 if 语句(九),在if语句嵌套中,特别注意else与if的配对问题C编译系统处理该问题的的原则是:else总是与同一语法层次中离它最近的尚未配对的if配对。为了避免出现else的配对错误,通常利用大括号将if-else语
28、句结构括起来。程序段一:程序段二:if(a=0)if(a=0)if(a0)printf(“a0n”);if(a0)printf(“a0n”);else printf(“a0n”);else printf(“a=0n”);,NS图,有了上述了解之后,我们来看解“谁做的好事”的程序框图,现在我们来分析“谁做的好事”的NS流程图。它是由两大块组成的,如图,第一块循环结构,第二块分支结构,第一块是循环结构,功能是产生被试对象,依次为A、B、C、D。并测试四句话有多少句为真,如有3句为真,则可确定做好事者,同时置有解标志为1。第二块为分支结构,功能是判断是否无解,如为真,则输出无解信息。这是粗看。再往细
29、看,第一块的循环体又由两块组成,如图中含两条赋值语句中含一条分支语句,讲这一段是希望你掌握NS图,这对今后的学习会有好处。按照程序框图很容易写出程序(如下页所示),thisman=64+k;sum=(thisman!=A)+(thisman=C)+(thisman=D)+(thisman!=D);,sum=3,真,假,输出该被测试者;有解标志置1;,/*/*程 序 名:3_5.cpp*/*作 者:李越辉*/*编制时间:2007年3月*/*主要功能:谁做的好事*/*#include/预编译命令void main()/主函数/主函数开始int k=0,sum=0,g=0;/声明变量为整数类型,且均
30、初始化为0char thisman=;for(k=1;k=4;k=k+1)/k既是循环控制变量,也表示第k个人/for 循环体开始thisman=64+k;sum=(thisman!=A)+(thisman=C)+(thisman=D)+(thisman!=D);if(sum=3)/如果4句话有3句话为真,则输出该人/输出做好事者cout 做好事者为 char(64+k)endl;g=1;/有解标志置1/for 循环体结束if(g!=1)/则输出无解信息 cout Cant found!endl;/主函数结束,#include void main()int k=0,sum=0,g=0;char
31、 thisman=;for(k=1;k=4;k=k+1)thisman=64+k;sum=(thisman!=A)+(thisman=D)+(thisman=C)+(thisman!=D);if(sum=3)cout 做好事者为 char(64+k)endl;g=1;if(g!=1)cout Cant found!endl;,/*/*程 序 名:3_6.cpp*/*作 者:李越辉*/*编制时间:2008的好事*/*#include/预编译命令void main()/主函数/主函数开始int k=0,sum=0,g=0;/声明变量为整数类型,且均初始化为0for(k=1;k=4;k=k+1)/循
32、环从k为1到4,sum=0;/循环体内的初始化if(k!=1)sum=sum+1;/如A的话为真,则让sum加1;if(k=3)sum=sum+1;/如B的话为真,则让sum加1;if(k=4)sum=sum+1;/如C的话为真,则让sum加1;if(k!=4)sum=sum+1;/如D的话为真,则让sum加1;if(sum=3)/若有三句话为真,则做下列两件事cout This man is char(64+k)endl;/输出做好事者g=1;/让有解标志置1if(g!=1)/则输出无解信息 cout Cant found!endl;/主函数结束,for(k=1;k=4;k=k+1)sum=
33、0;if(k!=1)sum=sum+1;/如A的话为真,则让sum加1;if(k=3)sum=sum+1;/如B的话为真,则让sum加1;if(k=4)sum=sum+1;/如C的话为真,则让sum加1;if(k!=4)sum=sum+1;/如D的话为真,则让sum加1;.,/*/*程 序 名:3_7.cpp*/*作 者:李越辉*/*编制时间:2008年3月*/*主要功能:谁做的好事*/*#include/预编译命令void main()/主函数/主函数开始int k=0,g=0;/声明变量为整数类型,且均初始化为0for(k=1;k=4;k=k+1)/k既是循环控制变量,也表示第k个人/fo
34、r 循环体开始if(k!=1)+(k=3)+(k=4)+(k!=4)=3)/如果4句话有3句话为真,则输出该人/输出做好事者cout 做好事者为 char(64+k)endl;g=1;/有解标志置1/for 循环体结束if(g!=1)/则输出无解信息 cout Cant found!endl;/主函数结束,上述程序可以简化为:,for(k=1;k=4;k=k+1)if(k!=1)+(k=3)+(k=4)+(k!=4)=3)cout 做好事者为 char(64+k)endl;g=1;,for(k=1;k=4;k=k+1)if(k!=1)+(k=3)+(k=4)+(k!=4)=3)cout“做好事
35、者为”char(64+k)endl;g=1;,3.5 switch语句(一),switch语句用于实现多重分支格式为 注意:如果需要执行完本case语句后就跳出switch语句,则在对应的case语句后加上一个break语句,switch(整型表达式)case 数值1:语句1;break;case 数值2:语句2;break;case 数值n:语句n;break;default:语句n+1,3.5 switch语句(二),switch语句由键盘输入一个成绩,然后输出相应的等级“优”、“良”、“中”、“及格”、“不及格”。,#include void main()int score;printf(“请输入学生分数:”);scanf(“%d”,举一反三:由键盘输入等级A、B、C、D,输出成绩范围。其中“A”代表85100分,“B”代表7085分,“C”代表6070分,“D”代表60分以下,3.5 switch语句(二),作业与上机练习,实验三,再 见,