C语言学习第六章
今天开始尝试改变!
今天要学习函数,一个C语言中的重要组成部分。
首先先聊聊为什么要使用函数?随着学习的深入很多人会发现某段的代码重复使用的几率很大,而如果用一次写一次的话很明显的效率就会比较低,如果有一种方法可以把之前写的相同或者相差不大的代码拿到现在来用的话是不是能提高写代码的效率呢,而且如果出错了纠正的时候也更加的清晰明了。这个时候我们就用到了今天将要学习的内容:函数,它很好的解决了我们想把一段代码多次重复使用的需求。下面让我们看看什么是函数,他的定义是什么。
函数:为了完成某些功能而编写若干行代码的集合。可以供同一个程序或其他程序调用。
函数是C语言的基本组成单位。
函数的优点:代码更加简洁,易于维护,可以提高代码的重用性。
通俗一点理解就是,可以把一段为了实现某种功能的小程序给打包了,打包成一个小包,并加上标签,然后就能随时方便的取用。
函数都在什么时候使用呢?每当写程序的时候重复性的需要实现某种功能的时候就最好用函数了,一个一个写当然也能完成,但是就像前面说的一样效率太低,有省力的方法干嘛不用呢?
使用的时机到了你还要找对使用的地方,以及怎么样去使用它,下面的一系列例子就是关于怎样使用以及使用的地方的一种示例。
函数分为内置函数及自定义函数,自定义函数的方法就是:
返回值类型 函数名称 (参数)
{
//函数体;
返回值;
}
生活案例:做火腿
{
杀猪;
脱毛;
剁肉;
加入淀粉;
加入调味品;
…..
}
[A2]函数名:为函数起一个名称,类似于人名(简单说就为函数起个名称,方便后期调用)
[A3]参数:原材料
[A4]函数体:描述当前函数具体需要完成的功能(简单说当前函数所做的事情)
[A5]返回值:函数最后要想外界输出的结果,返回值要和函数定义的返回类型向对应
C语言中的函数分为内置函数和自定函数
常见的内置函数有:
内置函数 |
头文件 |
用途 |
double sqrt(double x) |
math.h |
计算x的平方根 |
double pow(double x, double y) |
计算x的y次幂 |
|
double ceil(double x) |
求不小于x的最小整数,并以double形式显示 |
|
double floor(double x) |
求不大于x的最大整数,并以double形式显示 |
|
int toupper(int x) |
ctype.h |
如果x为小写字母,则返回对应的大写字母 |
int tolower(int x) |
如果x为大写字母,则返回对应的小写字母 |
|
int rand(void) |
stdlib.h |
产生一个随机数 |
void exit(int retval) |
终止程序 |
小示例,需要记住一个知识点,计算机中的元年,这个元年的具体时间是1970-01-01 00:00:00.直接随机的数字称为伪随机数,因为使用的相同的随机种子,如果加入另一个变量如当前时间距离元年的秒或分钟数将会生成真正的随机数.
//计算1~10平方根和立方 int i; double square,power; for(i=1;i<=10;i++){ square = sqrt(i);//使用sqrt(x)函数计算x平方根 power = pow(i,3);//使用pow(x,y)函数计算x的y次方 printf("%d的平方根是%.2lf,立方是%.2lf\n",i,square,power);//.2lf:double类型精确到小数点后两位 } //floor()和ceil()函数 printf("---------floor()函数------------\n");//floor(x);--->不大于x的最大整数,不会四舍五入 printf("floor(12.1)=%f\n",floor(12.1));//12 printf("floor(-12.1)=%f\n",floor(-12.1));//-13 printf("floor(12.8)=%f\n",floor(12.8));//12 printf("floor(-12.8)=%f\n",floor(-12.8));//-13 printf("---------ceil()函数------------\n");//ceil(x);--->不小于x的最小整数,不会四舍五 q入 printf("ceil(12.1)=%f\n",ceil(12.1));//13 printf("ceil(-12.1)=%f\n",ceil(-12.1));//-12 printf("ceil(12.8)=%f\n",ceil(12.8));//13 printf("ceil(-12.8)=%f\n",ceil(-12.8));//-12 //获取随机数 srand((unsigned)time(NULL)); //设置随机种子,time(NULL):获取当时间距1970-01-01 00:00:00的秒数 for(i=0;i<10;i++){ // printf("%d\t",rand());//rand():伪随机数;产生的随机数0~32767之间 //产生一个0~99之间的随机数 printf("%d\t",rand()%100); } |
示例2:使用随机实现人机猜拳大战
int userCount=0;//统计用户获胜的次数 int computerCount=0;//统计电脑获胜的次数 int user,computer;//用于保存用户或电脑出的拳 char isContinue;//是否继续 srand((unsigned)time(NULL)); //人机猜拳大战 (0:剪刀,1:石头,2:布) y do{ printf("***********************************\n"); printf("**********人机猜拳大战*************\n"); printf("***********************************\n"); computer = rand()%3; //产生0,1,2的随机数 printf("请出拳:0代表剪刀,1代表石头,2代表布\n"); scanf("%d",&user); //判断比赛结果: 人胜:(user==0&&computer==2||user==1&&computer==0||user==2&&computer==1) if((user==0&&computer==2)||(user==1&&computer==0)||(user==2&&computer==1)){ printf("恭喜你赢了~~~~~~~~~~~~~~~~~~\n"); userCount++; }else if(user==computer){ printf("平局,再来一次~~~~~~~~~~~~~~~~~~\n"); }else{ printf("对不起,你输了~~~~~~~~~~~~~~~~~~\n"); computerCount++; } printf("是否继续与电脑决战到天亮? y代表继续,n代表是退出\n"); fflush(stdin);//刷新(清空)缓冲区 isContinue=getchar();//获取输入的字符 }while(isContinue=='y'); printf("您赢了%d次,电脑胜了%d次\n",userCount,computerCount); if(userCount>computerCount){ printf("经过您的不懈努力,终于战胜了电脑!\n"); }else if(userCount==computerCount){ printf("你和电脑旗鼓相当,继续加油!\n"); }else{ printf("你被电脑打败了,继续加油!\n"); } |
上面是内置的别人写好的下面是自己自定义函数的方法.
自定义函数:
{
//函数体;
返回值;[A4]
}
[A1]返回值类型:如果无返回类型void,如果有返回值类型(int,double,float,short,long,char..)
C语言中的函数至多可以返回一个值,不能返回多个值;
返回值的数据类型必须与函数原型中返回值的数据类型匹配;
当遇到 return 语句时,函数执行将终止。程序控制流将立即返回调用函数;
[A2]函数名必须满足命名规则,与变量名命名规则类似.
[A3]形式参数(形参):数据类型 变量名,调用时具体传入的值为实际参数(实参),实参的类型,数量,顺序必须与形参相对于。形参是函数局部变量,只在该函数内部有效
[A4]其函数的返回值必须与返回值类型相匹配,如果你声明的是一有返回值的函数,但没有使用return语句,将报错.
示例:
//有返回值,有参数 a和b为形式参数(形参) int max(int a,int b[A1] ){ int m; if(a>b){ m=a; }else{ m=b; } return m; } |
调用: int m = max(2,3[A2] );//实际参数 |
[A1]形参:形式参数,标明了需要的数值类型和数量.
[A2]实参:实际参数,要与行参的类型,数量,顺序相对应,一模一样.
C语言调用自定义函数时要先在main函数上面声明头文件.调用函数原型说明在形式上与函数头部类似,最后加一个分号。原型说明中参数表里的参数名可以不写(只写参数类型)。
函数的调用,声明完头文件以后在main函数里面直接使用函数名就可以完成调用,程序会自动转到相应的函数体中运算.
示例:
#include <stdio.h> //函数原形定义 void juxing();//计算矩形的面积 void sanjiaoxing();//计算三角形的面积 [A1] void main(){ //根据用户输入的代码(0代表矩形,1代表三角形,2代表圆)计算其面积 int code; printf("请输入图形代码:0代表矩形,1代表三角形,2代表圆"); scanf("%d",&code); if(code==0){ juxing();[A2] //通过函数名调用 }else if(code==1){ sanjiaoxing();[A3] } } //计算矩形的面积 void juxing(){ int length,width,s; printf("请输入矩形的长\n"); scanf("%d",&length); printf("请输入矩形的宽\n"); scanf("%d",&width); if(length>0&&width>0){ s=length*width; printf("矩形的面积为%d\n",s); }else{ printf("您输入有误!长和宽必须大于零!\n"); } } //计算三角形的面积 void sanjiaoxing(){ int bottom,height; float s; printf("请输入三角的底\n"); scanf("%d",&bottom); printf("请输入三角形的高\n"); scanf("%d",&height); if(bottom>0&&height>0){ s=bottom*height/2; printf("三角形的面积为%f\n",s); }else{ printf("您输入有误!底和高必须大于零!\n"); } } |
[A1]函数原形
[A2]函数调用:将执行被调用函数中代码
[A3]函数调用
作业1:编写一个函数void isTri(),判定用户输入的三个边长是否能组成三角形。三角形的两个组成条件是:
1.三边都要大于0
2.任意两边之和大于第三边
void isTri();//三个边长是否能组成三角形 void main(){ isTri();//调用 } //判断是否能组成三角形的函数
void isTri() { int a,b,c; printf("请输入三角形的边长1:\n"); scanf("%d",&a); printf("请输入三角形的边长2:\n"); scanf("%d",&b); printf("请输入三角形的边长3:\n"); scanf("%d",&c); //判断三边边长是否都大于0 if(a>&&b>&&c>){ //任意两边之和大于第三边 if((a+b>c)&&(a+c>b)&&(b+c>a)){ printf("%d,%d,%d能组成三角形\n",a,b,c); }else{ printf("您输入的边长不满足任意两边之和大于第三边的条件\n"); } }else{ printf("您输入的边长有误,边长必须为正数!\n"); }
作业2:编写一个函数int pieAdd(int n),计算1+2+3+……+n的值并返回。比如pieAdd(3)的返回值是1+2+3=6
int pieAdd(int n);//计算从1~N累加和的程序 void main(){ int sum = pieAdd();//5实参要形参相对于(类型,数量,顺序) printf("累加为:%d\n",sum); } int pieAdd(int n){ int i,sum=; for(i=;i<=n;i++){ sum+=i; } return sum;//返回值要与返回值类型向对应 }
比如:1634=1^4+6^4+3^4+4^4作业3:写一个函数void rose(int n),判断某一个四位数是不是玫瑰花数(所谓玫瑰花数即该四位数各位数字的四次方和恰好等于该数本身。
void rose(int n);//判断N是否为玫瑰花数 void main() { rose();//函数调用 } void rose(int n){ int ge,shi,bai,qian,sum; //获取个位 //1234===>1234%10==>4 ge=n%; //获取十位 //1234==>1234/10==>123%10==>3 shi=n/%; //获取百位 //1234==>1234/10==>123/10==>12%10==>2 bai=n//%; //获取千位 //1234/10==>123/10==>12/10==>1 qian=n/; sum=pow(ge,)+pow(shi,)+pow(bai,)+pow(qian,); if(sum==n){ printf("%d是一个玫瑰花数\n",n); }else{ printf("%d不是一个玫瑰花数\n",n); } }
函数的嵌套调用,在一个函数里面调用另一个函数,要记住声明时应把所有调用的函数的原型都声明一下.
函数的递归调用:函数自身调用自身。
示例:使用递归实现计算N的阶乘
#include <stdio.h> int factorinal(int a);//函数递归调用实现计算阶乘 void main() { int sum = factorinal(); printf("5的阶乘为%d",sum); } //计算a的阶乘 int factorinal(int a) { if(a==){ return ; }else{ return a*factorinal(a-); } }
下面是代码执行过程分析图.
利用递归实现斐波那契数列: 1 1 2 3 5 8 13 21....
跟菲波那切数列有关的一个古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月,后每个月又生一对兔子,假如兔子都不死,1年后总共有多少对兔子?
根据规律得出公式:f(n)=f(n-1)+f(n-2); n>2
#include <stdio.h> int fibonacii(int n);//斐波那契数列 void main() { int num = fibonacii(); printf("1年后共有%d对兔子",num); } int fibonacii(int n){ if(n==||n==){ return ; }else{ return fibonacii(n-)+fibonacii(n-); } }
变量:程序中变量不同的使用范围,称为变量的作用域。变量的作用域决定变量的可访问性.出了作用域以后不在有效.程序中我们声明了很多的变量,下面我们要知道的是变量是有其作用范围的,变量分为全局变量和局部变量,全局变量如同国家主席,在一个国家里到哪刷脸都好用,而
局部变量:在函数内声明的变量,其作用范围仅限于该函数内
1.主函数中定义的变量也只能在主函数中使用,不能在其它
函数中使用。
2.允许在不同的函数中使用相同的变量名,它们代表不同的
变量,分配不同的存放单元,互不相干,不会发生混淆。
3.复合语句中定义的变量,也是复合语句的局部变量。所谓
复合语句,就是用{}包含起来的语句块。
#include <stdio.h>
void m();
void main()
{
int a=,b=;
{
int a=,b=;//这个的作用域就只在这个main函数中,
printf("复合语句的变量a=%d,b=%d\n",a,b);//打印出的结果也就是在这个函数中赋值的1,2
}
printf("main函数的变量a=%d,b=%d\n",a,b);
m();
} void m()
{
int a=,b=;
printf("m函数的变量a=%d,b=%d\n",a,b);//虽然同样是变量a,b此处打印的就是5,6
}
1.全局变量定义必须在所有的函数之外。包括main函数.
2.全局变量可加强函数模块之间的数据联系, 但是又使函数要依赖这些变量,因而使得函数的独立性降低。
3. 在同一源文件中,允许全局变量和局部变量同名。在局部变量的作用域内,同名的全局变量不起作用。
#include <stdio.h>
int sum=;//全局变量
void addNumbers()
{
int sum;//局部变量
int num1,num2;
printf("\n 请输入两个数:");
scanf("%d %d",&num1,&num2);
sum=num1+num2;
printf(" 子函数中 sum 的值是 %d \n",sum);
}
void main()
{
int sum=;//局部变量
addNumbers();
printf("\n 主函数中 sum 的值是 %d \n ",sum);
}
上面的就是一个全局变量的示例其打印的结果根据输入的数值的不同,第一次打印的变量sum的变量是在不停变动的,二第二次打印的sum则始终为0
小练习:输入一个数字计算阶乘;
#include <stdio.h>
int fun(int n);
void main(){
int n;
printf("请输入您要计算阶乘的数:\n");
scanf("%d",&n);
int sum=fun(n);
printf("%d的阶乘是%d",n,sum);
} //计算阶乘
int fun(int n){
int sum=;
while(n>){
sum*=n;
n--;
}
return sum;
}
小练习:大赛评分计算,10为评为为选手打分,去掉一个最高分和一个最低分,计算选手的最后得分。
#include <stdio.h>
void showMenu();
void getScores();
float calcAvg(); float scores[];//定义全局变量,用于保存评委的打分
void main(){
float avg;
//1.打印菜单
showMenu();
//2.获取评委打分
getScores();
//3.计算选手最后得分
avg = calcAvg();
printf("该选手去掉一个最高分和一个最低分最终得分为%.2f分\n",avg);
}
//1.打印菜单
void showMenu()
{
printf("************************************************\n");
printf("*************郑州尚学堂杯博客大赛***************\n");
printf("************************************************\n");
}
//2.获取10个评委打分
void getScores()
{
int i;
for(i=;i<;i++){
printf("请%d号评委打分:\n",i+);
scanf("%f",&scores[i]);//将评委的打分获取并保存到数组中
}
printf("评委打分完毕,分数正在紧张统计中.....\n");
}
//3.统计评委成绩去掉一个最高分和一个最低分,计算选手平均得分
float calcAvg()
{
float max,min,avg,sum=;
int i;
max=scores[];//假设第一个分数最高
min=scores[];//假设第一个分数最低
for(i=;i<;i++){//计算总分
sum+=scores[i];
if(scores[i]>max){//获取最高分
max=scores[i];
}
if(scores[i]<min){//获取最低分
min=scores[i];
}
}
//去除最低分和最高分计算平均分
avg=(sum-max-min)/;
return avg;
}
再啰嗦总结一下,什么是函数?函数就是一个为了实现某些功能的代码的一个集合,或者说是把实现某些功能的代码集合打包起来加了个标签(名字),这个带标签的代码集合就是函数,它的作用和定义下不多,就是可以把相对独立的某个功能抽离出来,使之成为程序中的一个独立个体,可以方便在一个程序或其他程序中重复使用.由此也就可以明白了,只要你需要重复实现某个功能的话就可以把它做好以后抽离出来打包好价格标签留着需要的时候拿出来用.这就是函数对于我们的作用.
#include <stdio.h> void m(); void main() { 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); m(); } void m() { int a=5,b=6; printf("m函数的变量a=%d,b=%d\n",a,b); } |
C语言学习第六章的更多相关文章
- Go语言学习笔记六: 循环语句
Go语言学习笔记六: 循环语句 今天学了一个格式化代码的命令:gofmt -w chapter6.go for循环 for循环有3种形式: for init; condition; increment ...
- 201671010140. 2016-2017-2 《Java程序设计》java学习第六章
java学习第六章 本周对与java中的接口,lambda表达式与内部类进行了学习,以下是我在学习中的一些体会: 1.接口: <1>.接口中的所有常量必须是public sta ...
- 【转载】Gradle学习 第六章:构建脚本基础
转载地址:http://ask.android-studio.org/?/article/11 6.1. Projects and tasks 项目和任务Everything in Gradle si ...
- Java基础知识二次学习--第六章 常用类
第六章 常用类 时间:2017年4月26日16:14:49~2017年4月26日16:56:02 章节:06章_01节~06章_06节 视频长度:20:57+1:15+8:44+1:26+11:2 ...
- C#高级编程 (第六版) 学习 第六章:运算符和类型强制转换
第六章 运算符和类型强制转换 1,运算符 类别 运算符 算术运算符 + - * / % 逻辑运算符 & | ^ ~ && || ! 字符串连接运算符 + 增量和减量运算符 ++ ...
- C语言学习第五章
今天要进行一个重要元素数组的学习了.这一章要掌握什么是数组,数组怎么样命名,数组怎么样使用,以及一些常见的错误和需要注意的事项. 一. 数组的基本概念 数组是可以在内存中连续存储多个元素的结 ...
- C语言学习笔记第一章——开篇
本文章B站有对应视频 (本文图片.部分文字引用c primer plus) 什么是C语言 顾名思义,c语言是一门语言,但是和我们所讲的话不同,它是一门编程语言,是为了让机器可以听懂人的意思所以编写的一 ...
- C 语言学习 第六次作业总结
本次作业,同学们开始学习函数.通过之前和同学们的沟通,似乎同学们在这里遇到的问题比较多.下面,我先帮同学们整理下函数的相关知识点. 什么是函数 首先,需要明确的是,什么是函数.所谓函数,也就是一段有名 ...
- C语言学习第七章
今天开始学习指针,指针在C语言中具有很重要的地位,按照老师所说,学C学不好指针跟没学一样,可见指针在C语言中的重要地位.废话不多说,首先我们先要知道什么是指针. 指针:指针是一个变量,它存储另一个对象 ...
随机推荐
- 【运维监控】四款云服务监控工具介绍:Nagios 、 ganglia、zabbix、onealert
在我们日常的工作中,有时候需要监控和管理平台的运行状况,而服务运行是否存在异常,是否有软硬件bug等,均需要第一时间知道.对服务状态了如指掌,是一个很重要的事情.那么这个如何做到呢,我们之前在进行私有 ...
- js动态加载的蒙板弹框
我们访问一些网站时总会遇到这种点击后,背景像被打上一层模板一样,这个是怎么做到的呢? 它是将这个弹框div独立于页面容器wrap,设置position为absolute,将其水平垂直之后都居中,设置弹 ...
- JAVA基础知识(2)--关键字static的使用
在Java类中声明属性.方法和内部类时,可使用关键字static作为修饰符,static标记的属性和方法可以由整个类进行共享,因此static修饰的属性称为类成员或者称为类方法:static修饰的方法 ...
- jsp中的动作标签
和html标签一样,使用尖括号'<>'包裹起来. 用于在jsp页面中处理业务逻辑,避免在jsp中过多的使用java脚本. <jsp:forward>用于请求转发,它与Reque ...
- pyqt样式表语法笔记(下)--原创
pyqt样式表语法笔记(下) python 启动界面 QSS pyqt 一.启动界面的设置 简单点~说话的方式简单点用一张静态图片作为程序启动界面为例. 原来的语句 python 7行 ...
- 初步认识Thymeleaf:简单表达式和标签。(二)
本篇文章是对上篇文章中Thymeleaf标签的补充. 1.th:each:循环,<tr th:each="user,userStat:${users}">,userSt ...
- 微信小程序首页总结
效果图如下 首先从大的方面来讲,就是设置了window的属性 "navigationBarBackgroundColor": "#AFE2E6",//bar ...
- JavaScript写一个表格排序类
依稀记得那是上个星期六的下午,我参加了网易暑期实习生招聘笔试.考得相当糟糕,编程题3个题通过了2个,简答题没做对,选择题貌似是20个题猜了6-7个,99%是挂了,唉唉唉!生活不只眼前的苟且,学习的脚步 ...
- display与visibility的使用(区别)
display:none;隐藏元素,且此元素无物理位置: visibility:hidden;隐藏元素,但元素的物理位置依然存在: 因为display:none导致页面上无此元素的空间,js就获取不到 ...
- 对象的创建过程(chapter5.7.3)
总结一下对象的创建过程,假设有一个名为Dog的类: 1. 即使没有显示地使用static关键字,构造器实际上也是静态的方法,因此,当首次创建类型为Dog的对象时(构造器可以看成静态方法),或者Dog类 ...