当前位置:首页 >> 院校资料 >>

C语言程序设计课件word版


程序设计语言一般分为机器语言、汇编语言和高级语言三大类。 程序设计语言一般分为机器语言、汇编语言和高级语言三大类。 1.机器语言 . 对于计算机来说,一组机器指令就是程序,称为机器语言程序。 对于计算机来说,一组机器指令就是程序,称为机器语言程序。 2.汇编语言 . 为了便于理解与记忆,人们采用能帮助记忆的英文缩写符号(称为指令助记符) 为了便于理解与记忆,人们采用能帮助记忆的英文缩写符号(称为指令助记符)来代 替机器语言指令代码中的操作码,用地址符号来代替地址码。 替机器语言指令代码中的操作码,用地址符号来代替地址码。 3.高级语言 . 机器语言和汇编语言都是面向机器的语言,一般称为低级语言。 机器语言和汇编语言都是面向机器的语言,一般称为低级语言。

程序,其功能是显示字符串“How do you do!”。 例 2.1 编写一个 C 程序,其功能是显示字符串 。 程序如下: 其 C 程序如下: #include "stdio.h" main() { printf("How do you do!\n"); ; } 程序作几点说明: 下面针对一般的 C 程序作几点说明: 语言程序可以由多个函数组成, (1)一个完整的 C 语言程序可以由多个函数组成,但必须包含一个且只能包含一个名为 ) main 的函数(主函数) 程序总是从 main 函数开始执行。 的函数(主函数) 。程序总是从 函数开始执行。 。 函数模块中,由左右花括号{ 括起来的部分是函数体 括起来的部分是函数体, (2)在一个 C 函数模块中,由左右花括号 }括起来的部分是函数体,其中的语句系列实现 ) 函数的预定功能。 函数的预定功能。 结束, (3)C 程序中的每一个语句必须以 ;”结束,但书写格式是自由的。 (4)#include 是编 ) 程序中的每一个语句必须以“; 结束 但书写格式是自由的。 ) 译预处理命令,其作用是将双引号或尖括号括起来的文件内容读到该命令的位置处 文件内容读到该命令的位置处。 译预处理命令,其作用是将双引号或尖括号括起来的文件内容读到该命令的位置处。

程序的任何位置处都可以用/* 作注释, (5)在 C 程序的任何位置处都可以用 ...... */作注释,以提高程序的可读性。 ) 作注释 以提高程序的可读性。 2.2.1 整型常量及其变量的定义 1.整型常量 . 语言中, 种类型的整型常量:基本整型常量、长整型常量、无符号整型常量。 在 C 语言中,有 3 种类型的整型常量:基本整型常量、长整型常量、无符号整型常量。 语言中,不管是哪种类型的整型常量, 种数制表示。 在 C 语言中,不管是哪种类型的整型常量,都可以用 3 种数制表示。 (1)十进制整型常量。 )十进制整型常量。 (2)十六进制整型常量。 )十六进制整型常量。 (3)八进制整型常量。 )八进制整型常量。 2.整型变量的定义 . 程序中,用于存放整型数据的变量称为整型变量 为整型变量。 在 C 程序中,用于存放整型数据的变量称为整型变量。 语言中,可以定义基本整型、长整型、 种类型的整型变量。 在 C 语言中,可以定义基本整型、长整型、短整型和无符号整型等 4 种类型的整型变量。 它们的定义方式如下。 它们的定义方式如下。 (1)基本整型变量 ) 定义基本整型变量的形式如下: 定义基本整型变量的形式如下: int 变量表列; 变量表列; (2)长整型 ) 定义长整型变量的形式如下: 定义长整型变量的形式如下: long [int] 变量表列; 变量表列; (3)短整型 )短整型 定义短整型变量的形式如下: 定义短整型变量的形式如下: short [int] 变量表列; 变量表列; (4)无符号整型 ) 定义无符号基本整型变量的形式如下: 定义无符号基本整型变量的形式如下: unsigned [int] 变量表列; 变量表列;

一个类型说明语句可以同时定义多个同类型的变量,各变量之间用逗号“, 分隔 分隔。 ① 一个类型说明语句可以同时定义多个同类型的变量,各变量之间用逗号 ,”分隔。 用类型说明语句定义的变量只是说明了为这些变量分配了存储空间,以便用于存放 ② 用类型说明语句定义的变量只是说明了为这些变量分配了存储空间,以便用于存放 与之相同类型的数据,在未对这些变量赋值前,这些变量中(即存储空间中) 与之相同类型的数据,在未对这些变量赋值前,这些变量中(即存储空间中)的值是随机 的。 语言允许在定义变量的同时为变量赋初值。 ③ C 语言允许在定义变量的同时为变量赋初值。 在为整型变量初始化或赋值时, ④ 在为整型变量初始化或赋值时,C 编译系统自动将被赋数据转换成与相应变量的类 型一致。 型一致。 由于各种整型变量所占的字节数有限,因此,它们所能存放的整数有一定的范围。 ⑤ 由于各种整型变量所占的字节数有限,因此,它们所能存放的整数有一定的范围。

实型常量及其变量的定义 1.实型(浮点型)常量 .实型(浮点型) (1)十进制数形式 ) (2)指数形式(科学记数法) )指数形式(科学记数法) 2.实型变量的定义 .

程序中,用于存放实型数据的变量称为实型变量。 在 C 程序中,用于存放实型数据的变量称为实型变量。 语言中,实型变量有单精度与双精度两种。 在 C 语言中,实型变量有单精度与双精度两种。 单精度 float 双精度 double

字符型常量及其变量的定义 1.字符型常量 . ' \n' 换行 ' \r' 回车 ' \b' 退格 ' \t' 制表(横向跳格) 制表(横向跳格) ' \'' 单引号(单撇号) 单引号(单撇号) ' \"' 双引号(双撇号) 双引号(双撇号) ' \ddd' 1~3 位八进制数所代表的 ASCII 码字符 ~ ' \xhh' 1~2 位十六进制数所代表的 ASCII 码字符 ~ ' \f' 走纸换页 ‘ \\’ 反斜杠字符 反斜杠字符 2.字符型变量的定义 . 字符型变量的定义方式如下: 字符型变量的定义方式如下: char 变量表列; 变量表列;

数据的输入与输出应包括以下几项: 数据的输入与输出应包括以下几项:

输入( ① 输入(出)的设备 输入( ② 输入(出)的格式 输入( ③ 输入(出)的内容

格式输出函数

格式输出函数的一般形式如下: 格式输出函数的一般形式如下: printf(*“格式控制 ,输出表 ; 格式控制”,输出表); 格式控制

其中格式控制部分要用一对双撇号括起来,它用于说明输出项目所采用的格式。 其中格式控制部分要用一对双撇号括起来,它用于说明输出项目所采用的格式。 1.整型格式说明符 . (1)十进制形式 ) (2)八进制形式 ) (3)十六进制形式 ) 2.实型格式说明符 .

如果以十进制数形式输出实型数据, 如果以十进制数形式输出实型数据,其格式说明符为 数形式输出实型数据 %f 或 %m.nf 如果以指数形式输出实型数据, 如果以指数形式输出实型数据,其格式说明符为

%e 或 %m.ne 3.字符型格式说明符 .

字符型数据的格式说明符为 %c 或 %mc 分隔。 (1)输出表中各输出项目之间要用 ,”分隔。 )输出表中各输出项目之间要用“, 分隔 (2)格式控制中的各格式说明符与输出表中的各输出项目在个数、次序、类型等方 )格式控制中的各格式说明符与输出表中的各输出项目在个数、次序、 面必须一一对应 须一一对应。 面必须一一对应。 (3)格式控制中除格式说明符外的其他字符将按原样输出。 )格式控制中除格式说明符外的其他字符将按原样输出。 (4)在输出格式说明符中,如果带有宽度说明,则在左边没有数字的位置上用空格填 )在输出格式说明符中,如果带有宽度说明, 即输出的数字是右对齐) 但如果在宽度说明前加一个负号(-) 则输出为左对齐, 。但如果在宽度说明前加一个负号 ,则输出为左对齐 满(即输出的数字是右对齐) 但如果在宽度说明前加一个负号(-) 则输出为左对齐, 。 , 即在右边补空格。 即在右边补空格。

格式输入函数

格式输入函数的一般形式如下: 格式输入函数的一般形式如下: scanf(“格式控制 ,内存地址表) 格式控制”, ( 格式控制 内存地址表) ; 1.整型格式说明符 . (1)十进制形式 ) 用于输入十进制形式的整型数据。 用于输入十进制形式的整型数据。 (2)八进制形式 ) 用于输入八进制形式的整型数据。 用于输入八进制形式的整型数据。 (3)十六进制形式 ) 用于输入十六进制形式的整型数据。 用于输入十六进制形式的整型数据。 2.实型格式说明符 . 用于输入的单精度实型格式说明符为 %f 或 %e 用于输入的双精度实型格式说明符为 %lf 3.字符型格式说明符 . 用于输入的字符型格式说明符为 %c 或 %mc

