C语言程序设计课件版
程序设计语言一般分为机器语言、汇编语言和高级语言三大类。
1 1 .机器语言
对于计算机来说,一组机器指令就是程序,称为机器语言程序。
2 2 .汇编语言
为了便于理解与记忆,人们采用能帮助记忆的英文缩写符号(称为指令助记符)来代替机器语言指令代码中的操作码,用地址符号来代替地址码。
3 3 .高级语言
机器语言和汇编语言都是面向机器的语言,一般称为低级语言。
例 例 2.1
编写一个 C C 程序,其功能是显示字符串 ‚How do you do!‛ 。
其 其 C C 程序如下:
#include "s tdio.h" main() { {
printf("How do you do!\ \ n") ; } } 下面针对一般的 C C 程序作几点说明:
(1 1的 )一个完整的 C C 语言程序可以由多个函数组成,但必须包含一个且只能包含一个名为n main 的函数(主函数)。程序总是从 n main 函数开始执行。
(2 2 )在一个 C C 函数模块中,由左右花括号 { } 括起来的部分是函数体,其中的语句系列实现函数的预定功能。
(3 3 )C C 程序中的每一个语句必须以 ‚ ; ‛ 结束,但书写格式是自由的。
(4 4 )e #include 是编译预处理命令,其作用是将双引号或尖括号括起来的 文件内容读到该命令的位置处。
(5 5 )在 C C 程序的任何位置处都可以用 /* ...... */ 作注释,以提高程序的可读性。
2.2.1
整型常量及其变量的定义 1 1 .整型常量
在 在 C C 语言中,有 3 3 。
种类型的整型常量:基本整型常量、长整型常量、无符号整型常量。
在 C C 语言中,不管是哪种类型的整型常量,都可以用 3 3 种数制表示。
(1 1 )十进制整型常量。
(2 2 )十六进制整型常量。
(3 3 )八进制整型常量。
2 2 .整型变量的定义
在 在 C C 程序中,用于存放整型数据的变量称 为整型变量。
在 在 C C 语言中,可以定义基本整型、长整型、短整型和无符号整型等 4 4 种类型的整型变量。它们的定义方式如下。
(1 1 )基本整型变量
定义基本整型变量的形式如下:
int
变量表列; (2 2 )长整型
定义长整型变量的形式如下:
long
[int]
变量表列;
(3 3 )短整 型 定义短整型变量的形式如下:
short
[int]
变量表列; (4 4 )无符号整型 定义无符号基本整型变量的形式如下:
unsigned
[int]
变量表列;
①
一个类型说明语句可以同时定义多个同类型的变量,各变量之间用逗号 ‚ , ‛ 分隔。
②
用类型说明语句定义的变量只是说明了为这些变量分配了存储空间,以便用 于存放。
与之相同类型的数据,在未对这些变量赋值前,这些变量中(即存储空间中)的值是随机的。
③
C C 语言允许在定义变量的同时为变量赋初值。
④
在为整型变量初始化或赋值时,C C 编译系统自动将被赋数据转换成与相应变量的类型一致。
⑤
由于各种整型变量所占的字节数有限,因此,它们所能存放的整数有一定的范围。
实型常量及其变量的定义
1 1 .实型(浮点型)常量 (1 1 )十进制数形式 (2 2 )指数形式(科学记数法)
2 2 .实型变量的定义 在 在 C C 程序中,用于存放实型数据的变量称为实型变量。
在 在 C C 语言中,实型变量有单精度与双精度两种。
单精度
float
双精度
double
字符型常量及其变量的定义
1 1 .字符型常量 " \ \ n"
换行 " \ \ r"
回车 " \ \ b"
退格 " \ \ t"
制表(横向跳格)
" \ \ ""
单引号(单撇号)
" \ \ ""
双引号(双撇号)
" \ \ ddd"
1 ~3 3 位八进制数所代表的 I ASCII 码字符 " \ \ xhh"
1 ~2 2 位十六进制数所代表的 I ASCII 码字符 " \ \ f"
走纸换页 ‘ \ \\ \ ’
反斜 杠字符 2 2 .字符型变量的定义 字符型变量的定义方式如下:
char
变量表列;
数据的输入与输出应包括以下几项:
①
输入(出)的设备 ②
输入(出)的格式 ③
输入(出)的内容
格式输出函数
格式输出函数的一般形式如下:
printf(*‚ 格式控制 ‛ ,输出表) ) ;
其中格式控制部分要用一对双撇号括起来,它用于说明输出项目所采用的格式。
1 1 .整型格式说明符 (1 1 )十进制形式
(2 2 )八进制形式 (3 3 )十六进制形式
2 2 .实型格式说明符
如果以十进制 数形式输出实型数据,其格式说明符为
%f 或
%m.nf 如果以指数形式输出实型数据,其格式说明符为
%e 或
%m.ne
3 3 .字符型格式说明符
字符型数据的格式说明符为
%c 或
%mc
(1 1 )输出表中各输出项目之间要用 ‚ , ‛ 分隔。
(2 2 )格式控制中的各格式说明符与输出表中的各输出项目在个数、次序、类型等方面必 须一一对应。
(3 3 )格式控制中除格式说明符外的其他字符将按原样输出。
(4 4 )在输出格式说明符中,如果带有宽度说明,则在左边没有数字的位置上用空格填满(即输出的数字是右对齐)。但如果在宽度说明前加一个负号(-),则输出为左对齐,即在右边补空格。
格式输入函数
格式输入函数的一般形式如下:
scanf ( ‚ 格式控制 ‛ ,内存地址表);
1 1 .整型格式说明符 (1 1 )十进制形式
用于输入十进制形式的整型数据。
(2 2 )八进制形式 用于输入八进制形式的整型数据。
(3 3 )十六进制形式 用于输入十六进制形式的整型数据。
2 2 .实型格式说明符 用于输入的单精度实型格式说明符为
%f 或
%e 用于输入的双精度实型格式说明符为
%lf
3 3 .字符型格式说明符 用于输入的字符型格式说明符为
%c 或
%mc
赋值运算
赋值运算符为 ‚ = ‛ 。赋值表达式为 变量名=表达式 (1 1 )在 C C 语言中, ‚ = ‛ 为赋值运算符,而不是等号; (2 2 )赋值运算符 ‚ = ‛ 左边必须是变量名,不能是表达式; (3 3 )赋值运算 符 ‚ = ‛ 两端的类型不一致时,系统将自动进行类型转换。
算术运算
在 C C 语言中,基本的算术运算符有以下几个:
+
加法运算符(双目运算符),或正值运算符(单目运算符)。如 x x +y y ,+x x 。
-
减法运算符(双目运算符),或负值运算符(单目运算符)。如 a a -3 3 ,-x x 。
*
乘法运算符(双目运算符)。如 3*x 。
/
除法运算符(双目运算符)。如 x/y 。
%
模余运算符(双目运算符)。只适用于整型数据 ,如 4 9%4 的值为 1 1 ,3 11%3 的值为 2 2 等。
关系运算
在 在 C C 语言中,基本的关系运算符有以下 6 6 个:
<
小于 <=
小于或等于 >
大于 >=
大于或等于 ==
等于 ! ! =
不等于
结果只有两个:
true
或者
false
执行 int x =2 2 ,y y =3 3 ;后表达式 x x =(y y ==3 3 )的值是 ( 1 )
逻辑运算
在 在 C C 语言中,逻辑常量只有两种:值非零表示 ‚ 真 ‛ ,值为零表示 ‚ 假 ‛ 。其基本的逻辑运算符有以下 3 3 个:
&& (逻辑与)
两个量都为真 时为真(1 1 ),否则为假(0 0 )
| | (逻辑或)
两个量中只要有一个为真时为真(1 1 ),只有都为假时为假(0 0 )
! (逻辑非)
一个量为真时为假(0 0 ),假时为真(1 1 )
自增++与自减--运算符
增 1 1 运算符 ‚ ++ ‛ 和减 1 1 运算符 ‚ -- ‛ 是两个单目(只有一个运算对象)运算符,它们的运算对象只能是整型或字符型变量。
增 增 1 1 运算符是将运算对象的值增 1 1 ;减 1 1 运算符是将运算对象的值减 1 1 。
假设定义变量
int a= 5 ;n in t b ; 前缀自增
b = ++a ; // a=6 b=6
后缀自增
b =
a++ ; // a=6 b=5
f sizeof 运算符
f sizeof 运算符有以下两种用法:
(1 1 )用于求得表达式计算结果所占内存的字节数。其一般形式为
sizeof
表达式 (2 2 )用于求得某种数据类型的量所占内存的字节数。其一般形式为
sizeof (类型名)
逗号运算符
逗号 ‚ , ‛是 是 C C 程序中常见的符号。
在 在 C C 语言中,逗号除作为 分隔符使用外,还可以作为运算符来使用,称为逗号运算符。
逗号表达式的一般形式为 子表达式 1 1 ,子表达式 2 2 , … ,子表达式 n n
在使用逗号运算符(逗号表达式)时,要注意以下几点:
(1 1 )逗号运算符是所有运算符中级别最低的一种运算符。
(2 2 )一个逗号表达式又可以与另一个表达式(可以是逗号表达式,也可以不是逗号表达式)连接成新的逗号表达式。
(3 3 )在许多情况下,使用逗号表达式的目的仅仅是为了得到各个子表达式的值,而并不一定要得到或使用整个逗号表达式的值。
C C 语言中的宏定义有两种形式 :符号常量定义与带参数的宏定义。
符号常量定义
在 在 C C 语言中,允许将程序中多处用到的 ‚ 字符串 ‛ 定义成一个符号常量。在 C C 语言中定义符号常量的一般形式如下:
#define
符号常量名
字符串
①
由于 C C 语言中的所有变量名、函数名等都使用小写字母,因此,符号常量名一般用大写字母表示,以便与 C C 语言中的保留关键字相区别。
②
C C 编译系统对定义的符号常量的处理只是进行简单的替换,不作任何语法检查。
③
#define 是一个命令,而不是语句,因此在行末不能加 ‚ ; ‛ ,并 且应独立占一行。
④
#define 命令一般应出现在程序中函数的外面,其作用域范围是从 #define
符号常量名
字符串 到 #undef
符号常量名( ( 或文件末) )
带参数的宏定义
带参数的宏定义的一般形式为
#define
宏名(参数表)
字符串
其中字符串中应包含在参数表中所指定的参数,并且,当参数表中的参数多于一个时,各参数之间要用逗号分隔。
在使用带参数的宏定义时,应注意以下两个问题。
(1 1 )在使用带参数 的宏定义时,一般应将宏定义字符串中的参数都要用括号括起来,否则经过宏展开后,可能会出现意想不到的错误。
(2 2 )在使用带参数的宏定义时,除了应将宏定义字符串中的参数都要用括号括起来,还需。
要将整个字符串部分也要用括号括起来,否则经过宏展开后,还会可能出现意想不到的错误。
书写一个求最大值的宏定义 # define MAX(a , b) ((a>b)? (a) ,(b))
3.1
语句与复合语句
在 在 C C 语言中,一个表达式后面跟随一个分号就构成了一个语句,这种语句称为表达式语句。
在 C C 语言中,分号(;)是表达式语句的终结符,而不是语句之间的分隔符,也就是说,分号是表达式语句的一个组成部分,只不过它位于表达式的后面。
在一个函数体内部,由左、右花括号括起来的语句称为复合语句,它的一般形式为 { { 说明部分;语句部分;} }
3.2
if 语
句
If 语句的形式为
if
(表达式)
语句 这种选择结构的流程图如图 1 3.1 所示。
下面对 f if 语句作几点说明:
(1 1 )f if 语句中的逻辑表达式(即条件)必须要用一 对圆括号括起来。
(2 2 )f if 语句后的语句可以是复合语句。
(3 3 )一个 f if 语句
用 最后需要强调的是,在使用 f if 语句时,一定要注意逻辑表达式的正确写法,特别是在连续使用多个 f if 语句时更要注意。
e 3.3
if…else 结构
在 在 C C 语言中,e if…else 结构的语句形式为
if
(表达式)
语句 1 1
else
语句 2 2
下面对 e if…else 结构作以下几点说明:
(1 1 )e if…else 结构中的语句 1 1 与语句 2 2 都可以是复合语 句。
(2 2 )在 f if …e else 结构中,语句 1 1 与语句 2 2 都可以是空语句。
(3 3 )在 f if …e else 结构中,如果在 e else 前面有多个 f if 语句,则 e else 与最近的 f if 配对。
(4 4 )如果有多个 e if……else 结构嵌套如下:
if
( 表达式 1)
语句 1 1
else
if
(表达式 2 2 )
语句 2 2
else
…
else
if
(表达式 n n )
语句 n n
else
语句 n n +1 1 则可简 写成
if
(表达式 1 1 )
语句 1 1
else if
(表达式 2 2 )
语句 2 2
…
else
if
(表达式 n n )
语句 n n
else
语句 n n +1 1
在 在 e if…else 结构中,如果语句 1 1 与语句 2 2 都是单一的赋值语句,并且都是给同一个变量赋值,则可以用条件运算符来进行处理。
下面对条件表达式作几点说明:
(1 1 )条件运算符优先级要比赋值运算符高。
(2 2 )条件运算符的优先级比关系运算符与算术运算符都要低,因此,条件表达式中的 ‚ 表
达式 1 1 ‛ 、 ‚ 表 达式 2 2 ‛ 与 ‚ 表达式 3 3 ‛ 都不必用括号括起来。
(3 3 )条件运算符的结合方向为 ‚ 从右到左 ‛ 。
在 在 C C 语言中提供了一个直接实现多路分支选择的结构,称为 h switch :
结构,其一般形式如下:
switch( 表达式) )
{
case
常量表达式 1:
语句 1 1
case
常量表达式 2:
语句 2 2
…
case
常量表达式 n:
语句 n n
default
:
语句 n n +1 1
} }
下面对 h switch 结构作几点说明:
(1 1 )h switch 结构中的表达式、常量表达式 1 1 、 …L 、常量表达式 n n 必须是整型或字符型。这是因为,在 h switch 结构中,其分支数一般是有限的,并且是离散的,因此,其表达式的值也应是有限的,且是离散的。
(2 2 )同一个 h switch 结构中的常量表达式值必须互不相同,否则就会出现矛盾的现象,即对于 ‚ 表达式 ‛ 的同一个值对应多种执行方案,这是错误的。
(3 3 )在 h switch 结构中, case 与
default 的顺序可以任意,各 e case 之间
。
的顺序也可以任意。
(4 4 )在执行 h switch 结构时,当执行完某 case 后的语句 后,将顺序执行后面 case 后的语句,直到遇
break 语句才退出整个 switch 结构的执行。
(5 5 )在 h switch 结构中,如果没有 default 且 ‚ 表达式 ‛ 值不等于任何 case 后常量表达式的值,则直接退出 switch 结构而转到其后的语句执行。
例 例 3.12
计算奖金。
当企业利润 P P 等于或低于 5 0.5 万元时,奖金为利润的 1% ;当 0.5 < P P ≤1 1 万元时,超过 过 5 0.5 万元部分的奖金为利润的 1.5% ,5 0.5 万元以下仍按 1% 计算;当 1 1 < P P ≤2 2 万元时,1 1 万元以下部分仍按前面的方法计算, 超过 1 1 万元的部分其奖金按利润的 2% 计算;当 2 2 < P P ≤5 5万元时,2 2 万元以下部分仍按前面的方法计算,超过 2 2 万元部分的奖金按利润的 2.5% 计算;当 当 5 5 < P P ≤0 10 万元时,5 5 万元以下部分仍按前面的方法计算,超过 5 5 万元部分的奖金按利润的 的 3% 计算;当 P P >0 10 万元时,0 10 万元以下部分仍按前面的方法计算,超过 0 10 万元部分按3.5% 计算。其中 P P 由键盘输入,计算并输出相应的奖金数 W 。
根据图 5 3.5 所示的流程图,用 f if…else if 结构写出 C C 程序如下:
#include
"stdio.h" main() { float
p ,w 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
求解一元二次方程 Ax 2 2 + Bx + C C =0 0 。
相应的 C C 程序如下:
#include
"stdio.h" #include
"math.h" main() {
double
a ,b b ,c c ,d d , x1 , x2 ,p p ;
printf("input a ,b b , c: ") ;
scanf("%lf%lf%lf" , &a , &b , &c) ;
if (a ==0 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 b - d)/( 2*a) ;
else
x1 =( ( -b 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 p =- b/(2*a) ;
printf("X1 = %f + j%f\ \ n" ,p p ,) d) ;
printf("X2 2 = %f - j%f\ \ n" ,p p ,) d) ;
} }
} } } }
4.1.1
当型循环结构 当型循环结构的流程图如图 1 4.1 所示。
e while 循环
实现当型循环结构的 C C 语句形式为
while
( 表达式 )
循环体语句
功能:当表达式值≠0 0 时,执行循环体,执行完后继续判断表达式值,只有当表达式值=0 0 时才退出循环。
例 例 4.2
从键盘输入各学生成绩,并对 0 90 分以上(包括 0 90 分)的学生人数进行计数,直到输入的成绩为负为止,最后输出成绩在 0 90 分以 上的学生人数。
其流程图如图 3 4.3 所示。其中变量 t count 为整型,用于对 0 90 分以上的学生人数进行计数。
相应的 C C 程序如下:
#include
"stdio.h" main() { int
count ;
float
grade ;
count =0 0 ;
scanf("%f" , &grade) ;
while (grade >= 0.0)
{ if (grade >= 90.0)
count = count +1 1 ;
scanf("%f" , &grade) ;
} }
printf( "count = %d\ \ n" , count) ; } }
直到型循环结构
直到型循环结构的流程图如图 4 4.4 所示。
do__while 循环
e do_ while 循环的执行过程是,首先执行循环体,然后判断条件(即计算逻辑表达式),如果条件满足(即逻辑表达式值为真),则退出循环结构;如果条件不满足(即逻辑表达式值为假),则继续执行循环体。
实现直到型循环结构的 C C 语句形式为 do
循环体语句
while (表达式);
功能:先执行循环体,然后判断表达式值,若表达式值≠0 0 ,则再次执行循环体,如此 循环,直到表达式值=0 0 为止。
例 例 4.3
计算并输出下列级数和:
直到某项的绝对值小于
为止 相应的流程图如图 5 4.5 所示。其中 f f 用于改变每一项的符号,因为这是一个各项符号相间的级数。
相应的 C C 程序如下:
#include
"stdio.h" main() { int
k ;
double
sum ,d d ,f f ;
sum = 1.0 ;
k k =1 1 ;f f = 1.0 ;
do
{ k =k k +1 1 ;f f =-f f ;d d = 1.0/(k*(k + 1)) ; sum = sum + f*d ;
} }
whiled (d >= 1.0e -) 4) ;
printf("sum = %lf\ \ n" , sum) ; } }
当型循环结构与直到型循环结构的区别与联系
当型循环结构与直到型循环结构既有共同之处,又有区别。主要体现在以下几个方面。
(1 1 )在 e while 循环中,其循环体可以一次也不执行(即执行 e while 循环结构的一开始,其条件就不满足)。
(2 2 )不管是 e while 循环结构还是 do —e while 循环结构,在循环体内部必须要有能改变条件( ( 即逻辑表达式值) ) 的语句,否则将造成死循环。
(3 3 )对于有些问题既可以用 e while 循环结 构来处理,也可以用 do —e while 循环结构来处理。
(4 4 )不管是 e while 循环结构还是 do —e while 循环结构,其循环体如果包含一个以上的语句,应以复合语句形式出现。
C C 语言提供的 r for 循环属于当型循环结构,其一般形式为
for (表达式 1 1 ;表达式 2 2 ;表达式 3 3 )
循环体语句(组)
它等价于下列的当型循环结构:
表达式 1 1 ; while (表达式 2 2 )
{
循环体语句
表达式 3 3 ;
} }
下面对 r for 循环语句作几点说明:
(1 1在 )在 r for 语句中,三个表达式中的任何一个表达式均可省 略,但其中的两个 ‚ ; ‛ 不能省略。
(2 2 )下列两个循环都是死循环:
for( 表达式 1 1 ;;表达式 3)
循环体 与
for( ;; )
循环体
式 因为它们都没有用于判断循环是否结束的条件(即表达式 2 2 )。
(3 3 )r for 循环本质上也是当型循环结构,只不过它对于事先可以确定循环次数的问题特别方便。
(4 4 )在 r for 循环中,循环体也可以是复合语句(即用一对花括号 { }。
括起来的语句组)。
循环的嵌套
。
所谓循环的嵌套是指一个循环体内又包含了另一个完整的循环结构。C C 语言 允许循环结构嵌套多层。循环的嵌套结构又称为多重循环。
例 例 4.6
计算并输出 0 10 以内( ( 包括 10) 所有自然数的阶乘值。即计算 ! 1! ,! 2! ,! 3! ,! 4! ,! 5! ,! 6! ,! 7! ,! 8! ,! 9! , 10! 。
采用的方法是,对于 0 10 以内的每一个自然数分别求它们的阶乘值。其流程图如图 7 4.7 所示。显然,这是一个二重循环结构。
相应的 C C 程序如下:
#include
"stdio.h" main() { int
n ,k k ;
double
s ;
for (n =1 1 ;
n n <= 10 ;
n n =n n +) 1)
{ s = 1.0 ;
for (k =1 1 ;
k k <=n n ;
k k =k k + 1)
s = s*k ;
printf("%2d! = %16.7f\ \ n " ,n n ,) s) ;
} } } } break 语句
C C 语言中的 k break 语句有以下两个功能:
(1 1 )跳出
switch 结构; (2 2 )退出当前循环结构,包括
while 结构、
do…while 结构和 r for 循环结构。
continue 语句
e continue 语句的功能是结束本次循环的执行,但不退出循环结构。
下面举两个例子来说明 e continue 语句的使用。
例 例 4.10
输出 100 ~0 200 之间所有能被 7 7 或 或 9 9 整除的自然数。
相应的 C C 程序如下:
#include
"stdio.h" main() { int
n ;
for (n = 100 ;
n n <= 200 ;
n n =n n +) 1)
{ if (n%7! = 0)&&(n%9! = 0))
continue ;
/* 结束本次循环,继续进行下次循环 */
printf("%d
\ \ n" , n) ;
} }
实际上,上述程序等价于 #include
"stdio.h" main() { int
n ;
for (n = 100 ;
n n <= 200 ;
n n =n n +) 1)
{ if (n%7 == 0) | | (n%9 == 0))
printf("%d
\ \ n" , n) ;
} } } }
5.1.1
函数的概念
在 在 C C 语言中,函数分为以下两种。
(1 1 )标准库函数
这种函数用户不必定义,但可直接使用。例如 scanf() ,
printf() ,
fabs() ,
sqrt() ,exp() , sin() , cos() 等都是 C C 语言中常用的库函数。
(2 2 )用户自己定义的函数
这种函数用以解决用户的专门问题,一般由用户自己编写。
例 例 5.1
从键盘输入两个正整数 m m 与 n n ( ( m m ≥ n n ) ) ,求
的值(即求
)。
其 其 C C 程序如下:
#include
"stdio.h" main()
/* 主函数 */ { int
m ,n n ;
int
p() ;
/* 说明本函数中要调用的函数 p() 是整型 */
scanf("%d , %d" , &m , &n) ;
if (m >= n)
printf("%d\ \ n" , p(m)/p(m - n)) ;
els e
printf("m < n ! \ \ n") ; } }
int p(k)
/* 计算阶乘值的函数 */ int k ; { int s ,i i ;
s s =1 1 ;
for (i =1 1 ;
i i <=k k ;
i i =i i + 1) s = s*i ;
return(s) ; } } 下面对函数作几点说明:
(1 1的 )一个完整的 C C 程序可以由若干个函数组成,其中必须有一个且只能有一个主函数main() 。
(2 2 )一个完整 C C 程序中的所有函数可以放在一个文件中,也可以放在多个文件中。
①
在编译命令行中键入各个函数所在的文件名(各文件名之间 用空格分隔)。
②
在主函数中用
#include 语句将各函数所在的文件包含进来。
(3 3 )C C 语言中的函数没有从属关系,各函数之间互相独立,可以互相调用。
函数的定义
在 在 C C 语言中,函数定义的一般形式为
类型标识符
函数名(形参表列)
形参类型说明
{
说明部分
语句部分
} }
在定义 C C 函数时要注意以下几点。
(1 1 )函数类型标识符同变量类型说明符,它表示返回的函数值类型。
(2 2 )如果省略函数的类型标识符,则默认为是 t int 型。
(3 3 )C C 语言允许定义空函数。如 dummy(){ }
(4 4 )函数中返回语句的形式为 return (表达式); 或 return 表达式; (5 5 )如果 ‚ 形参表列 ‛ 中有多个形式参数,则它们之间要用 ‚ , ‛ 分隔。
(6 6 )C C 语言允许在形参表中直接对形参的类型进行说明。
函数的调用
函数调用的一般形式为 函数名(实参表列)
(1 1 )函数调用可以出现在表达式中(有函数值返回);也可以单独作为一个语句( ( 无函数值返回) ) 。
(2 2 )实参表中的各实参可以是表达式,但它们的类型和个数应与函数中的形参一一对应。
(3 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) do uble x ,y y ; { double
s ;
s s = 3.1415926*(x*x + y*y) ;
return(s) ; } }
但 但 C C 语言规定,在以下几种情况下可以不在调用函数中对被调用函数作类型说明:
①
被调用函数为整型或字符型,自动按整型处理。
②
被调用函数的定义出现在调用函数之前。
③
在调用函数之前已经由别的函数(它可能也要调用该被调用函数)对被调用函数作了类型说明。
(4 4 )C C 语言虽不允许嵌套定义函数,但可以嵌套调用函数。
形参与实参的结合方式
1 1 .地址结合
所谓地址结合,是指在一个模块调用另一个模块时,并不是将调用模块中的实参值直接传送给被调用模块中的形参,而只是将存放实参的地址传送给形参。
2 2 .数值结合
所谓数值结合,是指调用模块中的实参地址与被调用模块中的形参地址是互相独立的,在一个模块调用另一个模块时,直接将实参值传送给形参被存放在形参地址中。
例 例 5.3
分析下列 C C 程序:
void
swap(x ,) y) int
x ,y y ; { int t ;
t t =x x ;
x x =y y ;
y y =t t ;
return ; }
#inc lude
"stdio.h" main() { int
x ,y y ;
scanf("x = %d ,y y = %d" , &x , &y) ;
swap(x ,) y) ;
printf("x = %d ,y y = %d\ \ n" ,x x ,) y) ; } }
在这个程序中共有两个函数。在主函数中分别为整型变量 x x 与 与 y y 输入数据,然后调用函数swap(x, ,) y) 。而函数 swap(x, ,) y) 的功能是实现变量 x x 值与 y y 值的交换。但在实际运行该程序时,如果从键盘输入 x x =6 6 ,y y = 8¿ 则输出的结果为 x x =6 6 ,y y =8 8
即没有达到交换的目的。这是因为在主函数中 调用函数 swap() 时,只是将实参 x x 和 和 y y
的值分别传递给了 swap() 函数中的形参 x x 和 和 y y ,但由于主函数中的实参 x x 和 和 y y 与函数 swap()中的形参 x x 和 和 y y 在计算机中的存储地址是不同的,因此,在函数 swap() 中虽然交换了形参 x x与 与 y y 的值,但实参 x x 与 与 y y 的值实际上没有改变,即它们没有被交换。
由此可以看出,在形参与实参为数值结合的情况下,实参与形参在计算机内存中的存储地址不是同一个,因此,即使在被调用函数中改变了形参值,调用函数中的实参值也是不会被改变的。
局部变量与全局变量
1 1 .局部变量
在函数内部 定义的变量称为局部变量。函数内部定义的变量只在该函数范围内有效,因此,不同函数中的局部变量可以重名,互不混淆。
2 2 .全局变量
在函数外定义的变量称为全局变量
除非十分必要,一般不提倡使用全局变量,其原因有以下几点:
①
由于全局变量属于程序中的所有函数,因此,在程序的执行过程中,全局变量都需要占用存储空间,即使实际正在执行的函数中根本用不着这些全局变量,它们也要占用存储空间。
②
在函数中使用全局变量后,要求在所有调用该函数的调用程序中都要使用这些全局变量,从而会降低函数的通 用性。
③
在函数中使用全局变量后,使各函数模块之间的互相影响比较大,从而使函数模块的 ‚ 内聚性 ‛ 差,而与其他模块的 ‚ 耦合性 ‛ 强。
④
在函数中使用全局变量后,会降低程序的清晰性,可读性差。
动态存储变量与静态存储变量
1 1 .用户程序的存储分配 一般来说,用户程序在计算机中的存储分配如图 1 5.1 所示。
程序区 静态存储区 动态存储区
其中:
程序区用于存放程序;
静态存储区是在程序开始执行时就分配的固定存储单元,如全局变量;
动态存储区是在函数调用过程中进行动态分配的存储单元,如函数形 参、自动变量、函数调用时的现场保护和返回地址等。
2 2 .变量的存储类型
①
数据类型:如整型( int )、实型( float )、字符型( char )、双精度型( double )等。
②
数据的存储类型:分为自动类型( auto )、静态类型( static )、寄存器类型( register )、外部类型( extern )。
例 例 5.4
计算并输出 1 1 ~5 5 的阶乘值。其 C C 程序如下:
int
fac(n)
int
n ; { static
int
f =1 1 ;
f f = f*n ;
return(f) ; } }
#i nclude
"stdio.h" main() { int
i ;
for (i =1 1 ;
i i <=5 5 ;
i i =i i +) 1)
printf("%d! = %d\ \ n" ,i i , fac(i)) ; } }
下面对静态存储变量作几点说明:
①
形参不能定义成静态类型。
②
对局部静态变量赋初值是在编译时进行的,在调用时不再赋初值;而对自动变量赋初值是在调用时进行的,每次调用将重新赋初值。
③
定义局部静态变量时若不赋初值,则在编译时将自动赋初值 0 0 ;但在定义自动变量时若不赋初值,则其初值为随机值。
④
若无多大必要,尽量不用局部静态变量。
3 3 .外部变量
全局变量如果在文件开头定义,则在整个文件范围内的所有函数都可以使用该变量。
一般来说,全局变量有以下几种用法:
①
在同一文件中,为了使全局变量定义点之前的函数中也能使用该全局变量,则应在函数中用 n extern 加以说明。
②
使一个文件中的函数也能用另一个文件中的全局变量。
③
利用静态外部变量,使全局变量只能被本文件中的函数引用。
内部函数与外部函数
在 在 C C 语言中,函数可以分为内部函数与外部函数。只能被 本文件中其他函数调用的函数称为内部函数,内部函数又称为静态函数。
定义内部函数的形式如下:
static
类型标识符
函数名(形参表)
定义外部函数的形式如下:
[extern]
类型标识符
函数名(形参表)
人们在解决一些复杂问题时,为了降低问题的复杂程度(如问题的规模等),一般总是将问题逐层分解,最后归结为一些最简单的问题。
例 例 5.5
编写一个 C C 函数,对于输入的参数 n n ,依次打印输出自然数 1 1 到 n n 。
这是一个很简单 的问题,实际上不用递归就能解决,其 C C 函数如下:
#include
"stdio.h" wrt(int
n) { int
k ;
for (k =1 1 ;k k <=n n ;k k ++ )
printf("%d\ \ n" ,) k) ;
return ; } } 解决这个问题还可以用以下的递归函数来实现:
#include "stdio.h" wrt1(int n) { if (n! =) 0)
{ wrt1(n -) 1) ;
printf("%d\ \ n" , n) ;}
return ; } } 功能:对于输入的参数 n n ,依次打印输出 自然数 1 1 到 n n
自己调用自己的过程称为递归调用过程。在 C C 。
语言中,自己调用自己的函数称为递归函数。
递归分为直接递归与间接递归两种。
所谓直接递归,是指直接调用函数本身。
例 例 5.6
编写一个函数,其功能是判断给定的正整数是否是素数,若是素数则返回函数值 1 1 ,否则返回函数值 0 0 。
其 其 C C 函数如下:
#include
"math.h" sushu(int n) { int
k ,i i , flag ;
k k = sqrt((double)n) ;
i i =2 2 ;
flag =0 0 ;
while ((i <=k k )&&(flag == 0))
{ if (n%i == 0) flag =1 1 ;
i i =i i +1 1 ;
} }
return(!flag) ; } }
例 例 i 5.8
Hanoi 塔问题。
相传古代印度有一座 h Bramah 庙,庙中有三根插在黄铜板上的宝石柱,在其中的一根柱子上放了 4 64 个金盘子,大盘在下,小盘在上,称为 i Hanoi 塔。有一天,庙里的和尚们想把这些盘子从一根柱子上移到另一根柱子上,规定每次只允许移动一个盘子,并且,在移动过程中都不允许出现大盘子压在小盘子上面的现象,但在移动盘子的过程中可以 利用三根柱子中的任何一根。
为了使问题具有普遍性,假设圆盘数为 n n ,按直径从小到大依次编号为 1 1 ,2 2 , … , n n ;三根柱子的名称分别为 X X , Y Y , Z Z 。开始时, n n 个圆盘按从大到小的顺序(即下面放大圆盘,上面放小圆盘)放在 X X 柱子上,现在要将 X X 柱子上的 n n 个圆盘移到 Z Z 柱子上,其移动的原则如上所述。这个问题称为 n n 阶 阶 i Hanoi 塔问题。
可以写出 C C 程序如下:
#include "stdio.h" main() { int n ;
char x = "X" ,y y = "Y" ,z z = "Z" ;
void hanoi() ;
pr intf("input n =) ") ;
scanf("%d" , &n) ;
hanoi(n ,x x ,y y ,) z) ; } }
void hanoi(n ,x x ,y y ,) z) int n ; char x ,y y ,z z ; { void move() ;
if (n == 1) move(x ,n n ,) z) ;
else
{ hanoi(n -1 1 ,x x ,z z ,) y) ;
move(x ,n n ,) z) ;
hanoi(n -1 1 ,y y ,x x ,) z) ;
} }
return ; } }
void move(x ,n n ,) z) int n ;
char
x x ,z z ; { {
printf("%c(%d) ---- >%c\ \ n" ,x x ,n n ,) z) ; } } 编译预处理功能是 C C 语言的一个重要特点。所谓编译预处理,是指 C C 语言编译系统首先对程序模块中的编译预处理命令进行处理。
C C 语言提供的编译预处理命令主要有以下 3 3 种:
(1 1 )宏定义;
(2 2 )文件包含命令;
(3 3 )条件编译命令。
编译预处理命令一般是在函数体的外面。正确使用编译预处理命令,可以编写出易于调试、易于移植的程序模块。
文件包含命令
文件包含是指一个源文件可以将另一个指 定的源文件包括进来。
文件包含命令的一般形式为
#include 〈文件名〉 或
#include
" 文件名" "
其功能是将指定文件中的全部内容读到该命令所在的位置后一起被编译。
在使用文件包含命令时,要注意以下几个问题:
(1 1 )当e #include 命令指定的文件中的内容改变时,包含这个文件的所有源文件都应该重新进行编译处理; (2 2 )一个e #include 命令只能指定一个被包含文件,如果需要包含多个文件,则要用多个# #e include 命令实现; (3 3 )被包含的文件应该是源文件,不能是经编译后的目标文件; (4 4 )文件包含可以嵌套使用,即被包含的文件中还可以使用e #include 命令; (5 5 )由e #include 命令所指定的文件中可以有任何语言成分,因此,通常可以将经常使用的、具有公用性质的符号常量、带参数的宏定义以及外部变量等集中起来放在这种文件中,以尽量避免一些重复操作。
6.1
一维数组
6.1.1
一维数组的定义与引用
定义一维数组的一般形式如下:
类型说明符
数组名[ [ 常量表达式] ] ;
其中类型说明符是定义数组中各元素的数据类型,常量表达式是说明数组的大小(即
数组中元素的个数。
数组的说明与变量的说明一样,其作用是为数组分配存储空间。
关于数组的说明要注意以下几个问题:
(1 1 )数组名的命名规则与变量名相同。
(2 2 )说明数组大小的常量表达式必须为整型,并且用方括号括起来(不能用圆括号)。
(3 3 )说明数组大小的常量表达式中可以包含符号常量,但不能是变量。
例 例 6.1
下面的程序说明了如何对数组定义和引用数组元素:
#include
"stdio.h" #define
N
5 main() { int
i ,
a[N] ;
for (i =0 0 ;
i i <N N ;
i i =i i + 1)
a[i] =i i ;
for (i =0 0 ;
i i <N N ;
i i =i i +) 1)
printf("%5d" , a[i]) ;
printf("\ \ n") ; } }
在这个程序中,首先定义了一个长度为 5 5 的整型一维数组 a a ,然后利用 r for 循环对其中的每一个元素( a[0] ~ a[4] )进行赋值,最后利用 r for 循环输出这 5 5 个元素值。
在 C C 语言中,凡是一般简 单变量可以使用的地方都可以使用数组元素。
一维数组的初始化
在 在 C C 语言中,给数组元素提供数据的方法有以下 3 3 种。
(1 1 )利用赋值语句逐个对数组中的元素进行赋值。
(2 2 )利用输入函数逐个输入数组中的各个元素。例如, #include
"stdio.h" main() { int
i ,
a[5] ;
for (i =0 0 ;
i i <5 5 ;
i i =i i + 1)
scanf("%d" , &a[i]) ; } } 其中 &a[i] 表示取数组元素 a[i] 的地址。
(3 3 )初始化。
下面对静态一维数组的初始化作三点说明:
(1 1 )可 以只给数组的前若干个元素赋初值,此时后面的元素均将自动赋以初值 0 0 。
(2 2 )在对全部元素赋初值时,说明语句中可以不指定数组长度,其长度默认为与初值表中数据的个数相同。
(3 3 )虽然标准 C C 语言规定只能对 ‚ 静态存储 ‛ 的数组进行初始化,即除了可以对外部( ( 全局) ) 数组进行初始化外,还可以对用 c static 说明的局部数组进行初始化。
例 例 6.3
分析下列程序的输出结果:
#include "stdio.h" main() { int k , x[5] ;
static int y[5] ;
int z[5] = {0 ,0 0 , 0} ;
for (k =0 0 ;
k k <5 5 ;
k k ++) )
{ printf("%5d%5d%5d" , x[k] , y[k] , z[k]) ;
printf("\ \ n") ;
} } } } 6.2
二维数组
二维数组的定义与引用
定义二维数组的一般形式如下:
类型说明符
数组名[ [ 常量表达式 1][ 常量表达式 ] 2] ;
二维数组的初始化
与一维数组一样,也可以对静态存储的二维数组进行初始化。
在对二维数组进行初始化时要注意以下几点。
(1 1 )在分行给二维数组赋初值时,对于每一行 都可以只对前几个元素赋初值,后面未赋初值的元素系统将自动赋初值 0 0 ;并且,还可以只对前几行元素赋初值。
(2 2 )在给全部元素赋初值时,说明语句中可以省略第一维的长度说明。
(3 3 )在分行赋初值时,也可以省略第一维的长度说明 6.3
字符数组与字符串
字符数组的定义与初始化
定义字符数组的一般形式如下:
char
数组名[ [ 常量表达式] ] ;
一维字符数组
char
数组名[ [ 常量表达式 1][ 常量表达式 ] 2] ;
二维字符数组
(1 1 )当对字符数组中所有元素赋初值时,数组的长度说明可以省略。
(2 2 )可以只对前若干元素赋初值。
(3 3准 )虽然标准 C C 语言规定只能对 ‚ 静态存储 ‛ 的字符数组进行初始化,即除了可以对外部( ( 全局) ) 字符数组进行初始化外,还可以对用 c static 说明的局部字符数组进行初始化。
字符串
C C 语言规定,字符串常量(简称字符串)要用一对双撇号括起来。在一个字符串常量中,最后还包括一个结束符 ‘\ \ 0’ 。
C C 语言允许用字符串常量对字符数组进行初始化。
字符数组与字符串 的输入与输出 1 1 .输入输出一个字符( ( 格式说明符为
%c)
在用于输入时,输入项为数组元素地址。在具体输入时,各字符之间不要分隔,字符也不要用单撇号括起来。
在用于输出时,输出项为数组元素。
2 2 .输入输出一个字符串(格式说明符为
%s )
在用格式说明符s %s 进行输入输出时,其输入输出项均为数组名。但在输入时,相邻两个字符串之间要用空格分隔,系统将自动地在字符串最后加结束符""\ \" 0" 。
字符串处理函数
下面简单介绍一些常用的字符串处理函数。
(1 1 )
puts (字 符数组名)
功能:输出一个字符串到终端。
(2 2 )
gets (字符数组名)
功能:从终端输入一个字符串到字符数组,并返回字符数组的地址。
(3...
热门文章:
- 制造业工人的述职报告模板3篇2023-12-20
- 学校副校长工作述职报告范文篇4篇2023-12-19
- 基层单位领导干部述职述廉报告5篇2023-12-18
- 2024年度班主任个人述职报告优萃5篇2023-12-16
- 社区党组书记党建工作述职报告4篇2023-12-16
- 2024一年级教师述职报告四章14篇2023-12-14
- 2024教师个人述职报告范文合集4篇2023-12-14
- 优推党委书记述职述廉报告例文三篇3篇2023-12-13
- 程序员述职报告怎么写参考范文8篇2023-12-12
- 财务负责人述职报告优选范文3篇2023-12-11
相关文章: