函数:为了完成某一项功能而编写的代码的集合。
C语言中的函数可以分为内置和自定函数。
内置函数:C语言中已经定义过的函数,不需要
声明,可以直接调用。
常见的内置函数:
函数名 |
类库 |
说明 |
double sqrt(double x) |
math.h |
计算x的平方根 |
double pow(double x int y) |
计算x的y次方 |
|
int ceil(double x) |
返回不小x的最小整数 |
|
int floor(double x) |
返回不大x的最大整数 |
|
int toupper(int x) |
ctype.h |
转大写 |
int tolower(int x) |
转小写 |
|
rand() |
stdlib.h |
返回一个[0,32767]之间随机数 |
示例1:
int i; double x=1.34; for(i=1;i<=10;i++){ printf("%d的平方根为%0.2f,立方为:%0.0f\n",i,sqrt(i),pow(i,3)); } printf("---ceil函数---\n"); printf("%lf\n",ceil(x)); printf("---floor函数---\n"); printf("%lf\n",floor(x)); |
示例2:
//产生10个[1,3]随机数 int i; long l = time(NULL);//返回当前时间距1970-1-1 00:00:00(元年)经历的总秒数 //printf("%ld",l); srand(l);//使用srand设置随机种子:随机种子不相同的情况下,rand()产生的随机数不相同 for(i=0;i<10;i++){ printf("%d\t",rand()%3+1); //rand()产生[0,32767]一个伪随机数 } |
示例3: //实现"人机猜拳大战" 0代表剪刀, 1代表石头,2代表布
规则采用7局4胜制
1.获取用户输入的出拳(0,1,2)
2.让电脑尝试一个[0,2]之间的随机数
3.判断当局输赢:
人胜: 人==0&&电脑==2 人==1&&电脑==0 人==2&&电脑==1
平局:人==电脑
电脑胜: 电脑==0&&人==2 电脑==1&&人==0 电脑==2&&人==1
4.评判最终结果:count1(人)>count2(电脑)
int user,computer;//声明两个变量用于保存用户和电脑的出拳 int count1=0,count2=0,i;//统计人和电脑所有各种胜利的局数 printf("*************************************************\n"); printf("*************郑州尚学堂人机猜拳大战**************\n"); printf("*************************************************\n"); for(i=1;i<=7;i++){ printf("\n\n第%d局开始:\n",i); printf("请出拳(0代表剪刀;1代表石头;2代表布):\n"); scanf("%d",&user);//获取用户出拳 //获取电脑出拳(产生一个[0,2]之间的一个随机) srand((unsigned)time(NULL)); //设置随机种子 computer = rand()%3;//rand()-->[0,32767]; if(user<0||user>2){ printf("您的出拳有误,请从新输入!\n"); }else{ if((user==0&&computer==2)||(user==1&&computer==0)||(user==2&&computer==1)){ count1++;//为用户计分 printf("第%d局,用户胜!\n",i); }else if(user==computer){ printf("第%d局,平局!\n",i); }else { count2++;//为电脑计分 printf("第%d局,电脑胜!\n",i); } } } printf("\n*****************比赛结果*******************\n"); //评判最终结果 if(count1>count2){ printf("比分%d VS %d,最终结果:用户胜!\n",count1,count2); }else if(count1==count2){ printf("比分%d VS %d,最终结果:平均!\n",count1,count2); }else{ printf("比分%d VS %d,最终结果:电脑胜!\n",count1,count2); } |
示例4:生成一个4位随机数作为验证码,有字母和数字组成。
分析: 1、创建一个数组用于保存字母,数组
2、生成4个[0,length-1]随机数作为访问数组的下标
char cs[]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','0','1','2','3','4','5','6','7','8','9'}; int i,index; printf("验证码为:\n"); //设置随机种子 srand((unsigned)time(NULL)); for(i=0;i<4;i++){ index = rand()%36;//获取[0,35]随机数 printf("%c",cs[index]); } printf("\n"); |
自定义函数:
必须直接或间接在main中调用,否则该自定义函数不会被执行。
返回值类型 函数名(参数类型 参数名,参数类型 参数名...)
{
//函数体;
return 返回值;
}
返回值类型:用于定义当前函数所返回值的类型;
函数名:为函数体中代码起一个名称,命名需要满足标识符的命名规则。
参数类型:类似于声明变量的数据类型,用于限定当前参数的类型。
函数体:为了完成某些功能的代码集合。
函数的调用:在C语言中通过函数名进行调用,一旦该函数被调用了,将执行函数体中的代码。
函数原型说明在形式上与函数头部类似,最后加一个分号。原型说明中参数表里的参数名可以不写(只写参数类型)。
示例:
#include <stdio.h> //声明函数的原型:参数名可以省略 void printRectangle(); void printfTriangle(); void printTriangle2(int rows); int getRand(); int getMax(int a,int b); void main() { /* int chioce; printf("请输入图形代码:1代表打印矩形,2代表打印三角形\n"); scanf("%d",&chioce); switch(chioce){ case 1: printRectangle();//利用函数名调用该函数 break; case 2: printfTriangle(); break; }*/ // printTriangle2(7); // int n = getRand();//无参数,有返回值。 // printf("%d\n",n); int m = getMax(3,2); printf("m=%d",m); } //无参数无返回值类型 //打印矩形 void printRectangle() { int i,j; for(i=0;i<4;i++){ for(j=0;j<8;j++){ printf("*"); } printf("\n"); } } //无参数无范围值 //打印三角形 void printfTriangle() { int i,j; for(i=0;i<4;i++) { for(j=0;j<=i;j++){ printf("*"); } printf("\n"); } } //无返回值,有参数 //打印指定行数的三角形 /* 定义函数时,参数为形式参数;调用函数时具体传入的值称为实际参数*/ void printTriangle2(int rows) { int i,j; for(i=0;i<rows;i++) { for(j=0;j<=i;j++){ printf("*"); } printf("\n"); } } /* 有返回值,无参数. 返回值:在函数内部使用return关键可以将值返回,C语言中只能返回一个值;返回值要和返回值的类型相匹配。 */ //生成一个[1,6]之间随机数 int getRand() { int num; srand((unsigned)time(NULL)); num = rand()%6+1;//获取一个[1,6]之间的随机数 return num; } //有返回值,有参数 int getMax(int a,int b) { /* int max; if(a>b){ max=a; }else{ max=b; }*/ int max = a>b?a:b; return max; } |
函数的嵌套调用:在一个函数中调用其他的函数。 只有当被调用的函数执行结束后,程序才会继续向下执行本函数的代码。
示例
#include <stdio.h> void m1(); void m2(); void areaRect(); void areaTri(); void testReturn(); /* 函数的嵌套调用:在一个函数中调用其他的函数。 只有当被调用的函数执行结束后,程序才会继续向下执行本函数的代码。 */ void main() { /* printf("main....begin....\n"); m1();//调用了m1()函数 printf("main....end....\n"); */ int select; while(1){//0代表假,非0代表真 printf("请选择您要计算的图形代码:\n"); printf("0代表退出,1代表长方形, 2代表三角形,3代表圆\n"); scanf("%d",&select); if(select==0){ //break;//跳出循环; //exit(0);//终止程序 return; }else if(select==1){ areaRect();//计算长方形的面积 }else if(select==2){ areaTri();//计算三角形的面积 }else if(select==3){ //计算圆形的面积 }else{ printf("您输入的代码编号有误,请重新输入[0,3]之间的代码!\n"); } } printf("谢谢使用,再见!\n"); //testReturn(); } void m1(){ printf("m1().....begin.....\n"); m2();//调用m2()函数 printf("m1().....end.....\n"); } void m2(){ printf("m2()....begin....\n"); printf("m2()....end....\n"); } //1.计算长方法的面积 void areaRect(){ int width,length,area; printf("请输入长方形的长:\n"); scanf("%d",&length); printf("请输入长方形的宽:\n"); scanf("%d",&width); if(width>0&&length>0){ area=length*width; printf("长方形的面积为:%d\n",area); }else{ printf("长方形的长和宽必须是正整数!\n"); } } //2.计算三角形的面积 //1.计算长方法的面积 void areaTri(){ float bottom,height,area; printf("请输入三角形的底:\n"); scanf("%f",&bottom); printf("请输入三角形的高:\n"); scanf("%f",&height); area = bottom*height/2; printf("三角形的面积为:%0.2f",area); } /* 返回值: 语法: return 表达式或值; 1.函数中最多只能返回一个值,不能返回多个。 2.函数的返回值必须与函数声明时的返回值类型相匹配。 3.程序执行的过程中,如果遇到return关键字,将返回到函数的被调用处(结束当前的方法)。 */ void testReturn(){ printf("return......before...."); return ; printf("return......after...."); } |
函数的递归调用:函数自身调用自身,类似循环。在编写递归程序时需要注意递归的条件,避免死循环发生。
示例: 利用递归实现阶乘
int factorial(int a) { if(a==1){ return 1; }else{ return a*factorial(a-1);//递归调用 } } |
示例2: 利用递归实现斐波那契数列
古典问题:兔子问题,有1对兔子,从第3个月开始每月可以生一对小兔子,小兔子三个月之后又可以每月生1对小兔子...
第12个月总共有多少对兔子?
斐波那契数列
1 1 2 3 5 8 13 21....
f(n)=f(n-1)+f(n-2) n>2
int fibonacci(int n) { if(n==1||n==2){ return 1; }else{ return fibonacci(n-1)+fibonacci(n-2); } } |
示例3:汉诺塔
#include <stdio.h> void Hanoi(int n, char a,char b,char c); void Move(int n, char a, char b); int count; /* void main() { int n=3; printf("请输入汉诺塔的层数:\n"); Hanoi(n, 'A', 'B', 'C'); } */ /* 分析: 当只有一个盘子的时候,只需要从将A塔上的一个盘子移到C塔上。 当A塔上有两个盘子是,先将A塔上的1号盘子(编号从上到下)移动到B塔上, 再将A塔上的2号盘子移动的C塔上,最后将B塔上的小盘子移动到C塔上。 当A塔上有3个盘子时,先将A塔上编号1至2的盘子(共2个)移动到B塔上(需借助C塔), 然后将A塔上的3号最大的盘子移动到C塔,最后将B塔上的两个盘子借助A塔移动到C塔上。 当A塔上有n个盘子是,先将A塔上编号1至n-1的盘子(共n-1个)移动到B塔上(借助C塔), 然后将A塔上最大的n号盘子移动到C塔上,最后将B塔上的n-1个盘子借助A塔移动到C塔上。 第一个参数n:代表盘子的个数 第二个参数a:代表源杆 第三个参数b:代表中间杆 第四个参数c:代表目标杆 */ void Hanoi(int n, char a, char b, char c) { if (n == 1)//当盘子的个数为1,直接将源杆上的盘子移动至目标杆 { Move(n, a, c); } else { Hanoi(n - 1, a, c, b);//先将初始塔(源杆)的前n-1个盘子借助目的塔(目标杆)移动到借用塔(中间杆)上 Move(n, a, c);//将剩下的一个盘子移动到目的塔(目标杆)上 Hanoi(n - 1, b, a, c);//将最后将借用塔(中间杆)上的n-1个盘子移动到目的塔上 } } /* 第一个参数n:代表要移动的盘子 第二参数a:源杆 第三个参数b:目标杆 */ void Move(int n, char a, char b) { count++;//记录所移动步数 printf("第%d次移动 Move %d: Move from %c to %c !\n",count,n,a,b); } |
局部变量和全局变量
局部变量:在函数内声明的变量,其作用范围仅限于该函数内
局部变量的作用域范围:仅限于当前变量所在那对"{}"之中。
局部变量需注意以下几点:
1.主函数中定义的变量也只能在主函数中使用,不能在其它
函数中使用。
2.允许在不同的函数中使用相同的变量名,它们代表不同的
变量,分配不同的存放单元,互不相干,不会发生混淆。
3.复合语句中定义的变量,也是复合语句的局部变量。所谓
复合语句,就是用{}包含起来的语句块。
void main(){ int sum=0; addNumbers(); printf("main函数中sum=%d\n",sum); int a=1,b=2; { int a=3,b=4; printf("复合语句中的a=%d,b=%d\n",a,b); } printf("main函数中的a=%d,b=%d\n",a,b); m1(); } void addNumbers() { int num1,num2,sum; printf("请输入两个整数:\n"); scanf("%d %d",&num1,&num2); sum = num1+num2; printf("addNumbers函数中sum=%d\n",sum); } void m1(){ int a=5,b=6; printf("m1函数中a=%d,b=%d\n",a,b); } |
全局变量:定义在函数外部的变量。 全局变量的作用域:从变量声明到程序结束,所有的函数都可以共享。
注意:
1.全局变量应该声明在所有函数的外部。
2.全局变量可以实现多个函数共享数据。
3.如果全局变量和局部变量同名,以局部变量的值为准(全局变量不起作用)。
示例:
int sum=0;//全局变量 void main() { int sum = 6;//局部变量 printf("main函数中sum=%d\n",sum); add(); printf("main函数中sum=%d\n",sum); } void add() { //int sum=0;//局部变量 int a,b; printf("请输入两个整数:\n"); scanf("%d %d",&a,&b); sum = a+b;//当前全局变量与局部变量同名时,全局变量不起作用 printf("add函数中sum=%d\n",sum); } |
示例5: 举行"尚学堂杯选秀大赛",参赛选手演出结束后,将有10名评委进行打分
评分规则:去掉一个最高分,去掉一个最低分,求平均分,该平均分为选手最终得分。
#include <stdio.h> void printMenu(); void getScore(); float calcAvg(); float scores[10];// 用于保存评委的打分 void main() { printMenu();//打印菜单 getScore(); //获取评委打分 float result = calcAvg();//计算平均分(最终得分) printf("您的最终得分为:%0.2f\n",result); } //打印菜单 void printMenu(){ printf("******************************\n"); printf("*******尚学堂杯选秀大赛*******\n"); printf("******************************\n"); } //获取评委打分,并将评委的打分保存到数组中 void getScore(){ int i; for(i=0;i<10;i++){ printf("请%d号评委打分:\n",i+1); scanf("%f",&scores[i]); } printf("评委打分完毕,结果正在紧张统计中.....\n"); } //计算最终得分:去掉一个最高分和一个最低分计算平均分 float calcAvg(){ float sum,avg; float max=scores[0];//假设第一个为最高分 float min=scores[0];//假设第一个为最低分 int i; for(i=0;i<10;i++){ sum+=scores[i];//计算总分数 if(scores[i]>max){//获取最高分 max=scores[i]; } if(scores[i]<min){//获取最低分 min=scores[i]; } } avg=(sum-max-min)/8;//计算平均分 return avg; } |