赋值运算 赋值运算符为“= 。 赋值运算符为 =”。赋值表达式为 变量名= 变量名=表达式 语言中, = 为赋值运算符 而不是等号; 为赋值运算符, (1)在 C 语言中,“=”为赋值运算符,而不是等号; ) 左边必须是变量名, (2)赋值运算符 =”左边必须是变量名,不能是表达式; )赋值运算符“= 左边必须是变量名 不能是表达式; 两端的类型不一致时, (3)赋值运算符“=”两端的类型不一致时,系统将自动进行类型转换。 )赋值运算符 = 两端的类型不一致时 系统将自动进行类型转换。

算术运算 语言中,基本的算术运算符有以下几个: 在 C 语言中,基本的算术运算符有以下几个: 加法运算符(双目运算符) 或正值运算符(单目运算符) ,或正值运算符 。如 + ,+ ,+x。 + 加法运算符(双目运算符) 或正值运算符(单目运算符) 如 x+y,+ 。 , 。 减法运算符(双目运算符) 或负值运算符(单目运算符) ,或负值运算符 。如 - ,- ,-x。 - 减法运算符(双目运算符) 或负值运算符(单目运算符) 如 a-3,- 。 , 。 * 乘法运算符(双目运算符) 。如 乘法运算符(双目运算符) 如 3*x。 。 。 / 除法运算符(双目运算符) 。如 。 除法运算符(双目运算符) 如 x/y。 。 % 模余运算符(双目运算符) 只适用于整型数据,如 9%4 的值为 1,11%3 模余运算符(双目运算符) 只适用于整型数据, 。只适用于整型数据 。 , 的值为 2 等。

关系运算 语言中, 在 C 语言中,基本的关系运算符有以下 6 个: < 小于 <= 小于或等于 > 大于 >= 大于或等于 == 等于 != = 不等于 结果只有两个: 结果只有两个:true 或者 false =(y== 执行 int x=2,y=3;后表达式 x=( == )的值是 1 ) = , = ; =( ==3)的值是(

逻辑运算 语言中,逻辑常量只有两种:值非零表示“真 ,值为零表示“假 。 在 C 语言中,逻辑常量只有两种:值非零表示 真”,值为零表示 假”。其基本的逻 辑运算符有以下 3 个: && (逻辑与) 逻辑与) | | (逻辑或) 逻辑或) (0) ) ! (逻辑非) 逻辑非) 一个量为真时为假( ) 假时为真( ) ,假时为真 一个量为真时为假(0) 假时为真(1) , 两个量都为真时为真( ) 否则为假( ) ,否则为假 两个量都为真时为真(1) 否则为假(0) 时为真 , 两个量中只要有一个为真时为真( ) ,只有都为假时为假 两个量中只要有一个为真时为真(1) 只有都为假时为假 ,

自增++与自减--运算符 自增++与自减--运算符 ++与自减-- 运算符“++ ++”和减 运算符“-- 是两个单目(只有一个运算对象)运算符, --”是两个单目 增 1 运算符 ++ 和减 1 运算符 -- 是两个单目(只有一个运算对象)运算符, 它们的运算对象只能是整型或字符型变量。 它们的运算对象只能是整型或字符型变量。 增 1 运算符是将运算对象的值增 1;减 1 运算符是将运算对象的值减 1。 ; 。 假设定义变量 int a= 5;int b; ; ; 前缀自增 b = ++a;// a=6 b=6 ;

后缀自增 sizeof 运算符

b = a++;// a=6 b=5 ;

sizeof 运算符有以下两种用法: 运算符有以下两种用法: (1)用于求得表达式计算结果所占内存的字节数。其一般形式为 )用于求得表达式计算结果所占内存的字节数。 sizeof 表达式 (2)用于求得某种数据类型的量所占内存的字节数。其一般形式为 )用于求得某种数据类型的量所占内存的字节数。 sizeof(类型名) (类型名)

逗号运算符 逗号“, 是 程序中常见的符号。 逗号 ,”是 C 程序中常见的符号。 语言中,逗号除作为分隔符使用外 还可以作为运算符来使用, 分隔符使用外, 在 C 语言中,逗号除作为分隔符使用外,还可以作为运算符来使用,称为逗号运 算符。 算符。

逗号表达式的一般形式为 子表达式 1,子表达式 2,…,子表达式 n , , ,

在使用逗号运算符(逗号表达式) 在使用逗号运算符(逗号表达式)时,要注意以下几点: 要注意以下几点: (1)逗号运算符是所有运算符中级别最低的一种运算符。 )逗号运算符是所有运算符中级别最低的一种运算符。 (2)一个逗号表达式又可以与另一个表达式(可以是逗号表达式,也可以不是逗号表 )一个逗号表达式又可以与另一个表达式(可以是逗号表达式, 达式)连接成新的逗号表达式。 达式)连接成新的逗号表达式。 (3)在许多情况下,使用逗号表达式的目的仅仅是为了得到各个子表达式的值,而并不 )在许多情况下,使用逗号表达式的目的仅仅是为了得到各个子表达式的值, 一定要得到或使用整个逗号表达式的值。 一定要得到或使用整个逗号表达式的值。 C 语言中的宏定义有两种形式:符号常量定义与带参数的宏定义。 语言中的宏定义有两种形式:符号常量定义与带参数的宏定义。

符号常量定义 语言中,允许将程序中多处用到的“字符串 定义成一个符号常量。 字符串”定义成一个符号常量 在 C 语言中,允许将程序中多处用到的 字符串 定义成一个符号常量。在 C 语言中定 义符号常量的一般形式如下: 义符号常量的一般形式如下: #define 符号常量名 字符串 语言中的所有变量名、函数名等都使用小写字母,因此, ① 由于 C 语言中的所有变量名、函数名等都使用小写字母,因此,符号常量名一般用大写 字母表示, 语言中的保留关键字相区别。 字母表示,以便与 C 语言中的保留关键字相区别。 编译系统对定义的符号常量的处理只是进行简单的替换,不作任何语法检查。 ② C 编译系统对定义的符号常量的处理只是进行简单的替换,不作任何语法检查。 是一个命令,而不是语句,因此在行末不能加“; , ③ #define 是一个命令,而不是语句,因此在行末不能加 ;”,并且应独立占一 行。 命令一般应出现在程序中函数的外面, ④ #define 命令一般应出现在程序中函数的外面,其作用域范围是从 #define 符号常量名 字符串 到

#undef 符号常量名 或文件末) 符号常量名(或文件末 或文件末

带参数的宏定义

带参数的宏定义的一般形式为 #define 宏名(参数表) 字符串 宏名(参数表)

其中字符串中应包含在参数表中所指定的参数, 并且, 当参数表中的参数多于一个时, 其中字符串中应包含在参数表中所指定的参数, 并且, 当参数表中的参数多于一个时, 各参数之间要用逗号分隔。 各参数之间要用逗号分隔。

在使用带参数的宏定义时,应注意以下两个问题。 在使用带参数的宏定义时,应注意以下两个问题。 的宏定义时, (1)在使用带参数的宏定义时,一般应将宏定义字符串中的参数都要用括号括起来,否则 )在使用带参数的宏定义时 一般应将宏定义字符串中的参数都要用括号括起来, 经过宏展开后,可能会出现意想不到的错误。 经过宏展开后,可能会出现意想不到的错误。 (2)在使用带参数的宏定义时,除了应将宏定义字符串中的参数都要用括号括起来,还需 )在使用带参数的宏定义时,除了应将宏定义字符串中的参数都要用括号括起来, 要将整个字符串部分也要用括号括起来,否则经过宏展开后, 要将整个字符串部分也要用括号括起来,否则经过宏展开后,还会可能出现意想不到的错 误。

书写一个求最大值的宏定义 # define MAX(a , b) ((a>b)? (a) ,(b))

3.1 语句与复合语句 语言中,一个表达式后面跟随一个分号就构成了一个语句, 在 C 语言中,一个表达式后面跟随一个分号就构成了一个语句,这种语句称为表 达式语句。 达式语句。 语言中,分号(; 是表达式语句的终结符,而不是语句之间的分隔符, )是表达式语句的终结符 在 C 语言中,分号(; 是表达式语句的终结符,而不是语句之间的分隔符,也就 ) 是说,分号是表达式语句的一个组成部分,只不过它位于表达式的后面。 是说,分号是表达式语句的一个组成部分,只不过它位于表达式的后面。

在一个函数体内部,由左、右花括号括起来的语句称为复合语句, 在一个函数体内部,由左、右花括号括起来的语句称为复合语句,它的一般形式为 {说明部分;语句部分;} 说明部分; 说明部分 语句部分; 3.2 if 语 句

If 语句的形式为 if (表达式) 语句 表达式) 所示。 这种选择结构的流程图如图 3.1 所示。

