nullnull教学目标:
主要讲授函数的基本概念、函数的定义、函数的调用、内部函数和外部函数、局部变量和全局变量、动态存储变量和静态存储变量等内容,使学生逐步建立起模块化
的思想。通过本章学习,要求学生能应用模块化设计的思想编制较复杂的应用程序。
本讲重点:
1.函数的概念、定义和函数调用过程;
2.函数调用时的参数传递规则;
3.函数嵌套调用的方法 ;
4.局部变量的定义和使用。
null本讲难点:
1.函数的调用过程;
2.函数参数的定义与使用;
3.函数的递归调用;
4.局部变量和全局变量的概念和作用域。
5.静态局部变量的生存期与作用域及其使用。
教学方法:
理论教学与实践教学相结合。
null第 6章 函 数 6.1 函数的定义
6.2 函数的调用
6.3 数据传递方法
6.4 嵌套调用和递归调用
6.5 变量的作用域
6.6 变量的存储类别
6.7 程序设计举例 null6.1 函数的定义 1. 函数头
函数头有经典与现代两种形式, 现代形式称之为函数原型。
经典形式:
函数属性 函数类型 函数名(函数参数
) 参数说明
如: static float f1(a,b,c)/*属性static,类型float,函数名f1,函数参
数表″a,b,c″/ float a, b, c; /*参数说明*/
现代形式:
函数属性 函数类型 函数名(参数说明)
如: static double f2(float x, float y, float z) null 2. 函数体
函数体由服务于函数的数据说明与执行语句两部分组成。数据说明包括数据定义和数据申明, 完成数据描述, 执行语句完成操作描述。TURBO C中数据说明必须位于函数体或复合语句的开始处, 但C++中可根据需要随时定义。 一个函数的函数体可以为空, 此时的函数称为空函数, 空函数常用于程序调试。
空函数的形式为:
void f( )
{ } null6.1.2 返回语句 通过在函数中使用返回语句, 返回一个值给函数, 同时终止函数的调用, 返回主函数。
格式:
return(表达式);
或return 表达式;
功能:
(1) 计算表达式的值, 将表达式的值返回给函数。
(2) 从被调用的函数返回主调函数。 null6.1.3 函数的定义 (1) 需定义函数的属性。
(2) 需定义函数的类型。
(3) 给函数取一个名字。
(4) 设计函数的参数。
(5) 对函数中使用的量进行定义。
(6) 对函数的执行部分进行描述。 null例 6 – 1 求两个数的最大值函数。 /*求两个数的最大值函数*/
float max(x, y) (1) 函数值类型float
float x, y; (2) 函数名max
{float m; (3) 函数参数x、 y, 类型为float
if (x>y) m=x;
else m=y;
return(m); /*返回最大值*/
} null说明:
(1) 函数头可以采用现代形式:
float max(float x, float y)
(2) 函数体也有多种等价形式:
形式一: if (x>y) return(x);
else return(y);
形式二: return(x>y?x: y); null例 6-2 判断两个数是否是相等函数。 方法一: /*判断两个数是否是相等函数*/
int eq(x, y) (1) 函数值类型int, 可以缺省
float x, y; (2) 函数名eq
{float t; (3) 函数参数x、 y, 类型为float
if (x==y) t=1;
else t=0;
return(t); /*相等返回1, 不等返回0*/
} null方法二:
/*判断两个数是否是相等函数*/
int eq(x, y)
float x, y;
{ if (x==y) return(1);
else return(0);
} null方法三:
/*判断两个数是否是相等函数*/
int eq(x, y)
float x, y;
{return(x==y);
} null例 6-3 符号函数。
方法一: /*符号函数*/
char sign(x) (1) 函数值类型char
float x; (2) 函数名sign
{char s; (3) 函数参数x, 类型为float
if (x>=0) s=′+′;
else s=′-′;
return(s);
} null方法二:
/*符号函数*/
char sign(x)
float x;
{char s;
if (x>=0) return(′+′);
else return(′-′);
} null例 6-4 求三角形面积函数。 /*求三角形面积函数*/
float sabc(a, b, c) (1) 函数值类型float
float a, b, c; (2) 函数名sabc
{float hl; (3) 函数参数a、 b、 c, 类型为float
hl=0.5*(a+b+c);
return(sqrt(hl*(hl-a)*(hl-b)*(hl-c)));
} null例 6 – 5 素数判断函数。
/*素数判断函数*/
int pn(n) (1) 函数值类型int
int n; (2) 函数名pn
{int i; (3) 函数参数n, 类型为int
int flag; /*素数标志*/
flag=1;
for(i=2; i<=n/2; i++)
if (n%i==0){flag=0; break; }
return(flag);
} null例 6-6 阶乘函数。
/* 阶乘函数*/
long int fn(n)
int n;
{int i;
long int t;
t=1;
for(i=1; i<=n; i++)
t*=i;
return(t);
} null 例6-7 平方函数。
/*平方函数*/
float sq(x)
float x;
{return(x*x); }
说明: C语言的函数是平等的关系、并列的关系, C语言的函数体中不能包含函数的定义, 不允许嵌套定义。 null6.2 函数的调用 6.2.1 函数调用的一般形式 函数调用的一般形式为:
函数名(实参表); null 说明:
(1) 如果调用无参函数, 则无实参表, 此时小括号不能省略。
(2) 调用时, 实参与形参的个数应相同, 类型应一致。
(3) 实参与形参按顺序对应, 一一传递数据。 调用后, 形参得到实参的值。
(4) 实参可以是表达式。 如是表达式实参, 先计算表达式的值, 再将值传递给形参。 null (5) 在C语言中, 实参表的求值顺序有的系统按自左至右的常规顺序, 有的系统则按自右至左的顺序求实参数值。大多数C(包括TURBO C)采用自右而左的顺序求值。
例如: int i=3;
printf(“%d, %d”, i, ++i);
① 实参求值自左至右, 输出3, 4;
② 实参求值自右至左, 输出4, 4。
为了避免出现意外情况, 尽可能将参数表达式的计算移至调用函数前进行。
(6) 主函数由系统调用。 null6.2.2 函数调用的方式 1. 表达式方式
函数调用出现在一个表达式中, 这种表达式称为函数表达式。 这时要求函数返回一个确定的值以参加表达式的运算。
例如: y=max(a, b)+max(c, d), 两次函数调用都是表达式的一部分, 分别以返回a与b、 c与d的最大值参与表达式运算。 null 2. 语句方式
把函数调用作为一个语句。常用于只要求函数完成一定的操作, 不要求函数返回值。这在scanf( )函数及printf( )函数的调用中已多次使用。
在其它高级语言中, 函数的调用只能以表达式方式进行。 C语言中的语句方式调用, 实际还是以表达式方式调用为基础。 null 3. 参数方式
函数调用作为另一个函数的实参。
例如: m=max(max(a, b), max(c, d)), max(a, b)与max(c, d)两次函数调用作为另一次max( )函数调用的实参, 用来求出a、 b、 c、 d的最大值。
以参数方式调用实际上是表达式调用方式的一种特殊情况。 null例 6-8 用调用函数的方式来求下面两个三角形的面积。 /*程序 7-8, 用调用函数的方式来求三角形的面积*/
float sf(a, b, c) /*求三角形的面积函数*/
float a, b, c;
{float hl;
hl=0.5*(a+b+c);
return(sqrt(hl*(hl-a)*(hl-b)*(hl-c)));
}
main( ) /*主函数*/
{float x, y, z;
clrscr( );
x=3, y=4, z=5; nullif ((x+y>z)&&(y+z>x)&&(z+x>y))
printf(″三边为%5.2f, %5.2f, %5.2f的三角形面积等于%5.2f \n″, sf(x, y, z));
else printf(″不能构成三角形!\n″);
x=y=z=1;
if ((x+y>z)&&(y+z>x)&&(z+x>y))
printf(″三边为%5.2f, %5.2f, %5.2f的三角形面积等于%5.2f \n″, sf(x, y, z));
else printf(″不能构成三角形!\n″);
}
运行结果:
三边为 3.00, 4.00, 5.00的三角形面积等于 6.00
三边为 1.00, 1.00, 1.00的三角形面积等于 0.43 null例 6-9 调用函数求 2~1000之间的所有素数。 /*程序 7 - 9, 调用函数求2~1000之间的所有素数*/
int pf(n) /*素数判断函数*/
int n;
{int i;
int flag;
flag=1;
for(i=2; i<=n/2; i++)
if (n%i==0){flag=0; break; }
return(flag);
} nullmain( ) /*主函数*/
{int i;
int count=0; /*统计素数个数, 用以控制输出格式*/
clrscr( );
printf(″2~1000之间的素数如下: \n″);
for(i=2; i<=1000; i++)
if (pf(i)==1)
{ printf(″%6d″, i);
count++;
if(count%5==0) printf(″\n″); /*每行输出5个素数*/
}
} null6.2.3 被调函数说明 用户自定义函数一般需在调用前在主调函数中进行说明。
函数说明是一种申明, 是告诉主调函数这里调用的是一个什么样的函数。
函数说明的一般形式为:
被调函数类型 被调函数名( );
注意, 不是函数定义, 其后有分号。 null例6-10 求2~n之间的所有素数。 main( )
{int n;
int i;
int count=0;
int pf( ); /*函数说明*/
clrscr( );
printf(″请输入n: ″);
scanf(″%d″, &n);
printf(″2~n之间的素数如下: \n″);
for(i=2; i<=n; i++)
if (pf(i)==1)/*调用前申明的函数*/
{ printf(″%6d″, i);
count++;
if(count%5==0) printf(″\n″);
}
} null 有下面一些情况, 在调用函数前可不加说明:
(1) 如果是整型函数或字符型函数, 可以不加说明, 系统自动按整型函数处理。
(2) 如果被调用函数的定义出现在主调函数之前, 可以不加说明。例7-8、7-9就属于这种情况。
(3) 如果已在所有函数定义之前, 或在文件的开头, 或在函数的外部已作说明, 可以不加说明。
除了上述情况, 其它情况均必须对被调用的函数在调用前进行说明。 null 另请注意:
(1) 函数一般先定义, 后使用。
(2) 为清晰起见, 一般均对被调用的函数在调用前进行说明, 以增加程序的可读性。
(3) 函数不能重复定义, 但可以反复说明。
(4) 对于
函数, 还应在文件开头用文件包含指令#include指明调用有关库函数时所需用到的信息。 例如: #include ″stdio.h″, stdio.h是一个头文件, 它包含了输入输出库函数所用到的一些宏定义信息, null6.3 数据传递方法 C语言程序由若干相对独立的函数组成, 在程序运行期间, 必然存在数据在函数中流动, 流入或流出, 这就是函数之间的数据传递, 也是函数之间的接口。一般语言中, 数据传递有参数传递和全局变量传递两种方法, C语言也提供这两种传递方法。参数传递是数据传递的主门(正门), 全局变量传递是数据传递的辅门(后门), 数据传递时一般宜用参数传递。 null例如, 求三个数的最大值:
① 主调函数: ……
m=max(a, b, c); a b c m(max)
…… ↓ ↓ ↓ ↑
② 被调函数: float max(x, y, z) x y z t
float x, y, z;
{ float t;
t=x;
if(y>t) t=y;
if(z>t) t=z;
return(t);
} null6.4 嵌套调用和递归调用6.4.1 嵌套调用 null 例 6-11 定义一个函数求2~n之间的完数, 调用完数判
断函数完成。 /*定义一个函数求2~n之间的完数, 调用完数判断函数完成*/
void wsh(n)
int n;
{int i;
int wf( ); /*函数说明*/
printf(″2~%d之间的完数如下: \n″, n);
for(i=2; i<=n; i++)
if (wf(i)==1) printf(″%6d″, i);
} null/*定义一个函数判断x是否为完数*/
int wf(x)
int x;
{int i, s=0;
int w;
for(i=1; i
0) j=n*jf(n-1); /*递归调用*/
else j=1; /*递归终止*/
return(j); } null我们也可先判断是否为递归调用终止条件, 如不是, 按转化规则转化来写递归函数。 long int jf(n) i
int n;
{long int j;
if (n==0) j=1; /* 递归终止*/
else j=n*jf(n-1); /*递归调用*/
return(j);
} null如下是计算4!的过程: if(4)=4*jf(3) if(4) =24
↓ ↑
if(3)=3*jf(2) if(3)=6
↓ ↑
if(2)=2*jf(1) if(2)=2
↓ ↑
if(1)=1*jf(0) if(1)=1
↓ ↑
if(0)=1 null例 6-13 用递归方法计算mn 的函数。
方法一:
① 转化: mn→mn-1→mn-2→…→m2→m1→m0
mn=m*mn-1
② 终止: n=0, m0 =1
相应的递归函数为:
long int mn(m, n) /* 计算m 的n次方递归函数*/
int m, n;
{long int j;
if (n>0) j=m*mn(m, n-1); /*递归调用*/
else j=1; /*递归终止*/
return(j); } null方法二:
① 转化: n为偶数, mn →mn/2→…→m0, mn=(mn/2)2
n为奇数, mn→m(n-1)/2→…→m0, mn=m*(m(n-1)/2)2
② 终止: n=0, m0 =1
相应的递归函数请读者自己编程实现。采用方法二, 递归调用的次数比方法一要少许多。 null例 6-14 用递归方法计算Fibonacci数列的第n项函数。
① 转化: n>2, f(n)=f(n-1)+f(n-2)
② 终止: n=1、 2, f(1)=f(2)=1
相应的递归函数为:
int fib(n) /* 计算Fibonacci数列的第n项*/
int n;
{int j;
if (n>2) j=f(n-1)+f(n-2); /*递归调用*/
else j=1; /*递归终止*/
return(j); } null 例 6-15 年龄问。有5个人坐在一起, 问第5个人多少岁, 他说比第 4 个人大2岁。问第4个人多少岁, 他说比第3个人大2岁。问第3个人多少岁, 又说比第2个人大2岁。问第2个人多少岁, 说比第1个人大2岁。最后问第1个人多少岁, 他说是10岁。请问第5个人多少岁?。
① 转化: n>1, age(n)=age(n-1)+2
② 终止: n=1, age(1)=10 nullage(n) /*求年龄的递归函数*/
int n;
{ int a; /*用作存放函数的返回值*/
if(n==1) a=10;
else a=age(n-1)+2;
return(a);
}
main( )/*主函数*/
{
printf(″第5个人的年龄=%d\n″, age(5));
}
运行结果: 第5个人的年龄=18 null6.5 变量的作用域 6.5.1 局部变量
(1) 在一个函数内部定义的变量是局部变量, 只能在函数内部使用。
(2) 在主函数内部定义的变量也是局部变量, 其它函数也不能使用主函数中的变量。
(3) 形式参数是局部变量。
(4) 在复合语句中定义的变量是局部于复合语句的变量, 只能在复合语句块中使用。
(5) 局部变量在函数被调用的过程中占有存储单元。 (6) 不同函数中可以使用同名变量。 null例如, 有如下程序:
main( )
{int a=1;
int b=2; /*a, b为局部变量*/
{int b=1; /*此b非前b, 语句块中局部变量*/
printf(″复合语句中a=%d, b=%d\n″, a, b);
}
printf(″复合语句外a=%d, b=%d\n″, a, b);
}
运行结果: 复合语句中a=1, b=1
复合语句外a=1, b=2 null6.5.2 全局变量 (1) 在函数外部定义的变量是全局变量, 其作用域是变量定义位置至整个程序文件结束。
(2) 使用全局变量, 可增加函数间数据联系的渠道。 全局变量可以将数据带入在作用域范围内的函数, 也可以将数据带回在作用域范围内的其它函数。 nullint a, b; /*a, b为全局变量*/
int s( )
{a=a*a; /*函数中a、 b即为前定义的全局变量*/
b=b*b;
return(a+b);
}
main( )
{int sum;
a=2;
b=3;
sum=s( );
printf(″sum=%d, a=%d, b=%d″, sum, a, b);
}
运行结果: sum=13, a=4, b=9 null(3) 提前引用外部变量, 需对外部变量进行说明, 或称申明。
形式: extern 类型 变量表;
作用: 说明这些变量是已在外部定义过的变量。
例如, 有如下程序:
main( )
{extern int a, b; /*外部变量说明*/
……
}
int a, b; /*外部变量定义*/ null (4) 使用程序中非本程序文件的外部变量, 也要对使用的外部变量进行同上的申明, 或用文件包含处理。
(5) 局部变量如与外部变量同名, 则在局部变量的作用域内, 外部变量存在, 但不可见, 外部变量的作用被屏蔽。
(6) 全局变量在程序运行过程中均占用存储单元。
(7) 在编程时, 原则上尽量少用全局变量; 能用局部变量, 不用全局变量,要避免局部变量全局化。 null 6.5.3 标识符的作用域
从变量的作用域可延伸考虑量的作用域, 进一步考虑标识符的作用域, 即标识符的使用范围。标识符除了标识变量, 还用来标识常量、 函数、 类型等。 null6.6 变量的存储类别 6.6.1 变量的存储类别 内存中供用户使用的存储空间分为代码区与数据区两个部分。变量存储在数据区, 数据区又可分为静态存储区与动态存储区。
静态存储是指在程序运行期间给变量分配固定存储空间的方式。如全局变量存放在静态存储区中, 程序运行时分配空间, 程序运行完释放。 null 动态存储是指在程序运行时根据实际需要动态分配存储空间的方式。 如形式参数存放在动态存储区中, 在函数调用时分配空间, 调用完成释放。
对于静态存储方式的变量可在编译时初始化, 默认初值为0或空字符。对动态存储方式的变量如不赋初值, 则它的值是一个不确定的值。
在C语言中, 具体的存储类别有自动(auto)、寄存器(register)、静态(static)及外部(extern)四种。静态存储类别与外部存储类别变量存放在静态存储区, 自动存储类别变量存放在动态存储区, 寄存器存储类别直接送寄存器。 null变量存储类别定义方法:
存储类别 类型 变量表;
例如:
(1) a, b, c为整型自动存储类别变量:
auto int a, b, c;
(2) x, y, z为双精度型静态存储类别变量:
static double x, y, z; null6.6.2 局部变量的存储方式 (1) 局部变量一般用自动方式存储, 用保留字auto加以定义, 此时称为自动变量, 是动态存储, 在函数的调用过程中存在, 由编译系统自动处理。例如:
void f( )
{auto int i, j;
auto float x, y; /*局部变量i, j, x, y以自动方式存储*/
……
} null (2) 如果希望函数调用完后局部变量的值被保留, 不释放其所占存储单元, 这时必须将其存储方式定义为静态存储方式, 用保留字static加以定义。用静态方式存储的局部变量称为局部静态变量, 在函数调用完后其值被保留, 由于“局部”的作用域, 这个保留的值其它函数并不能使用, 只有本函数能够使用。 null例 6-16 计算1到5的阶乘。 int jf(n)
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, jf(i));
}
运行结果为:
1!=1
2!=2
3!=6
4!=24
5!=120 null (3) 如果对数据的读写频繁, 存取速度要求较快, C语言允许用寄存器方式直接处理变量, 用保留字register加以定义, 此时称为寄存器变量。 例如:
long sum(n)
int n;
{int i;
register long s=0;
for(i=1; i<=n; i++)
s+=i;
return(s);
} null(4) 局部变量的缺省存储方式是自动存储方式。 null6.6.3 全局变量的存储方式 (1) 全局变量一般用外部存储方式存储, 用保留字extern加以定义。此时, 变量的作用域是构成整个程序的所有程序文件, 也就是定义的外部变量可供其它程序文件使用。
例如, 程序由两个程序文件file1.c与file2.c组成。 /*file1.c*/
extern int a; /*定义extern存储方式变量a*/
main( )
{int pow( );
int n;
int p; nullscanf(″%d″, &n);
p=pow(n);
printf(″p=%d\n″, p);
}
/*file2.c*/
extern int a; /*申明本文件中使用的是已定义的外部变量a*/
int pow(x)
int x;
{int i, t=1;
for(i=1; i<=x; i++)
t*=i;
return(t);
} null 2) 如果希望全局变量仅限于本程序文件使用, 而其它程序文件中不能引用, 这时必须将其存储方式定义为静态存储方式, 用保留字static加以定义。此时称为静态外部变量。
例如, 在上例文件file1.c中, 如果作这样的定义:
static int a;
则变量a的作用域被缩小至本程序文件file1.c, 文件file2.c中不能引用。 null (3) 全局变量的缺省存储方式是外部存储方式。 前面章节中的程序没有见到变量的存储类别定义, 实际上采用变量的缺省存储方式。对局部变量采用auto方式, 对全局变量采用extern方式。 null1. 变量定义的一般形式
存储类别 数据类型 变量表;
2. 变量定义的作用
① 规定了变量的取值范围。
② 规定了变量进行的运行操作。
③ 规定了变量的作用域。
④ 规定了变量的存储方式。
⑤ 规定了变量占用的存储空间。 null3. 局部变量和全局变量
局部变量:
① 自动变量, 即动态局部变量(离开函数, 值就消失).
② 静态局部变量(离开函数, 值仍保留)。
③ 寄存器变量(离开函数, 值就消失)。
④ 形式参数可以定义为自动变量或寄存器变量。
全局变量:
① 静态外部变量(只限本程序文件使用)。
② 外部变量(即非静态的外部变量, 允许其它程序文件引用)。 null4. 动态存储和静态存储 动态存储:
① 自动变量(函数内有效)。
② 寄存器变量(函数内有效)。
③ 形式参数。
静态存储:
① 静态局部变量(函数内有效)。
② 静态外部变量(本程序文件内有效)。
③ 外部变量(整个程序可引用)。 null 5. 静态存储区和动态存储区
从变量值存放的位置可将变量存储区分为静态存储区和动态存储区:
内存中静态存储区:
① 静态局部变量。
② 静态外部变量。
③ 外部变量(可被同一程序其它文件引用)。
内存中动态存储区: 自动变量和形式参数。 null 例 6-17 仔细阅读程序, 注意变量的作用域#, 存储类别, 程序的运行结果。 /*程序 7-17, 变量的作用域、 存储类别*/
void f1(x, y)
{auto int i;
static int j; /*调用完, j值保留*/
printf(″i=%5d, j=%5d\n″, i, j);
i=x+y;
j+=x+y;
printf(″i=%5d, j=%5d\n″, i, j);
printf(″x=%5d, y=%5d\n″, x, y);
} nullstatic int k, l, m; /*在本程序文件内使用*/
void f2(a, b, c)
int a, b, c;
{ k=a+b+c;
l=a*b*c;
m=k+l;
printf(″a=%5d, b=%5d, c=%5d\n″, a, b, c);
printf(″k=%5d, l=%5d, m=%5d\n″, k, l, m);
}
main( )
{int d, e, f, g, h;
int i, j, x, y, a, b, c;
printf(″请输入 d, e, f, g, h: ″);
scanf(″%d, %d, %d, %d, %d″, &d, &e, &f, &g, &h);
printf(″第一次调用函数f1( )\n″);
f1(d, e); nullprintf(″i=%5d, j=%5d\n″, i, j);
printf(″x=%5d, y=%5d\n″, x, y);
printf(″d=%5d, e=%5d\n″, d, e);
printf(″第二次调用函数f1( )\n″);
f1(d, e);
printf(″i=%5d, j=%5d\n″, i, j);
printf(″调用函数f2( )\n″);
f2(f, g, h);
printf(″k=%5d, l=%5d, m=%5d\n″, k, l, m);
printf(″a=%5d, b=%5d, c=%5d\n″, a, b, c);
printf(″f=%5d, g=%5d, h=%5d\n″, f, g, h);
} null运行结果:
请输入 d, e, f, g, h: 1, 2, 3, 4, 5
第一次调用函数f1( )
i= 34(随机值), j= 0
i= 3, j= 3
x= 1, y= 2
i= 34(随机值), j= 1985 (随机值)
x= -19(随机值), y= 2340(随机值)
d= 1, e= 2 null第二次调用函数f1( )
i= 34(随机值), j= 3
i= 3, j= 6
x= 1, y= 2
i= 34(随机值), j= 1985 (随机值)
调用函数f2( )
a= 3, b= 4, c= 5
k= 12, l = 60, m= 72
k= 12, l = 60, m= 72
a= 13(随机值), b= 124(随机值), c= 2525(随机值)
f= 3, g= 4, h= 5 null6.7程序设计举例【例6-18】用直接插入排序的方法将一组整数降序排列。
insertsort(int *a,int n)
{ int i,j,t;
for(i=1;i=0&&t>a[j];j--)
a[j+1]=a[j];
a[j+1]=t;
}
}
#define N 10nullmain()
{ int x[N],i;
for(i=0;i> %c\n",x,y);
}
int count=0;
hanoi(int n,char A,char B,char C)
{
if(n==1) { move(A,C); count++;}
else
{ hanoi(n-1,A,C,B);
move(A,C);count++;
hanoi(n-1,B,A,C);
}
}nullmain()
{ int n;
printf("How many plates? "); scanf("%d",&n);
hanoi(n,’A’,’B’,’C’);
printf("Total moved:%d\n",count);
}null〖运行结果〗:How many plates? 4↙
A ——>> B
A ——>> C
B ——>> C
A ——>> B
C ——>> A
C ——>> B
A ——>> B
A ——>> C
B ——>> C
B ——>> A
C ——>> A
B ——>> C
A ——>> B
A ——>> C
B ——>> C
Total moved:15
null【例6-20】将一个M×N的二维数组按列优先转存为一个长度
为M×N的一维数组。
#define M 3
#define N 4
void funab(int (*a)[N],int *b,int m,int n)
/* a为数组指针变量名 */
{ int i,j,k=0;
/* 在二维数组中按列扫描数组元素 */
for(j=0;j