C语言程序设计课件_第1页
C语言程序设计课件_第2页
C语言程序设计课件_第3页
C语言程序设计课件_第4页
C语言程序设计课件_第5页
已阅读5页,还剩426页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

•算法与程序设计1.1程序设计的基本概念•1.1.1什么是程序•1.1.2计算机如何运行程序•1.1.3如何实现程序设计1.2算法和流程图•1.2.1什么是算法•1.2.2算法应具备的特性•1.2.3怎样表示算法

解决某一问题的具体方法和步骤怎样表示呢?当然可以用语言来描述,除此之外,还可以采用传统流程图、N-S流程图等。下面我们分别介绍一下最常用的几种方法。1.自然语言描述法例1.1求n!(n≥0)•第一步:输入n的值。

第二步:判别一下n的值,如果小于0,则显示“输入错误”信息,然后执行第五步。第三步:判断一下n的值如果大于或等于0,则进行以下操作。(1)给存放连乘积的变量fac赋初值为1;(2)给代表乘数的变量i赋初值为1;(3)进行连乘运算:fac=fac

i;(4)乘数i增加1:i=i+1;(5)判断乘数i是否大于n?如果i的值不大于n,重复执行第三步,否则执行下一步;第四步:输出fac的值,即n!值。第五步:结束运行。2.传统流程图描述法•

使用自然语言描述算法通俗易懂,它是文字性的。所以,此种方法一般用于算法比较简单的问题。传统流程图是借助一些图形符号来表示算法的一种工具,如图1-3所示。这种表示方法直观形象,容易理解。这些图形符号均采用美国国家标准协会ANSI规定的通用符号,在世界上也是通用的。3.N-S流程图描述法

N-S流程图是由美国两位学者(I.Nassi和B.Schneiderman)提出的。这种算法描述工具完全取消了流程线,所有的算法均以三种基本结构作为基础。1.3结构化程序设计1.3.1为什么要采用结构化程序设计1.3.2结构化程序的基本组成

结构化程序的基本组成是顺序结构、分支结构和循环结构。这三种基本结构可用于表示任何一个复杂的算法结构。下面我们通过N-S流程图具体说明一下这三种基本结构。1.顺序结构•

顺序结构是三种结构中最简单的一种结构。这种结构的程序是按照语句的先后次序顺序执

行。图1-6是用N-S流程图表示的顺序结构,按照图1-6的图型所示,首先执行A语句,然后再顺序执行B语句。图1-6顺序结构的N-S流程图2.分支结构•

分支结构又称作为选择结构。在分支结构中必须包含条件判断语句,根据条件判断的结果,决定执行哪一个分支结构。图1-7是用N-S流程图表示的分支结构,按照图1-7的图形表示,当“条件”成立时,执行

A语句分支,当“条件”不成立时,执行B语句分支。图1-7分支结构的N-S流程图3.循环结构

循环结构的功能是:根据循环条件成立与否,来决定是否重复执行某一条或几条语句。循环结构又分为当型循环结构和直到型循环结构,如图1-8所示。图1-8循环结构的N-S流程图

图1-8(a)和图1-8(b)均为当型循环结构,它们是在条件成立的情况下执行A语句部分,条件不成立时,不执行A语句,跳出循环结构。图1-8(a)和图1-8(b)不同的情况是:循环条件与重复执行的语句A相对位置不一样,图1-8(a)是循环条件在前,称为前测型,先来判断循环条件是

否成立;而图1-8(b)是循环条件在后,称为后

测型,最少执行一次循环语句A,然后再来判断循环条件是否成立。循环条件成立则继续循环,循环条件不成立则结束循环。图1-8(c)和图1-8(d)均为直到型循环结构,它们的功能是:直到循环条件成立时,则跳出

循环结构,在循环条件不成立时,执行循环语

句A。图1-8(c)和图1-8(d)不同的是:图1-8(c)是前测型,首先判断循环条件是否成立;而图1-8(d)为后测型,最少执行一次循环语句A,然后再来判断循环条件是否成立。循环条件不成立

则继续循环,循环条件成立则跳出循环。注意:在C语言中没有提供“直到型循环”语句。当型循环和直到型循环的结构是可以互

相转换的。在由以上三种基本结构组成的结构化程序中,需满足以下基本条件:(1)整个程序只有一个入口和一个出口;(2)所有的语句都有可能执行到。以上我们已经按结构的划分对结构化程序设计进行了分别介绍,最后我们举一综合实例。1.3.3复杂问题的解决方法下面我们举一实例,加以具体说明。例如:学籍管理系统。

就整个系统来看,我们很难马上就写出解决问题的算法及对应的源程序,因为这个系统相对来说比较大、比较复杂,我们不妨把整个系统分解成若干个小问题,减小问题的规模和复杂程度。

经过系统分析,整个系统大致包括数据输入、数据修改、数据查询、数据统计和数据输出几个部分。根据不同问题的划分,每一类问题作为一个模块,可以画出整个学籍管理系统的一级模块图,如图1-10所示。图1-10学籍管理系统的一级模块图

此时的模块图比起最初的感觉要直观一些,每一个子模块要比整个系统要简单一些。这时

还可以把一级模块图中某一个子模块再进一步

划分。比如:数据输入可分解成学生基本情况

输入模块、学生成绩输入模块、学生奖惩情况

输入模块等,同样其他一级子模块也可继续细

分,这里就不再赘述了。

通过对该例解决问题思路的描述,我们对

“自上而下,逐步细化,模块化”的程序设计思想有了进一步的了解。希望读者在今后的程序设计中,不断地学习,不断地实践,逐步掌握这种设计方法。2.1简单C语言程序的组成和格式2.1.1一个简单的C语言程序

利用计算机解决各种类型,复杂程度各异的问题时,关键是用户需要编写出计算机能够

“读懂”的程序,使计算机能够按照程序设计者的意愿去工作。C语言就是一种在计算机上实现程序的描述语言。它在描述一个完整的程序时,有固定的结构要求和具体的描述方法,类似于我们说话、写文章要有主谓宾基本语句部分一样,缺少一部分就不成一句话了。在这一节中将向读者介绍一些用C语言进行程序设计的有关基本语法知识。我们先举一个简单的程序例子,使读者对

C语言程序的构成有一个初步的了解。例2.1根据圆的半径r,计算圆面积s。已知求圆面积的公式为:s=r

2源程序为:/*求圆面积*/#include<stdio.h>/*命令行*/••••main()/*主函数首部*/{int

r;/*定义变量r,说明为整型*/float

s;/*定义变量s,说明为单精度型*/r=4;/*给r赋值为4

*/s=3.141592

*

r

*

r