语句作几点说明: 下面对 if 语句作几点说明: 对圆括号括起来。 (1)if 语句中的逻辑表达式(即条件)必须要用一对圆括号括起来。 ) 语句中的逻辑表达式(即条件)必须要用一对圆括号括起来 (2)if 语句后的语句可以是复合语句。 ) 语句后的语句可以是复合语句。 (3)一个 if 语句 ) 最后需要强调的是, 语句时,一定要注意逻辑表达式的正确写法, 最后需要强调的是,在使用 if 语句时,一定要注意逻辑表达式的正确写法,特别是在连 语句时更要注意。 续使用多个 if 语句时更要注意。 3.3 if…else 结构 语言中, 在 C 语言中,if…else 结构的语句形式为 if (表达式) 语句 1 表达式) else 语句 2

结构作以下几点说明: 下面对 if…else 结构作以下几点说明: 都可以是复合语句 (1)if…else 结构中的语句 1 与语句 2 都可以是复合语句。 ) 结构中, 都可以是空语句。 (2)在 if…else 结构中,语句 1 与语句 2 都可以是空语句。 )

结构中, 语句, 配对。 (3)在 if…else 结构中,如果在 else 前面有多个 if 语句,则 else 与最近的 if 配对。 ) 结构嵌套如下: (4)如果有多个 if……else 结构嵌套如下: ) if (表达式 1) 语句 1 表达式 else if (表达式 2) 语句 2 ) else … else if (表达式 n) 语句 n ) else 语句 n+1 + 则可简写成 则可简写成 if (表达式 1) 语句 1 ) else if (表达式 2) 语句 2 ) … else if (表达式 n) 语句 n ) else 语句 n+1 +

结构中, 都是单一的赋值语句, 并且都是给同一个变量赋值, 在 if…else 结构中, 如果语句 1 与语句 2 都是单一的赋值语句, 并且都是给同一个变量赋值, 则可以用条件运算符来进行处理。 则可以用条件运算符来进行处理。

下面对条件表达式作几点说明: 下面对条件表达式作几点说明: (1)条件运算符优先级要比赋值运算符高。 )条件运算符优先级要比赋值运算符高。 (2)条件运算符的优先级比关系运算符与算术运算符都要低,因此,条件表达式中的 表 )条件运算符的优先级比关系运算符与算术运算符都要低,因此,条件表达式中的“表

都不必用括号括起来。 达式 1”、“表达式 2”与“表达式 3”都不必用括号括起来。 、 表 与 表达式 都不必用括号括起来 从右到左”。 (3)条件运算符的结合方向为 从右到左 。 )条件运算符的结合方向为“从右到左 语言中提供了一个直接实现多路分支选择的结构, 结构, 其一般形式如下: 在 C 语言中提供了一个直接实现多路分支选择的结构, 称为 switch 结构, 其一般形式如下: switch(表达式 表达式) 表达式 { case 常量表达式 1: 语句 1 case 常量表达式 2: 语句 2 … case 常量表达式 n: 语句 n default : 语句 n+1 + }

结构作几点说明: 下面对 switch 结构作几点说明: 结构中的表达式、 必须是整型或字符型。 (1)switch 结构中的表达式、常量表达式 1、…Λ、常量表达式 n 必须是整型或字符型。 ) 、 Λ 这是因为, 结构中,其分支数一般是有限的,并且是离散的,因此, 这是因为,在 switch 结构中,其分支数一般是有限的,并且是离散的,因此,其表达式的 值也应是有限的,且是离散的。 值也应是有限的,且是离散的。 结构中的常量表达式值必须互不相同,否则就会出现矛盾的现象, (2)同一个 switch 结构中的常量表达式值必须互不相同,否则就会出现矛盾的现象,即 ) 对于“表达式 的同一个值对应多种执行方案,这是错误的。 表达式”的同一个值对应多种执行方案 对于 表达式 的同一个值对应多种执行方案,这是错误的。 结构中, case 与 default 的顺序可以任意, case 之间 的顺序也可以任意。 的顺序可以任意, 的顺序也可以任意。 (3) switch 结构中, ) 在 各 结构时, 后的语句后 将顺序执行后面 case 后的语句, 后的语句, (4) ) 在执行 switch 结构时, 当执行完某 case 后的语句后, 结构的执行。 直到遇 break 语句才退出整个 switch 结构的执行。 结构中, 表达式”值不等于任何 (5)在 switch 结构中,如果没有 default 且“表达式 值不等于任何 case 后常量表达式的 ) 表达式 结构而转到其后的语句执行。 值,则直接退出 switch 结构而转到其后的语句执行。

计算奖金。 例 3.12 计算奖金。 万元时, 当企业利润 P 等于或低于 0.5 万元时,奖金为利润的 1%;当 0.5<P≤1 万元时, ; < ≤ 万元时, 计算; 超过 0.5 万元部分的奖金为利润的 1.5%,0.5 万元以下仍按 1%计算;当 1<P≤2 万元时, , 计算 < ≤ 万元时, 1 万元以下部分仍按前面的方法计算, 万元以下部分仍按前面的方法计算, 计算; 超过 1 万元的部分其奖金按利润的 2%计算; 2<P 计算 当 < 万元时, 万元以下部分仍按前面的方法计算, ≤5 万元时,2 万元以下部分仍按前面的方法计算,超过 2 万元部分的奖金按利润的 2.5% 计算; 计算;当 5<P≤10 万元时,5 万元以下部分仍按前面的方法计算,超过 5 万元部分的奖金 < ≤ 万元时, 万元以下部分仍按前面的方法计算, 计算; 按利润的 3%计算;当 P>10 万元时,10 万元以下部分仍按前面的方法计算,超过 10 万元 计算 > 万元时, 万元以下部分仍按前面的方法计算, 计算。 由键盘输入, 部分按 3.5%计算。其中 P 由键盘输入,计算并输出相应的奖金数 W。 计算 。

所示的流程图, 程序如下: 根据图 3.5 所示的流程图,用 if…else if 结构写出 C 程序如下: #include "stdio.h" main() { float p,w; , ; printf("input p: "); ; scanf("%f",&p); , ; if (p<= <=0.0) w=0.0; <= = ; else if (p<= <=0.5) w=0.01*p; <= = ; else if (p<= <=1.0) w=0.005+0.015*(p-0.5); <= = + - ; else if (p<= <=2.0) w=0.0125+0.02*(p-1.0); <= = + - ; else if (p<= <=5.0) w=0.0325+0.025*(p-2.0); <= = + - ; else if (p<= <=10.0) w=0.1075+0.03*(p-5.0); <= = + - ; else w=0.2575+0.035*(p-10.0); = + - ; printf("w=%f\n",w); = , ; } 例 3.14 求解一元二次方程 Ax2+Bx+C=0。 + + = 。

程序如下: 相应的 C 程序如下: #include "stdio.h" #include "math.h" main() { double a,b,c,d,x1,x2,p; , , , , , , ; printf("input a,b,c: "); , , ; scanf("%lf%lf%lf",&a,&b,&c); , , , ; if (a== ==0.0) == { if (b== ==0.0) printf("ERR\n"); == ; else printf("X=%f\n",- ,-c/b); = ,- ; } else if (b== ==0.0) == { d=c/a; = ; if (d<= <=0.0) <= { printf("X1=%f\n",sqrt(-d)); = , - ; printf("X2=%f\n",- ,-sqrt(-d)); = ,- - ; } else { printf("X1=+j%f\n",sqrt(d)); = , ; printf("X2=- =-j%f\n",sqrt(d)); =- , ; } else if (c== ==0.0) == { printf("X1=0.0\n"); = ; printf("X2=%f\n",- ,-b/a); = ,- ;

} else { d=b*b-4*a*c; = - ; if (d>= >=0.0) >= { d=sqrt(d); = ; if (b>0.0) x1=(-b-d)/(2*a); > =- - ; else x1=(-b+d)/(2*a); =- + ; x2=c/(a*x1); = ; printf("X1=%f\n",x1); = , printf("X2=%f\n",x2); = , ; } else { d=sqrt(-d)/(2*a); = - ; p=- =-b/(2*a); =- ; printf("X1=%f+j%f\n",p,d); = + , , ; printf("X2=%f-j%f\n",p,d); = - , , ; } } }

4.1.1 当型循环结构 所示。 当型循环结构的流程图如图 4.1 所示。 while 循环

实现当型循环结构的 C 语句形式为 while (表达式 循环体语句 表达式) 表达式 功能:当表达式值≠ 执行循环体,执行完后继续判断表达式值, 功能:当表达式值≠0 时,执行循环体,执行完后继续判断表达式值,只有当表达式 时才退出循环。 值=0 时才退出循环。

