第5章使用函数封装代码_第1页
第5章使用函数封装代码_第2页
第5章使用函数封装代码_第3页
第5章使用函数封装代码_第4页
第5章使用函数封装代码_第5页
已阅读5页,还剩62页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第五章使用函数封装代码办公地点:信息学院(主楼四层)411室办公室电话:010-62336516E-mail:什么是函数?函数是完成特定功能的程序段。main()#include<stdio.h>

intmain(void){printf("ThisisaCprogram.\n");return0;}main()函数的特点?一个可以执行的C程序中,一定有一个主函数main()。一个可以执行的C程序中,除了包含一个主函数main()以外,还可以包含其他的函数。但程序总是从main()开始执行。#include<stdio.h>voidmy_c(void);

intmain(void){

my_c();return0;}voidmy_c(void){printf("ThisisaCprogram.\n");return;}所有的C程序都是由函数构成的什么是函数在处理复杂任务时,通常要通过细致的分析来拆解任务,即将复杂任务分解为一个个独立的简单任务。每个简单任务由独立的一个程序段来处理,这一个个独立的程序段就是一个个自定义函数。学生成绩管理学生成绩录入e()学生成绩修改m()学生成绩排序s()学生成绩输出p()…….main()e()m()s()p()…….结构化程序设计利用结构化程序设计方法去设计一个计算器程序main()加法函数jia_fa()减法函数jian_fa()乘法函数cheng_fa()除法函数chu_fa()编程中建立和使用函数的目的是为了实现结构化程序设计。加法函数jia_fa()voidjia_fa(void){doublex,y;printf(enterxandy:");scanf("%lf%lf",&x,&y);printf(“\n%f+%f=%f\n”,x,y,x+y);return;}函数和结构化程序设计main()jia_fa()jian_fa()cheng_fa()chu_fa()结构化程序设计的三个重要原因:程序更容易编写;程序更容易调试;可以共享使用相同的函数段,从而提高工作效率。

函数和C程序函数:一般将相对独立的或可能反复使用的操作过程设计成函数。用户通过调用这个函数来完成函数的功能。C程序一个C程序可以只有一个main()函数,或者由一个main()函数及其他函数组成。执行程序时,必须从主函数(main())开始执行。即无论main()函数位于程序的什么位置,它都是程序执行的开始点,且是惟一的。除了主函数main()可以调用其他的函数外,函数之间允许相互调用。只是main()不以可被其他函数调用。调用函数时,是从主调函数的调用点转向被调函数;被调函数运行结束后,一定要返回到主调函数的调用处。函数有两类C语言函数包括:自定义函数标准库函数已经学习过哪些“标准库函数”?由编程者根据实际需要而定义和编写的函数,被称为自定义函数。5.4函数定义什么是函数定义?对函数所要完成的功能动作做描述,即为实现功能目标而设计和编写的语句代码段。如何定义一个函数double

cube(doublea){

returna*a*a;}函数的类型函数名(形式参数表){

函数体的语句序列}像使用变量一样,函数在使用之前必须先声明,后使用形参表是函数的入口函数名相当于说明运算的规则;形参天里的形参相当于运算的操作数,也是内部变量;返回值就是运算的结果。建立自定义函数用函数编写计算整数n的阶乘n!longpower(intn){intk;longresult=1;for(k=1;k<=n;k++){result=result*k;}returnresult;}如何设计一个main()来调用它?函数的入口参数?函数的返回值?函数的功能?函数定义return(返回语句)它是放在函数体内;执行函数体的语句时,一旦执行到return语句,就结束当前函数,返回到主调函数的调用点。return语句中有表达式时,还要将表达式的值返回主调函数。return语句的形式:return要返回的数据;return(要返回的数据);return;double

cube(doublea){doubleb;b=a*a*a;

returnb;}建立自定义函数(1)给定一个整数,获得该数的立方值intcube(intx){returnx*x*x;}intcube(intx){inty;y=x*x*x;returny;}如何设计一个main()来调用它?向函数传递值和从函数返回值——函数调用函数调用程序中使用已经定义好的函数,称为函数调用。如果函数A调用函数B,则函数A为主调函数函数B为被调函数函数调用的一般形式:函数名(实际参数表)

函数名()实参与形参的个数必须相等,类型必须一致。通过函数名及其后面一对圆括号括起的实参表来实现调用。如果被调函数是一个无参函数,则调用函数的语句中,被调函数没有实参表,但函数名后的一对圆括号不能省略。了解函数调用过程的执行顺序C程序的执行总是从main()函数开始。函数调用C程序通过对函数的调用来改变程序执行的顺序。主调函数可以将数据传递给被调函数(即将实参值传给被调函数的形参中),并将执行权从主调函数转移到被调函数。当调用结束时,执行权又返回到主调函数的调用点,继续执行主调函数中未执行的语句。#include<stdio.h>intcube(intx){returnx*x*x;}intmain(void){intnum;printf("Inputaanumber:");scanf("%d",&num);printf(“立方值是%d\n“,cube(num));system(“Pause”);return0;}函数调用的三种方式语句方式:直接以函数调用语句的形式出现。scanf("%d",&x);printf("x=%f,y=%f\n",x,y)

;

表达式方式:函数调用可以出现在表达式中,一般适用于有返回值的函数。x=sqrt(n);result=2.69*sin(x)+my_sum(x,y,z);参数方式:函数调用也可以作为一个实参。printf("y=%f\n",sqrt(n));又如:

data=min(cos(x),cos(y),0.206);

函数调用#include<stdio.h>voidprinttria(int);intmain(void){intnum;printf("Inputaanumber:");scanf("%d",&num);

printtria(num);return0;}voidprinttria(intn){intk,m;for(k=1;k<=n;k++){for(m=1;m<=k;m++) printf("*"); putchar('\n');}return;}建立自定义函数(3)判定一个一元二次方程有无实根,建立约定:函数值为1表示有两个不等实根函数值为-1表示有两个复根函数值为0表示有两个相等的实根intcube(floata,floatb,floatc){floatd;d=b*b-4*a*c;if(d>0)return1;elseif(d<0)return-1;elsereturn0;}intcube(floata,floatb,floatc){floatd,y;d=b*b-4*a*c;if(d>0)y=1;elseif(d<0)y=-1;elsey=0;return(y);}如何设计一个main()来调用它?函数原型设计自定义函数时,一般习惯于同时建立该自定义函数的函数原型。函数原型——用于对自定义函数进行声明。它是提供给C编译器的,C编译器使用函数原型来校验函数调用的合法性。函数原型将告诉C编译器:自定义函数的返回类型自定义函数自带的形式参数的类型、个数、排列次序例如,写出前面几个自定义函数的原型intcube(int);longpower(int);intcube(float,float,float);intcube(intx);longpower(intx);intcube(floata,floatb,floatc);建议在程序的编译命令区(程序开始位置处)内放置函数原型语句。一旦这样做了,设计编写程序时,就可以不必考虑自定义函数与主函数的位置关系了。#include<stdio.h>voidprinttria(int);intmain(void){intnum;printf("Inputaanumber:");scanf("%d",&num);

printtria(num);return0;}voidprinttria(intn){intk,m;for(k=1;k<=n;k++){for(m=1;m<=k;m++) printf("*"); putchar('\n');}return;}#include<stdio.h>voidprinttria(int);voidprinttria(intn){intk,m;for(k=1;k<=n;k++){for(m=1;m<=k;m++) printf("*"); putchar('\n');}return;}intmain(void){intnum;printf("Inputaanumber:");scanf("%d",&num);

