1、机器语言:
由计算机硬件系统可以识别的二进制指令组成的语言称为机器语言。
汇编语言:
汇编语言将机器指令映射为一些可以被人读懂的助记符,如ADD、SUB等。
高级语言:
高级语言屏蔽了机器的细节,提高了语言的抽象层次,程序中可以采用具有一定涵义的数据命名和容易理解的执行语句。这使得在书写程序时可以联系到程序所描述的具体事物。
高级语言:包括面向过程的高级语言和面向对象的高级语言 。
C语言的特点
丰富的数据类型8、实型常量指数形式:1.2×10-3 ---------? 1.2e-3
例如123.456可以表示为:
123.456e0、12.3456e1、1.23456e2、…
把其中的1.23456e2称为“规范化的指数形式”:
即在字母e(或E)之前的小数部分中,小数点左边应有一位(且只能有一位)非零的数字。
所有的实型常量均视为双精度类型。
字符常量是指用一对单引号括起来的一个字符。如 ‘ a ’ , ‘9’ , ‘!’
11、(1) 基本整型 :以int表示。
(2) 短整型:以short int表示,或以short表示。
(3) 长整型:以long int表示,或以long表示。
取值范围:long>=int>=short
int型变量的值范围:-32768~32767
无符号型变量只能存放不带符号的整数,而不能存放负数。一个无符号整型变量中可以存放的正数的范围比一般整型变量中正数的范围扩大一倍。
数据类型转换有两种方式:自动类型转换、强制类型转换。
无论是自动类型转换还是强制类型转换,都并没有改变变量本身的数据类型。
14、
15、表达式=运算符+运算对象
16、单目算术运算符:自增、自减运算符为单目算术运算符,具有右结合性。
作用是使变量的值增1或减1,如:
++i,--i (在使用i之前,先使i的值加(减)1)
i++,i-- (在使用i之后,使i的值加(减)1)
17、条件运算符是C语言中唯一的一个三目运算符。
格式:表达式1?表达式2:表达式3
功能:根据表达式1的真假来决定整个条件表达式的取值。
18、字符输出函数putchar()
(1)参数c可以是字符型变量、整型变量、字符常量或整型常量(要求在0-255范围内)。
(2)函数返回值为输出字符的ASCII码值。
(3)putchar函数也可以输出转义字符。
(4)一个putchar函数只能输出一个字符。
19、字符输入函数 getchar()
(1)函数返回值为输入字符的ASCII码值。
(2)getchar函数的值可以赋给一个字符变量或整型变量,也可以不赋给任何变量。
(3)一个getchar函数只能接收一个字符。
20、printf(格式控制,输出表列)
“格式控制” 包括两种信息:
① 格式说明:由“%”和格式字符组成。② 普通字符:即需要原样输出的字符。
原则上,输出表列中变量的个数和类型应与格式控制中指定的数据的个数和类型应一致,且从左到右一一对应。
(1) printf(“%e”,123.456); 输出:1.234560e+002。
(2) int n=10;
printf("%d,%o,%x\n",n,n,n);
printf("%#o,%#x\n",n,n); 运行结果:10,12,a 012,0xa
(3)float f=123.456;
printf("%f %10f %10.2f %.2f %-10.2f\n", f,f,f,f,f);
输出结果如下:
123.456001 123.456001 123.46 123.46 123.46
21、格式输入函数 scanf()
scanf(格式控制,地址表列)
“格式控制”的含义同printf函数;
“地址表列”是由若干个地址组成的表列,可以是变量的地址,或字符串的首地址。
说明:
1、在执行数据输入时,以一个或多个空格、或回车键、或跳格键(Tab)作为分隔符。
2、“&”是地址运算符,作用于变量,其地址在变量定义时由编译程序确定。
22、(1)可以指定输入数据所占列数,系统自动按它截取所需数据。
scanf("%3d%3d",&a,&b);
输入: 123456
系统自动将123赋给a,456赋给b。
(2)此方法也可用于字符型:
scanf(“%3c”,&ch);
如果从键盘连续输入3个字符abc,由于ch只能容纳一个字符,系统就把第一个字符‘a’赋给ch。
(3)输入数据时不能规定精度,例如,
scanf("%7.2f",&a);
是不合法的,不能企图用这样的scanf函数并输入以下数据而使a的值为12345.67。
(4)如果在“格式控制”字符串中除了格式说明以外还有其他字符,则在输入数据时应输入与这些字符相同的字符。
注意:
(1)在scanf中应使用变量的地址。
(2)选择合适的输入分隔符。
(3)可以指定输入数据的宽度,系统自动截取。
(4)在用“%c”输入字符时,空格和“转义字符”都作为有效字 符输入,不需要用空格作间隔。
(5)输入数据时不能规定精度。
(6)在输入数据时,遇到以下情况该数据认为结束:遇空格、回车、跳格键(Tab)、遇宽度结束、遇非法输入。
24、表达式语句。表达式语句由表达式加上分号组成。
格式:表达式;功能:计算表达式的值。
说明:C语言中的任何一个表达式都可以构成语句。
注意:如果没有分号,如“x=y+z”只是一个表达式,而不是一条语句。
25、函数调用语句。此类语句由函数调用加上分号构成。
格式:函数名[(实参列表)];
功能:调用函数,以完成函数所规定的功能。
例如:printf(“C Program”);
控制语句。控制语句用于控制程序的流程,以实现程序的各种结构方式。
空语句。空语句仅由一个分号组成。
格式: ; 功能:不执行任何操作。
编程风格:正确性、可靠性、规范化、可读性、灵活性:
if语句格式一:if (表达式)
语句
功能:如果表达式为真,则执行其后的语句,否则不执行语句。
30、格式2:if (表达式)
语句1
else
语句2
功能:如果表达式为真,则执行语句1;否则执行语句2。
31、格式3:if (表达式1)
语句1
else if (表达式2)
语句2
else if (表达式3)
语句3
……
else if (表达式n)
语句n
else
语句n +1
32、if关键字之后均为表达式。该表达式可以是逻辑表达式、关系表达式以及其它表达式。只要表达式运算的结果为非0,就按“真”处理,执行相应的语句;否则按“假”处理,执行相应的语句。
在if语句中的条件判断表达式必须用圆括号括起来,每个语句之后必须加分号。
在if语句的第二、三种形式中,else子句不能作为语句单独使用,必须是if语句的一部分,应与if配对使用。
在if语句的三种形式中,所有的语句应为单个语句,如果想在满足条件时执行一组(多个)语句,则必须把这一组语句用“{}”括起来组成一个复合语句。但是在“}”之后不能加分号。
在if语句的表达式中,一定要避免判断实数与零值的等值比较。
虽然在C里面,常量NULL、零值都是false,非零值都是true,但是为了使得程序清晰易读,建议在表达式中不要使用“if (a)”这样的语句。
if语句的嵌套:
格式:if (表达式)
if语句
或者:if (表达式)
if语句
else
if语句
注意:
正确书写格式。一般按层次缩进书写,以便掌握配对关系.
在多重嵌套时,else总是与在它之前出现的、尚未匹配的且离它最近的if匹配。
如果if与else数目不相等,最好用花括号确定配对关系。
形成多重嵌套实质上是为了进行多分支选择,这种问题一般可以使用if语句的第三种形式,即“if-else-if”语句,或者将要介绍的switch语句完成。因此,在一般情况下,较少使用if语句的嵌套结构,以使程序更便于阅读理解。
选择结构——switch语句
格式:switch (表达式)
{
case 常量表达式1:语句1
case 常量表达式2:语句2
?
case 常量表达式n:语句n
default: 语句n+1
}
功能:计算表达式的值,并逐个与其后的常量表达式进行比较,当表达式的值与某个常量表达式的值相等时,即执行其后的语句,然后不再进行判断,继续执行后面所有case后的语句。如表达式的值与所有case后的常量表达式均不相同时,则执行default后的语句。
说明:
“case 常量表达式”只相当于一个语句标号,表达式的值和某标号相等则转向该标号执行,但不能在执行完该标号的语句后自动跳出整个switch语句。为了避免上述情况,C提供了break语句。
在case后的各个常量表达式的值不能相同,否则会出现错误。
在case后,允许有多个语句,可以不用{}括起来。
各个case和default子句的先后顺序可以变动,不影响程序的执行结果。
default子句可以省略不用,此时当表达式的值与所有case后的常量表达式的值不同时,退出switch语句,继续执行后续程序。
switch后面括号中的表达式只能是整型、字符型、枚举类型,case后的常量表达式的类型必须与之匹配。
各个case之后是常量表达式,一定不要试图使用条件表达式或者逻辑表达式。
多个case可以共用一组执行语句。
循环结构——while语句
格式:while (表达式) 语句
功能:计算表达式的值,当值为真时,执行循环体。
说明:(1)while语句中的表达式一般是关系表达式或者逻辑表达式,只要值为真就可以继续执行循环体。
如果循环体包含一个以上的语句,必须用{}括起来构成复合语句。
do-while语句
格式:do {
语句
}while(表达式);
功能:先执行一次循环体,再判别表达式的值,如果为真则继续执行循环,否则终止循环。
说明:
(1)do-while语句的表达式后必须加分号。
(2)如果循环体由多个语句组成,也必须由{}括起来,组成一个复合语句。
37、for语句
格式:
for (表达式1;表达式2;表达式3)
语句
功能:(1)首先计算表达式1的值;
(2)再计算表达式2的值,若值为真,则执行一次循环体,否则跳出循环;
(3)计算表达式3的值,转回第(2)步重复执行。
38、for语句最易理解的如下形式:
for(循环变量赋初值;循环条件;循环变量增值)
语句
39、说明:
for语句的各个表达式均可省略,但是分号不可缺少。
如果循环变量已经在for语句前赋初始值,那么表达式1可以省略。
如果省略表达式2,一般在循环体中加入break语句来退出循环。
若省略表达式3,应在循环体中修改循环变量,保证循环能结束。
可以同时省略三个表达式中的任意2个。
三个表达式可以全部省略。
循环体可以是空语句。
表达式1可以是设置循环变量初值的赋值表达式,也可以是与循环变量无关的其它表达式。
表达式2一般是关系表达式或者逻辑表达式,但也可以是数值表达式或者字符表达式,只要其值为非零,就可以执行循环。
表达式3一般是改变循环变量的赋值表达式,但也可以是与循环变量无关的其它表达式。
表达式1和表达式3都可以是逗号表达式。
40、 break语句
格式:break;
功能:用于跳出switch结构,和从循环体内中途跳出循环体,即提前结束循环,执行循环下面的语句。
说明:
(1)在循环语句中,break语句一般与if语句一起使用。
(2)break语句不能用于循环语句和switch语句之外的其它任何语句之中。
41、 continue语句
格式:continue;
功能:跳过循环体中剩余的语句而强制执行下一次循环,即结束本次循环,跳过循环体中下面尚未执行的语句,接着进行下一次是否执行循环的判定。
说明:continue语句只能用在循环语句中,且一般都是与if语句一起使用。
42、continue语句和break语句的区别是:
continue语句只结束本次循环,而不是终止整个循环的执行。
break语句则是结束整个循环过程,不再判断执行循环的条件是否成立。
循环结构——百钱买百鸡问题
“百钱买百鸡”是我国古代的著名数学题。问题是这样描述的:3文钱可以买1只公鸡,2文钱可以买一只母鸡,1文钱可以买3只小鸡。用100文钱买100只鸡,那么各有公鸡、母鸡、小鸡多少只?
方法一:
#include
void main()
{
int i,j,k;
for (i=0;i<=33;i++)
for (j=0;j<=50;j++)
for (k=0;k<=300;k++)
if (3i+2j+k/3==100 && i+j+k==100 && k%3==0)
printf("公鸡%d只,母鸡%d只,小鸡%d只。\n",i,j,k);
}
方法二:
#include
void main()
{
int i,j,k;
for (i=0;i<=33;i++)
for (j=0;j<=50;j++)
{
k=100-i-j;
if (3i+2j+k/3==100 && k%3==0)
printf("公鸡%d只,母鸡%d只,小鸡%d只。\n",i,j,k);
}
}
方法三:
#include
void main()
{
int i,j,k;
for (i=0;i<=33;i++)
for (j=0;j<=(100-3i)/2;j++)
{
k=100-i-j;
if (3i+2j+k/3==100 && k%3==0)
printf("公鸡%d只,母鸡%d只,小鸡%d只。\n",i,j,k);
}
}
例 输出下列图形: 1 1 2 1 2 3 1 2 3 4 1 2 3 4 5 1 2 3 4 5 6 1 2 3 4 5 6 7 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 9
#include
void main()
{
int m,n;
for (n=1;n<=9;n++)
{ for(m=1;m<=n;m++)
printf("%4d",m);
printf("\n"); }
}
45、数组是有序数据的集合。
数组中的每一个元素都属于同一个数据类型。
用一个统一的数组名和下标来唯一地确定数组中的元素。
46、一维数组的定义
类型 数组名[常量表达式];
如: float a[10]; (a[0]~a[9]称为数组元素)
常量表达式中可以包括常量和符号常量,不能包含变量。
47、一维数组元素的引用
数组必须先定义,然后使用。
C语言规定只能逐个引用数组元素而不能一次引用整个数组。
数组元素的表示形式:
数组名[下标]
例如: a[0] = a[5] + a[23];
48、int a[10]={0,1,2,3,4};
等价于:
int a[10]={0,1,2,3,4,0,0,0,0,0};
int a[5] = { 1,2,3,4,5 };
可以写成
int a[ ]= { 1,2,3,4,5 };
例 用冒泡法对6个数排序(由小到大)。
#include
#define N 6
void main()
{
int a[N];
int i,j,t;
printf("input numbers:\n");
for(i=0;i scanf("%d",&a[i]);
printf("the unsorted numbers:\n");
for(i=0;i printf("%d ",a[i]);
printf("\n");
//核心代码部分:开始冒泡排序
for(i=1;i<=N-1;i++)
for(j=1;j<=N-i;j++)
if(a[j-1]>a[j])
{ t=a[j-1]; a[j-1]=a[j]; a[j]=t; }
printf("the sorted numbers:\n");
for(i=0;i printf("%d ",a[i]);
}
50、二维数组的定义
类型 数组名[常量表达式1][常量表达式2];
常量表达式1声明二维数组的行数
常量表达式2声明二位数组的列数;
例如:
float b[3][4] ; //a为3×4(3行4列)的数组。
不能写成:
float b[3,4];
51、二维数组的引用
二维数组的元素的表示形式为:
数组名[下标][下标]
在使用数组元素时,应该注意下标值应在已定义的数组大小
的范围内。
常出现的错误是:
int a[3][4]; //a为3×4的数组
…
a[3][4]=3; //引用a]3]]4]超过了数组的范围
52、二维数组的初始化
二维数组初始化:
(1) 分行给二维数组赋初值。如
int a[3][4] = { { 1,2,3,4 } , { 5,6,7,8 } , { 9,10,11,12 } };
(2) 将所有数据写在一个花括弧内,按数组排列的顺序对各元素赋初值。如:
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
(3) 可以对部分元素赋初值。
int a[3][4] = { {1} , {5} , {9} };
可以只对某几行元素赋初值:
int a[3][4] = { {1} , {5,6} };
(4) 如果对全部元素都赋初值(即提供全部初始数据),则定义数组时对第一维的长度可以不指定,但第二维的长度不能省。如:
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
等价于:
int a[ ][4]={1,2,3,4,5,6,7,8,9,10,11,12};
(5)有的编译系统,如VC6.0中,初始化数组时不能出现空的花括号,如
int a[3][4]={{1,2},{},{3,4}};
53、字符数组
用来存放字符数据的数组是字符数组。
54、一维字符数组的定义
格式:char 字符数组名[常量表达式]
功能:定义一维字符数组
【例如】char a[4], str[5];
【说明】
(1)字符型数据在内存中存放的是ASCII码,每个字符占一个字节的存储空间。
(2)C语言允许使用整型数组来存放字符型数据。如
int a[5];
a[0]=’a’;
scanf(”%c”,&a[1]);
55、C语言中,字符串作为一维字符数组存放在内存中。如字符串“C Language”,包含字符个数为10,但在内存中占11个字节,最后一个字节存放空字符‘\0’。
说明:
字符串最后的空字符‘\0’称为字符串结束标志,其ASCII码为0,由系统自动加上。程序中主要依靠检测‘\0’的位置来判定字符串是否结束,而非根据数组的长度来判断。
【说明】字符串输出时不包括结束符‘\0’
56、字符数组的初始化
(1)逐个字符初始化字符数组。如
char str[4]={‘A’,‘B’,‘C’,’\0’};
char str[4]={65,66,67,0};
char str[ ]={‘A’,‘B’,‘C’,’\0’};
char str[4]={‘A’,‘B’,‘C’};
(2)用字符串常量初始化字符数组。如
char str[4]={“ABC”};
char str[4]=“ABC”;
char str[ ]=“ABC”;
【说明】
字符串对应的字符数组必然以‘\0’结尾,但字符数组也可不含‘\0’字符,也可以包含多个空字符‘\0’,甚至‘\0’后可以有非空字符。如 char a[3]={ ‘A’,‘B’,‘C’};
char str[6]={‘A’,‘B’,‘\0’,‘C’‘\0’‘\0’};
【注意】
以字符串常量初始化字符数组时,字符数组的长度要比字符串有效长度大1。
二维字符数组可以看作一个特殊的一维数组,该一维数组的每个元素都是一个一维字符数组。每个一维字符数组可以存放一个字符串,因此,一个N行M列的二维字符数组就可以用来存放N个字符串,且每个字符串的最大有效长度为M-1。
字符数组的输入输出
字符数组的输入输出可以有两种方法:
逐个字符输入输出。用 “%c”输入或输出一个字符。
即在scanf和printf函数中用格式符“%c”进行输入或输出。
例如:char str[5]; int i;
for(i=0;i<5;i++)scanf(“%c”,&str[i]);
for(i=4;i>=0;i--)printf(“%c”,str[i]);
(2) 将整个字符串一次输入或输出。用“%s” 输出字符串。例如:
char c[ ]={"china"};
printf(“%s",c);
在内存中数组c的状态如图所示。
请注意:
(1) 输出字符不包括结束符‘\0’。
(2) 用“%s”格式符输出字符串时,printf函数中的输出项是字
符数组名,而不是数组元素名。写成下面这样是不对的:
printf("%s",c[0]);
(3) 如果数组长度大于字符串实际长度,也只输出到遇‘\ 0’结
束。如:
char c[10]={"china"};
printf("%s",c); 输出“china”
(4)可以用scanf函数输入一个字符串。例如:
char c[6];
scanf("%s",c); 输入:china
如果利用一个scanf函数输入多个字符串,则以空格分隔。例如:
char strl[5],str2[5],str3[5];
scanf("%s%s%s",str1,str2,str3);
59、字符串处理函数
下面介绍几种常用的函数。
1. puts(字符数组)
其作用是:将一个字符串(以‘\0’结束的字符序列)输出到终端。
用puts函数输出的字符串中可以包含转义字符。
使用puts函数或以字符串整体进行输出时,系统一旦遇到‘\0’便停止输出,而且只有遇到‘\0’才停止输出。
使用puts(str);或printf(“%s”,str);输出字符数组str时,str中一定要有‘\0’。
2. gets(字符数组)
其作用是:
从键盘输入一个字符串(该字符串中可以包含空格),直至遇到回车符为止,并将该字符串存放到由指定的数组中(或内存区域)。
并且得到一个函数值。该函数值是该字符数组的起始地址。
注意:
用puts和gets函数只能输入或输出一个字符串,
不能写成puts(str1,str2)或gets(str1,str2)
使用gets函数或以字符串整体进行输入时,系统自动在末尾添加‘\0’;
输入字符串时,gets函数以回车作输入结束标志,而scanf以空格、Tab及回车符作为结束标志。
3. strcat(字符数组1,字符数组2)
作用是:连接两个字符数组中的字符串,把字符串2接到字
符串1的后面,结果放在字符数组1中,函数调用后得到一个
函数值——字符数组1的地址。
说明:
字符数组1必须足够大,以便容纳连接后的新字符串。
连接前两个字符串的后面都有一个‘\0’,连接时将字符串1后面的‘\0’取消,只在新串最后保留一个‘\0’。
4、strcpy(字符数组1,字符串2)
它是“字符串复制函数”。作用是将字符串2复制到字符数组1
中去。例如:
char str1[10],str2[ ]={"china"};
strcpy(str1,str2);
说明:
(1) 字符数组1必须定义得足够大。
(2) strcpy(str1,"china");作用与前相同。
(3) 复制时连同字符串后面的‘\0’一起复制到字符数组1中。
(4)复制后字符数组1原来内容被覆盖。
(5) 下面两行都是不合法的:
str1={"china"};
str1=str2;
5. strcmp(字符串1,字符串2)
作用是比较字符串1和字符串2。例如:
strcmp(str1,str2);
strcmp("china","Korea");
strcmp(str1,"beijing");
字符串比较的规则:对两个字符串自左至右逐个字符相比(按
ASCII码值大小比较),直到出现不同的字符或遇到‘\0’为止。
如全部字符相同,则认为相等;若出现不相同的字符,则以
第一个不相同的字符的比较结果为准。
“a”<“b”, “a”>“A”,“computer”>“compare”,“these”>“that”,“36+54”>“!”,“china”>“canada”,“DOG”<“cat” 。
比较的结果由函数值带回。
(1) 如果字符串1=字符串2,函数值为0。
(2) 如果字符串1>字符串2,函数值为一正整数。
(3) 如果字符串1<字符串2,函数值为一负整数。
注意:对两个字符串比较,不能用以下形式:
if(str1==str2) printf(“yes");
而只能用
if(strcmp(str1,str2)==0) printf(“yes”);
6. strlen(字符数组)
测试字符串长度的函数。函数的值为字符串中的实际长度,
不包括‘\0’在内。
7. strlwr(字符串)
函数的作用是将字符串中大写字母换成小写字母。
8. strupr(字符串)
函数的作用是将字符串中小写字母换成大写字母。
60、输出杨辉三角形的前10行
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
. . . . . . .
#include
#define N 10
void main( )
{
int a[N][N],i,j;
for(i=0;i {
a[i][0]=1;
a[i][i]=1;
for(j=1;j a[i][j]=a[i-1][j-1]+a[i-1][j];
}
printf("杨辉三角的前%d行为:\n",N);
for(i=0;i {
for(j=0;j<=i;j++)
printf("%5d",a[i][j]);
printf("\n");
}
}
61、一个C程序可由一个主函数和若干个函数构成。
由主函数调用其他函数,其他函数也可以互相调用。
同一个函数可以被一个或多个函数调用任意多次。
62、函数定义的一般形式
类型标识符 函数名(类型标识符 形参1 , 类型标识符 形参2 , …)
{
函数体变量定义或声明部分;
函数体可执行语句部分;
}
例如:
int max(int x,int y)
{
int z;
z=x>y?x:y;
return z;
}
63、说明:
1. 如果是定义无参函数,则“形参表列”就不再需要,但括弧不能省略。
2. 当函数只完成特定的操作而不需要返回值时,可用类型标识符void。
3. 可以有“空函数”。即函数体为空。它的形式为:
类型说明符 函数名(类型标识符 形参1 , 类型标识符 形参2 , …)
{ }
“空函数”表明 “这里要调用一个函数”, 而现在这个函数没有起作用, 等以后扩充函数功能时补充上。
在同一个C程序中不可定义同名的变量,同样也不能定义同名的函数。
函数的调用
函数调用的一般形式
函数名(实参表列);
如果是调用无参函数,则“实参表列”可以没有,但括弧不能
省略。即:函数名( );
形参:函数定义时“()”内的参数为形参。
实参:函数调用时“()”内的参数为实参。
如果实参表列包含多个实参,则各参数间用逗号隔开。
实参与形参的个数应相等,类型应一致。
实参与形参按顺序对应,一一传递数据。
函数调用的方式
1. 函数语句
把函数调用作为一个语句。
2. 函数表达式
函数出现在一个表达式中,这种表达式称为函数表达式。
3. 函数参数
函数调用作为一个函数的实参。
66、函数的声明 函数“声明” 的作用:
把函数类型、函数的名字以及形参的类型、个数和顺序通知编译系统,以便在调用该函数时系统按此进行对照检查。
函数 “声明”的格式:
已定义的函数的首部,再加一个分号。
如: float circle_area(int r) ;
函数声明中也可以不写形参名,而只写形参的类型。
如: float circle_area(int) ;
在C语言中,把以上形式的函数声明称为函数原型。
函数原型的一般形式为:
(1) 函数类型 函数名(参数类型1, 参数类型2……);
(2) 函数类型 函数名(参数类型1 参数名1,
参数类型2 参数名2……);
编译系统不检查参数名。因此参数名是什么都无所谓。
对被调用函数的声明
首先被调用的函数必须是已经存在的函数(是库函数或用户自己定义的函数)。
如果使用库函数,一般还应该在本文件开头用#include命令将调用有关库函数时所需用到的信息“包含”到本文件中来。例如,#include
如果使用用户自己定义的函数,而且该函数与调用它的函数(即主调函数)在同一个文件中,一般还应该在主调函数中对被调用的函数作声明。
68、函数参数:形式参数和实际参数
在定义函数时函数名后面括弧中的变量名称为“形式参数”(简称“形参”);
在主调函数中调用一个函数时,函数名后面括弧中的参数(可以是一个表达式)称为“实际参数”(简称“实参”)。
Ps:关于形参与实参的说明:
(1) 当发生函数调用时,函数swap中的形参才被分配内存单元。在调用结束后,形参所占的内存单元即被释放。
(2)实参可以是常量、变量或表达式,如:
max(3 , a+b);
但要求它们有确定的值。
(3) 在被定义的函数中,必须指定形参的类型。
(4) 实参和形参在类型上应当相同或者赋值兼容。
例如:上例中输入:3.14 , 6.2
(5) C语言规定,实参变量对形参变量的数据传递都是“值传递”,即单向传递,只由实参传给形参,而不能由形参传回来给实参。在内存中,实参单元与形参单元是不同的单元。
69、函数的返回值
(1) 函数的返回值是通过函数中的return语句获得的。
return z; 与 return(z); 等价。
(2) 函数值的类型。
int max(float x,float y) / 函数值为整型 /
double min(int x,int y) / 函数值为双精度型 /
(3) 如果函数值的类型和return语句中表达式的值不一致,则以函数类型为准。即函数类型决定返回值的类型。
建议不要采用这种方法,而应做到使函数类型与return返回值的类型一致。
如果被调用函数中没有return语句,并不是指函数不带回值,而只是带回的是一个不确定的值。
为了明确表示“不带回值”,可以用“void”定义“无类型”(或称“空类型”)。
70、函数的递归调用
在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用。
例 用递归方法求n!。
可用下面的递归公式表示:
n!=1 (n=0,1)
n!=n(n-1)! (n>1)
有了上例的基础,很容易写出本题的程序:
#include
long fac(int n)
{
long f;
if(n<0) printf("n<0,dataerror!");
else if(n==0||n==1) f=1;
else f=fac(n-1)n;
return f;
}void main()
{
int n;
long y;
printf("input an integer number:");
scanf("%d",&n);
y=fac(n);
printf("%d!=%10ld",n,y);
}
71、数组作为函数参数
数组名也可以作实参和形参,传递的是整个数组。
1. 数组元素作函数实参
数组元素作为函数的实参,是单向传递,即“值传送”方式。
2. 数组名可作函数参数
(1) 用数组名作函数参数,应该在主调函数和被调用函数分别定义数组。
(2) 实参数组与形参数组类型应一致。
(3) C编译对形参数组大小不做检查,只是将实参数组的首地址传给形参数组。因此,score[n]和array[n]指的是同一单元。
(4) 形参数组也可以不指定大小,在定义数组时在数组名后面跟一个空的方括弧,为了在被调用函数中处理数组元素的需要,可以另设一个参数,传递数组元素的个数,上例可以改写为下例形式。
(5) 最后应当说明一点: 用数组名作函数实参时,不是把数组的值传递给形参,而是把实参数组的起始地址传递给形参数组,这样两个数组就共占同一段内存单元。形参数组中各元素的值如发生变化会使实参数组元素的值同时发生变化,这一点是与变量做函数参数的情况不相同的,务请注意。在程序设计中可以有意识地利用这一特点改变实参数组元素的值(如排序)。
例 用冒泡法对数组中10个整数按由小到大排序。
#include
void sort(int array[],int n)
{
int i,j,k,t;
for(i=0;i<=n-2;i++)
{
for(j=0;j<=n-2-i;j++)
{
if(array[j]>array[j+1])
{
t=array[j];
array[j]=array[j+1];
array[j+1]=t;
}
}
}
}
void main()
{
int i,j;
int nArray[10]={20,30,12,45,78,8,9,56,2,12};
printf("排序前的数组是:\n");
for(i=0;i<10;i++)
printf("%d ",nArray[i]);
sort(nArray,10);
printf("\n排序后的数组是:\n");
for(i=0;i<10;i++)
printf("%d ",nArray[i]);
}
3. 用多维数组名作函数参数
可以用多维数组名作为实参和形参,在被调用函数中对形参数组定义时可以指定每一维的大小,也可以省略第一维的大小说明。
int array[3][10]; //合法
int array[ ][10]; //合法
int array[ ][ ]; //不合法
int array[3][ ]; //不合法
形参数组第一维的大小可以是任意的。
如:实参数组定义为int score[5][10];
形参数组定义为int array[3][10]; //合法
C编译不检查第一维的大小。
第 2 页 共 17 页
|
|