从键盘输入各学生成绩, 分以上( 的学生人数进行计数, 例 4.2 从键盘输入各学生成绩,并对 90 分以上(包括 90 分)的学生人数进行计数,直到 输入的成绩为负为止, 分以上的学生人数 上的学生人数。 输入的成绩为负为止,最后输出成绩在 90 分以上的学生人数。 所示。 为整型, 分以上的学生人数进行计数。 其流程图如图 4.3 所示。其中变量 count 为整型,用于对 90 分以上的学生人数进行计数。

程序如下: 相应的 C 程序如下: #include "stdio.h" main() { int count; ; float grade; ; count=0; = ; scanf("%f",&grade); , ; while (grade>= >=0.0) >= { if (grade>= >=90.0) count=count+1; >= = + ; scanf("%f",&grade); , ; } printf("count=%d\n",count); = , ; }

直到型循环结构 所示。 直到型循环结构的流程图如图 4.4 所示。 do__while 循环

do_ while 循环的执行过程是,首先执行循环体,然后判断条件(即计算逻辑表达式) 如果 循环的执行过程是,首先执行循环体,然后判断条件(即计算逻辑表达式) ,如果 , 条件满足(即逻辑表达式值为真) 则退出循环结构;如果条件不满足( ,则退出循环结构 条件满足(即逻辑表达式值为真) 则退出循环结构;如果条件不满足(即逻辑表达式值为 , ,则继续执行循环体 假) 则继续执行循环体。 ,则继续执行循环体。 实现直到型循环结构的 C 语句形式为 do 循环体语句 while(表达式) (表达式) ; 功能:先执行循环体,然后判断表达式值,若表达式值≠ ,则再次执行循环体, 功能:先执行循环体,然后判断表达式值,若表达式值≠0,则再次执行循环体,如 循环,直到表达式值= 为止。 此循环,直到表达式值=0 为止。 计算并输出下列级数和: 例 4.3 计算并输出下列级数和:

1 1 (?1) K SUM = 1 ? + ?L+ +L 1× 2 2 × 3 K ( K + 1)
直到某项的绝对值小于 10 ?4 为止 所示。 用于改变每一项的符号, 相应的流程图如图 4.5 所示。其中 f 用于改变每一项的符号,因为这是一个各项符号相间的 级数。 级数。

程序如下: 相应的 C 程序如下: #include "stdio.h" main() { int k; ; double sum,d,f; , ,; sum=1.0; k=1;f=1.0; = ; = ;= ; do { k=k+1;f=- ;d=1.0/(k*(k+1));sum=sum+f*d; } =-f; = = + ; =- + ; = + ; while(d>= >=1.0e-4); >= - ; printf("sum=%lf\n",sum); = , ; }

当型循环结构与直到型循环结构的区别与联系

当型循环结构与直到型循环结构既有共同之处,又有区别。 当型循环结构与直到型循环结构既有共同之处,又有区别。主要体现在以下几个 方面。 方面。 循环中,其循环体可以一次也不执行( 循环结构的一开始, (1)在 while 循环中,其循环体可以一次也不执行(即执行 while 循环结构的一开始,其 ) 条件就不满足) 循环结构, 条件就不满足) (2)不管是 while 循环结构还是 do—while 循环结构,在循环体内部必 。 ) 须要有能改变条件(即逻辑表达式值 的语句,否则将造成死循环。 即逻辑表达式值)的语句 须要有能改变条件 即逻辑表达式值 的语句,否则将造成死循环。 循环结构来处理 构来处理, 循环结构来处理。 (3)对于有些问题既可以用 while 循环结构来处理,也可以用 do—while 循环结构来处理。 ) 循环结构,其循环体如果包含一个以上的语句, (4)不管是 while 循环结构还是 do—while 循环结构,其循环体如果包含一个以上的语句, ) 应以复合语句形式出现。 应以复合语句形式出现。

C 语言提供的 for 循环属于当型循环结构,其一般形式为 循环属于当型循环结构,

for(表达式 1;表达式 2;表达式 3) 循环体语句(组) ( ; ; ) 循环体语句( 它等价于下列的当型循环结构: 它等价于下列的当型循环结构: 表达式 1; ; while(表达式 2) ( ) { 循环体语句 表达式 3; ; } 循环语句作几点说明: 下面对 for 循环语句作几点说明: 语句中,三个表达式中的任何一个表达式均可省略 但其中的两个“; 不能 (1)在 for 语句中,三个表达式中的任何一个表达式均可省略,但其中的两个 ;”不能 ) 省略。 省略。 (2)下列两个循环都是死循环: )下列两个循环都是死循环: for(表达式 1; 表达式 3) 循环体 ;表达式 表达式 ; ; 与 for(; ;) ; ; 循环体 因为它们都没有用于判断循环是否结束的条件( 因为它们都没有用于判断循环是否结束的条件(即表达式 2) ) 。 (3)for 循环本质上 ) 也是当型循环结构,只不过它对于事先可以确定循环次数的问题特别方便。 也是当型循环结构,只不过它对于事先可以确定循环次数的问题特别方便。 循环中,循环体也可以是复合语句(即用一对花括号{ 括起来的语句组 。 括起来的语句组) (4)在 for 循环中,循环体也可以是复合语句(即用一对花括号 }括起来的语句组) )

循环的嵌套 所谓循环的嵌套是指一个循环体内又包含了另一个完整的循环结构。 语言允许循环 所谓循环的嵌套是指一个循环体内又包含了另一个完整的循环结构。C 语言允许循环 结构嵌套多层。循环的嵌套结构又称为多重循环。 结构嵌套多层。循环的嵌套结构又称为多重循环。 以内(包括 所有自然数的阶乘值。 例 4.6 计算并输出 10 以内 包括 10)所有自然数的阶乘值。即计算 1!,2!,3!,4!,5!,6!, 所有自然数的阶乘值 , , , , , , 7!,8!,9!,10!。 , , , 。 采用的方法是, 以内的每一个自然数分别求它们的阶乘值。 所示。 采用的方法是,对于 10 以内的每一个自然数分别求它们的阶乘值。其流程图如图 4.7 所示。 显然,这是一个二重循环结构。 显然,这是一个二重循环结构。

程序如下: 相应的 C 程序如下:

#include "stdio.h" main() { int n,k; , ; double s; ; for (n=1; n<= ; n=n+1) <=10; = + = ; <= { s=1.0; = ; for (k=1; k<= ; k=k+1) s=s*k; <=n; = + = ; <= = ; printf("%2d!=%16.7f\n ",n,s); = , , ; } } break 语句 C 语言中的 break 语句有以下两个功能: 语句有以下两个功能: 结构; (1)跳出 switch 结构; ) 结构、 循环结构。 (2)退出当前循环结构,包括 while 结构、 do…while 结构和 for 循环结构。 )退出当前循环结构, continue 语句 continue 语句的功能是结束本次循环的执行,但不退出循环结构。 语句的功能是结束本次循环的执行,但不退出循环结构。 语句的使用。 下面举两个例子来说明 continue 语句的使用。 整除的自然数。 例 4.10 输出 100~200 之间所有能被 7 或 9 整除的自然数。 ~ 程序如下: 相应的 C 程序如下: #include "stdio.h" main() { int n; ; for (n=100; n<= ; n=n+1) <=200; = + = ; <= { if (n%7!=0)&&(n%9!=0)) continue; /*结束本次循环,继续进行下次循环 结束本次循环, = = ; 结束本次循环 继续进行下次循环*/ printf("%d \n",n); , ; }

实际上, 实际上,上述程序等价于 #include "stdio.h" main() { int n; ; for (n=100; n<= ; n=n+1) <=200; = + = ; <= { if (n%7== | | (n%9== ==0) ==0)) printf("%d \n",n); == == , ; } }

5.1.1 函数的概念 语言中,函数分为以下两种。 在 C 语言中,函数分为以下两种。 (1)标准库函数 ) 这种函数用户不必定义, 但可直接使用。 这种函数用户不必定义, 但可直接使用。 例如 scanf() , printf() , fabs() , sqrt() , exp(),sin(),cos()等都是 C 语言中常用的库函数。 , , 等都是 语言中常用的库函数。 (2)用户自己定义的函数 ) 这种函数用以解决用户的专门问题,一般由用户自己编写。 这种函数用以解决用户的专门问题,一般由用户自己编写。 的值( 例 5.1 从键盘输入两个正整数 m 与 n(m≥n),求 ≥ , 的值(即求 (m ? n)! 程序如下: 其 C 程序如下: #include "stdio.h" main() /*主函数 主函数*/ 主函数 { int m,n; , ; int p(); /*说明本函数中要调用的函数 p()是整型 是整型*/ ; 说明本函数中要调用的函数 是整型 scanf("%d,%d",&m,&n); , , , ; if (m>= >=n) printf("%d\n",p(m)/p(m-n)); >= , - ; else printf("m<n ! \n"); < ; } int p(k) /*计算阶乘值的函数 计算阶乘值的函数*/ 计算阶乘值的函数 int k; ; { int s,i; ,; s=1; = ; for (i=1; i<= ; i=i+1) s=s*i; <=k; = + = ; = ; <= return(s); ; } 下面对函数作几点说明: 下面对函数作几点说明: 程序可以由若干个函数组成, (1)一个完整的 C 程序可以由若干个函数组成,其中必须有一个且只能有一个主函数 ) main()。 。 (2)一个完整 C 程序中的所有函数可以放在一个文件中,也可以放在多个 ) 程序中的所有函数可以放在一个文件中, 文件中。 在编译命令行中键入各个函数所在的文件名(各文件名之间用空格分隔 。 用空格分隔) 文件中。 ① 在编译命令行中键入各个函数所在的文件名(各文件名之间用空格分隔) 语句将各函数所在的文件包含进来。 (3)C 语言中的函数 ② 在主函数中用 #include 语句将各函数所在的文件包含进来。 ) 没有从属关系,各函数之间互相独立,可以互相调用。 没有从属关系,各函数之间互相独立,可以互相调用。

m!

n Am

。 )

函数的定义 语言中, 在 C 语言中,函数定义的一般形式为

函数名(形参表列) 类型标识符 函数名(形参表列) 形参类型说明 { 说明部分 语句部分 }

函数时要注意以下几点。 在定义 C 函数时要注意以下几点。 (1)函数类型标识符同变量类型说明符,它表示返回的函数值类型。 )函数类型标识符同变量类型说明符,它表示返回的函数值类型。 (2)如果省略函数的类型标识符,则默认为是 int 型。 )如果省略函数的类型标识符, (3)C 语言允许定义空函数。如 ) 语言允许定义空函数。 dummy(){ } (4)函数中返回语句的形式为 ) return(表达式) (表达式) ; 或 return 表达式; 表达式; 形参表列”中有多个形式参数 分隔。 (5)如果 形参表列 中有多个形式参数,则它们之间要用 ,”分隔。 )如果“形参表列 中有多个形式参数,则它们之间要用“, 分隔 (6)C 语言允许在形参表中直接对形参的类型进行说明。 ) 语言允许在形参表中直接对形参的类型进行说明。