printtria(num);return0;}打印三角形图案#include<stdio.h>intfunc(double);intmain(void){doublex;intresult;printf("Inputax:");scanf("%lf",&x);result=func(x);if(result==1) printf(“\n%f

>=0\n\n",x);else printf("\n%f<0\n\n",x);system("Pause");return0;}intfunc(doublez){ intj; if(z>=0)

j=1; else

j=-1;

return(j)

;}观察参数的传递

(判断数据的正负性)练习编写自定义函数设计一个乘法和除法器程序,要求乘法和除法的运算过程由自定义函数mul()和div()处理。voidmul(void){

doublex,

y;printf("请输入被乘数和乘数:");scanf("%lf%lf",&x,&y);printf("\n\t%f*%f=%f\n\n\n",x,y,x*y);return;}voiddiv(void){

doublex,y;printf("请输入被除数x和除数y:");scanf("%lf%lf",&x,&y);while(y==0){printf("\n除数y不能为0,请重新输入除数y:");scanf("%lf",&y);}printf("\n\t%f/%f=%f\n\n\n",x,y,x/y);return;}编写函数编写函数主函数:设计一个菜单列表,显示选择乘、除法运算过程,其中,1是乘法,2是除法,3是结束。在选择了一种运算操作以后,调用mul()或div()函数,完成乘法或除法运算。#include<stdio.h>voidmul(void);voiddiv(void);intmain(void){charsel=0,flag=0;do{puts("\n\t-----------------\n");puts("\t(1)乘法运算");

puts("\t(2)除法运算");

puts("\t(3)结束");

printf("\n\t输入一个选项编号:");

scanf("%c",&sel);

if(sel!='1'&&sel!='2'&&sel!='3')puts("\n\n\t++++选项错误++++\n");elseswitch(sel){case'1':mul();break;case'2':div();break;}

getchar();}while(sel!='3');puts("\n\t-----Bye-----\n\n");system("Pause");return0;}调用随机函数rand()随机函数rand()是C语言编译系统在标准函数库中提供的一个标准库函数随机函数是一个专门产生模拟随机数的函数一般应用于程序的模拟测试或游戏软件的制作调用随机函数的语句形式如下:

x=rand();随机函数每调用一次随机函数rand(),系统都会产生一个0至RAND_MAX之间的整数,RAND_MAX是在头文件<stdlib.h>中定义的符号常量,ANSI标准规定RAND_MAX的值不得小于32767。5.5标准库函数和头文件标准库函数(详见书后的附录)#include<stdio.h>#include<stdlib.h>intmain(void){

intn;

for(n=1;n<=30;n++)

{

printf("%d\t",rand());

}

return0;}例5.4获得30个随机数。(P108)程序清单1随机函数srand()是一个带有单一unsigned类型整数作参数的函数。为了实现每次执行程序时能获取不同的随机数序列,首先要确保每次执行程序时,都可以改变srand()函数的参数,然后调用srand()函数来确立新的随机数种子,最后通过多次调用rand()来获得新的随机数序列。调用srand()函数的语句形式如下:

srand(seed);随机函数srand(seed);seed是无符号整数,也被称为随机数种子。头文件<stdlib.h>中列出了srand()的函数原型。一种能随时改变随机数种子的简单方法是:

srand(time(NULL)

);函数time()返回以秒计算的当前系统时间值。time()的函数原型存在于头文件<time.h>中。#include

<stdio.h>#include

<stdlib.h>#include

<time.h>intmain(void){ intn;

srand(

time(NULL)

); for(n=1;n<=30;n++) { printf("%d\t",

rand()

); }return0;}例5.4程序清单2实验机房更改地址T01T07获取指定区间范围内的数据如果模拟产生某一个数据范围内的随机数,如:产生符合[a,b]数据区间内的need值,则通过所需数据范围的起始值a和终结值b,利用如下的算法语句即可:

need=a+rand()%(b-a);其中,a被称为初值,它等于所需的连续整数范围内的第一个数;(b-a)被称为比例因子,它等于所需的连续整数范围的宽度。获取指定区间范围内的数据例如

假设要获取10至50范围内的随机数,则可以使用如下形式的语句来产生符合其指定范围的数值:

need=10+rand()%40;练习:产生50个[10,50]区间中的数据。调用exit()函数exit()的作用是终止程序的执行,并将控制权归还操作系统。exit()函数的语法如下:

exit(status);其中,status是exit()接收的唯一参数,它是int类型,是可以返回给操作系统的一个值。使用exit()函数时,应该包含头文件stdlib.h。5.7函数的位置一个C程序可以由一个或多个自定义函数组成。自定义函数代码可以与main()函数一起放在同一个源文件中,他们之间的位置没有固定的次序,只要保证在文件开始处声明自定义函数的原型即可。也可以将自定义函数与main函数分放在不同的源代码文件中。一个源代码文件可以由一个或多个函数组成,并作为一个编译单位执行编译过程。对于较大的程序,一般不希望把所有的内容全放在同一个源代码文件中,而是将其分放于若干个不同的源文件,以便于分别编写和分别编译,从而提高调试程序的效率。例5.5

制作一个简单的游戏程序——猜数。

1)要猜的数的大小在0~20之间;

2)每猜一个数据,最多给三次猜测的机会,并给予提示;

3)可以反复玩,直至输入-1为止。#include<stdio.h>#include<stdlib.h>#include<time.h>#defineMAX_DATA20#defineNO0#defineYES1intfun_play(int);intmain(void){intluck,newone;srand(time(NULL));do{ luck=rand()%MAX_DATA; printf("\nHavegotanewRandomnumber.\n"); newone=fun_play(luck);}while(newone);printf("\n*****GameOver*****\n");