;/*计算圆面积,将值赋给s

*/printf("圆面积s=%f\n",s);/*显示圆面积的值*/}以上程序运行后,在计算机屏幕上显示如下结果:圆面积s=50.265472源程序的第一行用“/*”和“*/”符号括起来的一串字符是对程序的注释,这对符号必须成对使用,“/”和“*”之间不能有空格。注释内容可以用中文或西文,它对程序的运行不起作用,只起注释作用。好的注释可以使人们在阅读程序时,能较好地理解程序的功能及含义。第二行是命令行,它的功能是在调用系统

的输出函数(printf函数)时,需要写该命令行。第三行是主函数的首部,其中:main是主函数名,函数名后面的一对小括号是不能省略的,它的功能是:表明函数从此开始。函数具体要完成的内容放在其后一对花括号{}中,用这对花括号括起来的部分称为函数体。“{”符号表示函数体开始,源程序最后一行的“}”符号表示函数到此结束。在C语言源程序中只能包括一个主函数,在一个或多个函数组成的程序中,程序的执行都是由主函数开始。在该主函数的函数体中共有五行,完成指定的任务:根据圆的半径,计算并输出显示该圆的面积。在这五行中,除了注释之外,每一条语句均以分号“;”号结束,完成某一项功能。函数体中第一条和第二条语句为声明部分,分别定义了一个整型变量r和一个单精度型变量s。函数体中第三条至第五条语句为执行部分。此例中分别完成了对变量r(圆的半径)的赋值(值为4),然后根据变量r的数值计算圆面积,计算后赋给变量s。最后通过调用系统的printf输出函数,将圆的面积s输出显示在屏幕上。2.1.2

C语言程序的组成和格式2.1.3关键字和标识符

在例2.1的源程序中,我们遇到了诸如main、int、r、float、s、printf等符号,它们的作用和性质并不完全相同,它们代表什么意思呢?1.关键字

关键字又称为保留字。它们是C语言中预先规定的具有固定含义的一些单词,如:int表示

为整型数据、float表示为单精度实型数据等等。用户只能按其给定的含义来使用,不能重新定

义另作它用。C语言所提供的关键字请见附录一。2.标识符•

标识符分为系统预定义标识符和用户自定义标识符两种。(1)系统预定义标识符这些标识符也是由一些单词所组成,它们的功能和含义是由系统预先定义好的,如:main代表主函数名、printf代表输出函数名等等。

它们与关键字不同的是:系统预定义标识符允许由用户赋予新的含义,这样做的结果,往往会引起一些误解,因此建议用户不要把这些系统预定义标识符另作它用,否则会带来不必要的麻烦。(2)用户自定义标识符

用户可根据需要自行定义一些标识符,用作为符号名、变量名、数组名、函数名、文件名等等,如例2.1中:r代表变量名,用于存储圆的半径、s代表变量名,用于存储圆的面积。用户自定义标识符的命名必须遵守一定的规则。合法的用户自定义标识符应满足以下条件。①只能由大小写英文字母、阿拉伯数字和下划线组成。标识符的开头必须是字母或下划

线,大小写字母是有区别的,视为不同的字母。②标识符的长度视不同的编译器规定而不同,一般可识别前8个字符。按照以上规则,mystery、_start、r1、R_1都是合法的标识符,而12b、D$?_I、int都不是合法的用户自定义标识符。

为使程序具有较好的可读性,标识符的命名应尽可能反映出它所代表的含义,做到“见名知义”。如:用pi代表圆周率,用sum代表总和,用name代表名字等等。2.1.4常量和变量

在计算机处理的程序中,我们不免经常与数据打交道,根据数据的值是固定的,还是可变的,我们将数据分为两大类:常量和变量。1.常量

在程序运行过程中其值不能改变的量称为常量。如例2.1中的圆半径4和圆周率3.141592都属于常量。常量有不同的类型之分,有整型常量、实型常量、字符常量、字符串常量等。2.变量•

在程序运行过程中其值可以改变的量称为变量。如例2.1中的表示圆半径的变量r和表示圆面积的变量s都属于变量。与常量相同的是,变量也有类型之分,同样有整型变量、实型变量、字符变量等。程序中的变量由用户标识符来表示,在C语言中,所有变量必须遵循“先定义,后使用”的原则。变量的定义一般放在函数体的开头,即声明部分。变量定义语句的形式为:类型名变量名1,变量名2,…;其中:类型名由关键字表示,不同的关键字表示不同的数据类型,变量名是用户标识符,由用户命名。如例2.1中语句int

r;,表示定义了一个整型变量,变量名为r,而语句float

s;,表示定义了一个单精度型变量,变量名为s。通常,定义了一个变量而未赋初值时,一般变量中存放的是随机值。因此,为使定义的变量有一确切的数值,需给定义的变量赋一初值。所以,C语言也允许在定义变量的同时为其赋初值,其形式为:类型名变量名1=常量1,变量名2=常量2,…;如例2.1函数体中的第一条语句int

r;语句,也可改写成int

r=4;,表示定义了一个整型变量

r,初值为4。第二条语句float

s;语句,也可改写成float

s=0.0;,表示定义了一个单精度型变量s,初值为0.0。

一个变量代表着内存中一个具体的存储单元,用变量名来标识。存储单元中存放的数据称为变量的值,变量的值可以通过赋值的方法获得和改变。读者一定要区分开变量名和变量值这两个不同的概念。2.2简单的数据类型•2.2.1为什么要区分不同的数据类型•2.2.2整型常量和变量•2.2.3实型常量和变量•2.2.4字符型常量和变量•2.2.5符号常量、不可变的变量•2.2.6无值型2.3算术运算2.3.1算术运算符和表达式1.基本算术运算符C语言提供的基本算术运算符见表2-3。说明(1)“单目”和“双目”指的是参与运算的对象个数;(2)两个整数相除,运算结果仍为整数,得到的商舍去小数部分;(3)求余运算限定运算对象必须为整数,其中在运算符左侧的为被除数,右侧的为除数,两个数求余运算后的结果是取整除后的余数和

被除数的符号(不同的机器系统有差异)。2.算术运算符的优先级、结合性和算术表达式•

由算术运算符、圆括号和运算对象连接起来的式子称为算术表达式。其中运算对象可包括常量、变量和函数。例如:数学表达式:b2–4ac

写成C语言算术表达式应是:b*b

–4*a*cC语言中的表达式与数学中的表达式在书写格式上是有区别的,请读者注意以下几点:(1)表达式中只能使用系统允许的标识符。例如:数学表达式2r写成C语言表达式应是

2*3.1415926*r;(2)乘法运算符“*”不能省略。例如:数学表达式4x+2写成C语言表达式应是:4*x+2;(3)C语言表达式没有分数形式,对数学表达式中的分数运算要做适当的转换。例如:写成C语言表达式应是(a–b)/数学表达式

(c+d);(4)在表达式中要想改变运算顺序,优先运算哪一步,只能使用圆括号“(”和“)”,不能使用方括号“[”和“]”和花括号“{”和

“}”,因为这两种括号C语言系统另有它用。