函数的调用

函数调用的一般形式为 函数名(实参表列) 函数名(实参表列) ;也可以单独作为一个语句 (1)函数调用可以出现在表达式中(有函数值返回) 也可以单独作为一个语句 无函数值 )函数调用可以出现在表达式中(有函数值返回) 也可以单独作为一个语句(无函数值 ; 返回)。 返回 。 (2)实参表中的各实参可以是表达式,但它们的类型和个数应与函数中的形参一一对应。 )实参表中的各实参可以是表达式,但它们的类型和个数应与函数中的形参一一对应。 数中, (3)在调用函数中,通常要对被调用函数的返回值类型进行说明(一般在调用函数的函数 )在调用函数中 通常要对被调用函数的返回值类型进行说明( 体中的说明部分) 包括函数类型、函数名和一对圆括号。 ,包括函数类型 体中的说明部分) 包括函数类型、函数名和一对圆括号。 , 下列程序的功能是计算输出一个圆台两底面积之和。 例 5.2 下列程序的功能是计算输出一个圆台两底面积之和。 #include "stdio.h" main() { double r1,r2; , ; double q(); ; printf("input r1 ,r2: "); ; scanf("%lf,%lf",&r1,&r2); , , , ; printf("s=%f\n",q(r1,r2)); = , , ; } double q(x,y) , double x,y; , ; { double s; ; s=3.1415926*(x*x+y*y); = + ; return(s); ; } 语言规定,在以下几种情况下可以不在调用函数中对被调用函数作类型说明: 但 C 语言规定,在以下几种情况下可以不在调用函数中对被调用函数作类型说明:

被调用函数为整型或字符型,自动按整型处理。 ① 被调用函数为整型或字符型,自动按整型处理。 被调用函数的定义出现在调用函数之前。 ② 被调用函数的定义出现在调用函数之前。 在调用函数之前已经由别的函数(它可能也要调用该被调用函数) ③ 在调用函数之前已经由别的函数(它可能也要调用该被调用函数)对被调用函数 作了类型说明。 作了类型说明。 (4)C 语言虽不允许嵌套定义函数,但可以嵌套调用函数。 ) 语言虽不允许嵌套定义函数,但可以嵌套调用函数。

形参与实参的结合方式 1.地址结合 . 所谓地址结合,是指在一个模块调用另一个模块时, 所谓地址结合,是指在一个模块调用另一个模块时,并不是将调用模块中的实参值直 接传送给被调用模块中的形参,而只是将存放实参的地址传送给形参。 接传送给被调用模块中的形参,而只是将存放实参的地址传送给形参。 2.数值结合 . 所谓数值结合,是指调用模块中的实参地址与被调用模块中的形参地址是互相独立的, 所谓数值结合,是指调用模块中的实参地址与被调用模块中的形参地址是互相独立的, 在一个模块调用另一个模块时,直接将实参值传送给形参被存放在形参地址中。 在一个模块调用另一个模块时,直接将实参值传送给形参被存放在形参地址中。

程序: 例 5.3 分析下列 C 程序: void swap(x,y) , int x,y; , ; { int t; ; t=x; x=y; y=t; = ; = ; =; return; ; } #include "stdio.h" main() { int x,y; , ; scanf("x=%d,y=%d",&x,&y); = , = , , ; swap(x,y); , ; printf("x=%d,y=%d\n",x,y); = , = , , ; } 在这个程序中共有两个函数。 输入数据, 在这个程序中共有两个函数。在主函数中分别为整型变量 x 与 y 输入数据,然后调用函数 swap(x,y)。而函数 swap(x,y)的功能是实现变量 x 值与 y 值的交换。但在实际运行该程序 值的交换。 , 。 , 的功能是实现变量 时,如果从键盘输入 x=6,y=8? = , = ? 则输出的结果为 x=6,y=8 = , = 即没有达到交换的目的。这是因为在主函数中调用函数 即没有达到交换的目的。这是因为在主函数中调用函数 swap()时,只是将实参 x 和 y 时

的值分别传递给了 swap()函数中的形参 x 和 y, 函数中的形参 , 但由于主函数中的实参 x 和 y 与函数 swap() 在计算机中的存储地址是不同的, 因此, 中的形参 x 和 y 在计算机中的存储地址是不同的, 因此, 在函数 swap()中虽然交换了形参 x 中虽然交换了形参 的值, 的值实际上没有改变,即它们没有被交换。 与 y 的值,但实参 x 与 y 的值实际上没有改变,即它们没有被交换。

由此可以看出,在形参与实参为数值结合的情况下, 由此可以看出,在形参与实参为数值结合的情况下,实参与形参在计算机内存中的存储地 址不是同一个,因此,即使在被调用函数中改变了形参值, 址不是同一个,因此,即使在被调用函数中改变了形参值,调用函数中的实参值也是不会 被改变的。 被改变的。

局部变量与全局变量 1.局部变量 . 在函数内部定义的变量称为局部变量 函数内部定义的变量只在该函数范围内有效, 定义的变量称为局部变量。 在函数内部定义的变量称为局部变量。函数内部定义的变量只在该函数范围内有效, 因此,不同函数中的局部变量可以重名,互不混淆。 因此,不同函数中的局部变量可以重名,互不混淆。 2.全局变量 . 在函数外定义的变量称为全局变量

除非十分必要,一般不提倡使用全局变量,其原因有以下几点: 除非十分必要,一般不提倡使用全局变量,其原因有以下几点: 由于全局变量属于程序中的所有函数,因此,在程序的执行过程中, ① 由于全局变量属于程序中的所有函数,因此,在程序的执行过程中,全局变量都 需要占用存储空间,即使实际正在执行的函数中根本用不着这些全局变量, 需要占用存储空间,即使实际正在执行的函数中根本用不着这些全局变量,它们也要占用 存储空间。 存储空间。 在函数中使用全局变量后, ② 在函数中使用全局变量后,要求在所有调用该函数的调用程序中都要使用这些全 局变量,从而会降低函数的通用性 用性。 局变量,从而会降低函数的通用性。 在函数中使用全局变量后,使各函数模块之间的互相影响比较大, ③ 在函数中使用全局变量后,使各函数模块之间的互相影响比较大,从而使函数模 块的“内聚性 内聚性”差 而与其他模块的“耦合性 耦合性”强 块的 内聚性 差,而与其他模块的 耦合性 强。 在函数中使用全局变量后,会降低程序的清晰性,可读性差。 ④ 在函数中使用全局变量后,会降低程序的清晰性,可读性差。

动态存储变量与静态存储变量 1.用户程序的存储分配 . 一般来说, 所示。 一般来说,用户程序在计算机中的存储分配如图 5.1 所示。

程 序 区 静 态 存 储 区 动 态 存 储 区

其中: 其中:

程序区用于存放程序; 程序区用于存放程序; 静态存储区是在程序开始执行时就分配的固定存储单元,如全局变量; 静态存储区是在程序开始执行时就分配的固定存储单元,如全局变量; 动态存储区是在函数调用过程中进行动态分配的存储单元 如函数形参、自动变量、 储区是在函数调用过程中进行动态分配的存储单元, 动态存储区是在函数调用过程中进行动态分配的存储单元,如函数形参、自动变量、 函数调用时的现场保护和返回地址等。 函数调用时的现场保护和返回地址等。