return0;}intfun_play(intlucky){ intguess,counter; printf("\nHello.Pickanumberbetween0and%d(-1toend):",MAX_DATA); scanf("%d",&guess);If(guess<0) returnNO; else { counter=1; while(guess!=lucky) { if(guess<lucky) printf("It'stooless.\n"); else printf("It'stoolarge.\n"); counter++; printf("\nPickanumberbetween0and%d:",MAX_DATA); scanf("%d",&guess); } printf("Goog!TheRandomnumberis%d.",lucky); printf("\nYouguessedrightin%dguesses!\n",counter); printf("\n---RESTART---\n"); returnYES; }}什么是函数封装将函数内部的具体内容封闭起来,使外界对函数的影响仅限于几个入口参数。而函数对外界的影响也仅限于一个返回值。函数入口出口longjc(intm){longst=1;inti;for(i=1;i<=m;i++){st=st*i;}returnst;}求正整数n的阶乘n!#include<stdio.h>longjc(int);intmain(void){ intn; do {

printf("请输入一个正整数n(n>0):");scanf("%d",&n);}while(n<1);printf("\n\t%d!=%d\n\n",n,jc(n)); system("pause"); return0;}jc()st的值mnstistst设计一个只做加减法的计算器#include<stdio.h>doublecalc(double,char,double);intmain(void){ doublex,y,z;charop;printf("请输入加法或减法算式(exp:2+3):");scanf("%lf%c%lf",&x,&op,&y);while(op!='+'&&op!='-'){printf("本程序只做加减法\n请重新输入算式:");scanf("%lf%c%lf",&x,&op,&y);}z=calc(x,op,y);printf("\n\n\t%f%c%f=%f\n\n",x,op,y,z);system("pause");return0;}x,op,ycalc()函数值doublecalc(doubled1,charopt,doubled2){switch(opt){case'+':returnd1+d2;case'-':returnd1-d2;}}什么是递归调用?如果一个对象部分地由它自己组成或按它自己定义,则我们称它是递归的。“函数自己调用自己”的函数调用就称为递归调用,这样的函数则称为递归函数。fact1.cfact2cfact3c递归调用与递归函数………………中国有一个古老的故事……中国有一个古老的故事……中国有一个古老的故事……if(story?)return(womanisatiger)elsereturn(nextstory)建立一个递归函数去计算n的阶乘n!。fact1.cfact2cfact3cf(n)=n*f(n-1)longf(intn){if(n==0||n==1)return1;elsereturn(n*f(n-1));}递归调用与递归函数如果一个对象部分地由它自己组成或按它自己定义,则我们称它是递归的。“函数自己调用自己”的函数调用就称为递归调用,这样的函数称为递归函数。什么是递归调用?如果一个对象部分地由它自己组成或按它自己定义,则我们称它是递归的。“函数自己调用自己”的函数调用就称为递归调用,这样的函数则称为递归函数。fact1.cfact2cfact3c递归调用与递归函数用递归算法设计程序,对任给的n,输出如下算式(不用计算累加值):a+aa+aaa+aaaa+......最后一项数据含有的a的个数是n个。例如:设a=3,如果n=5,则显示3+33+333+3333+333335.8变量的作用域变量的作用域是指该变量起影响作用的区域。区域指的是什么?用花括号括起来的范围(语句块)语句块有:函数体、分支语句,还有循环语句#include<stdio.h>intmain(void){intx=109,y=30;printf("%d\n",x+y);system("pause");return0;}变量的作用域规则是:每个变量仅在定义它的语句块(包括下级语句块)内有效,并且拥有自己的存储空间。变量的作用域变量的作用域规则是:每个变量仅在定义它的语句块(包括下级语句块)内有效,并且拥有自己的存储空间。在语句块内定义的变量称为局部变量。#include<stdio.h>voidadd(void);voidmul(void);intmain(void){charysf;printf("输入加减号:");ysf=getchar();switch(ysf){case'+':add();break;case'-':mul();break;default:puts("Error\n");}system("pause");return0;}voidadd(void){floatx=20,y=10;printf("%f+%f=%f\n",x,y,x+y);return;}voidmul(void){floatx=20,y=10;printf("%f-%f=%f\n",x,y,x-y);return;}形参是函数体内的局部变量变量的作用域局部变量是在函数内部定义的变量,其作用域为它所在的函数内部。例如,前面介绍的函数的形参和函数内部声明的变量都属于局部变量。不在任何语句块内定义的变量称为全局变量。全局变量的作用域是整个程序。#include<stdio.h>voidadd(void);voidmul(void);intmain(void){charysf;printf("输入加减号:");ysf=getchar();switch(ysf){case'+':add();break;case'-':mul();break;default:puts("Error\n");}system("pause");return0;}voidadd(void){floatx=20,y=10;printf("%f+%f=%f\n",x,y,x+y);return;}voidmul(void){floatx=20,y=10;printf("%f-%f=%f\n",x,y,x-y);return;}floatx=20,y=10;该语句放在程序的开始处,则它对三个函数都可用。变量的作用域外部变量:在所有函数之外声明的变量。外部变量是全局变量的一种。外部变量的作用域是从它的定义点到本文件的结尾。如果要在该外部变量定义点之前,或者在其他文件中使用它,则要用关键字extern对其进行说明。#include<stdio.h>voidadd(void);voidmul(void);intmain(void){charysf;printf("输入加减号:");ysf=getchar();switch(ysf){case'+':add();break;case'-':mul();break;default:puts("Error\n");}system("pause");return0;}voidadd(void){printf("%f+%f=%f\n",x,y,x+y);return;}voidmul(void){printf("%f+%f=%f\n",x,y,x-y);return;}floatx=20,y=10;【注意:】普通的变量声明与extern声明是不同的,前者给变量预留了存储空间,后者则指出“该函数使用了一个在其他地方声明的外部变量,其名称和类型分别是……”,不需要再为其分配内存。【注意:】应该谨慎使用外部变量。因为只要修改某个外部变量的值,就将影响所有引用其值的函数。过多的使用和依赖外部变量,将破坏函数的独立性及其个体的封闭性,它不符合结构化程序设计的原则。小结什么是函数封装将函数内部的具体内容封闭起来,使外界对函数的影响仅限于几个入口参数。而函数对外界的影响也仅限于一个返回值。函数的组成函数的工作原理函数的建立方式、调用方式变量的作用域函数入口出口动态局部变量和静态局部变量默认情况下的局部变量都是动态的,这意味着每次调用函数时,都要重新创建变量;而当函数执行完毕后,变量将被自动释放。也就是说,在程序的一次执行中,函数的两次调用之间,该函数的动态局部变量由于经过了释放与再分配存储单元的过程,使其原值无法保留。动态局部变量和静态局部变量有时希望函数中的局部变量的值在函数调用结束后不消失而保留原值,即其占用的存储单元不释放,在下一次该函数被调用时,该变量仍保留着上一次函数调用后的值,这时就应该指定该局部变量为“静态局部变量”,用关键字static进行声明。声明格式如下:

statictypevariable_name;

其中type是变量的数据类型,variable_name是变量名。静态局部变量存储于专门的静态存储区中,在程序执行过程中它们始终占据着固定的存储单元,直至程序终止时才释放。例5.9

观察动态局部变量x与静态局部变量y之间的区别。#include<stdio.h>voidprt_data(void);intmain(void){ inti; for(i=1;i<=3;i++) prt_data();return0;}voidprt_data(void){

intx=0;

staticinty=0; x=x+5; y=y+5; printf("x=%d\ty=%d\n",x,y);

system("Pause"); return;}课堂练习设计一个算术(+,-,*,/)运算器,每个运算过程使用一个自定义函数处理,主函数main来调用指定的自定义函数实现指定的运算。main()加法函数fadd()减法函数fsub()乘法函数fmul()除法函数fdiv()doublefadd(double,double);z=fadd(x,y);#include<stdio.h>doublefadd(double,double);……intmain(void){doublex,y,z;charop;printf(“\t输入一个算式:");scanf("%lf%c%lf",&x,&op,&y);switch(op){case‘+’:z=fadd(x,y);

break;case‘-’:z=fsub(x,y);

break;case‘*’:z=fmul(x,y);

break;case‘/’:

while(y==0){printf("\n除数y不能为0,请重新输入除数y:");scanf("%lf",&y);}z=fdiv(x,y);

break;defause:pus(“本程序无法识别的运算”);}printf(“\n%f%op%f=%f\n”,x,op,y,z);puts("\n---Bye---\n\n");return0;}doublefmul(doublex,doubley){

doublez;z=x*y;returnz;}doublefdiv(doublex,doubley){

doub

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论