在C语言进行表达式求值运算过程中,各运算符均有优先级的问题,运算符与两侧的运算对象之间还有结合性的问题。有关C语言中算术运算符的优先级和结合性内容如表2-4所示。在C语言算术表达式中优先级别高的先运算,优先级别低的后运算。“结合性”是指当一个运算对象两侧运算符优先级别相同时,是按“从左至右”的顺序

运算(称为左结合性);还是按“从右至左”

的顺序运算(称为右结合性)。例如:表达式:

a+b–c

运算次序应该是先进行加法运算,后再进行减法运算。2.3.2数据类型的转换2.3.3如何使用C语言的标准库函数•

标准库函数是C语言编译系统预先编写好的函数,在附录四中给出了C语言中常用的库函数。库函数的一般调用形式为:函数名(参数表)2.4赋值运算、逗号运算和自加、自减运算2.4.1赋值运算符和表达式1.赋值表达式•

当用户欲将一个数或表达式的值赋给某一指定的变量时,可以通过赋值表达式实现。赋值表达式的形式如下:变量名=表达式

其中:“=”是赋值运算符,表示赋值的含义,它的功能是将运算符右侧的表达式的值放入以左边变量为标识的存储单元中。2.复合的赋值表达式复合的赋值运算符共5个,它们是:•+=、-=、*=、/=、%=3.赋值运算中的类型转换2.4.2自加、自减运算符和表达式•

自加运算符“++”和自减运算符“––”的作用是:使变量的值增1和减1。“++”和“––”运算符为单目运算符,运算对象必须是变量,不能是常量和表达式。该

运算符对运算对象来说,既可以作为前缀运算

符,也可以作为后缀运算符,但结果有所区别。2.4.3逗号运算符和表达式逗号表达式的形式如下:表达式1,表达式2,…,表达式n其中:符号“,”为逗号运算符。2.5

Turbo

C环境下的上机操作步骤2.5.1如何进入和退出Turbo

C

2.01.进入Turbo

C

2.0

在已安装Turbo

C

2.0软件的目录下,运行

tc.exe文件。该文件运行完毕后,屏幕显示如图

2-1所示的界面。图2-1

Turbo

C

2.0软件的主界面屏幕中央显示软件的版本信息,按任一键后即可开始使用该软件。Turbo

C

2.0软件的主界面分为四部分:主菜单、编辑窗口、监视窗口和常用功能键提示行。当用户按下E键或Esc键,光标将定位在编辑窗口的左上角。此时用户可以输入C语言的源程序了。2.主菜单功能介绍主菜单共有八项,包含了软件的所有功能。File项:文件和目录处理。Edit项:编辑。Run项:运行状态控制。Compile项:编译与链接。Project项:工程文件管理。Option项:选项设置。Debug项:调试处理。Break/watch项:断点设置及变量监视。利用左、右箭头键(←、→)可以在主菜单的各项之间进行选择。选中的项在亮度或颜色上与其他项有区别。这时按回车键便可进入相应的状态或调出相应的下拉子菜单。也可按下Alt键和主菜单某选项的第一个字母,以快捷键的方式选择某一主菜单项。在任何情况下按下F10键都能进入主菜单。3.编辑窗口上方的编辑信息含义

在编辑窗口的上方有一行信息,各项的含义如下。Line

n:当前光标所在的行号。Col

n:当前光标所在的列号。Insert:插入/改写方式切换开关。反复按

Ins键,此信息会交替出现。当屏幕上有此信息时,屏幕编辑是处在“插入”状态;当屏幕上无此信息时,屏幕编辑是处在“改写”状态。Indent:程序行缩进方式。Tab

Fill:可用Tab键插入制表符。C:NONAME.C:当前正在编辑的文件名。系统给新文件取的缺省文件名为NONAME.C。4.功能键提示行•••

在屏幕底部的一行是功能键提示行,各功能键的含义如下。F1(Help):打开一个“帮助”窗口,用以查看各种编辑命令。按Esc键返回。F5(Zoom):放大/还原当前活动窗口。

F6(Switch):在编辑窗口和信息窗口之间切换,以确定当前活动窗口。F7(Trace):逐行执行编辑窗口内的程序。F10(Menu):使光标跳到主菜单。5.退出Turbo

C

2.0可用以下两种方法退出Turbo

C

2.0:(1)执行File下拉菜单中Quit项。(2)直接按快捷键Alt+X。2.5.2如何编辑源程序文件

编辑源程序文件包括建立新文件和修改已有文件。1.建立新文件步骤如下。

(1)选择File下拉菜单中的New项,进入编辑状态。(2)在编辑窗口中输入源程序。

(3)输入结束后,可选择File下拉菜单中的Write

to项,输入新文件名(应包括完整的路径)后,保存新文件。2.修改已有文件步骤如下。

(1)选择File下拉菜单中的Load项,输入已有文件名(应包括完整的路径)后,按下

Enter键确认。(2)被选择的文件调入编辑窗口后,就可进行编辑和修改了。(3)修改结束后,可选择File下拉菜单中的Save项,保存已修改的文件。注意:无论是新建立的源程序,还是进行修改的老程序,都不要急于运行,应该先将编辑的程序以文件的形式保存到磁盘上,以避免因意外导致输入的源程序丢失。2.5.3如何编译和运行程序1.如何编译源程序•

当文件建立或修改完毕并存盘后,即可进行编译,具体方法有以下两种。(1)选择Compile菜单中Compile

to

OBJ项,进行编译,编译后得到一个后缀为.obj的目标文件,然后再选择Compile菜单中Link

EXE项,生

成一个后缀为.exe的可执行文件。•

(2)也可将编译和链接合为一步进行,直接选择Compile菜单中Make

EXE

file项,生成后缀为.exe的可执行文件。在编译过程中,屏幕的中间会出现一个信息框,显示编译处理时的信息。若编译没有错误,将出现“success”信息,按任意键后返回编辑窗口;若编译出错,在信息框中将显示错误信息。

按任意键后,光标将停在编辑窗口内的出错行上(注意:出错信息并不完全准确,需要根据前后语句进行分析)。这时应进行改错,改错后保存文件,再重新进行编译。2.如何运行程序•运行程序的方法有以下两种。

(1)确认编译无误后,就可运行程序了。方法是直接按Ctrl+F9键或在Run菜单中选择Run项,程序便可运行。程序运行完毕后,将返回编辑窗口。若要查看程序运行结果,应在Run菜单中选择Userscreen项或按Alt+F5键。看完结果后按任意键返回编辑窗口。3.1顺序结构问题的提出

顺序结构是结构化程序设计中三种结构之一,是一种最简单、最常见的程序结构,其特

点是:按照语句的前后次序,自前向后顺序逐

条执行。尽管这种结构简单,但也蕴含着一定