2.变量的存储类型 . 数据类型:如整型( ) 实型( 、实型 、字符型 、双精度型 ① 数据类型:如整型(int) 实型(float) 字符型(char) 双精度型(double)等。 、 ) 字符型( 、 ) 双精度型( 、 ) 数据的存储类型:分为自动类型( 、静态类型 、寄存器类型 ② 数据的存储类型:分为自动类型(auto) 静态类型(static) 寄存器类型(register) ) 静态类型( 、 ) 寄存器类型( 、 ) 、 外部类型( 外部类型(extern) ) 。 程序如下: 例 5.4 计算并输出 1~5 的阶乘值。其 C 程序如下: ~ 的阶乘值。 int fac(n) int n; ; { static int f=1; = ; f=f*n; = ; return(f); ; } #include "stdio.h" main() { int i; ; for (i=1; i<= ; i=i+1) <=5; = + = ; <= printf("%d!=%d\n",i,fac(i)); = ,, ; }

下面对静态存储变量作几点说明: 下面对静态存储变量作几点说明:

形参不能定义成静态类型。 ① 形参不能定义成静态类型。 对局部静态变量赋初值是在编译时进行的,在调用时不再赋初值; ② 对局部静态变量赋初值是在编译时进行的,在调用时不再赋初值;而对自动变量赋 初值是在调用时进行的,每次调用将重新赋初值。 初值是在调用时进行的,每次调用将重新赋初值。 定义局部静态变量时若不赋初值, ③ 定义局部静态变量时若不赋初值,则在编译时将自动赋初值 0;但在定义自动变量时 ; 若不赋初值,则其初值为随机值。 若不赋初值,则其初值为随机值。 若无多大必要,尽量不用局部静态变量。 ④ 若无多大必要,尽量不用局部静态变量。 3.外部变量 . 全局变量如果在文件开头定义,则在整个文件范围内的所有函数都可以使用该变量。 全局变量如果在文件开头定义,则在整个文件范围内的所有函数都可以使用该变量。 一般来说,全局变量有以下几种用法: 一般来说,全局变量有以下几种用法: 在同一文件中,为了使全局变量定义点之前的函数中也能使用该全局变量, ① 在同一文件中,为了使全局变量定义点之前的函数中也能使用该全局变量,则应在函 加以说明。 数中用 extern 加以说明。 使一个文件中的函数也能用另一个文件中的全局变量。 ② 使一个文件中的函数也能用另一个文件中的全局变量。 利用静态外部变量,使全局变量只能被本文件中的函数引用。 ③ 利用静态外部变量,使全局变量只能被本文件中的函数引用。

内部函数与外部函数 语言中,函数可以分为内部函数与外部函数。 在 C 语言中,函数可以分为内部函数与外部函数。只能被本文件中其他函数调用的函 数称为内部函数,内部函数又称为静态函数。 数称为内部函数,内部函数又称为静态函数。

定义内部函数的形式如下: 定义内部函数的形式如下: static 类型标识符 函数名(形参表) 函数名(形参表) 定义外部函数的形式如下: 定义外部函数的形式如下: [extern] 类型标识符 函数名(形参表) 函数名(形参表)

人们在解决一些复杂问题时,为了降低问题的复杂程度(如问题的规模等) ,一般总是将问 人们在解决一些复杂问题时,为了降低问题的复杂程度(如问题的规模等) 一般总是将问 , 题逐层分解,最后归结为一些最简单的问题。 题逐层分解,最后归结为一些最简单的问题。 函数, 例 5.5 编写一个 C 函数,对于输入的参数 n,依次打印输出自然数 1 到 n。 , 。 这是一个很简单的问题,实际上不用递归就能解决, 函数如下: 这是一个很简单的问题,实际上不用递归就能解决,其 C 函数如下: #include "stdio.h" wrt(int n) { int k; ; for (k=1;k<= ;k++ printf("%d\n",k); <=n; ++ ++) = ; <= , ; return; ; } 解决这个问题还可以用以下的递归函数来实现: 解决这个问题还可以用以下的递归函数来实现: #include "stdio.h" wrt1(int n) { if (n!=0) = { wrt1(n-1); - ; printf("%d\n",n);} , ; return; ; } 功能: 功能:对于输入的参数 n,依次打印输出自然数 1 到 n , 自己调用自己的过程称为递归调用过程。 语言中,自己调用自己的函数称为递归函数。 自己调用自己的过程称为递归调用过程。在 C 语言中,自己调用自己的函数称为递归函数。

递归分为直接递归与间接递归两种。 递归分为直接递归与间接递归两种。

所谓直接递归,是指直接调用函数本身。 所谓直接递归,是指直接调用函数本身。 编写一个函数,其功能是判断给定的正整数是否是素数, 例 5.6 编写一个函数,其功能是判断给定的正整数是否是素数,若是素数则返回函数值 1, , 否则返回函数值 0。 。 函数如下: 其 C 函数如下: #include "math.h" sushu(int n) { int k,i,flag; ,, ; k=sqrt((double)n); i=2; flag=0; = ; = ; = ; while ((i<= <=k)&&(flag== ==0)) <= == { if (n%i== flag=1; ==0) == = ; i=i+1; =+ ;

} return(!flag); ; } 例 5.8 Hanoi 塔问题。 塔问题。

庙中有三根插在黄铜板上的宝石柱, 相传古代印度有一座 Bramah 庙,庙中有三根插在黄铜板上的宝石柱,在其中的一根 个金盘子,大盘在下,小盘在上, 有一天, 柱子上放了 64 个金盘子,大盘在下,小盘在上,称为 Hanoi 塔。有一天,庙里的和尚们想 把这些盘子从一根柱子上移到另一根柱子上,规定每次只允许移动一个盘子,并且, 把这些盘子从一根柱子上移到另一根柱子上,规定每次只允许移动一个盘子,并且,在移 动过程中都不允许出现大盘子压在小盘子上面的现象 现大盘子压在小盘子上面的现象, 动过程中都不允许出现大盘子压在小盘子上面的现象,但在移动盘子的过程中可以利用三 根柱子中的任何一根。 根柱子中的任何一根。 为了使问题具有普遍性, 为了使问题具有普遍性,假设圆盘数为 n,按直径从小到大依次编号为 1,2,…,n; , , , , ; 三根柱子的名称分别为 X,Y,Z。开始时,n 个圆盘按从大到小的顺序(即下面放大圆盘, , , 。开始时, 个圆盘按从大到小的顺序(即下面放大圆盘, 上面放小圆盘) 柱子上, 柱子上, 上面放小圆盘)放在 X 柱子上,现在要将 X 柱子上的 n 个圆盘移到 Z 柱子上,其移动的原 则如上所述。 塔问题。 则如上所述。这个问题称为 n 阶 Hanoi 塔问题。

程序如下: 可以写出 C 程序如下: #include "stdio.h" main() { int n; ; char x='X',y='Y',z='Z'; = , = , = ; void hanoi(); ; printf("input n="); = ; scanf("%d",&n); , ; hanoi(n,x,y,z); , , , ; } void hanoi(n,x,y,z) , , , int n; ; char x,y,z; , , ; { void move(); ; if (n== move(x,n,z); ==1) == , , ; else { hanoi(n-1,x,z,y); - , , , ; move(x,n,z); , , ; hanoi(n-1,y,x,z); - , , , ; } return; ; } void move(x,n,z) , , int n; ;

char x,z; , ; { printf("%c(%d)---- ---->%c\n",x,n,z); ---- , , , ; } 语言的一个重要特点。所谓编译预处理, 编译预处理功能是 C 语言的一个重要特点。所谓编译预处理,是指 C 语言编译系统首先对 程序模块中的编译预处理命令进行处理。 程序模块中的编译预处理命令进行处理。 C 语言提供的编译预处理命令主要有以下 3 种: (1)宏定义; )宏定义; (2)文件包含命令; )文件包含命令; (3)条件编译命令。 )条件编译命令。 编译预处理命令一般是在函数体的外面。正确使用编译预处理命令, 编译预处理命令一般是在函数体的外面。正确使用编译预处理命令,可以编写出易于 调试、易于移植的程序模块。 调试、易于移植的程序模块。 文件包含命令 文件包含命令

文件包含是指一个源文件可以将另一个指定的源文件包括进来。 文件包含是指一个源文件可以将另一个指定的源文件包括进来。 文件包含命令的一般形式为 #include 〈文件名〉 文件名〉 或 #include "文件名 文件名" 文件名 其功能是将指定文件中的全部内容读到该命令所在的位置后一起被编译。 其功能是将指定文件中的全部内容读到该命令所在的位置后一起被编译。

在使用文件包含命令时,要注意以下几个问题: 在使用文件包含命令时,要注意以下几个问题: 命令指定的文件中的内容改变时, (1)当#include 命令指定的文件中的内容改变时,包含这个文件的所有源文件都应该重新 ) 进行编译处理; 进行编译处理; 命令只能指定一个被包含文件 如果需要包含多个文件, 指定一个被包含文件, ( 2)一个 )一个#include 命令只能指定一个被包含文件,如果需要包含多个文件,则要用多个 #include 命令实现; 命令实现; (3)被包含的文件应该是源文件,不能是经编译后的目标文件; )被包含的文件应该是源文件,不能是经编译后的目标文件; 命令; (4)文件包含可以嵌套使用,即被包含的文件中还可以使用 )文件包含可以嵌套使用,即被包含的文件中还可以使用#include 命令; 命令所指定的文件中可以有任何语言成分,因此,通常可以将经常使用的、 (5)由#include 命令所指定的文件中可以有任何语言成分,因此,通常可以将经常使用的、 ) 具有公用性质的符号常量、带参数的宏定义以及外部变量等集中起来放在这种文件中, 具有公用性质的符号常量、带参数的宏定义以及外部变量等集中起来放在这种文件中,以 尽量避免一些重复操作。 尽量避免一些重复操作。

