在前面已经介绍过,C源程序是由函数组成的。虽然在前面各章的程序中大都只有一个
主函数 main(),但实用程序往往由多个函数组成。函数是C源程序的基本模块,通过对函
数模块的调用实现特定的功能。C语言中的函数相当于其它高级语言的子程序。C语言不仅
提供了极为丰富的库函数(如 Turbo C,MS C 都提供了三百多个库函数),还允许用户建立自
己定义的函数。用户可把自己的算法编成一个个相对独立的函数模块,然后用调用的方法来
使用函数。可以说C程序的全部工作都是由各式各样的函数完成的,所以也把C语言称为函
数式语言。
由于采用了函数模块式的结构,C语言易于实现结构化程序设计。使程序的层次结构清
晰,便于程序的编写、阅读、调试。
在C语言中可从不同的角度对函数分类。
【例 8.1】
#include "string.h"
#include
int max(int a, int b)
{
if (a > b)
return a;
else
return b;
}
main()
{
int max(int a, int b);
int x, y, z;
printf("input two numbers:\n");
scanf("%d%d", &x, &y);
z = max(x, y);
printf("maxmum=%d", z);
}
【例 8.2】可以说明这个问题。
#include "string.h"
#include
main()
{
int n;
printf("input number\n");
scanf("%d", &n);
s(n);
printf("n=%d\n", n);
}
int s(int n)
{
int i;
for (i = n - 1; i >= 1; i--)
n = n + i;
printf("n=%d\n", n);
}
【例 8.3】
#include
main()
{
int i = 8;
printf("%d\n%d\n%d\n%d\n", ++i, --i, i++, i--);
}
【例 8.4】计算s=(2^2)! + (3^2)!;
#include
long f1(int p)
{
int k;
long r;
long f2(int);
k = p * p;
r = f2(k);
return r;
}
long f2(int q)
{
long c = 1;
int i;
for (i = 1; i <= q; i++)
c = c * i;
return c;
}
main()
{
int i;
long s = 0;
for (i = 2; i <= 3; i++)
s = s + f1(i);
printf("\ns=%ld\n", s);
}
【例 8.5】用递归法计算 n!
用递归法计算 n!可用下述公式表示:
n!=1 (n=0,1)
n×(n-1)! (n>1)
按公式可编程如下:
#include
long ff(int n)
{
long f;
if (n < 0)
printf("n<0,input error");
else if (n == 0 || n == 1)
f = 1;
else
f = ff(n - 1) * n;
return (f);
}
main()
{
int n;
long y;
printf("\ninput a inteager number:\n");
scanf("%d", &n);
y = ff(n);
printf("%d!=%ld", n, y);
}
一块板上有三根针,A,B,C。A 针上套有 64 个大小不等的圆盘,大的在下,小的在上。
如图 5.4 所示。要把这 64 个圆盘从 A 针移动 C 针上,每次只能移动一个圆盘,移动可以借
助 B 针进行。但在任何时候,任何针上的圆盘都必须保持大盘在下,小盘在上。求移动的步
骤。
本题算法分析如下,设 A 上有 n 个盘子。
如果 n=1,则将圆盘从 A 直接移动到 C。
如果 n=2,则:
1.将 A 上的 n-1(等于 1)个圆盘移到 B 上;
2.再将 A 上的一个圆盘移到 C 上;
3.最后将 B 上的 n-1(等于 1)个圆盘移到 C 上。
如果 n=3,则:
A. 将 A 上的 n-1(等于 2,令其为 n)个圆盘移到 B(借助于 C),步骤如下: (1)将 A 上的 n
-1(等于 1)个圆盘移到 C 上。
(2)将 A 上的一个圆盘移到 B。
(3)将 C 上的 n-1(等于 1)个圆盘移到 B。 B. 将 A 上的一个圆盘移到 C。 C. 将 B 上的 n-1(等于 2,令其为 n
)个圆盘移到 C(借助 A),步骤如下:
(1)将 B 上的 n-1(等于 1)个圆盘移到 A。 (2)将 B 上的一个盘子移到 C。 (3)将 A 上的 n
-1(等于 1)个圆盘移到 C。
到此,完成了三个圆盘的移动过程。
从上面分析可以看出,当 n 大于等于 2 时,移动的过程可分解为三个步骤:
第一步 把 A 上的 n-1 个圆盘移到 B 上;
第二步 把 A 上的一个圆盘移到 C 上;
第三步 把 B 上的 n-1 个圆盘移到 C 上;其中第一步和第三步是类同的。
当 n=3 时,第一步和第三步又分解为类同的三步,即把 n-1 个圆盘从一个针移到另一 个针上,这里的 n
=n-1。 显然这是一个递归过程,据此算法可编程如下:
#include
move(int n, int x, int y, int z)
{
if (n == 1)
printf("%c-->%c\n", x, z);
else
{
move(n - 1, x, z, y);
printf("%c-->%c\n", x, z);
move(n - 1, y, x, z);
}
}
main()
{
int h;
printf("\ninput number:\n");
scanf("%d", &h);
printf("the step to moving %2d diskes:\n", h);
move(h, 'a', 'b', 'c');
}
【例 8.7】判别一个整数数组中各元素的值,若大于 0 则输出该值,若小于等于 0 则输出 0
值。编程如下:
#include
void nzp(int v)
{
if (v > 0)
printf("%d ", v);
else
printf("%d ", 0);
}
main()
{
int a[5], i;
printf("input 5 numbers\n");
for (i = 0; i < 5; i++)
{
scanf("%d", &a[i]);
nzp(a[i]);
}
}
【例 8.8】数组 a 中存放了一个学生 5 门课程的成绩,求平均成绩。
#include
float aver(float a[5])
{
int i;
float av, s = a[0];
for (i = 1; i < 5; i++)
s = s + a[i];
av = s / 5;
return av;
}
void main()
{
float sco[5], av;
int i;
printf("\ninput 5 scores:\n");
for (i = 0; i < 5; i++)
scanf("%f", &sco[i]);
av = aver(sco);
printf("average score is %5.2f", av);
}
【例 8.9】题目同 8.7 例。改用数组名作函数参数。
#include
void nzp(int a[5])
{
int i;
printf("\nvalues of array a are:\n");
for (i = 0; i < 5; i++)
{
if (a[i] < 0)
a[i] = 0;
printf("%d ", a[i]);
}
}
main()
{
int b[5], i;
printf("\ninput 5 numbers:\n");
for (i = 0; i < 5; i++)
scanf("%d", &b[i]);
printf("initial values of array b are:\n");
for (i = 0; i < 5; i++)
printf("%d ", b[i]);
nzp(b);
printf("\nlast values of array b are:\n");
for (i = 0; i < 5; i++)
printf("%d ", b[i]);
}
【例 8.10】如把例 8.9 修改如下:
#include
void nzp(int a[8])
{
int i;
printf("\nvalues of array aare:\n");
for (i = 0; i < 8; i++)
{
if (a[i] < 0)
a[i] = 0;
printf("%d ", a[i]);
}
}
main()
{
int b[5], i;
printf("\ninput 5 numbers:\n");
for (i = 0; i < 5; i++)
scanf("%d", &b[i]);
printf("initial values of array b are:\n");
for (i = 0; i < 5; i++)
printf("%d ", b[i]);
nzp(b);
printf("\nlast values of array b are:\n");
for (i = 0; i < 5; i++)
printf("%d ", b[i]);
}
【例 8.11】
#include
void nzp(int a[], int n)
{
int i;
printf("\nvalues of array a are:\n");
for (i = 0; i < n; i++)
{
if (a[i] < 0)
a[i] = 0;
printf("%d ", a[i]);
}
}
main()
{
int b[5], i;
printf("\ninput 5 numbers:\n");
for (i = 0; i < 5; i++)
scanf("%d", &b[i]);
printf("initial values of array b are:\n");
for (i = 0; i < 5; i++)
printf("%d ", b[i]);
nzp(b, 5);
printf("\nlast values of array b are:\n");
for (i = 0; i < 5; i++)
printf("%d ", b[i]);
}
本程序 nzp 函数形参数组 a 没有给出长度,由 n 动态确定该长度。在 main 函数中,函
数调用语句为 nzp(b,5),其中实参 5 将赋予形参 n 作为形参数组的长度。
d. 多维数组也可以作为函数的参数。在函数定义时对形参数组可以指定每一维的
长度,也可省去第一维的长度。因此,以下写法都是合法的。
int MA(int a[3][10])
或
int MA(int a[][10])。
【例 8.12】
#include
main()
{
int i = 2, j = 3, k;
k = i + j;
{
int k = 8;
printf("%d\n", k);
}
printf("%d\n", k);
}
【例 8.13】输入正方体的长宽高 l,w,h。求体积及三个面 xy,xz,y*z 的面积。
#include
int s1, s2, s3;
int vs(int a, int b, int c)
{
int v;
v = a * b * c;
s1 = a * b;
s2 = b * c;
s3 = a * c;
return v;
}
main()
{
int v, l, w, h;
printf("\ninput length,width and height\n");
scanf("%d%d%d", &l, &w, &h);
v = vs(l, w, h);
printf("\nv=%d,s1=%d,s2=%d,s3=%d\n", v, s1, s2, s3);
}
【例 8.14】外部变量与局部变量同名。
#include
int a = 3, b = 5; /*a,b 为外部变量*/
max(int a, int b) /*a,b 为外部变量*/
{
int c;
c = a > b ? a : b;
return (c);
}
main()
{
int a = 8;
printf("%d\n", max(a, b));
}
【例 8.15】考察静态局部变量的值。
#include
f(int a)
{
auto b = 0;
static c = 3;
b = b + 1;
c = c + 1;
return (a + b + c);
}
main()
{
int a = 2, i;
for (i = 0; i < 3; i++)
printf("%d", f(a));
}
对静态局部变量的说明:
【例 8.16】打印 1 到 5 的阶乘值。
#include
int fac(int n)
{
static int f = 1;
f = f * n;
return (f);
}
main()
{
int i;
for (i = 1; i <= 5; i++)
printf("%d!=%d\n", i, fac(i));
}
输出结果:
1!=1
2!=2
3!=6
4!=24
5!=120
【例 8.17】使用寄存器变量。
#include
int fac(int n)
{
register int i, f = 1;
for (i = 1; i <= n; i++)
f = f * i return (f);
}
main()
{
int i;
for (i = 0; i <= 5; i++)
printf("%d!=%d\n", i, fac(i));
}
输出结果
1!=1
2!=2
3!=6
4!=24
5!=120
说明:
【例 8.18】用 extern 声明外部变量,扩展程序文件中的作用域。
函数声明
// header.h
extern void printMessage(void); // 声明函数
// file1.c
#include "header.h"
void printMessage() {
printf("Hello, World!\n");
}
// main.c
#include "header.h"
int main() {
printMessage(); // 使用声明的函数
return 0;
}
变量声明
// file1.c
int globalVar = 10; // 定义并初始化全局变量
// file2.c
extern int globalVar; // 声明globalVar是在别处定义的