strlen("ab\nc\103de");为什么显示是7 不是9?

每个语句和数据声明的最后必须有一个分号
时间: 8:32:33
第一章&&&&?本章要点?C语言的特点??C程序的结构在计算机上运行C程序的方法&&&&§1-1 C语言出现的历史背景? C语言是国际上广泛流行的高级语言。 ? C语言是在B语言的基础上发展起来的。 ? B (BCPL)语言是1970年由美国贝尔实验 室设计的, 并用于编写了第一个UNIX操作 系统,在PDP 7上实现。优点:精练,接近硬 件,缺点:过于简单,数据无类型。 ? 1973年贝尔实验室的D.M.Ritchie 在B语言 的基础上设计出了C语言,对B取长补短, 并用之改写了原来用汇编编写的UNIX,(即 UNIX第5版),但仅在贝尔实验室使用。&&&&§1-1C语言出现的历史背景? 1975年UNIX第6版发布,C优点突出引起关注。 ? 1977年出现了《可移植C语言编译程序》 , 推动了UNIX在各种机器上实现 ,C语言也得 到推广,其发展相辅相成。 ? 1978年影响深远的名著《The C Programming Language》由 Brian W.Kernighan和Dennis M.Ritchie 合著,被称为标准C。 ? 之后,C语言先后移植到大、中、小、微型计 算机上,已独立于UNIX和PDP,风靡世界,成为 最广泛的几种计算机语言之一。&&&&§1-1C语言出现的历史背景 ? 1983年,美国国家标准化协会(ANSI)根据C语 言各种版本对C的发展和扩充,制定了新的标 准ANSI C ,比标准C有了很大的发展。 ? 1988年K & R按照 ANSI C修改了他们的《The C Programming Language》。 ? 1987年,ANSI公布了新标准——87 ANSI C。 ? 1990年,国际标准化组织接受了87 ANSI C为 ISO C 的标准(ISO)。 ? 1994年,ISO又修订了C语言标准。 ? 目前流行的C语言编译系统大多是以ANSI C为 基础进行开发的。&&&&§1-1C语言出现的历史背景 说明:不同版本的C编译系统所实现的语言 功能和语法规则又略有差别,因此读者 应了解所用的C语言编译系统的特点(可 以参阅有关手册)。本书的叙述基本上以 ANSI C 为基础。&&&&§1-2 C语言的特点(1)语言简洁、紧凑,使用方便、灵活。 32 个关键字、9种控制语句,程序形式自由 (2)运算符丰富。34种运算符 (3)数据类型丰富,具有现代语言的各种数据 结构。 (4)具有结构化的控制语句 ,是完全模块化 和结构化的语言。 (5)语法限制不太严格,程序设计自由度大。&&&&§1-2 C语言的特点(6)允许直接访问物理地址,能进行位操 作,能实现汇编语言的大部分功能,可直 接对硬件进行操作。兼有高级和低级语 言的特点 。 (7)目标代码质量高,程序执行效率高。 只比汇编程序生成的目标代码效率低10 %-20%。 (8)程序可移植性好(与汇编语言比)。 基本上不做修改就能用于各种型号的计 算机和各种操作系统。&&&&§1-2 C语言的特点问题:既然有了面向对象的C++语言,为 什么还要学习C语言? 解释1:C++是由于开发大型应用软件的需 要而产生的,并不是所有的人都要去编 写大型软件; 解释2:面向对象的基础是面向过程。C++ 是面向对象的语言,C是面向过程的,学 起来比C语言困难得多,所以不太适合程 序设计的初学者。&&&&说明: 本程序的作用是输出一行信息:§1-3 简单的C语言程序介绍 This is a C program. #include &stdio.h& /*文件包含*/ void main( ) /*主函数 */ { /*函数体开始*/ printf (&This is a C program.\n&); /*输出语句*/ } /*函数体结束*/说明: main-主函数名, void-函数类型? ? ? ?每个C程序必须有一个主函数main { }是函数开始和结束的标志,不可省 每个C语句以分号结束 使用标准库函数时应在程序开头一行写: #include &stdio.h&&&&&说明: 输出一行信息:sum is 579例1.2 求两数之和 #include &stdio.h& void main( ) /*求两数之和*/ { int a,b, /*声明,定义变量为整型*/ /*以下3行为C语句 */ a=123; b=456; sum=a+b; printf(〃sum is %d\n〃,sum); } 说明: /*??*/表示注释。注释只是给人 看的,对编译和运行不起作用。所以可以用 汉字或英文字符表示,可以出现在一行中 的最右侧,也可以单独成为一行。&&&&? 程序运行情况如下: 例1.3 求3个数中较大者。 8,5 ↙(输入8和5赋给a和b) ? #include &stdio.h& ? max=8 (输出c的值) void main( ) /* 主函数*/ { int max(int x,int y); / 对被调用函数max的声明 */ int a, b, /*定义变量a、b、c */ scanf(〃%d,%d〃,&a,&b); /*输入变量a和b的值*/ max(a,b); c=max(a,b); /*调用max函数,将得到的值赋给c */x, inty); int max(int x,int y) printf(〃max=%d\\n〃,c); { /*输出c的值*/ } 说明:本程序包括main和被调用 if (x&y) z=x; 函数max两个函数。max函数的 else z=y; 作用是将x和y中较大者的值赋 return (z); 给变量z。return语句将z的值 } 返回给主调函数main。&&&&§1-3 简单的C语言程序介绍C程序:(1) C程序是由函数构成的。 这使得程序容易实现 模块化。 (2) 一个函数由两部分组成: 函数的首部:例1.3中的max函数首部 int max(int x,int y ) 函数体:花括号内的部分。若一个函数有多个花 括号,则最外层的一对花括号为函数体的范围。 函数体包括两部分 : 声明部分:int a,b,c; 可缺省 执行部分:由若干个语句组成。可缺省&&&&§1-3 简单的C语言程序介绍注意:函数的声明部分和执行部分都可缺省,例如:void dump ( ) { }这是一个空函数,什么也不做,但是合法的函数。&&&&§1-3 简单的C语言程序介绍小结:(3) C程序总是从main函数开始执行的,与main函数 的位臵无关。 (4) C程序书写格式自由,一行内可以写几个语句, 一个语句可以分写在多行上,C程序没有行号。 (5) 每个语句和数据声明的最后必须有一个分号。 (6) C语言本身没有输入输出语句。输入和输出的操 作是由库函数scanf和printf等函数来完成的。C对 输入输出实行?函数化?。&&&&§1-4 运行C程序的步骤和方法 一、运行C程序的步骤 ?上机输入与编辑源程序 ?对源程序进行编译 ?与库函数连接 ?运行目标程序&&&&§1-4 运行C程序的步骤和方法 二、上机运行C程序的方法目前使用的大多数C编译系统都是集成环境(IDE)的。 可以用不同的编译系统对C程序进行操作? ?常用的有Turbo C 2.0、Turbo C++ 3.0、Visual C++等Turbo C++ 3.0:是一个集成环境,它具有方便、直观 和易用的界面,虽然它也是DOS环境下的集成环境, 但是可以把启动Turbo C++ 3.0 集成环境的DOS执行文 件tc.exe生成快捷方式,也可以用鼠标操作。??Visual C++:也可以用Visual C++对C程序进行编译。&&&&例:Turbo C++ 3.0的使用将Turbo C++ 3.0编译程序装入磁盘某一目录下,例如: 放在C盘根目录下一级TC3.0子目录下。 (1) 进入Turbo C++ 3.0集成环境 ①在DOS环境下 C:\TC3.0&tc ↙?&&&&② 在Windows环境下 找到可执行文件tc.exe,执行该文件。主菜单:11个菜单项:? File Edit Search Run Compile Debug Project Options Window Help?&&&&(2) 编辑源文件 新建:单击“File”菜单下 的“New”,修改:选择“File”→“Open”(即单击“File” 的下拉菜单 中的“Open”项,修改已有的源程序。&&&&在编辑(EDIT) 状态下光标表示当前进行编辑的位置,在此位 置可以进行插入、删除或修改,直到自已满意为止。&&&&保存:在编辑(EDIT) 状态下光标表示当前进行编辑的位置, 在此位置可以进行插入、删除或修改,直到自已满意为止。&&&&(3) 对源程序进行编译 选择“Compile”(或“Alt+F9”)对源程序进行编译。c1.cpp源程序,出现1个错误(error) ,0个警告 (warming)。&&&&(4) 将目标程序进行连接选择菜单“Compile” →“Link” ,如果不出现 错误,会得到一个后缀为.exe的可执行文件。 (5) 执行程序。 选菜单“Run” →“Run”( 或按“Ctrl+F9” 键)。 (6) 退出Turbo C++ 3.0环境 选择“File”→“Quit” 。&&&&第二章&&&&?本章要点?算法的概念??算法的表示结构化程序设计方法&&&&?主要内容2.1 算法的概念2.2 简单算法举例2.3 算法的特性2.4 怎样表示一个算法 2.5 化程序设计方法&&&&一个程序应包括两个方面的内容:? 对数据的描述:数据结构(data structure) ? 对操作的描述:算法(algorithm) 著名计算机科学家沃思提出一个公式: ?? 数据结构 + 算法 = 程序?完整的程序设计应该是:数据结构+算法+程序设计方法+语言工具&&&&§2.1 算法的概念广义地说,为解决一个问题而采取的方 法和步骤,就称为?算法?。 对同一个问题,可有不同的解题方法和步骤 例: 求?nn ?1100? 方法1:1+2,+3,+4,一直加到100 加99次 ? 方法2:100+(1+99)+(2+98)+…+(49 +51)+50 = 100 + 49×100 +50 加51次&&&&§2.1 算法的概念为了有效地进行解题,不仅需要保证 算法正确,还要考虑算法的质量,选择合 适的算法。希望方法简单,运算步骤少。 计算机算法可分为两大类别: ? 数值运算算法:求数值解,例如求方程的 根、求函数的定积分等。 ? 非数值运算:包括的面十分广泛,最常见 的是用于事务管理领域,例如图书检索、 人事管理、行车调度管理等。&&&&§2.2 简单算法举例例2.1: 求1×2×3×4×5步骤1:先求1×2,得到结果2? 步骤2:将步骤1得到的乘积2再乘以3,得到结果6 步骤3:将6再乘以4,得24? 步骤4:将24再乘以5,得120如果要求1×2×…×1000,则要写999个步骤&&&&可以设两个变量:一个变量代表被乘数,一 个变量代表乘数。不另设变量存放乘积结 果,而直接将每一步骤的乘积放在被乘数 变量中。设p为被乘数,i为乘数。用循环 算法来求结果, 算法可改写:S1:使p=1? S2:使i=2? S3:使p×i,乘积仍放在变量p中,可表示为:p×ip S4:使i的值加1,即i+1i。? S5:如果i不大于5,返回重新执行步骤S3以及其后 的步骤S4和S5;否则,算法结束。最后得到p的值就 是5!的值。&&&&如果题目改为:求1×3×5×……×1000 算法只需作很少的改动: S1:1p? S2:3i? S3:p×ip? S4:i+2p? S5:若i≤11,返回S3。否则,结束。&&&&用这种方法表示的算法具有通用性、 灵活性。S3到S5组成一个循环,在实现 算法时 要反复多次执行S3,S4,S5等步 骤,直到某一时刻,执行S5步骤时经过 判断,乘数i已超过规定的数值而不返回 S3步骤为止。此时算法结束,变量p的值 就是所求结果。&&&&例2.2 有50个学生,要求将他们之中成绩在80 分以上者打印出来。设n表示学号, n1代表 第一个学生学号, 代表第i个学生学号。用G 代表学生成绩 , gi代表第i个学生成绩,算法 表示如下:S1:1i? S2:如果≥80,则打印和,否则不打印。? S3:i+1i? S4:如果i≤50,返回S2,继续执行。否则算法结束变量i作为下标,用来控制序号(第几个学 生,第几个成绩)。当i超过50时,表示 已对 50个学生的成绩处理完毕,算法结束。&&&&例2.3 判定年中的每一年是否闰年, 将结果输出。 分析:闰年的条件是:(1)能被4整除,但不能被 100整除的年份都是闰年,如年是闰 年;(2)能被100整除,又能被400整除的年份是 闰年。如年是闰年。不符合这两个条 件的年份不是闰年。 变量i作为下标,用来控制序号(第几个学 生,第几个成绩)。当i超过50时,表示 已对 50个学生的成绩处理完毕,算法结束。&&&&设y为被检测的年份,算法可表示如下 :? S1:2000y? S2:若y不能被4整除,则输出y “不是闰年?。然后转 到S6。? S3:若y能被4整除,不能被100整除,则输出y “是闰 年?。然后转到S6。? S4:若y能被100整除,又能被400整除,输出y“是闰年 ?,否则输出?不是闰年?。 然后转到S6。 S5: 输出y “不是闰年?。 S6:y+1y? S7:当y≤2500时,转S2继续执行,如y>2500,算法停止。?&&&&以上算法中每做一 步都分别分离出一 些范围(巳能判定为 闰年或非闰年),逐 步缩小范围,直至 执行S5时,只可能 是非闰年。 ?其它? 包括能被4 整除,又能被100整 除,而不能被400整 除的那些年份(如 1990) 是非闰年。&&&&例2.4 求1 ? 1 ? 1 ? 1 ? ......? 1 ? 1 算法如下 :S1:sign=1??2 3 4 99 100单词作变量名,以使算 S2:sum=1? 法更易于理解: S3:deno=2? sum表示累加和,deno是 S4:sign=(-1)×sign? 英文分母(denom inator) 缩写,sign代表数值的符 S5:term=sign×(1/deno)? 号,term代表某一项。 S6:sum=sum+term? S7:deno=deno+1? S8:若deno≤100返回S4,否则算法结束。?反复执行S4到S8步骤,直到分母大于100为止。 一共执行了99次循环,向sum累加入了99个分数。 sum最后的值就是多项式的值。&&&&例2.5 对一个大于或等于3的正整数,判断 它是不是一个素数。概念:所谓素数,是指除了1和该数本身之外, 不能被其它任何整数整除的数。例如,13是 素数。因为它不能被2,3,4,…,12整除。分析:判断一个数n(n≥3)是否素数的方法: 将n作为被除数,将2到(n-1)各个整数轮流作 为除数,如果都不能被整除,则n为素数。&&&&算法如下 :S1:输入n的值? S2:i=2 ? (i作为除数) S3:n被i除,得余数r? S4:如果r=0,表示n能被i整除,则打印n“不是 素数?,算法结束。否则执行S5? S5:i+1?i? S6:如果i≤n-1,返回S3。否则打印 n “是素数 ?。然后结束。?实际上,n不必被2到(n-1)的整数除,只 需被2到n/2间整数除,甚至只需被2到 n 之间 的整数除即可。&&&&§2.3 算法的特性一个算法应该具有以下特点: ? 有穷性:包含有限的操作步骤 ? 确定性:算法中的每一个步骤都应当是确 定的 ? 有零个或多个输入:输入是指在执行算法 时需要从外界取得必要的信息 ? 有一个或多个输出:算法的目的是为了求 解,?解? 就是输出 ? 有效性:算法中的每一个步骤都应当能有 效地执行,并得到确定的结果 。&&&&§2.4 算法的表示可以用不同的方法表示算法,常用的有: –自然语言 –传统流程图 –结构化流程图 –伪代码 –PAD图&&&&§2.4.1 用自然语言表示算法 自然语言就是人们日常使用的语言,可 以是汉语或英语或其它语言。用自然语言 表示通俗易懂,但文字冗长,容易出现? 歧义性?。自然语言表示的含义往往不大 严格,要根据上下文才能判断其正确含义 ,描述包含分支和循环的算法时也不很方 便。因此,除了那些很简单的问题外,一 般不用自然语言描述算法。&&&&§2.4.2 用流程图表示算法 美国国家标准化协会ANSI(American National Standard Institute)规定了一 些常用的流程图符号:起止框 判断框 处理框 输入/输出框注释框流向线连接点&&&&例2.6 将求5!的算法用流程图表示 如果需要将最后结 果打印出来,可在 菱形框的下面加一 个输出框。&&&&例2.7 将例2.2的算 法用流程图表示。打 印50名 学生中成绩在 80分以上者的学号和 成绩。&&&&如果如果包括 这个输入数据 的部分,流程 图为&&&&例2.8 将例 2.3判定闰 年的算法用 流程图表示用流程图表示算法要比 用文字描述算法逻辑清 晰、易于理解。&&&&例2.9 将例2.4的算法用流程图表示 1 1 1 1 1 1 ? ? ? ? ......? ? 2 3 4 99 100&&&&例2.10 将例2.5判断素数 的算法用流程图表示&&&&小结:? 流程图是表示算法的较好的工具。 一个流程图包括以下几部分 : (1)表示相应操作的框; (2)带箭头的流程线; (3)框内外必要的文字说明。&&&&§2.4.3 三种基本结构和改进的流程图 1、传统流程图的弊端 传统流程图用流程线指出各框的执行 顺序,对流程线的使用没有严格限制。因 此,使用者可以毫不受限制地使流程随意 地转向,使流程图变得毫无规律,阅读者 要花很大精力去追踪流程,使人难以理解 算法的逻辑。如图:&&&&缺点:难以阅读、修改,使算法的 传统流程图的流程可以是: 可靠性和可维护性难以保证。 解决办法:必须限制箭头的滥用, 即不允许无规律地使流程随意转向, 只能顺序地进行下去。这种如同乱麻一样的算法称为BS型算 法,意为一碗面条(A Bowl of Spaghetti),乱无头绪。&&&&2、三种基本结构 Bohra和Jacopini提出了以下三种基本 结构: 顺序结构、选择结构、循环结构 用这三种基本结构作为表示一个良好算 法的基本单元。&&&&三种基本结构的图示:顺序结构选择结构&&&&循环结构的图示:当型(While型)循环结构直到型(Until型)循环&&&&三种基本结构的共同特点:? (1)只有一个入口; (2)只有一个出口;(请注意:一个菱形判断 框有两个出口,而一个选择结构只有一个出 口。不要将菱形框的出口和选择结构的出口 混淆。)? (3)结构内的每一部分都有机会被执行到; (4)结构内不存在?死循环?(无终止的循环) 。&&&&不正确的流程表示:图中没有一条 从入口到出口的 路径通过A框。流程内的死循环&&&&小结: ? 由三种基本结构顺序组成的算法结构 ,可以解决任何复杂的问题。由基本 结构所构成的算法属于?结构化?的 算法,它不存在无规律的转向,只在 本基本结构内才允许存在分支和向前 或向后的跳转。&&&&扩展: ? 只要具有上述四 个特点的都可以 作为基本结构。 可以自己定义基 本结构,并由这 些基本结构组成 结构化程序。此图符合基本结构的特点&&&&这是一个多分 支选择结构,根据 表达式的值决定执 行路线。虚线框内 的结构是一个入口 一个出口,并且有 上述全部的四个特 点。由此构成的算 法结构也是结构化 的算法。可以认为 这是由三种基本结 构所派生出来的。&&&&§2.4.4 用N--S流程图表示算法1973年美国学者I.Nassi和B.Shneiderman 提出了一种新的流程图形式。在这种流程图 中,完全去掉了带箭头的流程线。全部算法 写在一个矩形框内,在该框内还可以包含其 它的从属于它的框,或者说,由一些基本的 框组成一个大的框。这种流程图又称N--S结 构化流程图 。&&&&N--S流程图用以下的流程图符号:(1)顺序结构? (2)选择结构?(3)循环结构?&&&&用三种N--S流程图中的基本框,可以组成复 杂的N--S流程图。图中的A框或B框,可以是一 个简单的操作,也可以是三个基本结构之一。A框可以是一个选择结构B框可以是一个循环结构&&&&例2.11 将例2.1 的求5!算法用 N--S图表示&&&&例2.12 将例2.2 的算法用N--S 图表示。( 打印50名学 生中成绩高 于80分的学 号和成绩)没有输入数据&&&&例2.12 将例2.2 的算法用N--S 图表示。( 打印50名学 生中成绩高 于80分的学 号和成绩)有输入数据&&&&例2.13 将例2.3 判定闰 年的算 法用N-S图表示&&&&例2.14 将例2.4的算 法用N--S图表示1 1 1 1 1 1 ? ? ? ? ......? ? 2 3 4 99 100&&&&例2.15 将例2.5判别 素数的算法用N--S 流程图表示。 传统流程图分析:此图不符合基本结构特点! 由于不能分解为三种基本结 构,就无法直接用N--S流程 图的三种基本结构的符号来 表示。因此,应当先作必要 的变换。 出口1出口2&&&&例2.15 将例2.5判别 素数的算法用N--S 流程图表示。 传统流程图变换为:一个出口&&&&用 流 程 图 表 示 :N--S&&&&N--S图表示算法的优点 ? 比文字描述直观、形象、 易于理解; 比传统流程图紧凑易画。尤其是它废除 了流程线,整个算法结构是由各个基本 结构按顺序组成的,N--S流程图中的上 下顺序就是执行时的顺序。用N--S图表 示的算法都是结构化的算法,因为它不 可能出现流程无规律的跳转,而只能自 上而下地顺序执行。&&&&小结: ? 一个结构化的算法是由一些基本结构顺序 组成的。在基本结构之间不存在向前或向 后的跳转,流程的转移只存在于一个基本 结构范围之内(如循环中流程的跳转);一 个非结构化的算法可以用一个等价的结构 化算法代替,其功能不变 。如果一个算 法不能分解为若干个基本结构,则它必然 不是一个结构化的算法。&&&&§2.4.5 用位代码表示算法? 概念:伪代码是用介于自然语言和计算机 语言之间的文字和符号来描述算法。 ? 特点:它如同一篇文章一样 ,自上而下地 写下来。每一行(或几行)表示一个基本操 作。它不用图形符号,因此书写方便 、格 式紧凑,也比较好懂,也便于向计算机语 言算法(即程序)过渡。 ? 用处:适用于设计过程中需要反复修改时 的流程描述。?&&&&例: ?打印x的绝对值 ?的算法可以用伪代 码表示为:IF x is positive THEN? print x? ELSE? print -x也可以用汉字伪代码表示:若 x为正 打印 x? 否则? 打印 -x?也可以中英文混用,如:?IF x 为正? print x? ELSE? print -x?&&&&例2.16 求5!。用伪代 码表示算法:也可以写成以下形式:BEGIN{算法开始}? 1?t 2 ? i? while i≤5 {t×i ?t ? i+1 ? i?} print t? END{算法结束}开始置t的初值为1置i的初值为2? 当i&=5,执行下面操作: 使t=t×i? 使i=i+1? {循环体到此结束}? 输出t的值? 结束&&&&例2.17 输出50个学生中成绩高于80 分者的学号和成绩。? BEGIN{算法开始}? 用伪代码表示算法: 1 ? i?while i≤50? {input and ? i+1 ? i} 1 ? i? while i≤50? {if ≥80 print and i+1 ? i} END{算法结束}&&&&§2.4.6 用计算机语言表示算法 ? 概念:用计算机实现算法。计算机是无法 识别流程图和伪代码的。只有用计算机语 言编写的程序才能被计算机执行。因此在 用流程图或伪代码描述出一个算法后,还 要将它转换成计算机语言程序。 ? 特点:用计算机语言表示算法必须严格遵 循所用的语言的语法规则,这是和伪代码 不同的。 ? 用处:要完成一件工作,包括设计算法和 实现算法两个部分。设计算法的目的是为 了实现算法。&&&&例 2.20 将例2.16表示 的算法(求5!)用 C语言表示。#include &stdio.h& void main( ) {int i,t; t=1; i=2; while(i&=5) {t=t*I; i=i+1; } printf(“%d\n”,t); }&&&&? 应当强调说明:写出了C程序,仍然 只是描述了算法,并未实现算法。只 有运行程序才是实现算法。应该说, 用计算机语言表示的算法是计算机能 够执行的算法。&&&&§ 2.5结构化程序设计方法? 一个结构化程序 就是用高级语言表示的结构 化算法。用三种基本结构组成的程序必然是 结构化的程序,这种程序便于编写、便于阅 读、便于修改和维护。 ? 结构化程序设计强调程序设计风格和程序结 构的规范化,提倡清晰的结构。 ? 结构化程序设计方法的基本思路是:把一个 复杂问题的求解过程 分阶段进行,每个阶段 处理的问题都控制在人们容易理解和处理的 范围内。&&&&§ 2.5结构化程序设计方法采取以下方法来保证得到结构化的程序:? ? 自顶向下; ? 逐步细化; ? 模块化设计; ? 结构化编码。? 两种不同的方法: ? 自顶向下,逐步细化; ? 自下而上,逐步积累。 ?&&&&用这种方法逐步分解,直到作者认为可以直接将 各小段表达为文字语句为止。这种方法就叫 做?自顶 向下,逐步细化?。?&&&&自顶向下,逐步细化方法的优点: 考虑周全,结构清晰,层次分明,作 者容易写,读者容易看。如果发现某一部 分中有一段内容不妥,需要修改,只需找 出该部分修改有关段落即可,与其它部分 无关。我们提倡用这种方法设计程序。这 就是用工程的方法设计程序。?&&&&模块设计的方法: ?模块化设计的思想实际上是一种?分而治之? 的思想,把一个大任务分为若干个子任务, 每一个子任务就相对简单了。 ?在拿到一个程序模块以后,根据程序模块的 功能将它划分为若干个子模块,如果这些子 模块的规模还嫌大,还再可以划分为更小的 模块。这个过程采用自顶向下方法来实现。 ?子模块一般不超过50行 ?划分子模块时应注意模块的独立性,即:使 一个模块完成一项功能,耦合性愈少愈好。&&&&第三章&&&&?本章要点?数据的描述规则?数据的操作规则&&&&?主要内容 3.1 C的数据类型 3.2 常量与变量3.3 整型数据3.4 浮点型数据运行3.5 字符型数据&&&&?主要内容3.6变量赋初值 3.7 各类数值型数据间的混合运算 3.8 算术运算符和算术表达式 3.9 赋值运算符和赋值表达式 3.10 逗号运算符和逗号表达式&&&&§ 3.1C的数据类型整型 int char 单精度实型 float 双精度实型 doubleC语言提供了以下一些数据类型。 基本类型字符型实型(浮点型)数组类型数据类型 构造类型 指针类型结构类型 联合类型 枚举类型struct union enum空类型(无值类型) void&&&&§3.2 常量与变量3.2.1 常量和符号常量? 在程序运行过程中,其值不能被改变的量称为常量 ? 常量区分为不同的类型:整型 100,125,-100,0 实型 3.14 , 0.125,-3.789 字符型 ‘a?, ?b?,‘2? 字符串 ‘a?, ?ab?,‘1232?&&&&运行结果: total=300 例3.1 符号常量的使用 #define PRICE 30? #include &stdio.h& void main ( )? {? int num,? num=10;? total=num * PRICE;? printf(〃total=%d\n〃,total);? ? 说明:如再用赋值语句给PRICE赋值是错误 说明:用一个标识符代表一个常量的,称为符 }? 说明: 程序中用#define命令行定义PRICE 的。? 号常量,即以标识符形式出现的常量。符号 ? 代表常量30,此后凡在本文件中出现的 PRICE=40;? /* 错误,不能给符 常量的值在其作用域(在本例中为主函数) PRICE都代表30,可以和常量一样进行运算 号常量赋值。 内不能改变,也不能再被赋值。&&&&§3.2 常量与变量3.2.2 变量 ? 变量代表内存中具有特定属性的一个存储单 元,它用来存放数据,这就是变量的值,在 程序运行期间,这些值是可以改变的。 ? 变量名实际上是一个以一个名字对应代表一 个地址,在对程序编译连接时由编译系统给 每一个变量名分配对应的内存地址。从变量 中取值,实际上是通过变量名找到相应的内 存地址,从该存储单元中读取数据。图&&&&§3.2 常量与变量变量命名的规定:C语言规定标识符只能由 字母、数字和下划线三种字符组成,且第一 个字符必须为字母或下划线。 例:sum,_total, month, Student_name,lotus_1_2_3,BASIC, li_ling M.D.John, ¥123,3D64,a&b??&&&&§3.2 常量与变量注意:? 编译系统将大写字母和小写字母认为是两 个不同的字符。 ? 建议变量名的长度最好不要超过8个字符。 ? 在选择变量名和其它标识符时,应注意做 到?见名知意?,即选有含意的英文单词 (或其缩写)作标识符。 ? 要求对所有用到的变量作强制定义,也就 是?先定义,后使用? 。&&&&§3.3整型数据3.3.1整型常量的表示方法 整型常量即整常数。在C语言中,整常数 可用以下三种形式表示:(1)十进制整数。 如:123, -456.4。 (2)八进制整数。以0头的数是八进制数。 如:0123表示八进制数123,等于十进制数 83,-011表示八进制数-11,即十进制数-9。&&&&§3.3整型数据(3)十六进制整数。以0x开头的数是16进制数。 如:0x123,代表16进制数123,等于十进制数 291。 -0x12等于十进制数-10。3.3.2 整型变量 (1)整型数据在内存中的存放形式数据在内存中是以二进制形式存放的。如:i=10;/* 定义为整型变量 */ /* 给i赋以整数10 图 */&&&&§3.3整型数据注意:? 十进制数10的二进制形式为1010,Turbo C 2.0和Turbo C++ 3.0为一个整型变量在 内存中分配2个字节的存储单元(不同的编 译系统为整型数据分配的字节数是不相同 的,VC++ 6.0则分配4个字节)。 ? 数值是以补码(complement) 表示的。&&&&§3.3整型数据有符号基本整型 有符号短整型 有符号长整型 无符号基本整型 无符号短整型 无符号长整型 (signed)int (signed)short (int ) (signed) long (int) unsigned int unsigned short (int) unsigned long (int)(2)整型变量的分类:共六种注意:括号表示其中的内容是可选的.&&&&§3.3类型基本型 短整型整型数据类型说明符int short? 整数类型的有关数据:长度2字节 2字节 2字节 4字节数的范围-3 -215~215-1 0~535 0~(232-1)长整型无符号整型longunsigned4字节 -231~231-1无符号短整型 unsigned short 2字节 无符号长整型 unsigned long&&&&§3.3整型数据(3)整型变量的定义: C规定在程序中所有用到的变量都必须在 程序中定义,即?强制类型定义?。 例如: int a,b(指定变量a、b为整型) unsigned short c,d;(指定变量c、d为无符号短整型)long e,f;(指定变量e、f为长整型)&&&&例3.2 整型变量的定义与使用 运行结果: a+u=22 #include &stdio.h& ,b+u=-14 void main() {int a,b,c,d; /*?指定a、b、c、d为整 型变量?*/ unsigned u; /*?指定u为无符号整型变量 ?*/ a=12;b=-24;u=10; c=a+u;d=b+u; 说明: 可以看到不同种类的整型数据可以 printf(〃a+u=%d,b+u=%d\n〃 ,c,d); 进行算术运算 }&&&&例3.3 整型数据的溢出 #include &stdio.h& void main() {int a,b; a=32767; b=a+1; printf(“%d,%d\n”,a,b); 说明:数值是以补码表示的。一个整型变量 } 只能容纳-3范围内的数,无法表示大于32767或小于-32768的数。遇此情 况就发生“溢出”。运行结果: 3&&&&§3.3整型数据3.3.3 整型常量的类型 (1)一个整数,如果其值在-32768~+32767范 围内,认为它是int型,它可以赋值给int型 和long int型变量。 (2) 一个整数,如果其值超过了上述范围, 而在-~+范围内,则 认为它是为长整型。可以将它赋值给一个 long int型变量。&&&&§3.3整型数据(3) 如果所用的C版本(如Turbo C)分配给 short int与int型数据在内存中占据的长度 相同,则它的表数范围与int型相同。因此 一个int型的常量同时也是一个short int型 常量,可以赋给int型或short int型变量。&&&&§3.3整型数据(4) 一个整常量后面加一个字母u或U,认 为是unsigned int型,如12345u,在内存 中按unsigned int规定的方式存放(存储 单元中最高位不作为符号位,而用来存储 数据)。如果写成-12345u,则先将-12345 转换成其补码53191,然后按无符号数存 储。&&&&§3.3整型数据(5) 在一个整常量后面加一个字母l或L,则 认为是long int型常量。例如123l.432L.0L 等。这往往用于函数调用中。如果函数的形 参为long int型,则要求实参也为long int 型。&&&&§3.4 浮点型数据3.4.1浮点型常量的表示方法 两种表 示形式小数 0.123指数 3e-3注意:字母e(或E)之前必须有数字,且e后面的 指数必须为整数??1e3、1.8e-3、-123e-6、-.1e-3 e3、2.1e3.5、.e3、e&&&&§3.4 浮点型数据规范化的指数形式:在字母e(或E)之前的小数部分中,小数点左边 应有一位(且只能有一位)非零的数字.例如: 123.456可以表示为:123.456e0, 12..., 0., 0.e 其中的1.23456e3称为?规范化的指数形式 ?。&&&&§3.4 浮点型数据3.4.2 浮点型变量 (1)浮点型数据在内存中的存放形式 一个浮点型数据一般在内存中占4个字 节(32位)。与整型数据的存储方式不同, 浮点型数据是按照指数形式存储的。系统 把一个浮点型数据分成小数部分和指数部 分,分别存放。指数部分采用规范化的指 数形式。图&&&&§3.4 浮点型数据(2) 浮点型变量的分类浮点型变量分为单精度(float型)、双精度 (double型)和长双精度型(long double)三类 形式。类型 float double型 long double 位数 32 64 128 数的范围 10-37 ~ ~1~104932 有效数字 6~7 位 15~16位 18~19位&&&&例3.4 浮点型数据的舍入误差 #include &stdio.h& void main() {float a,b; a = e5; b = a + 20 ; printf(“%f\n”,b); 说明:一个浮点型变量只能保证的有效数字是7位 } 有效数字,后面的数字是无意义的,并不准确地表示该数。应当避免将一个很大的数和一个很小 的数直接相加或相减,否则就会“丢失”小的数运行结果: e5&&&&§3.4 浮点型数据3.4.3 浮点型常量的类型 C编译系统将浮点型常量作为双精度来处理。 例如:f = 2.45678 * 4523.65系统先把2.4.65作为双精度数,然后 进行相乘的运算,得到的乘也是一个双精度数。最 后取其前7位赋给浮点型变量f。如是在数的后面加 字母f或F(如1.65f, 654.87F),这样编译系统就 会把它们按单精度(32位)处理。&&&&§3.5字符型数据3.5.1 字符常量(1)用单引号包含的一个字符是字符型常量 (2)只能包含一个字符?a?,?A?, ?1? ?abc?、“a”?&&&&§3.5字符型数据有些以?\”开头的特殊字符称为转义字符\n \t \r \\ \ddd \xhh换行 横向跳格 回车 反斜杠 ddd表示1到3位八进制数字 hh表示1到2位十六进制数字&&&&? 打印机上的显示结果: 显示屏上的运行结果:例3.5 转义字符的使用 fab c gde gde f h jik #include &stdio.h& h j k void main() {printf(〃 ab c\t de\rf\tg\n〃); printf(〃h\ti\b\bj k\n〃); }&&&&§3.5字符型数据3.5.2字符变量? 字符型变量用来存放字符常量,注意只能放 一个字符。 ? 字符变量的定义形式如下:char c1,c2; ? 在本函数中可以用下面语句对c1,c2赋值: c1=‘a?;c2= ‘b? ; ? 一个字符变量在内存中占一个字节。&&&&§3.5字符型数据3.5.3字符数据在内存中的存储形式及其使用方法 ? 将一个字符常量放到一个字符变量中,实际上并 不是把该字符本身放到内存单元中去,而是将该 字符的相应的ASCII代码放到存储单元中。 这样使字符型数据和整型数据 之间可以通用。一个字符数据 既可以以字符形式输出,也可 以以整数形式输出。 图&&&&例3.6 向字符变量赋以整数。 a b #include &stdio.h& 97 98 void main() {char c1,c2; c1=97; c2=98; printf(“%c %c\n”,c1,c2); ? 说明:在第3和第4行中,将整数97和98分 printf(“%d %d\n”,c1,c2); 别赋给c1和c2,它的作用相当于以下两个赋值语 } 句:c1=′a′;c2=′b′; 因为’a’和’b’的ASCII码为97和98? 运行结果:&&&&例3.7 大小写字母的转换 #include &stdio.h& void main() {char c1,c2; c1=’a’; c2=’b’; c1=c1-32; ? 说明:程序的作用是将两个小写字母a和b转换成 c2=c2-32; 大写字母A和B。从ASCII代码表中可以看到 printf(“%c %c〃,c1,c2); 每一个小写字母比它相应的大写字母的ASCI I码大32。C语言允许字符数据与整数直接进 }行算术运算。? 运行结果:A B&&&&§3.5字符型数据说明:有些系统(如Turbo C)将字符变量定义为signed char型。其存储单元中的最高位作为符号位,它的取 值范围是-128~127。如果在字符变量中存放一个 ASCII码为0~127间的字符,由于字节中最高位为0, 因此用%d输出字符变量时,输出的是一个正整数。如 果在字符变量中存放一个ASCII码为128~255间的字 符,由于在字节中最高位为1,用%d格式符输出时, 就会得到一个负整数。&&&&§3.5字符型数据3.5.4字符串常量? 字符串常量是一对双撇号括起来的字符序列. ? 合法的字符串常量: ?How do you do.”, “CHINA”, ?a” , ?$123.45” ? 可以输出一个字符串,如 printf(“How do you do.”);&&&&§3.5字符型数据?a’是字符常量,?a?是字符串常量,二 者不 同。如:假设C被指定为字符变量 :char c ? c=’a’;结论:不能把一个字符串常量赋给一个字符 变量。?c=”a”;c=”CHINA”;&&&&§3.5字符型数据? C规定:在每一个字符串常量的结尾加一个 ?字 符 串结束标志?,以便系统据此判断字符串是否结束。 C规定以字符’\0’作为字符串结束标志。 ,实 如:如果有一个字符串常量”CHINA” 际上在内存中是:C H I N A \0它占内存单元不是5个字符,而是6个字符, 最后一个字符为’\0’。但在输出时不输出’ \0’。&&&&§3.6变量赋初值字符串常量 (1)C语言允许在定义变量的同时使变量初始化 如: int a=3; // 指定a为整型变量,初值为3float f=3.56; // 指定f为浮点型变量,初值 为3.56 char c= ‘a’; // 指定c为字符变量,初值 为‘a’&&&&§3.6变量赋初值(2)可以使被定义的变量的一部分赋初值。如: int a,b,c=5; 表示指定a、b、c为整型变量,但只对c初始化,c的初值为5 (3)如果对几个变量赋以同一个初值, 应写成:int a=3,b=3,c=3; 表示a、b、c 的初值都是3。 不能写成∶ int a=b=c3; 注意:初始化不是在编译阶段完成的而是在程序运 行时执行本函数时赋初值的,相当于有一个赋值语 句。&&&&§3.7各类数值型数据间的混合运算整型(包括int,short,long)、浮点型(包括 float,double)可以混合运算。在进行运算时 ,不同类型的数据要先转换成同一类型,然后 进行运算. 上述的类型转换是由 系统自动进行的图&&&&§3.8算术运算符和算术表达式3.8.1 C运算符简介C的运算符有以下几类: (1)算术运算符 (+ - * / %) (2)关系运算符 (><==>=<=!=) (3)逻辑运算符 (!&&||) (4)位运算符 (&& && ~ |∧&) (5)赋值运算符 (=及其扩展赋值运算符) (6)条件运算符 (?:) (7)逗号运算符 (,)&&&&§3.8算术运算符和算术表达式(8)指针运算符 (*和&) (9)求字节数运算符(sizeof) (10)强制类型转换运算符( (类型) ) (11)分量运算符(.-&) (12)下标运算符(〔 〕) (13)其他 (如函数调用运算符())&&&&§3.8? ? ? ? ? + - * / %算术运算符和算术表达式(加法运算符,或正值运算符。如:3+5、+3) (减法运算符,或负值运算符。如:5-2、-3)(乘法运算符。如:3*5)3.8.2 算术运算符和算术表达式 (1)基本的算术运算符:(除法运算符。如:5/3) (模运算符,或称求余运算符,%两侧均应为整型数据,如:7%4的值为3)。&&&&§3.8算术运算符和算术表达式(2) 算术表达式和运算符的优先级与结合性基 本的算术运算符:用算术运算符和括号将运算对象(也称操作数) 连接起来的、符合C语法规则的式子,称为C算 术表达式。运算对象包括常量、变量、函数等。例如: a*b/c-1.5+′a′是一个合法的表达式&&&&§3.2 常量与变量? C语言规定了运算符的优先级和结合性。在表达式求值时,先按运算符的优先级别高低次序执行,例如先乘除后加减。? C规定了各种运算符的结合方向(结合性)算术运算符的结合方向为“自左至右”,即先 左后右 。&&&&§3.8算术运算符和算术表达式(3)强制类型转换运算符可以利用强制类型转换运算符将一个表达式转换成 所需类型。 一般形式:(类型名)(表达式) 例如: ? (double)a 将a转换成double类型 ? (int)(x+y) 将x+y的值转换成整型 ? (float)(5%3) 将5%3的值转换成float型&&&&例3.8 强制类型转换。 ? 运行结果: x=3.600000, i=3 #include &stdio.h& voidmain() {float x; int i; x=3.6; i=(int)x; ? 说明:有两种类型转换,一种是在运算时不必用 printf(&x=%f, i=%d\n&,x,i); } 户指定,系统自动进行的类型转换,如3+6.5。第二种是强制类型转换。当自动类型转换不能实 现目的时,可以用强制类型转换。&&&&§3.8算术运算符和算术表达式(4) 自增、自减运算符作用是使变量的值增1或减1如:? ? ++i,--i(在使用i之前,先使i的值加 (减)1) i++,i--(在使用i之后,使i的值加( 减)1)&&&&§3.8算术运算符和算术表达式i++与++i的区别:++i是先执行i=i+1后,再使用i的值; i++是先使用i的值后,再执行i=i+1。例如:①j=++i; i的值先变成4, 再赋给j,j的值均为4 ②j=i++; 先将 i的值3赋给j,j的值为3,然后i变为4&&&&§3.8注意:算术运算符和算术表达式(1)自增运算符(++),自减运算符(--), 只能用于变量,而不能用于常量或表达式, (2)++和--的结合方向是?自右至左?。 自增(减)运算符常用于循环语句中使循环变量 自动加1。也用于指针变量,使指针指向下一个地址&&&&§3.8算术运算符和算术表达式(5) 有关表达式使用中的问题说明 ①ANSI C并没有具体规定表达式中的子表达式的求 值顺序,允许各编译系统自己安排。 a = f1( )+f2( ) 并不是所有的编译系统都先调用f1( ), 然后 调用f2( )。在有的情况下结果可能不同。有时会出 现一些令人容易搞混的问题,因此务必要小心谨慎。例如:对表达式&&&&§3.8算术运算符和算术表达式②C语言中有的运算符为一个字符,有的运算符由 两个字符组成 ,为避免误解,最好采取大家都能理 解的写法。例如:不要写成i+++j的形式,而应写成(i++)+j的形式&&&&§3.8算术运算符和算术表达式③在调用函数时,实参数的求值顺序,C标准并无统 一规定。 例如:i的初值为3,如果有下面的函数调用: printf(〃%d,%d〃,i,i++) 在有的系统 中,从左至右求值,输出“3,3”。在多数系 统中对函数参数的求值顺序是自右而左,pri ntf函数输出的是“4,3”。以上这种写法 不宜提倡, 最好改写成 不要写出别人看不懂的也 j = i++; 不知道系统会怎样执行程 printf(&%d, %d&, 序 j,i)&&&&§3.9 赋值运算符和赋值表达式(1)赋值运算符赋值符号“=”就是赋值运算符,它的作用是 将一个数据赋给一个变量。如“a=3”的作用 是执行一次赋值操作(或称赋值运算)。把常 量3赋给变量a。也可以将一个表达式的值赋 给一个变量.&&&&§3.9 赋值运算符和赋值表达式(2)类型转换 如果赋值运算符两侧的类型不一致,但都 是数值型或字符型时,在赋值时要进行类型 转换。①将浮点型数据(包括单、双精度)赋给整 型变量时,舍弃浮点数的小数部分。如:i为整型变量,执行?i=3.56”的结果是使i的值为3,以整数形式存储在整型变量中.&&&&§3.9 赋值运算符和赋值表达式②将整型数据赋给单、双精度变量时,数值不变, 但以浮点数形式存储到变量中如: 将23赋给float变量f,即执行f=23,先将23转换成23.00000,再存储在f中。 将23赋给double型变量d,即执行d= 23,则将23补足有效位数字为23.00000 000000000,然后以双精度浮点数形式存储 到变量d中。&&&&§3.9 赋值运算符和赋值表达式③将一个double型数据赋给float变量时,截取其前 面7位有效数字,存放到float变量的存储单元(4个 字节)中。但应注意数值范围不能溢出。 如:double d=123.; f=d; 就出现溢出的错误。 如果将一个float型数据赋给double变量时,数值不 变,有效位数扩展到16位,在内存中以8个字节存储&&&&§3.9 赋值运算符和赋值表达式④字符型数据赋给整型变量时,由于字符只占1个字 节,而整型变量为2个字节,因此将字符数据(8个 二进位)放到整型变量存储单元的低8位中。 第一种情况: 如果所用系统将字符处理为无符号的字符类型,或程 序已将字符变量定义为unsigned char 型,则将字符的8位放到整型变量低8位,高8位补 零 图 例如:将字符‘\376’赋给int型变量i&&&&§3.9 赋值运算符和赋值表达式第二种情况:如果所用系统(如Turbo C++)将字符处理为带符号的(即signed char),若字符最高位为0,则整型 变量高8位补0;若字符最高位为1,则高8位全补 1。这称为?符号扩展?,这样做的目的是使数值保 持 不变,如变量c(字符‘\376’)以整数形式输 出 图 为-2,i的值也是-2。&&&&§3.9 赋值运算符和赋值表达式⑤将一个int、short、long型数据赋给一个char型变 量时,只将其低8位原封不动地送到char型变量(即 截断)。例如:int i=289;char c=′a′;c=i; 赋值情况 :c的值为33, 如果用“%c”输 出c,将得到字符“!” (其 ASCII码为33)。图&&&&§3.9 赋值运算符和赋值表达式⑥ 将带符号的整型数据(int型)赋给long型变 量时,要进行符号扩展,将整型数的16位送到 long型低16位中: 如果int型数据为正值(符号位为0),则long 型变量的高16位补0; 如果int型变量为负值(符号位为1),则long 型变量的高16位补1,以保持数值不改变。 反之,若将一个long型数据赋给一个int型变量 ,只将long型数据中低16位原封不动地送到整型 变量(即截断)。? ?&&&&§3.9 赋值运算符和赋值表达式例如:int a; long b=8;a=b 赋值情况如图 :如果b=65536(八进制 数0200000),则 赋值后a值为0。见图 3.14图 图3.14&&&&§3.9 赋值运算符和赋值表达式⑦将unsigned int型数据赋给long int型变量时,不 存在符号扩展问题,只需将高位补0即可。将一个 unsigned类型数据赋给一个占字节数相同的非 unsigned型整型变量(例如:unsigned int -&int,unsigned long-&long,unsigned short -&short),将unsigned型变量的内容原样送到非 unsigned型变量中,但如果数据范围超过相应整型的 范围,则会出现数据错误。&&&&§3.9 赋值运算符和赋值表达式例如:unsigned int a=65535;b=a;将a整个送到b中,由于b是int, 第1位是符号位,因此b成了 负数。根据补码知识可知,b的 值为-1,可以用printf(〃%d〃, b);来验证。 ⑧将非unsigned型数据赋给长度 相同的unsigned型变量,也 是原样照赋(连原有的符号 位也作为数值一起传送)。图&&&&例3.9 有符号数据传送给无符号变量。 65535 #include &stdio.h& void main() {unsigned a; int b=-1; a=b; printf(〃%u\n〃,a) ; ? 说明:“%u”是输出无符号数 } 时所用的格式符。如果b为正值,且在0~32767之间,则赋值后数值不变。赋值情况见图 图?运行结果:&&&&§3.9 赋值运算符和赋值表达式(3) 复合的赋值运算符在赋值符“=”之前加上其他运算符,可以构成复 以“a+=3”为例来说明, 它相当于使a进行一次自加 合的运算符。(3)的操作。即先使a加 3,再赋给a。例如:? ? ?a+=3 等价于 a=a+3 x*=y+8 等价于 x=x*(y+ 8) x%=3 等价于 x=x%3&&&&§3.9 赋值运算符和赋值表达式为便于记忆,可以这样理解: ① a += b (其中a为变量,b为表达式) ② a += b(将有下划线的?a+”移到?=”右侧 ) |___↑ ③ a = a + b (在?=”左侧补上变量名a)&&&&§3.9 赋值运算符和赋值表达式注意:如果b是包含若干项的表达式,则相当于它有括号。凡是二元(二目)运 算符,都可以与赋值 符一起组合成复合赋 值符。如: ① x %= y+3 ② x %= (y+3) |__↑ ③ x = x %(y+3)(不要错写成x=x%y+3)C语言规定可以使用10种复合赋值运算符: +=,-=,*=,/=,%=,&&=,&&=,&= ,∧=,|=&&&&§3.9 赋值运算符和赋值表达式(4) 赋值表达式 由赋值运算符将一个变量和一个表达式连接 起来的式子称为“赋值表达式”。 一般形式为: &变量&&赋值运算符&&表达式&例如:“a=5”是一个赋值表达式&&&&§3.9 赋值运算符和赋值表达式对赋值表达式求解的过程是: ①求赋值运算符右侧的?表达式?的值; ②赋给赋值运算符左侧的变量。 例如: 赋值表达式?a=3*5”的值为15,执行表 达式后,变量a的值也是15。 注意: 一个表达式应该有一个值&&&&§3.9 赋值运算符和赋值表达式左值 ? ? ? (lvalue) : 赋值运算符左侧的标识符 变量可以作为左值; 而表达式就不能作为左值(如a+b); 常变量也不能作为左值,右值 (lvalue) :出现在赋值运算符右侧的表达式 左值也可以出现在赋值运算符右侧,因而左值 都可以作为右值。&&&&§3.9 赋值运算符和赋值表达式赋值表达式中的“表达式”,又可以是一个赋值表达式.例如: a=(b=5)分析:括弧内的?b=5”是一个赋值表达式,它的值等于5。执行表达式?a=(b=5)”相当于执 行 ?b=5”和?a=b”两个赋值表达式。 赋值运算 符 按照?自右而左?的结合顺序,因此,?(b= 5)” 外面的括弧可以不要,即?a=(b=5)”和 ?a=b=5”&&&&§3.9 赋值运算符和赋值表达式请分析下面的赋值表达式∶(a=3*5)=4*3分析:先执行括弧内的运算,将15赋给a,然后执行4*3的运算,得12,再把12赋给a。最后a的值为12, 整个表达式的值为12。可以看到∶(a=3*5)出现在赋 不能写成: 值运算符的左侧,因此赋值表达式(a=3*5)是左值 a=3*5=4*3注意:在对赋值表达式(a=3*5)求解后,变量a得到值15执行(a=3*5)=4*3时,实际上是将4*3的积12赋给变 量a,而不是赋给3*5。&&&&§3.9 赋值运算符和赋值表达式赋值表达式也可以包含复合的赋值运算符。 如:a+=a-=a*a 分析:此赋值表达式的求解步骤如下∶① 先进行?a-=a*a?的运算, 它相当 于a=a-a*a,a的值为12-144 =-132。 ②再进行?a+=-132?的运算,相当 于a=a+(-132),a的值为-132-132=264。&&&&§3.9 赋值运算符和赋值表达式将赋值表达式作为表达式的一种,使赋值操作不 仅可以出现在赋值语句中,而且可以以表达式形 式出现在其他语句(如输出语句、循环语句等) 中.如:printf(&%d&,a=b);分析:如果b的值为3, 则输出a的值(也是表达式a=b的值)为3。在一个语句中完成 了赋值和输出双重功能。&&&&§3.10 逗号运算符和逗号表达式逗号表达式 的 逗号运算符:将两个表达式连接起来,又称为?顺序求 值为14 值运算符?如:3+5,6+8一般形式:表达式1,表达式2求解过程: 先求解表达式1,再求解表达式2。整个逗号 表达式的值是表达式2的值。&&&&§3.10 逗号运算符和逗号表达式 a的值为15, 例:逗号表达式a=3*5,a*4然后求解a*4,得60。整个 分析:赋值运算符的优先级别高于逗号运算符, 因 逗号表达式的 此应先求解a=3*5. 值为60。一个逗号表达式又可以与另一个表达式组成一 个新的逗号表达式 如:(a=3*5,a*4) a+5先计算出a的值等于15,再进行a*4的 运算得60(但a值未变,仍为15),再进行a +5得20,即整个表达式的值为20。&&&&§3.10 逗号运算符和逗号表达式逗号表达式的一般形式可以扩展为赋值表达式, 它的值为表达式n的值。 将一个逗号表 逗号运算符是所有运算符中级别最低的 达式的值赋给 x,x的值等 例: ① x=(a=3,6*3) 于18表达式1,表达式2,表达式3,……,表达式n② x=a=3,6*3逗号表达式,包括 一个赋值表达式和 一个算术表达式, x的值为3,整个 逗号表达式的值为 18。&&&&§3.10 逗号运算符和逗号表达式 “a,b,c”并不是一个逗 注意:并不是任何地方出现的逗号都是作为逗 号表达式,它 是printf函数的3 号运算符。例如函数参数也是用逗号来间 个参数 隔的。如:printf(“%d,%d,%d”,a,b,c); printf(“%d,%d,%d”,(a,b,c),b,c) “(a,b,c)”是一个 逗号表达式, 它的值等于c 的值。&&&&第四章&&&&?主要内容4.1 C语句概述4.2 赋值语句4.3 数据输入输出的概念及在c语言中的实现4.4 字符数据的输入输出4.5 格式输入与输出 4.6 顺序结构程序设计举例&&&&§ 4.1C语句概述C程序源程序文件1源程序文件2源程序文件n预处理命令数据声明函数1函数n函数首部函数体数据声明执行语句&&&&§ 4.1C语句概述(续)? 一个c程序可以有若干个源程序文件组成 ? 一个源文件可以有若干个函数和预处理命令 以及全局变量声明部分组成 ? 一个函数有函数首部和函数体组成 ? 函数体由数据声明和执行语句组成 控制语句 ? C语句分为 5类 函数调用语句表达式语句 空语句 复合语句&&&&§ 4.1C语句概述(续)完成一定的控制功能6 break 间断语句 7 switch() 开关语句 8 goto 转向语句 9 return 返回语句(一)控制语句1 if() ~else 条件语句 2 for()~ 循环语句 3 while()~循环语句 4 do ~while();循环语句 5 continue 继续语句&&&&§ 4.1C语句概述(续)(二)函数调用语句 有一个函数调用加一个分号构成一个语句Printf(“This is a C statement.”);&&&&§ 4.1C语句概述(续)(三)表达式语句 有一个表达式加一个分号构成一个语句赋值表达式分号表达式语句a = 3 ;&&&&§ 4.1C语句概述(续)只有一个分号的语句(四)空语句(什么也不做)? 用来做流程的转向点 ? 用来作为循环语句中的循环体&&&&§ 4.1C语句概述(续)用一对{}括起来的语句(五)复合语句{z=x+y; t=z/100; printf(“%f”,t);}&&&&§ 4.2赋值语句?赋值语句是由赋值表达式加上一个分号构成 例:a=100 赋值表达式 a=100; 赋值语句?条件中不能含有赋值符号,但是赋值表达式可以 包含于条件表达式中 例:if(a=b) t=a; 错误 if((a=b)&0) t=a; 正确&&&&§ 4.2赋值语句(续)问题:c语言中的赋值语句于其他高级语言 的赋值语句有什么不同点? 1:C语言中的赋值号“=”是一个运算符, 在其他大多数语言中赋值号不是运算符. 2:其他大多数高级语言没有“赋值表达式 ”这一概念.&&&&§ 4.3数据输入输出的概念及在C语言中的实现(一).所谓输入输出是以计算机主机为主体而言的输出:从计算机向外部输出设备(显示器,打印机) 输出数据 输入:从输入设备(键盘,鼠标,扫描仪)向计算机 输入数据.&&&&§ 4.3数据输入输出的概念及在C语言中的实现(二).C语言本身不提供输入输出语句,输入和输出 操作是由C函数库中的函数来实现的 例如: 字符输入函数: getchar 字符输出函数:putchar 格式输入函数: scanf 格式输出函数: printf 字符串输入函数:gets 字数穿输出函数:puts&&&&§ 4.3数据输入输出的概念及在C语言中的实现(三).在使用系统库函数时,要用预编译命令 ?#include”将有关的?头文件?包括到用户源 文件中. 例如:在调用标准输入输出库函数时,文件开头应 头文 该有: 件 #include “stdio.h” 或: #include &stdio.h&&&&&§ 4.4字符数据的输入输出(一).字符输出函数 ? 一般形式:putchar(c)字符型变量 整型变量? 函数作用:向终端输出一个字符&&&&§ 4.4字符数据的输入输出(续)例4.1 输出单个字符。 #include&stdio.h& 运行结果:B void main() O { Y char a,b,c; a=‘B’;b=‘O’;c=‘Y’; putchar(a);putchar(b);putchar(c);putchar(‘\n’); putchar(a);putchar(?\n?);putchar(b);putchar(?\n?);putchar(c);putchar(?\n?); }运行结果:BOY&&&&§ 4.4字符数据的输入输出(续)(二).字符输入函数? 一般形式:getchar() ? 函数作用:从终端(或系统隐含指定的输入设备 )输入一个字符。 ? 函数值: 从输入设备得到的字符。&&&&§ 4.4字符数据的输入输出(续)运行程序:从键盘输入字符‘a’ 按Enter键 屏幕上将显示输出的字符‘a’a a例4.2 输入单个字符。 #include&stdio.h& void main() { c=getchar(); putchar(c); putchar(‘\n’); }&&&&§ 4.5格式输入与输出(一).格式输出函数 ? 函数作用:向终端(或系统隐含指定的输出设备 )输出若干个任意类型的数据。 ? 一般格式:printf(格式控制,输出表列)%d:以带符号的十进制形式输出整数 %o:以八进制无符号形式输出整数 %x:以十六进制无符号形式输出整数 To be continued……&&&&§ 4.5格式输入与输出(续)%u:以无符号十进制形式输出整数 %c:以字符形式输出,只输出一个字符 %s:输出字符串 %f:以小数形式输出单,双精度数,隐含输出六位小数 %e:以指数形式输出实数 %g:选用%f或%e格式中输出宽度较短的一种格式,不输 出无意义的0&&&&§ 4.5格式输入与输出(续)几种常见的格式符的修饰符:L:用于长整型整数,可加在格式符d,o,x,u前面 M(代表一个正整数):数据最小宽度 N(代表一个正整数):对实数,表示输出n位小数; 对字符串,表示截取的字符个数 —:输出的数字或字符在域内向左靠&&&&§ 4.5格式输入与输出(续)(1) d格式符。用来输出十进制整数。几种用法: ① %d:按十进制整型数据的实际长度输出。 ② %md:m为指定的输出字段的宽度。如果数据的位数小于m, 则左端补以空格,若大于m,则按实际位数输出。 例: printf(〃%4d,%4d〃,a,b); 若a=123,d=12345,则输出结果为 123,12345 ③ %ld:输出长整型数据。 例: long a=135790;/* 定义a为长整型变量*/ printf(〃%ld〃,a);&&&&§ 4.5格式输入与输出(续)(2) o格式符。以八进制整数形式输出。输出的数值不带符号,符号位也一起作为八进制数的一部分输出。 例:int a=-1; printf(&%d,%o&,a,a); -1在内存单元中的存放形式(以补码形式存放)如下: 1111 输出为: -1,177777 不会输出带负号的八进制整数。对长整数(long型)可以 用?%lo?格式输出。还可以指定字段宽度, 例:printf(&%8o&,a); 输出为: 177777。 (数字前有2个空格)&&&&§ 4.5格式输入与输出(续)(3)x格式符。以十六进制数形式输出整数。同样不会出 现负的十六进制数。 例: int a=-1;printf(〃%x,%o,%d〃,a,a,a); 输出结果为: ffff,177777,-1 可以用?%lx?输出长整型数,也可以指定输出字段的宽度 例: “%12x?&&&&§ 4.5格式输入与输出(续)(4)u格式符,用来输出unsigned型数据.一个有符号整数(int型)也可以用%u格式输出; 一个unsigned型数据也可以用%d格式输出。 unsigned型数据也可用%o或%x格式输出。(5)c格式符,用来输出一个字符。如:char d=′a′; printf(〃%c〃,d); 输出字符′a′. 一个整数,只要它的值在0~255范围内,可以用 ?%c?使之按字符形式输出,在输出前,系统会将该整数 作为ASCII码转换成相应的字符;一个字符数据也可以用 整数形式输出。&&&&§ 4.5格式输入与输出(续)例4.3 无符号数据的输出。 #include&stdio.h& void main() { unsigned int a=65535;int b=-2; printf(“a=%d,%o,%x,%u\n”,a,a,a,a); printf(“b=%d,%o,%x,%u\n”,b,b,b,b); } 运行结果: a=-1,177777,ffff,65535 b=-2,177776,fffe,65534&&&&§ 4.5格式输入与输出(续)例4.4 字符数据的输出。 运行结果: #include&stdio.h& a,97 指定输出字数的宽度, void main() a,97 printf(“%3c”,c); { 则输出: char c=‘a’; a int i=97; printf(“%c,%d\n”,c,c); printf(“%c,%d\n”,i,i); }&&&&§ 4.5(6)s格式符格式输入与输出(续)输出字符串.① %s。例如: printf(〃%s〃,〃CHINA〃) 输出字符串?CHINA?(不包括双引号)。 ② %ms,输出的字符串占m列,若串长大于m,则全部输出,若串长 小于m,则左补空格。 ③ %-ms,若串长小于m,字符串向左靠,右补空格。 ④ %m. ns,输出占m列,只取字符串中左端n个字符,输出在m列的 右侧,左补空格。 ⑤ %-m.ns,n个字符输出在m列的左侧,右补空格,若n〉m,m自 动取n值。&&&&§ 4.5格式输入与输出(续)例4.5字符串的输出。 #include&stdio.h& void main() { printf(“%3s,%7.2s,%.4s,%-5.3s\n”, “CHINA”, “CHINA”, “CHINA”, “CHINA”); }运行结果: CHINA, CH ,CHIN,CHI&&&&§ 4.5格式输入与输出(续)(7)f格式符。用来以小数形式输出实数(包括单双精度)有以下几种用法: ① %f。不指定字段宽度,由系统自动指定字段宽度,使整数 部分全部输出,并输出6位小数。应当注意,在输出的数字中 并非全部数字都是有效数字。单精度实数的有效位数一般为7位。 ②%m.nf。指定输出的数据共占m列,其中有n位小数。如果 数值长度小于m,则左端补空格。 ③%-m.nf与%m.nf基本相同,只是使输出的数值向左端 靠,右端补空格。&&&&§ 4.5格式输入与输出(续)例4.6 输出实数时的有效位数。#include &stdio.h& void main() { float x,y; x=111111.111;y=222222.222; printf(〃%f〃,x+y); }运行结果:333333.328125&&&&§ 4.5格式输入与输出(续)例4.7输出双精度数时的有效位数。#include &stdio.h& void main() {double x,y; x=1.; y=2.; printf(“%f”,x+y); }运行结果:3.333010&&&&§ 4.5格式输入与输出(续)例4.8 输出实数时指定小数位数。#include &stdio.h& void main() { float f=123.456; printf(“%f%10f%10.2f%.2f%-10.2f\n”,f,f,f,f,f); }运行结果:123...46 123.46 123.46&&&&§ 4.5格式输入与输出(续)(8)e格式符,以指数形式输出实数。可用以下形式: ① %e。不指定输出数据所占的宽度和数字部分的小数位数. 例: printf(〃%e〃,123.456); 输出: 1.234560 e+002 6列 5列 所输出的实数共占13列宽度。(注:不同系统的规定略有不同)&&&&§ 4.5格式输入与输出(续)② %m.ne和%-m.ne。 m、n和?-?字符的含义与前相同。 此处n指拟输出的数据的小数部分(又称尾数)的小数位数。 若f=123.456,则: printf(&%e %10e %10.2e %.2e %-10.2e&,f,f,f,f,f); 输出如下: 说明: 1.2 1.2 1.23e+002 1.23e+002 未指定n,自动使n=6. 13列 13列 10列 9列 超过给定的10列,乃突破10列的限制,按实际长度输出。 1.23e+002 第3个数据共占10列,小数部分占2列。 10列 只指定n=2,未指定m,自动使m等于数据应占的长度。 第5个数据应占10列,数值只有9列,由于是?%-10.2e? 数值向左靠,右补一个空格。 (注:有的C系统的输出格式与此略有不同)&&&&§ 4.5格式输入与输出(续)(9)g格式符,用来输出实数.它根据数值的大小,自动选f格式或e格式(选择输出时占宽度 较小的一种),且不输出无意义的零。 例:若f=123.468,则 printf(〃%f %e %g〃,f,f,f); 输出如下: 说明: 123..2 123.468 用%f格式输出占10列,用%e格式输出占13列,用%g 10列 13列 10列 格式时,自动从上面两种格式中选择短者(今以%f格式为短) 故占10列,并按%f格式用小数形式输出,最后3个小数位为 无意义的0,不输出,因此输出123.468,然后右补3个空格。 %g格式用得较少。&&&&§ 4.5说明:格式输入与输出(续)? 除了X,E,G外,其他各式字符必须用小写。 ? 可以在printf函数中的“格式控制”字符串中包含 转义字符。 ? 一个格式说明必须以“%”开头,以9个格式字符之 一为结束,中间可以插入附加格式字符。 ? 想输出%,则应该在格式控制字符串中用连续两 个%表示&&&&§ 4.5格式输入与输出(续)(一).格式输入函数 ? 函数作用:按照变量在内存的地址将变量值存 进去。 ? 一般格式:scanf(格式控制,地址表列)同printf函数 是由若干个地址组成的表列,可以是变量的 地址,或字符串的首地址&&&&§ 4.5格式输入与输出(续)例4.9 用scanf函数输入数据。 #include&stdio.h& a在内存中的地 void main() 址 { &是地址运算符 int a,b,c; scanf(“%d%d%d”,&a,&b,&c); printf(“%d,%d,%d\n”,a,b,c); } 运行情况: 3 4 5 (输入a,b,c的值) 3,4,5 (输出a,b,c的值)&&&&§ 4.5格式输入与输出(续)说明:? 对unsigned型变量所需要的数据,可以用%u,%d 或%o,%x格式输入。 ? 可以指定输入数据所占的列数,系统自动按它截 取所需数据。 ? 如果在%后有一个“*”附加说明符,表示跳过它 指定的列数。 ? 输入数据时不能规定精度。&&&&§ 4.5格式输入与输出(续)使用scanf函数时应注意的问题 :(1)scanf函数中的?格式控制?后面应当是变量地址,而不应 是变量名。 (2) 如果在?格式控制?字符串中除了格式说明以外还有其他字符, 则在输入数据时在对应位臵应输入与这些字符相同的字符。 (3) 在用?%c?格式输入字符时,空格字符和?转义字符?都作为 有效字符输入 (4) 在输入数据时,遇以下情况时认为该数据结束。 ① 遇空格,或按?回车?或?跳格?(Tab)键; ② 按指定的宽度结束,如?%3d?,只取3列; ③ 遇非法输入。&&&&§ 4.6 顺序结构程序设计举例例4.10 输入三角形的三边 长,求三角形面积。 假设:三个边长a,b,c能构 成三角形。 已知面积公式: area= s(s ? a)(s? b)(s ? c) s=(a+b+c)*0.5开始输入三边长 计算s 计算面积 结束&&&&§ 4.6 顺序结构程序设计举例(续)#include&stdio.h& 数学函数库 #include&math.h& 因为要用到 void main() 其中的sqrt {float a,b,c,s, 函数 scanf(“%f,%f,%f,&a,&b,&c); s=1.0/2*(a+b+c); area=sqrt(s*(s-a)*(s-b)*(s-c)); printf(“a=%7.2f, b=%7.2f, c=%7.2f, 运行情况: s=%7.2f\n”,a,b,c,s); 3,4,6 printf(“area=%7.2f\n”,area);} s= 6.50 a= 3.00, b= 4.00, c= 6.00,area= 5.33&&&&§ 4.6 顺序结构程序设计举例(续)例4.11 从键盘输入一个大写字母,要求改用小写字母输 出。 运行情况:#include &stdio.h& A↙? void main() A,65 { char cl,c2; cl=getchar(); a,97 printf(〃%c,%d\n〃,cl,cl); c2=cl+32; printf(〃%c,%d\n〃,c2,c2); }&&&&§ 4.6 顺序结构程序设计举例(续)例4.12 求ax2+bx+c=0方程的根。a,b,c由键盘输入,设 b 2 ? 4ac >0。 众所周知,一元二次方程式的根为? b ? b 2 ? 4ac x1= ? b ? b ? 4ac x2= 2a 2a2可以将上面的分式分为两项:?b p= , q= 2ab 2 ? 4ac 2ax1=p+q,x2=p-q&&&&§ 4.6 顺序结构程序设计举例(续)#include &stdio.h& #include &math.h& void main ( ) { float a,b,c,disc,x1,x2,p,q; scanf(&a=%f,b=%f,c=%f&,&a,&b,&c); disc=b*b-4*a*c; p=-b/(2*a); 运行情况: q=sqrt(disc)/(2*a); a=1,b=3,c=2↙? x1=p+q;x2=p-q; x1=-1.00 printf(&\n\nx1=%5.2f\nx2=%5.2f\n&,x1,x2); x2=-2.00 }&&&&第五章&&&&?本章要点??关系表达式 逻辑表达式?选择结构程序设计&&&&?主要内容5.1 关系运算符和关系表达式5.2 逻辑运算符和逻辑表达式5.3 if语句5.4 switch语句5.5 程序举例&&&&§5.1 关系运算符和关系表达式(一).关系运算符及其优先次序 1. & (小于) 2. &= (小于或等于) 优先级相同(高) 3. & (大于) 4. &= (大于或等于) 5. == (等于) 优先级相同(低) 6. != (不等于)说明:关系运算符的优先级低于算术运算符 关系运算符的优先级高于赋值运算符&&&&§5.1 关系运算符和关系表达式(续)(二).关系表达式 ? 用关系运算符将两个表达式(可以是算术表达式或 关系表达式,逻辑表达式,赋值表达式,字符表达式) 接起来的式子,称关系表达式例:a&b,a+b&b+c,(a=3)&(b=5),?a?&?b?,(a&b)&(b&c)? 关系表达式的值是一个逻辑值,即?真?或?假?。 例:关系表达式?a&b”的值为?真?,表达式的值为1。&&&&§5.2 逻辑运算符和逻辑表达式(一).逻辑运算符及其优先次序 1. && (逻辑与) 相当于其他语言中的AND 2. || (逻辑或) 相当于其他语言中的OR 3. ! (逻辑非) 相当于其他语言中的NOT 例:a&&b 若a,b为真,则a&&b为真。 a||b 若a,b之一为真,则a||b为真。 !a 若a为真,则!a为假。优先次序:?!(非)-&&&()-&||() ?逻辑运算符中的?&&”和?||”低于关系运算符,?!”高于算 术运算符&&&&§5.2 逻辑运算符和逻辑表达式(续)(二)逻辑表达式 ?用逻辑运算符将关系表达式或逻辑量连接起来的式子就 是逻辑表达式 ?逻辑表达式的值应该是一个逻辑量?真?或?假?。 例:设a=4,b=5: !a的值为0 a||b的值为1 4&&0||2的值为1a&&b的值为1 !a||b的值为1任何非零的数值被认作?真?&&&&§5.2 逻辑运算符和逻辑表达式(续)例:5&3&&8&4-!0自左向右运算5&3逻辑值为1 !0逻辑值为1 4-1值为3表达式值为01&&0逻辑值为08&3逻辑值为0&&&&§5.2 逻辑运算符和逻辑表达式(续)在逻辑表达式的求解中,并不是所有的逻辑运算符都要被执行。 (1)a&&b&&c 只有a为真时,才需要判断b的值,只有a和b都为真时, 才需要判断c的值。 (2)a||b||c 只要a为真,就不必判断b和c的值,只有a为假,才 判断b。a和b都为假才判断c例:(m=a&b)&&(n=c&d) 当a=1,b=2,c=3,d=4,m和n的原值为1时,由于?a&b”的值 为0,因此m=0,而?n=c&d”不被执行,因此n的值不是0而 仍保持原值1。&&&&§5.2 逻辑运算符和逻辑表达式(续)用逻辑表达式来表示闰年的条件?能被4整除,但不能被100整除。 ?能被4整除,又能被400整除答 案(year%4==0&&year%100!=0)||year%400==0值为真(1)是闰年,否则为非闰年。&&&&§5.3 if语句一.If语句的三种基本形式(1)if (表达式) 语句 ch=getchar(); if(ch&=?a?&&ch&=?z?) ch=ch-?a?+?A?; putchar();表达式 真(非0)语句假 (0)ch=getchar(); if(ch&=?a?&&ch&=?z?) {ch=ch-?a?+?A?; putchar();}&&&&§5.3 if语句(续)(2)if(表达式) else 语句1 语句2非0 条件 语句10 语句2例:if(x&y) printf(“%d”,x); else printf(“%d”,y);&&&&§5.3 if语句(续)(3)if(表达式1)语句1 else if(表达式2)语句2 else if(表达式3)语句3 …… else if(表达式m)语句m else 语句n&&&&§5.3 if语句(续)例:if (number&500)cost=0.15; else if(number&300)cost=0.10; else if(number&100)cost=0.075; else if(number&50)cost=0.05; else cost=0;&&&&§5.3 if语句(续)说明:(1).3种形式的if语句中在if后面都有表达式, 一般为逻辑表达式或关系表达式。 (2).第二,第三种形式的if语句中,在每个 else前面有一个分号,整个语句结束处有一 个分号。 (3).在if和else后面可以只含有一个内嵌的操 作语句,也可以有多个操作语句,此时用花 括号将几个语句括起来成为一个复合语句。&&&&§5.3 if语句(续)例5.1 输入两个实数,按代数值由小到大的顺序输出这两 个数。 #include&stdio.h& a&b void main() {float a,b,t; y scanf(“%f,%f”,&a,&b); n T=a if(a&b) A=b {t=a; B=t a=b; b=t;} printf(“%5.2f,%5.2f\n”,a,b);}&&&&§5.3 if语句(续)例5.2 输入三个数a,b,c,要求按由小到大的顺序输出。a&b n a&c y y nIf a&b If a&c If b&c将a和b对换 将a和c对换 将b和c对换yb&ca和b交换a和c交换c和b交换&&&&§5.3 if语句(续)#include &stdio.h& void main ( ) { float a,b,c,t; scanf(?%f,%f,%f?,&a,&b,&c); if(a&b) {t=a;a=b;b=t;} if(a&c) {t=a;a=c;c=t;} if(b&c) {t=b;b=c;c=t;} printf(&%5.2f,%5.2f,%5.2f\n&,a,b,c); }&&&&§5.3 if语句(续)二.If语句的嵌套在if语句中又包含一个或多个if语句称为if语句的嵌套。 形式: If() if() 语句1 else 语句2 内嵌if Else if() 语句3 else 语句4&&&&§5.3 if语句(续)匹配规则: Else总是与它上面的,最近的,同一复合语句中的,未配 对的if语句配对。例:If() if() 语句1例:If() {if() 语句1}elseif() 语句2 else 语句3elseif() 语句2 else 语句3当if和else数目不同时,可以加花括号来确定配对关系。&&&&§5.3 if语句(续)?-1 (x&0) 例 5.3 有一个函数 y= ? 0 (x=0),编一程序,输入一个x 值,输出y值。 ? 1 (x&0)算法1: 输入x 若x&0,则y=-1 若x=0,则y=0 若x&0,则y=1 输出y 算法1: 输入x 若x&0,则y=-1 否则: 若x=0,则y=0 若x&0,则y=1 输出y&&&&§5.3 if语句(续)#include&stdio.h& void main() { int x,y; scanf(“%d”,&x); { 程序段 } printf(“x=%d,y=%d\n”,x,y); }&&&&? -1 (x&0) y= ? 0 (x=0) §5.3 if语句(续) ? 1 (x&0) 上例中的程序段有四个,请判断哪个是正确的?程序1: if(x&0) 正 Y=-1; 确 else if(x==0) y=0; else y=1; 程序3: y=-1; if(x!=0) If(x&0) y=1; else y=0; 程序2:if(x&=0) if(x&0) y=1; 正 else y=0; 确 else y=-1;程序4: y=0; if(x&=0) if(x&0) y=1; else y=-1;&&&&§5.3 if语句(续)三.条件运算符?格式: ?功能: 表达式1?表达式2∶表达式3 判断表达式1的值,如果成立就执行表 达式2,否则就执行表达式3 ?使用场合:若在if语句中,当被判别的表达式的 值为?真?或?假? 时,都执行一个赋值语 句且向同一个变量赋值时,可以用一个 条件运算符来处理。&&&&§5.3 if语句(续)例:if (a>b) max=a; else max=b; 当a&b时将a的值赋给max,当a≤b时将b的值赋给max, 可以看到无论a&b是否满足,都是向同一个变量赋值。 可以用下面的条件运算符来处理:max=(a>b)?a∶b;&&&&§5.3 if语句(续)说明:(1).条件运算符的执行顺序:先求解表达式1,若为非0(真) 则求解表达式2,此时表达式2的值就作为整个条件表达式 的值。若表达式1的值为0(假),则求解表达式3,表达 式3的值就是整个条件表达式的值。 (2).条件运算符优先级高于赋值运算符 ,低于关系运算符 和算术运算符。 (3).条件运算符的结合方向为?自右至左?。 (4).“表达式2”和?表达式3”不仅可以是数值表达式,还可以 是赋值表达式或函数表达式。 (5).条件表达式中,表达式1的类型可以与表达式2和表达 式3的类型不同。&&&&§5.3 if语句(续)例5.4输入一个字符,判别它是否大写字母,如果是,将 它转换成小写字母;如果不是,不转换。然后输出最后 得到的字符。#include &stdio.h& void main ( ) { scanf(&%c&,& ch); ch=(ch&='A'&& ch&='Z')?(ch+32): printf(&%c\n&,ch); }如果字符变量ch的值为大写字母, 则条件表达式的值为(ch+3 2),即相应的小写字母。如果ch 的值不是大写字母,则条件表达式 的值为ch,即不进行转换。&&&&§5.4 switch语句switch语句的格式:switch(表达式) {case 常量表达式1:语句1 case 常量表达式2:语句2 … case 常量表达式n:语句n default :语句n+1 }&&&&§5.4 switch语句(续)例:要求按照考试成绩的等级输出百分制分数段,用 switch语句实现:switch(grade) {case ′A′∶printf(〃85~100\n〃); case ′B′∶printf(〃70~84\n〃); case ′C′∶printf(〃60~69\n〃); case ′D′∶printf(〃<60\n〃); default∶printf(〃error\n〃); }&&&&§5.4 switch语句(续)说明:(1)switch后面括弧内的?表达式?, ANSI标准允许 它为任何类型。 (2) 当表达式的值与某一个case后面的常量表达式的值相 等时,就执行此case后面的语句,若所有的case 中的常量表达式的值都没有与表达式的值匹配的,就执行 default后面的语句。 (3) 每一个case的常量表达式的值必须互不相同,否则就 会出现互相矛盾的现象(对表达式的同一个值,有两种或 多种执行方案)。&&&&§5.4 switch语句(续)(4) 各个case和default的出现次序不影响执行结 果。例如,可以先出现?default:…”,再出现 ?case ′D′:…”,然后是?case ′A′:…”。 (5) 执行完一个case后面的语句后,流程控制转移到下一 个case继续执行。?case常量表达式?只是起语句 标号作用,并不是在该处进行条件判断。在执行 switch语句时,根据switch后面表达式的值 找到匹配的入口标号,就从此标号开始执行下去,不再进 行判断。应该在执行一个case分支后,可以用一个 break语句来终止switch语句的执行。 (6) 多个case可以共用一组执行语句。&&&&§5.5 程序举例例5.5 写程序,判断某一年是否闰年。&&&&#include &stdio.h& void main() if(year%4!=0) leap=0; §5.5 程序举例(续) {int year, else if(year%100!=0) scanf(&%d&,&year); leap=1; if (year%4==0) else if(year%400!=0) {if (year%100==0) leap=0; {if (year%400==0) leap=1; else leap=1; else leap=0;} else leap=1;} else leap=0; if (leap) printf(&%d is &,year); 运行情况: else printf(&%d is not &,year); 1989↙? leap year.\n&);} printf(&a 1989 is not a leap year. 2000↙? 2000 is a leap year.&&&&§5.5 程序举例(续)例5.7 运输公司对用户计算运费。路程(s)越远,每公里运费越低。标准如下: s<250km 没有折扣 250≤s<500 2%折扣 500≤s<1000 5%折扣 1000≤s<2000 8%折扣 2000≤s<3000 10%折扣 3000≤s 15%折扣 设每公里每吨货物的基本运费为p,货物重为w,距离为s, 折扣为d,则总运费f的计算公式为: f=p*w*s*(1-d)&&&&§5.5 程序举例(续)分析折扣变化的规律性:折扣的?变化点?都是250的倍数 在横轴上加一种坐标c,c的值为s/250。c代表250的倍数。c&1,无折扣; 1≤c<2,折扣d=2%; 2≤c<4,d=5%; 4≤c<8,d=8%; 8≤c<12,d=10%; c≥12,d=15%。&&&&#include &stdio.h& void main ( ) §5.5 程序举例(续) {int c,s; float p,w,d,f; scanf(&%f,%f,%d&,&p,&w,&s); if(s&=3000) c=12; else c=s/250; switch(c){ case 0:d=0; case 1:d=2; case 2:case 3:d=5;break; case 4:case 5:case 6:case 7:d=8; case 8:case 9:case 10: case 11:d=10; case 12:d=15; } f=p*w*s*(1-d/100.0); printf(&freight=%15.4f\n&,f);}&&&&第六章&&&&?本章要点?循环的基本概念??不同形式的循环控制多重循环问题&&&&?主要内容6.1 概述 6.2 goto语句以及用goto语句构成循环 6.3 用while语句实现循环 6.4 用do-while语句实现循环 6.5 用for 语句实现循环 6.6 循环的嵌套 6.7 几种循环的比较 6.8 break语句continue和语句 6.9 程 序 举 例&&&&§6.1 概述问题1: ? ? n yn ?1 100什么是循环? 为什么要使用循环?问题2:求学生平均成绩分数相加后除以课数在许多问题中需要用到循环控制。循环结构 是结构化程序设计的基本结构之一,它和顺序 结构、选择结构共同作为各种复杂程序的基本 构造单元。&&&&§6.2goto语句以及用goto语句构成循环1? goto语句为无条件转向语句,它的一般形式 为 goto 语句标号; ? 语句标号用标识符表示,它的定名规则与变 量名相同,即由字母、数字和下划线组成, 其第一个字符必须为字母或下划线。 例如:goto label_1; 合法; goto 123; 不合法.&&&&§6.2goto语句以及用goto语句构成循环结构化程序设计方法主张限制使用goto语句,因 为滥用goto语句将使程序流程无规律、可读性差. 一般来说,可以有两种用途:(1) 与if语句一起构成循环结构; (2) 从循环体中跳转到循环体外。但是这种用法不符合结构化原则,一般不宜采 用,只有在不得已时(例如能大大提高效率)才使 用.&&&&?nn ?1100运行结果:5050 例6.1 用if语句和goto语句构成循环,求1到100的和 void main( ) { int i, sum=0; i=1; loop: if(i&=100) { sum=sum+i; i++; } printf(&%d\\n〃,sum); } 说明:这里用的是“当型”循环 结构,当满足“i&=100” 时 执行花括弧内的循环体。&&&&§6.3 用while语句实现循环 while语句用来实现?当型?循环结构。一般形式:while (表达式) 语句 当表达式为非0值时,执行while语 句中的内嵌语句。其特点是:先判断表 达式,后执行语句。图&&&&?nn ? 求1到100的和 #include &stdio.h& void main() {int i,sum=0; i=1; while (i&=100) { sum=sum+i; i++; } printf(〃%d\\n〃,sum); } 说明:(1)循环体如果包含一个以上 的语句,应该用花括弧括起来,以 复合语句形式出现.(2)在循环体中运行结果:5050&&&&§6.3用while语句实现循环注意:(1) 循环体如果包含一个以上的语句,应该用 花括弧括起来,以复合语句形式出现。 (2) 在循环体中应有使循环趋向于结束的语句 。如果无此语句,则i的值始终不改变, 循环永不结束。&&&&§6.4 用do-while语句实现循环do-while语句的特点:先执行循环体,然后判断循环条件 是否成立。 一般形式:do 循环体语句 while (表达式);执行过程:先执行一次指定的循环体语句,然后判 别表达式,当表达式的值为非零(“真?) 时,返 回重新执行循环体语句,如此反复,直到表达式 的值等于0为止,此时循环结束。&&&&?nn ?1100运行结果:5050 例6.3 求1到100的和 #include &stdio.h& void main() { int i,sum=0; i=1; do {sum=sum+i; i++; } while(i&=100); printf(&%d\\n〃,sum); }&&&&§6.4 用do-while语句实现循环while语句和用do-while语句的比较: 在一般情况下,用while语句和用do-while语 句处理同一问题时,若二者的循环体部分是一 样的,它们的结果也一样。但是如果while后面 的表达式一开始就为假(0值)时,两种循环的结 果是不同的。&&&&?nn ? while和do-while循环的比较 (1) #include &stdio.h& (2) #include &stdio.h& void main ( ) void main( ) {int sum=0,i; {int sum=0,i; scanf(“%d〃,&i); scanf(”%d〃,&i); while (i&=10) do {sum=sum+I; { sum=sum+i; i++; i++; } while (i&=10); printf(“sum=%d\\n〃 ,sum); } printf(“sum=%d\\n”,sum); } 1)当while后面的表达式的 次的值为“真”时,两种循运1s再s&&&&§ 6.5 用for 语句实现循环? C语言中的for语句使用最为灵活,不仅可以用于 循环次数已经确定的情况,而且可以用于循环次 数不确定而只给出循环结束条件的情况,它完全 可以代替while语句。 ? 一般形式: for(表达式1;表达式2;表达式3) 语句&&&&§ 6.5 用for 语句实现循环for语句的执行过程:(1) 先求解表达式1。 (2) 求解表达式2,若其值为真(值为非0),则执 行for语句中指定的内嵌语句,然后执行下 面第(3)步。若为假(值为0),则结束循环, 转到第(5)步。 (3) 求解表达式3。 (4) 转回上面第(2)步骤继续执行。 (5) 循环结束,执行for语句下面的一个语句&&&&§ 6.5 用for 语句实现循环执行表达式1 表达式2?成立 不成立循环初始条件 循环控制条件执行语句执行表达式3循环体 ? for语句等价于下列语句: 表达式1; while (表达式2) { 语句; 表达式3; }执行for循环之后的语句&&&&§ 6.5 用for 语句实现循环? for语句最简单的应用形式也就是最易理解的如 下形式:for(循环变量赋初值;循环条件;循环变量增值)例如: for(i=1;i&=100;i++) sum=sum+i;它相当于以下语句: i=1; 显 然 , 用 for 语 句 简单、方便。 while(i&=100) {sum=sum+i;i++;}&&&&§ 6.5 用for 语句实现循环说明:(1) for语句的一般形式中的“表达式1”可以省略,此 时应在for语句之前给循环变量赋初值。注意省略表 达式1时,其后的分号不能省略。如 for(;i&=100;i++) sum=sum+i; 执行时,跳过“求解表达式1”这一步,其他不变。&&&&§ 6.5 用for 语句实现循环 说明:(2) 如果表达式2省略,即不判断循环条件,循环无终 止地进行下去。也就是认为表达式2始终为真。 例如:for(i=1; ;i++) sum=sum+i; 表达式1是一个赋值表达式,表达式2空缺。它相当于: i=1; while(1) {sum=sum+1;i++;}&&&&§ 6.5 用for 语句实现循环 说明:(3) 表达式3也可以省略,但此时程序设计者应另外设 法保证循环能正常结束。如: for(i=1;i&=100;) {sum=sum+i;i++;} 在上面的for语句中只有表达式1和表达式2,而没有 表达式3。i++的操作不放在for语句的表达式3的位置 处,而作为循环体的一部分,效果是一样的,都能使 循环正常结束。&&&&§ 6.5 用for 语句实现循环 说明:(4) 可以省略表达式1和表达式3,只有表达式2,即只 给循环条件。如: for(;i&=100;) while(i&=100) {sum=sum+i; 相当于 {sum=sum+i; i++;} i++;} 在这种情况下,完全等同于while语句。可见for语句 比while语句功能强,除了可以给出循环条件外,还可 以赋初值,使循环变量自动增值等。&&&&§ 6.5 用for 语句实现循环 说明:(5) 3个表达式都可省略,如: for(; ;) 语句 相当于 while(1) 语句 即不设初值,不判断条件(认为表达式2为真值), 循环变量不增值。无终止地执行循环体。&&&&§ 6.5 用for 语句实现循环 说明:(6) 表达式1可以是设置循环变量初值的赋值表达式, 也可以是与循环变量无关的其他表达式。如: for (sum=0;i&=100;i++) sum=sum+i; 表达式3也可以是与循

我要回帖

更多关于 de分别是ab 的文章

 

随机推荐