6.1 一维数组 6.1.1 一维数组的定义与引用

定义一维数组的一般形式如下 定义一维数组的一般形式如下: 数组名[常量表达式 常量表达式]; 类型说明符 数组名 常量表达式 ; 其中类型说明符是定义数组中各元素的数据类型,常量表达式是说明数组的大小( 其中类型说明符是定义数组中各元素的数据类型,常量表达式是说明数组的大小(即

数组中元素的个数。 数组中元素的个数。 数组的说明与变量的说明一样,其作用是为数组分配存储空间。 数组的说明与变量的说明一样,其作用是为数组分配存储空间。

关于数组的说明要注意以下几个问题: 关于数组的说明要注意以下几个问题: (1)数组名的命名规则与变量名相同。 )数组名的命名规则与变量名相同。 (2)说明数组大小的常量表达式必须为整型,并且用方括号括起来(不能用圆括号) )说明数组大小的常量表达式必须为整型,并且用方括号括起来(不能用圆括号) 。 (3)说明数组大小的常量表达式中可以包含符号常量,但不能是变量。 )说明数组大小的常量表达式中可以包含符号常量,但不能是变量。 下面的程序说明了如何对数组定义和引用数组元素: 例 6.1 下面的程序说明了如何对数组定义和引用数组元素: #include "stdio.h" #define N 5 main() { int i, a[N]; , ; for (i=0; i<N; i=i+1) a[i]=i; = ; < ; =+ =; for (i=0; i<N; i=i+1) = ; < ; =+ printf("%5d",a[i]); , ; printf("\n"); ; } 在这个程序中, 在这个程序中,首先定义了一个长度为 5 的整型一维数组 a,然后利用 for 循环对其中的每 , 一个元素( 循环输出这 个元素值。 一个元素(a[0]~a[4])进行赋值,最后利用 for 循环输出这 5 个元素值。 ~ )进行赋值, 语言中,凡是一般简单变量可以使用的地方都可以使用数组元素。 在 C 语言中,凡是一般简单变量可以使用的地方都可以使用数组元素。

一维数组的初始化 语言中, 在 C 语言中,给数组元素提供数据的方法有以下 3 种。 (1)利用赋值语句逐个对数组中的元素进行赋值。 )利用赋值语句逐个对数组中的元素进行赋值。 (2)利用输入函数逐个输入数组中的各个元素。例如, )利用输入函数逐个输入数组中的各个元素。例如, #include "stdio.h" main() { int i, a[5]; , ; for (i=0; i<5; i=i+1) scanf("%d",&a[i]); = ; < ; =+ , ; } 其中&a[i]表示取数组元素 a[i]的地址。 的地址。 其中 表示取数组元素 的地址 (3)初始化。 )初始化。 下面对静态一维数组的初始化作三点说明: 下面对静态一维数组的初始化作三点说明: (1)可以只给数组的前若干个元素赋初值,此时后面的元素均将自动赋以初值 0。 (2) )可以只给数组的前若干个元素赋初值, 。 ) 在对全部元素赋初值时,说明语句中可以不指定数组长度, 在对全部元素赋初值时,说明语句中可以不指定数组长度,其长度默认为与初值表中数据 的个数相同。 语言规定只能对“静态存储 的数组进行初始化, 静态存储”的数组进行初始化 的个数相同。 (3)虽然标准 C 语言规定只能对 静态存储 的数组进行初始化,即除了可 ) 以对外部(全局 数组进行初始化外, 全局)数组进行初始化外 说明的局部数组进行初始化。 以对外部 全局 数组进行初始化外,还可以对用 static 说明的局部数组进行初始化。 分析下列程序的输出结果: 例 6.3 分析下列程序的输出结果:

#include "stdio.h" main() { int k,x[5]; , ; static int y[5]; ; int z[5]={0,0,0}; = , , ; for (k=0; k<5; k++ ++) = ; < ; ++ { printf("%5d%5d%5d",x[k],y[k],z[k]); , , , ; printf("\n"); ; } } 6.2 二维数组

二维数组的定义与引用

定义二维数组的一般形式如下: 定义二维数组的一般形式如下: 数组名[常量表达式 常量表达式 ; 类型说明符 数组名 常量表达式 1][常量表达式 2];

二维数组的初始化

与一维数组一样,也可以对静态存储的二维数组进行初始化。 与一维数组一样,也可以对静态存储的二维数组进行初始化。 在对二维数组进行初始化时要注意以下几点。 在对二维数组进行初始化时要注意以下几点。 (1)在分行给二维数组赋初值时,对于每一行都可以只对前几个元素赋初值,后面未 )在分行给二维数组赋初值时,对于每一行都可以只对前几个元素赋初值, 赋初值的元素系统将自动赋初值 0;并且,还可以只对前几行元素赋初值。 ;并且,还可以只对前几行元素赋初值。 (2)在给全部元素赋初值时,说明语句中可以省略第一维的长度说明。 )在给全部元素赋初值时,说明语句中可以省略第一维的长度说明。 (3)在分行赋初值时,也可以省略第一维的长度说明 )在分行赋初值时, 6.3 字符数组与字符串

字符数组的定义与初始化

定义字符数组的一般形式如下: 定义字符数组的一般形式如下: char 数组名 常量表达式 ; 数组名[常量表达式 常量表达式]; 一维字符数组 char 数组名 常量表达式 1][常量表达式 2]; 数组名[常量表达式 常量表达式 ; 二维字符数组 (1)当对字符数组中所有元素赋初值时,数组的长度说明可以省略。 )当对字符数组中所有元素赋初值时,数组的长度说明可以省略。 (2)可以只对前若干元素赋初值。 )可以只对前若干元素赋初值。 语言规定只能对“静态存储 的字符数组进行初始化, 静态存储”的字符数组进行初始化 (3)虽然标准 C 语言规定只能对 静态存储 的字符数组进行初始化,即除了可以对外 ) 全局)字符数组进行初始化外 说明的局部字符数组进行初始化。 部(全局 字符数组进行初始化外,还可以对用 static 说明的局部字符数组进行初始化。 全局 字符数组进行初始化外,

字符串 C 语言规定,字符串常量(简称字符串)要用一对双撇号括起来。在一个字符串常量 语言规定,字符串常量(简称字符串)要用一对双撇号括起来。 最后还包括一个结束符‘\0’。 中,最后还包括一个结束符 。 C 语言允许用字符串常量对字符数组进行初始化。 语言允许用字符串常量对字符数组进行初始化 字符串常量对字符数组进行初始化。

字符数组与字符串的输入与输出 1.输入输出一个字符 格式说明符为 %c) .输入输出一个字符(格式说明符为 在用于输入时,输入项为数组元素地址。在具体输入时,各字符之间不要分隔, 在用于输入时,输入项为数组元素地址。在具体输入时,各字符之间不要分隔, 字符也不要用单撇号括起来。 字符也不要用单撇号括起来。 在用于输出时,输出项为数组元素。 在用于输出时,输出项为数组元素。 2.输入输出一个字符串(格式说明符为 %s) .输入输出一个字符串( ) 在用格式说明符%s 进行输入输出时,其输入输出项均为数组名。但在输入时,相邻两 进行输入输出时,其输入输出项均为数组名。但在输入时, 在用格式说明符 个字符串之间要用空格分隔,系统将自动地在字符串最后加结束符'\0'。 个字符串之间要用空格分隔,系统将自动地在字符串最后加结束符 。

字符串处理函数

下面简单介绍一些常用的字符串处理函数。 下面简单介绍一些常用的字符串处理函数。 介绍一些常用的字符串处理函数 (1)puts(字符数组名) ) (字符数组名) 功能:输出一个字符串到终端。 功能:输出一个字符串到终端。 (2)gets(字符数组名) ) (字符数组名) 功能:从终端输入一个字符串到字符数组,并返回字符数组的地址。 功能:从终端输入一个字符串到字符数组,并返回字符数组的地址。 (3)strcat(字符数组 1,字符串 2) ) ( , ) 功能: 的后面, 的地址。 功能:将字符串 2 连接到字符串 1 的后面,并返回字符串 1 的地址。 (4)strcpy(字符数组 1,字符串 2) ) ( , ) 功能: 功能:字符串 2 拷贝到字符数组 1 中。 (5)strcmp(字符串 1,字符串 2) ) ( , ) 功能:比较字符串。 功能:比较字符串。 这个函数的返回值如下: 这个函数的返回值如下: 若字符串 1=字符串 2,则返回值为 0; = , ; 若字符串 1>字符串 2,则返回值为正整数; > ,则返回值为正整数; 若字符串 1<字符串 2,则返回值为负整数。 < ,则返回值为负整数。