的算法,它是按次序顺序执行,中间没有跳跃,也不允许“逆行”。3.2赋值语句在赋值表达式的尾部添加一个“;”号(语句结束标志),就构成了赋值语句。赋值语句具有双重功能:计算和赋值。首先对赋值号右侧的表达式进行计算,然后将结果赋给赋值号左侧的变量进行存储。由于自加、自减表达式具有赋值功能,因此同样也可以构成赋值语句。例如:a=5;b

=

a+3;i++;j

=

(a

=2

)+(b

=3

);x*=

5;以上语句均属赋值语句。C语言中有形式多样的赋值语句,用法灵活,因此读者只有首先掌握好赋值表达式的运算规律,才能用好赋值语句,并能正确地推算出赋值语句的结果。3.3数据输入语句数据输入是指通过键盘(也可由其他方式)将数据送入计算机的内存。C语言本身没有提供用于输入或输出数据的语句,所有需要进行输入或输出数据的操作都是通过调用标准库函数(由系统提供)来实现的。例如:用于按格式输入的scanf函数和用于字符输入的getchar函数。C语言的标准库函数是分类存放在不同的文件中,在使用输入输出标准库函数前,应该包含#include

"stdio.h"或#include

<stdio.h>命令行。3.3.1

scanf格式输入函数的使用scanf函数调用的形式:scanf(格式控制字符串,输入项表)

在该函数调用时,在其后面加上“;”分号,就构成了格式输入语句。例如:a为已定义的int类型变量,x为已定义的float类型变量,则:

scanf

("%d%f",&a,&x);语句可以实现通过键盘

分别向变量a和变量x输入整型数据和实型数据。3.3.2

getchar字符输入函数的使用•getchar函数的形式为:getchar()

调用该函数时,也需在调用之前加命令行:

#include"stdio.h"或#include<stdio.h>此函数不需任何参数,它的作用是从键盘读入一个字符作为函数的返回值。例如:char

c1;c1=getchar

(

)

;当程序执行到getchar函数调用语句时,将等待输入,只有当用户输入字符,并按Enter键后,字符才被送到内存的缓冲区,准备赋给指定的变量。并且对空格符、制表符(Tab键)和回车符(Enter键)都被当作有效字符读入。例如:#include"stdio.h"main(){

char

c1,

c2

;c1=getchar

(

)

;c2=getchar

(

)

;……}若运行上述程序时,输入:a↙则变量c1得到了输入字符a,而变量c2中存放的是换行符。3.4数据输出语句3.4.1

printf格式输出函数的使用printf函数调用的形式:printf(格式控制字符串,输出项表)或printf(字符串)

在该函数调用时,在其后面加上分号,就构成了格式输出语句。例如:printf("i=%d,m=%f\n",i,m);其中:i为已定义的int类型变量,m为已定义的float类型变量。执行此语句后,可将变量i的值和变量m的值显示在屏幕上。3.4.2

putchar字符输出函数的应用putchar函数的形式为:putchar(ch)

其中:参数ch可以是字符型常量或字符型变量,也可以是代表一个字符的ASCII代码的整型常量或整型变量。函数的功能是输出参数所代表的字符。若在函数调用后加上一个分号,就成为一条字符输出语句。例如:char

c1="a";putchar

(c1)

;/*在屏幕上显示输出字母a

*/putchar

(65)

;/*在屏幕上显示输出字母A

*/putchar

("\n")

;/*输出换行符,即光标换行*/3.5顺序结构程序设计举例

例3.1计算银行利率。设银行定期一年期的存款年利率r为1.98%,若存款年数为n,存款额为m,则利用公式m

(1+r)n可计算存款到期后的本利之和total=m

(1+r)n。源程序如下:#

include

"math.h"main

(){

int

n,

m

;float

r

=0.0198,

total

;printf

("please

enter

n

&

m

:

"

)

;/*提示语,请用户输入n和m的数值*/scanf

("%d%d

",

&n,

&m

)

;total=m*pow

(

1+r

,

n

)

;printf

("

total=%f\n",

total

)

;}程序的运行情况如下:please

enter

n

&

m

:

1

500↙total=511.2500003.6复合语句和空语句3.6.1复合语句

复合语句是由一些语句组成,它们放在一对大括号中。其语句形式如下:{语句1

语句2

……

语句n}在形式上看,一对大括号中含有多条语句,但在C语言语法规则上是作为一条语句来处理,

所以称为复合语句。例如:{t=a;a=b;b=t;}这

是一条复合语句,语句功能是实现两个变量中的数据交换。在后面将要介绍的分支语句和循环语句中,这种复合语句得到了广泛应用。3.6.2空语句•

根据语句的构成规则,分号“;”是C语句的结束标志,因此,一个单独的分号“;”也可以构成一条语句,我们称为空语句。空语句没有任何执行结果,那么这种空语句有何实际意义呢?一般常用于在程序设计初期,表示某一部分有语句存在,有待后面进一步完成。4.1分支结构问题的提出

上一章所讲到的顺序结构程序中,各语句是按照语句的前后顺序依次执行,没有选择,没有跳跃,也没有重复执行的问题,但是我们在解决实际问题时,经常遇到这样的问题:当客观现实事物满足不同的条件,会有不同的结果出现。比如:某一门课程考试成绩大于等于60分,该课程考核视为通过;如果考试成绩小于60分,则视为不通过。遇到类似这样的问题,首先需要判断一下具体的情况是什么,然后决定选择什么样的处理方式。不同的情况,会有不同的处理结果。对以上问题的解决,在程序设计中需要采用分支结构,也称为选择结构。上述提到的“条件”,在C语言中是如何表示的呢?4.2判断条件的描述方法4.2.1用关系表达式描述判断条件4.2.2用逻辑表达式描述判断条件4.3解决简单的分支问题4.3.1

if语句语句形式:if(表达式)语句

if语句的执行是:遇到if关键字,首先计算圆括号中的表达式的值,如果表达式的值为非0,则执行圆括号其后的语句,然后执行if语句后面的下一个语句。如果表达式的值为0,则跳过圆

括号后面的语句,直接执行if语句后面的下一个语句。if语句执行过程如图4-1所示。图4-1

if语句的执行4.3.2

if-else语句•语句形式:if(表达式)语句1else语句2该语句遇到关键字if,首先运算小括号中的表达式,如表达式的值为非0,则执行紧跟其后的语句1,执行完语句1后,执行if-else结构后面的语句;如果表达式的值为0,则执行关键字

else后面的语句2,接着执行if-else结构后面的语句。执行过程如图4-2所示。图4-2

if-else语句的执行过程4.3.3

if语句的嵌套

在if语句结构中,根据关键字if后面的表达式的值。决定选择那一个分支,执行相应的语

句。这个对应的语句只要是合法的语句,都可

以执行。因此有时根据实际问题的需要,我们

可以在if语句结构中再包含if语句结构,这就称为if语句的嵌套。4.3.4条件运算符和条件表达式

在C语言中使用if语句,实现了分支结构,同时系统还提供了条件运算符,同样可以实现简单的分支结构。条件运算符为:?:该运算符是由两个运算符所组成,为三目运算符。由条件运算符所构成的条件表达式为:表达式1?表达式2:表达式3它的运算功能是:当表达式1的值为非0时,运算表达式2,此时表达式2的值就作为整个条件表达式的值;当表达式1的值为0时,运算表达式3,此时表达式3的值就作为整个条件表达式的值。条件运算符的优先级高于赋值运算符,但低于逻辑运算、关系运算和算术运算符。例如:y

=x

>9?100∶200,由于赋值号的优先级低于条件运算符,因此先求条件表达式的值,如x>9关系表达式成立,则条件表达式的值为100;如x>9不成立,则条件表达式的值为200,然后将条件表达式的值赋给变量y。4.4解决多重分支的问题4.4.1利用if语句的嵌套功能请看以下语句结构:if

(表达式1)语句1else

if

(表达式2)if

(表达式1)语句1else

if

(表达式2)语句2语句2else

if

(表达式3) else

if

(表达式3)语句3整理后语句3......elseelse•语句n+1语句n+1

以上语句结构,除最后一个else子句中,均嵌入了if-else语句,此语句结构执行过程是:从上到下逐一对if后面的表达式进行运算。当某一个表达式的值为非0时,就执行紧跟其后的相关子句中的语句,而后面的其余部分均被跳过。

因此有n个if语句,就有n+1个分支。4.4.2使用switch语句实现多重分支•

除了使用嵌套的if语句,实现多重分支选择之外,C语言系统还专门提供了一种多重分支选择语句switch语句。switch语句的一般形式为:switch

(表达式){case常量表达式1:语句1case常量表达式2:语句2...case常量表达式n:语句ndefault:语句n+1}说明(1)switch关键字后面的表达式,可以是任意合法的表达式。每个case关键字后面的常

量表达式的类型,必须与switch关键字后面的表达式类型一致。(2)执行switch语句,首先计算其后的表达式的值,然后自上而下顺序寻找一个case后面的常量与该值相匹配,找到后按顺序执行此

case后面的所有语句,包括后续的case子句,

而不再进行判断。如果所有case中的常量值都

不能与switch后面的表达式的值相等,就执行

default关键字后面的语句;若既没有相匹配的

case,也没有default关键字,则直接跳过switch语句。4.5程序测试的问题1.结构测试法

这种测试方法的特点是:让测试用例尽可能地覆盖程序结构中的每一部分。2.功能测试法

功能测试法的特点是:从程序需实现的功能出发来选取测试用例。5.1循环结构问题的提出在用计算机解决大量的实际问题时,经常会遇到如下许多重复运算的问题。(1)求某一同学一学期的平均分。解决方法是将该同学这一学期所有考核成绩累加,再除以考核门数,就得到该生的平均分。(2)计算:1*2*3*…*n。这是一个累乘的问题,每个乘数与前面的一个数都有固定的关系(后面的数比前面的数大1)。因此每次累乘的数都是前面的数加1,方法相同,实际这是一个重复累乘的问题。这一类问题,重复的次数有些情况是已知的,有些情况是未知的。但是这些问题都带有重复性的工作,解决这类问题,采用循环结构最为适当。有些问题,采用单重循环就能解决,比如上面所举的两个例子,都可以采用单重循环;

而有些问题,比如说二维表格数据输出的问题,则需要采用双重循环才能解决。C语言提供了三种实现循环结构的语句,它们分别是:while语句、do-while语句和for语句,三种循环语句各有不同的特点,我们可以灵活使用。5.2解决单重循环的问题5.2.1

while循环语句while循环语句的形式如下:while(表达式)循环体语句while循环语句的执行过程如图5-1所示。图5-1while语句的执行说明(1)用while语句构成的是“当型”循环结构,它的特点是:“先判断,后执行”,如果表达式的最初值为0,则循环体语句一次也不执行。只有当表达式的值为非0时,才能执行循环体语句。执行完循环体语句后,再返回循环的开始部位,判断表达式的值,决定是否继续循环。(2)循环体语句只能是一条语句,如需要使用多条语句,必须采用复合语句的形式。(3)循环体内一定要有能够改变表达式的值的操作,最终使其表达式的值变为0,否则将形成无休止的“死”循环。例5.1求:1+2+3+…+n的累加求和的值。问题分析:(1)我们首先需要设置一个存放累加求和的变量sum,每一次加一个数放入变量sum中;(2)再设置一个存放加数的变量i,每一次累加时被加的数均需比前一个数大1;(3)最后还需设置一个结束累加的变量n,确定累加到什么数为止。根据以上分析,写出源程序如下:main

(

){

int

i,

n,

sum;i=1;sum=0;printf

("

Please

input

n

:

"

);scanf

("%d",

&n

);•while(i<=n)/*累加的数i小于或等于终止数n就循环累加,否则结束循环*/{

sum=sum+i;i++;}printf

("sum=%d\n",

sum

);}说明(1)存放累加求和的变量sum,说明后必须赋初值,一般为0,否则由于说明的变量其原有初值不确定,导致结果有误。(2)程序中sum=sum+i;语句是一个累加求和功能的语句,它是将变量sum中的数值加

上变量i中的数值,求和后再放入变量sum中,此时变量sum中存放的数值已经变为新的数值,原有数值已被覆盖掉。以上程序运行情况如下:Please

input

n

:

100↙sum=50505.2.2

do-while循环语句do-while循环语句的形式如下:do循环体语句while

(表达式);do-while语句的执行过程如图5-2所示。图5-2

do-while语句的执行过程说明(1)用do-while语句构成的仍是“当型循环”结构。它的特点是:“先执行,后判断”。遇到do关键字后,首先执行循环体语句,然后计算表达式的值,如表达式的值为非0,则继续执行循环体语句,然后再计算表达式的值,如表达式的值为0,则结束循环,执行do-while语句后面的语句。因此这种循环结构,最少也可以执行一次循环体语句。••

(2)循环体语句仍然只能是一条语句,如需要使用多条语句,必须采用复合语句的形式。循环体语句中也一定要有改变表达式的值的操作,最终使其表达式的值变为0,结束循环。否则将成为“死”循环。在关键字while的小括号的后面,一定要加分号“;”,千万不能忘记,它表示do-while语句到此结束。例5.2求:n!,即计算1×2×3×…×n的值。源程序如下:main

(

){

int

i,

n,

s;i

=1;s

=1;printf

(

"Please

input

n:

"

);scanf

("%d",

&n

);do{

s

=

s*i

;/*使用“累乘”的公式*/i++;

}while

(

i<=n);printf

("%d!=

%d\n",

n,

s

);}说明(1)存放累乘求和的变量s,说明后必须赋初值,一般为1,否则由于说明的变量其原有初值不确定,导致结果有误。(2)程序中s

=s*i;语句是一个累乘求和功能的语句,它是将变量s中的数值乘上变量i中的数值,累乘后再放入变量s中,此时变量s中存放的数值已经变为新的数值,原有数值已被覆盖掉。以上程序运行情况如下:Please

input

n

:

5↙5!=1205.2.3

for循环语句•for循环语句的形式如下:

for(表达式1;表达式2;表达式3)循环体语句for语句的执行过程如图5-3所示。图5-3

for语句的执行过程说明(1)由图5-3可知,for循环语句的特点仍是“先判断,后执行循环体”。遇到for关键字,先计算表达式1的值,然后再判断表达式2的值,如其值为非0,则执行循环体语句,执行完循环体语句后,再来计算表达式3的值,然后再判断表达式2的值。如其值为0,则结束for循环语句,执行for循环语句后面的语句。(2)循环体语句仍然只能是一条语句,必要时可采用复合语句的形式。(3)此结构仍需最终使表达式2的值变为

0,以结束循环。否则将会造成“死”循环。(4)for语句的表示形式相当灵活,其中:表达式1和表达式3均可省略,但一定要确保表达式2最终值等于0。表达式1或表达式3省略后,其分号“;”必须有,不能省略,即:for(;表达式2;)循环体语句

(5)通常情况下:表达式1代表循环控制

变量的初值,表达式2代表循环控制变量的终值,而表达式3代表循环控制变量的增量,例如:求

n!,可简单表示成:s=1;for(i=1;i<=n;i++)s=s*i;5.2.4三种循环语句的比较

for循环和while循环语句结构均是先判断循环条件,条件成立,才执行循环体,具有“先判断,后执行”特点;而do-while循环语句则

是先执行循环体,然后再判断循环条件,具有

“先执行,后判断”的特点。5.3解决多重循环的问题5.3.1三种循环语句的混合嵌套问题例5.8求2~100之间的所有素数,并输出。问题分析

判断一个数是否是素数的方法,我们在前面已经介绍了。设某一个数为a,判断该数是否为素数,就是用这个数分别被2~去除,如果都不能被除尽,则该数为素数,如有一次被除尽,则该数就不是素数。现需求2~100之间的所有素数,判断素数的方法是相同的,只要利用循环依次从2~100之间取一个数,判断是否是素数,如是素数就输出显示,不是素数就继续判断下一个数,直至判断到100为止。源程序如下:#

include

"math.h"main

(

){

int

n,

i,

j,

flag,

x=0;for

(

i=2;

i<=100;

i++){

flag=1;

j=2;n=(int)sqrt((double)i

);while

(

flag

&&

j<=n

){

if

(

i%j=

=0

)

flag=0;j++;}if

(

flag

){

printf

("%d

,

",

i

);

x++;if

(

x%5==0

)

printf

("\n");}}}

程序运行时,当i=2或3时,变量j的初值也为2,大于变量n的值,内嵌的while循环不执行,

flag变量值为1,输出素数2或3;当i>3时,进入内层循环,若i为素数,flag的值不变,仍为1,若i不是素数,flag的值变为0,并立即结束内循环。当退出内循环后,if语句判断flag的值为1时,输出素数i;若i不是素数,flag的值变为0,不做

输出。

外层循环继续取下一个数,通过内层循环判断是否是素数,直到外层循环取的数i大于

100后,结束外层循环,结束程序运行。

通过以上例子我们看到,外层循环的目的

是,每次循环分别从2~100的数中取某一个数,已知循环的次数为99次,采用for循环比较合适;而内层循环是判断某个数是否是素数,在每一

次的除法中,当某一次除法运算出现余数为0时,表明该数不是素数,立即结束内层循环,所以

内层循环次数事先难以确定,因此采用while循环最为适当。

在解决多重循环问题时,往往需要具体问题具体分析,根据实际问题的内容和特点,采

用不同的循环结构。因此在解决多重循环问题

时,三种循环结构并举,适合哪一种循环结构,就采用哪一种循环结构。读者可在实践过程中

灵活使用。5.3.2

continue语句和break语句在循环中的应用1.Continue语句continue语句的一般形式:continue;

该语句的功能是:结束本次循环。也就是说,不管在该语句的后面是否还有其他执行语句,遇到continue;语句,本次循环到此结束,接着进行下一次循环的判断。例5.9将10~100之内的不能被5整除的数输出。源程序如下:main

(

){

int

n;for

(

n=10;

n<=100;

n++

){

if

(

n%5==0

)continue;printf

("%d

",

n

);}}

程序运行时,当n能被5整除时,将执行

continue;语句,这次循环到此结束,不再执

行printf("%d",n);语句,只有当n不能被5整除时,才执行printf("%d",n);语句。2.Break语句break语句的一般形式是:break;

在循环结构中使用break;语句,可强制结束循环。不管循环条件是否成立,都将跳出它

所在的本重循环,结束本重循环的执行。注意:它不能跳出多重循环,只能跳出本重循环。例5.10使用break语句的例子。源程序如下:main

(

){

int

i,

s;s=0;for

(

i=1;

i<=10;

i++

){

s=s+i;if

(

s>5

)

break;printf

("s=%d\n",

s

);}}此例中,如果没有break语句,则循环将执行10次;而含有break语句后,当循环执行到第3次时,i等于3,s的值为6,if语句的条件成立,将会执行到break语句,于是for循环到此结束,提前终止了循环。break语句只能用于循环语句和switch语句中。break语句是终止循环,而continue语句只是结束本次循环,两条语句功能不同,请不要混淆。6.1问题的提出

我们曾经在第1章的结构化程序设计问题中提出,解决复杂问题的方法应该采用“模块化的设计”思想,把一个庞大的应用程序分解成若干个程序模块,每一个程序模块实现一个特定的功能。在C语言系统中,“模块化的设计”使用的是函数,我们可以将每一个程序模块,编写出对应的函数,从而实现“模块化的设计”。

因此,我们可以说C程序是由函数所构成的。但是不管程序中包含有多少个函数,程序中必须要有一个主函数main(),而且只能有一个主函数。程序的执行总是从主函数main()开始,主函数再调用其他函数,其他函数之间也可以互相调用,但是其他函数不能调用主函数。

函数分为系统函数和用户自定义函数。C语言系统已将一些常用的功能模块编写成函数,

放在标准的函数库中提供给用户使用,这类函

数属于系统函数,例如:printf函数、scanf函数等,我们在前面已经大量使用了。除此之外,

用户根据自己的需要而编写的函数我们称为用

户自定义函数。这一章所介绍的就是有关用户

自己定义函数的问题,包括函数的定义、函数

的调用和函数的说明等问题。6.2函数的定义6.2.1函数的定义形式•••函数定义的形式为:

类型说明符函数名(类型名形参1,类型名形参2,…){声明部分执行部分}

我们前面编写完成各种功能的主函数main(),就是这样一种形式,只不过根据实际情况没有包含函数名前的类型说明符和函数名后面圆括号中的形参。因此函数的定义我们不该陌生。只是有些问题需向读者说明。6.2.2函数的返回值

当函数运行结束后,若需要将函数运行的结果返回到原调用函数的地方,如何实现呢?它是通过return语句实现的。return语句的形式如下:return表达式;或

return

(表达式);6.3函数的调用6.3.1函数原型说明

一般来说,调用函数时必须遵循“先说明,后调用”的原则。函数原型说明用来告诉编译

系统被调用函数的函数值类型,以及函数的参

数情况。6.3.2函数的调用函数调用的一般形式是:函数名(实参表)

其中:实参表是由实际参数(实际数据)组成,多于一个实参时,用逗号分开,它们的类型、个数和顺序同定义函数或说明函数时的形参表要一致。实参的形式既可以是变量,也可以是常量,也可以是表达式。6.4函数的嵌套调用函数的嵌套调用是指在调用一个函数的过程中,被调用的函数又去调用另一个函数,这种方式就称为函数的嵌套调用。7.1地址和指针的概念7.1.1地址和指针的概念1.“地址”的概念2.存储单元“地址”的表示3.“指针”的概念7.1.2为什么使用指针

使用指针,实现了“间接访问”变量,这只是一个过程,其实质是可以达到方便地引用

数组,提高计算机的运行效率,调用函数时可

以修改或返回多个参数值,还可以描述更复杂

的数据结构,……为了加深读者对指针重要性的理解,下面我们举一函数调用的实例。例7.1欲想调用fun函数,计算出两个数相加和相减的值,然后在main函数中显示结果。程序如下:fun

(

int

x

,

int

y

){

int

add=0

,

sub=0

;add=x+y

;sub=x–y

;}main

(

){

int

a

,

b

,

add=0

,

sub=0

;scanf

(

"

%d

%d

"

,

&a

,

&b

)

;printf

(

"

a=%d

,

b=%d

\n

"

,

a

,

b

)

;fun

(

a

,

b

)

;printf

(

"

%d

+

%d

=%d

\n

"

,

a

,

b

,

add

)

;printf

(

"

%d

%d

=%d

\n

"

,

a

,

b

,

sub

)

;}假设程序运行时给变量a输入8,给变量b输入5,程序运行结果:a=8

,

b=58

+

5=08

5=0

程序运行结果与我们“想象”的不一致,为什么呢?其原因是fun函数中变量add和sub与main函数中变量add和sub各自占用自己的存储单元,因此fun函数中变量add存放的两个数的求和值无法传回到main函数的变量add中,

同理,fun函数中变量sub存放的两个数的相减值也无法传回到main函数的变量中。下面我们修改一下源程序,借助指针,将fun函数中运行的结果传回到main函数中。7.2指针变量的定义和指针变量的基类型7.2.1指针变量的定义和指针变量的基类型定义指针变量的一般形式如下:类型名*指针变量名1,*指针变量名2,……;例如:int

*pi,*pj;以上定义语句中,pi和pj都是用户标识符,表示具体的变量名,现在每个变量名前加一星

号“*”说明符,用来说明所定义的变量是指针

变量。注意:变量名前的星号“*”不可省略,若省略了星号“*”说明符,就变成了普通整型变量。int是数据类型名,在这里,说明了pi和pj是两个指向整型(int类型)变量的指针,也就是说变量pi和pj中只能存放int类型变量的地址,这时我们称int是指针变量pi和pj的基类型。又如:double

*pd

;char

*s1

,

*s2

;在这里定义了三个指针变量pd、s1和s2,其中指针变量pd的基类型为double类型,在指

针变量pd中,只能存放double类型变量的地址,指针变量s1和s2的基类型为char类型,在指针

变量s1和s2中只能存放char类型变量的地址。

又如:int

**p

;以上是定义了一个指向指针的指针变量p,该指针变量p只能存放基类型为int类型的指针变量的地址。又如:int

*pi

,

**p

,

k

;以上语句是在同一语句中,同时定义了指针变量pi、指向指针的指针变量p和变量k,这是允许的。7.2.2指针变量的基类型的作用•

任何一个指针变量都是用于存放它所指向变量的地址,只要能存放地址就可以了,为何还要区别不同的基类型呢?其原理是:不同的数据类型变量,C语言系统为它们开辟的存储空间的字节数是不同的,int类型的数据存储空间是2个字节,float类型的数据存储空间是4个字节,……,系统表

示每一个存储空间的地址时,是取该存储空间

的第1个字节的地址作为该变量存储空间的地址。那么当一个基类型为int类型的指针变量p指向了一个int类型的变量a时,是将该变量a所占的2个字节的存储空间中的第1个字节存储空间的“地

址”存入指针变量p中,如图7-2(b)所示。图7-2指针和指针所指向的对象所以根据指针变量p中存放的“地址”,

只能寻找到变量a第1个字节的存储空间,如果

只提取变量a所占存储空间第1个字节的数据,

显而易见不是int类型变量a的原值,因为变量a的原值是通过2个字节来存储的数据。此时我们

可以通过指针变量p的基类型解决问题,知道了

变量a的第1个字节的地址,再根据指针变量p的基类型为int类型,系统就将从变量a的第1个字

节所在的地址开始,连续提取2个字节中的数据,此时的数据就是int类型变量a的原值。同理,基类型为float类型的指针变量,根据指针变量中存放float类型变量的地址值,可

以寻找到所需存储空间中的第1个字节所在位置,然后再根据基类型为float类型,连续地提取4个字节中的数据,作为被访问的数据,这才是

float类型变量中存放的真实数据。由此,我们

可以看到指针变量在定义时,其基类型是何等

的重要。因此,定义什么样的基类型指针变量,该指针变量只能存放什么样类型变量的地址,

两者必须一致,否则就可能出现了张冠李戴的

错误现象。7.3给指针变量赋值7.3.1使指针指向一个对象

1.通过求地址运算符(&)把一个变量的地址赋给指针变量

“&”是求地址运算符,该运算符为单目运算符,用于求变量的地址,且该变量必须为内存变量。例如:int

k=1,j=2,*q1,*q2,*p;float

x=4.5

;q1=&k

;q2=&j

;以上第三条语句,是把变量k的地址赋给了指针变量q1,使指针变量q1中存放了变量k的地址,或称指针变量q1指向了变量k。同理,以上第四条语句,是把变量j的地址赋给了指针变量q2,使指针变量q2中存放了变量j的地址,或称指针变量q2指向了变量j。注意:在使用&运算符求变量的地址,并赋给指针变量时,一定要确保所求地址的变量数据类型与存放该变量地址的指针变量基类型一致。接上例,如执行p=&x;语句,则是绝对错误的。为什么?请读者想一想!读者还记得在前面调用scanf函数时,其函数调用格式中,输入数据所对应的各变量名之前都必须加运算符&,这就是我们所说的求地址运算符。scanf函数把从终端读入的数据依次放入这些地址所代表的存储单元中,也就是说scanf函数要求输入项是地址值。因此接上例,

scanf("%d%d",&k,&j);语句和scanf("%d%

d",q1,q2);语句是等价的,都是将终端输入

的整型数据存入到变量k和变量j所在的存储单元

中。2.同类型指针变量之间可以直接赋值••

可以把指针变量的值赋给指针变量,但一定要确保这两个指针变量的基类型是相同的。接上例:p=q1;执行以上语句后,使指针变量p也存放了变量k的地址,也就是说指针变量p和q1同时指向了变量k。7.3.2给指针变量赋“空”值

为了使指针变量有一确定的数值,除了给指针变量赋一地址值外,当指针变量没有指向的对象时,也可以给指针变量赋NULL值,此值为空值。例如:int

*p;p=NULL;表示指针变量

p的值为空。NULL是在stdio.h头文件中定义的预定义符,因此在使用NULL时,应该在程序的前面出现预定义命令行:#include"stdio.h"。NULL的代码值为0,所以语句p=NULL;等价于:p=0;,都是表示指针变量p是一个空指针,没有指向任何对象。7.4对指针变量的操作7.4.1通过指针或地址引用一个存储单元

当指针变量中存放了一个确切的地址值时,通过指针可以用“间接运算符”(*)来引用该地址所代表的存储单元。

1.在赋值号右边由“*”运算符和指针变量组成的表达式,代表指针所指存储单元的内容例如:int

*p,i=10,j;p=&i

;j=*p

;第二条语句是把变量i的地址赋给了指针变量p,第三条语句是把指针变量p所指向的变量i存储单元的值10赋给变量j。“*”号在这里是一个“间接运算符”,它为单目运算符,与运算对象自右至左结合,且运算对象必须为一个地址对象。例如:j=*&i;该语句中“&”运算符求出变量i的地址,

“*”运算符取变量i地址中的值10赋给变量j。例如:int

**pp,*p,k=20,j;p=&k

;pp=&p

;j=**pp

;以上语句执行后的结果是:把变量k的地址赋给了指针变量p,把指针变量p的地址赋给了

指向指针的指针变量pp,这种关系如图7-4所示。最后一条语句是把变量k中的值20赋给了变量j,这条语句使用了两个“间接运算符”,**p表示获取指针变量p中的值(此值为变量k的地址值),**pp表示通过指针变量p,再获取变量k中的值20。图7-4变量pp、p和k之间的关系

2.在赋值号左边由“*”和指针变量组成的表达式,代表指针所指的存储单元例如:int

*p,k=0;p=&k

;*p=150

;以上第三条语句是把整数150存入变量k中。*p=*p

+1

;

*p+=1

;以上语句是获取指针变量p所指向的存储单元k中的值150,然后加1再放入指针变量p所指向的存储单元k中,此时变量k中存放的数值为151。例如:int

**p,*p,k;p=&k

;pp=&p

;**pp=200

;以上第四条语句是将整数200存入变量k中。例7.3指针指向三个变量,通过指针运算选出数值最小的那个数并打印出来。main(){

int

a

,

b

,

c

,

min

,

*pa

,

*pb

,

*pc

,

*pmin

;pa=&a

;pb=&b

;

pc=&c

;

pmin=&min

;scanf

(

"

%d

%d

%d

"

,

pa

,

pb

,

pc

)

;/*将键盘输入的三个整数依次放入变量a、b、c中*/printf

(

"

a=%d

,

b=%d

,

c=%d

\n

"

,

a

,

b

,

c

)

;

*pmin=*pa;/*假定变量a中的数值最小,将其放入变量min

*/if

(*pmin>

*pb

)

*pmin=

*pb

;/*若b中的数值比min小,将其放入变量min

*/if

(*pmin>

*pc

)

*pmin=

*pc

;/*若c中的数值比min小,将其放入变量min

*/printf

(

"

min=%d

\n

"

,

min

)

;/*通过直接访问方式输出变量min中的值*/printf

(

"

min=%d

\n

"

,

*pmin

)

;/*通过间接访问方式输出变量min中的值*/}当运行程序时输入25

12

36↙程序运行结果:a=25

,

b=12

,

c=36min=12min=12程序运行结果说明,当指针指向变量后,可以通过指针对所指向的存储单元进行数据的存取,直接访问方式和间接访问方式的结果是相同的。7.4.2指针(变量)的运算1.指针的移动2.指针的比较7.5指针在函数方面的应用7.5.1在被调用函数中直接改变主调用函数中的参数值

在第6章中,我们曾经介绍过,通过return语句可以返回函数值,但这种方式只能返回一个数据,若想修改或传回多个数值,可以借用指针。8.1了解一维数组8.1.1一维数组的用途8.1.2一维数组的定义••

在C语言中,数组必须先定义才可以使用。当定义数组时,要传递给编译器两方面的信息:①数组共有多少个元素?②每个元素占多少个字节?根据以上信息,编译器决定分配多大的存储空间给该数组使用。例如:int

a[10];这里a是数组的名称,方括号中的10表明数组一共有10个元素,下标应该从0开始到9结束;类型名int限定数组a的每个元素中只能存放整型数。根据这一定义,系统将为数组a开辟能容纳10个整型数的连续存储单元。一维数组定义语句的语法形式为:类型名数组名[常量表达式],……;说明(1)“类型名”决定了数组中可以存放的数据的类型。(2)“数组名”和变量名相同,必须遵循标识符的命名规则。(3)“常量表达式”代表的是数组元素的个数,也就是数组的长度。它必须是无符号整型常量,不允许是0、负数和浮点数,也不允许是变量。(4)C语言中规定:每个数组第一个元素的下标固定为0,称为下标的下界;最后一个元素的下标为元素个数减1,称为下标的上界。(5)数组的定义可以和普通变量的定义出现在同一个定义语句中。例如:float

k,x[5],y[20];以上语句在定义单精度变量k的同时,定义了两个单精度型的一维数组x和y。数组x共有

5个元素,下标的使用范围是0~4;数组y共有20个元素,下标的使用范围是0~19。8.1.3一维数组元素的引用

数组一经建立,在内存中就占据着一串连续的存储单元。8.1.4一维数组的初始化8.2一维数组的简单应用例8.1编写程序,在数组x中存储自然数1~20,然后按以下要求输出数据:①按逆序分两行输出元素值。②在一行上输出所有下标为偶数的数组元素。③在一行上输出所有值为偶数的数组元素。问题分析本例题涉及的是对数组元素进行操作的基本算法。对一维数组各元素的访问,通常是在单重循环中实现。通过循环变量与循环体内语句的配合,可以灵活地、有选择地访问指定元素。读者在阅读以下程序时,应理解数组元素下标与数组元素值的区别;掌握如何用循环变量控制数组元素的下标;以及如何在连续输出的过程中控制输出换行。源程序如下:main(

){

int

x[20],i;for(i=0;

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论