(6)strlen(字符串) ) (字符串) 功能:测试字符串长度。 功能:测试字符串长度。 (7)大小写转换函数 ) 大小写转换函数有以下两个: 大小写转换函数有以下两个: strlwr(字符串) 将字符串中大写字母转换成小写字母。 (字符串) 将字符串中大写字母转换成小写字母。 strupr(字符串) 将字符串中小写字母转换成大写字母。 (字符串) 将字符串中小写字母转换成大写字母。

6.4 数组作为函数参数 形参数组与实参数组的结合 用选择法对无序序列进行排序。 例 6.8 用选择法对无序序列进行排序。

select(b,n) for i=0 to n–2

k=I for j=i+1 to yes k=j yes b[i]?b[k] 结束返回 k≠i no n–1 b[j]<b[k] no

C 程序如下: 程序如下: /* select.c */ select(b,n) , int n,b[]; , ; { int i,j,k,d; ,, , ; for (i=0; i<=n-2; i=i+1) = ; = - ; =+ { k=i; =; for (j=i+1; j<=n-1; j=j+1) =+ ; = - ; =+ if (b[j]<b[k]) k=j; =; if (k!=i) {d=b[i]; b[i]=b[k]; b[k]=d;} = = ; = ; = ; } } /* ex.c */ #include "stdio.h" #include "select.c" main() { int k; ; static int s[10]={3,5,4,1,9,6,10,56,34,12}; = , , , , , , , , , ; printf("\n"); ; for (k=0; k<10; k=k+1) printf("%4d",s[k])); = ; ; = + , ; printf("\n"); ; select(s,10); , ; for (k=0; k<10; k=k+1) printf("%4d",s[k])); = ; ; = + , ; printf("\n"); ; }

语言中,形参数组与实参数组之间的结合要注意以下几点 以下几点: 在 C 语言中,形参数组与实参数组之间的结合要注意以下几点: 调用函数与被调用函数中分别定义数组, 其数组名可以不同, 但类型必须一致。 (1) ) 调用函数与被调用函数中分别定义数组, 其数组名可以不同, 但类型必须一致。 (2) ) 语言中,形参变量与实参之间的结合是采用数值结合的,因此, 在 C 语言中,形参变量与实参之间的结合是采用数值结合的,因此,如果在被调用函数中 改变了形参的值,是不会改变实参值的。 改变了形参的值,是不会改变实参值的。 (3)实参数组与形参数组的大小可以一致也可 ) 以不一致, 编译系统对形参数组的大小不作检查, 以不一致,C 编译系统对形参数组的大小不作检查,调用时只将实参数组的首地址传给形 参数组。 参数组。 (4)虽然函数中的形参数组一般不指定大小,但为了控制形参数组的使用范围,一般要 )虽然函数中的形参数组一般不指定大小,但为了控制形参数组的使用范围, 在函数中另设一个传送形参数组元素个数的形参变量, 在函数中另设一个传送形参数组元素个数的形参变量,如函数 select()中的形参 n。 中的形参 。

二维数组作为函数参数 二维数组作为函数参数与一维数组完全类似。 二维数组作为函数参数与一维数组完全类似。 利用函数求两个矩阵的乘积矩阵。 例 6.9 利用函数求两个矩阵的乘积矩阵。 中说明了两个矩阵相乘的方法。 在例 6.4 中说明了两个矩阵相乘的方法。但在例 6.4 中,只能对固定的两个矩阵进行相 没有通用性。在本例中, 来实现矩阵相乘, 乘,没有通用性。在本例中,用函数 matmul()来实现矩阵相乘,在主函数 main()中再用具 来实现矩阵相乘 中再用具 体的矩阵来调用它。 体的矩阵来调用它。 程序如下: 具体的 C 程序如下: #include "stdio.h" main() { int i,j,c[2][3]; ,, ; static int a[2][4]={1,2,3,4,5,6,7,8}; = , , , , , , , ; static int b[4][3]={1,2,3,4,5,6,7,8,9,10,11,12}; = , , , , , , , , , , , ; matmul(a,b,c,2,4,3); , , , , , ; for (i=0; i<2; i=i+1) = ; < ; =+ { for (j=0;j<3; j=j+1) = ;< ; =+ printf("%5d",c[i][j]); , ; printf("\n"); ; } printf("\n"); ; } matmul(a,b,c,m,n,k) , , , , , int m,n,k,a[2][4],b[4][3],c[2][3]; , , , , , ; { int i,j,t; ,,; for (i=0; i<m; i=i+1) = ; < ; =+ for (j=0; j<k; j=j+1) = ; < ; =+ { c[i][j]=0; = ; for (t=0; t<n; t=t+1) = ; < ; =+ c[i][j]=c[i][j]+a[i][t]*b[t][j]; = + ; } return; ;

}

6.5 程序举例 从键盘输入年、 计算并输出该日是该年的第几天。 例 6.10 从键盘输入年、月、日,计算并输出该日是该年的第几天。 C 程序如下: 程序如下: #include "stdio.h" main() { int year,month,day,k,sum; , , , , ; static int t[]={31,0,31,30,31,30,31,31,30,31,30,31}; = ; printf("input year,month,day:"); ; scanf("%d,%d,%d",&year,&month,&day); , , , , , ; if ((year%4== && year%100!=0)||year%400== ==0 ==0) == = == t[1]=29; = ; else t[1]=28; = ; sum=day; = ; for (k=0;k<month-1;k=k+1) = ; < - ; = + sum=sum+t[k]; = + ; printf("Dyas=%d\n",sum); = , ; } 的线性表进行冒泡排序的函数。 例 6.12 编写一个对长度为 n 的线性表进行冒泡排序的函数。

冒泡排序的过程如下: 冒泡排序的过程如下: 从前到后扫描待排序序列,依次比较相邻两个项目的大小,若发现逆序就进行交换, 从前到后扫描待排序序列,依次比较相邻两个项目的大小,若发现逆序就进行交换, 最后使最大者换到序列的最后;然后从后到前扫描剩下的序列, 最后使最大者换到序列的最后;然后从后到前扫描剩下的序列,依次比较相邻两个项目的 大小,若发现逆序就进行交换,最后使最小者换到序列的最前面。 大小,若发现逆序就进行交换,最后使最小者换到序列的最前面。对剩下的序列重复这个 过程,直到剩下的序列为空为止。 过程,直到剩下的序列为空为止。 C 函数如下: 函数如下: void prbub(p,n) , int n; double p[]; ; ; { int m,k,j,i; , ,,; double d; ; k=0; m=n-1; = ; = - ; while (k<m= < = { j=m-1; m=0; = - ; = ; for (i=k; i<= ; i++ <=j; ++ ++) = ; <= if (p[i]>p[i+1]) > + { d=p[i]; p[i]=p[i+1]; p[i+1]=d; m=i;} = ; = + ; + = ; =; j=k+1; k=0; = + ; = ; for (i=m; i>= ; i-- >=j; -- --) = ; >= if (p[i-1] >p[i]) - { d=p[i]; p[i]=p[i-1]; p[i-1]=d; k=i;} = ; = - ; - = ; =;

} return; ; }


赞助商链接
相关文章:
C语言:后面章节练习题&&期末复习(Word版)
搜试试 5 悬赏文档 全部 DOC PPT TXT PDF XLS ...C语言:后面章节练习题&&期末复习(Word版)_理学_...C.全局变量声明语句可以放在源程序文件 中的任何位置...
纯C语言编写图书管理系统WORD文档bbszp
纯C语言编写图书管理系统WORD文档bbszp - 《C 语言程序设计》课程设计 实验报告 题目: 图书管理系统 专业: 班级: 姓名: 成绩: 指导教师: 完成日期: 年月 日 ...
2011年全国计算机等级考试二级C语言真题word版
2011年全国计算机等级考试二级C语言真题word版_IT认证_资格考试/认证_教育专区。等级考试真题,word版可下载 2011 年 3 月二级 C 语言程序设计笔试试卷(考试时间 ...
C语言词法分析器_内容说明注释完整_可运行代码
搜试试 5 悬赏文档 全部 DOC PPT TXT PDF XLS ...1. 实验目的及要求本次实验通过用 C 语言 设计、...是 输出word 为关键字 程序: #include<string.h>...
201203计算机二级C语言笔试真题文字word版 详细答案解析
搜试试 5 悬赏文档 全部 DOC PPT TXT PDF XLS ...201203计算机二级C语言笔试真题文字word版 详细答案...设计测试用例着眼于程序外部结构、 不考虑内部逻辑...
200909计算机二级C语言笔试真题文字word版 详细答案解析
搜试试 5 悬赏文档 全部 DOC PPT TXT PDF XLS ...200909计算机二级C语言笔试真题文字word版 详细答案...(6)下列选项中不属于结构化程序设计原则的是___。...
2012年3月计算机二级C语言笔试真题文字word版+详细答案...
搜试试 5 悬赏文档 全部 DOC PPT TXT PDF XLS ...2012年3月计算机二级C语言笔试真题文字word版+详细...设计测试用例的主要根据是 A、程序外部功能 B、程序...
更多相关标签: