一、 为什么需要函数
避免了重复性操作
有利于程序的模块化
#include<stdio.h>
//max是函数的名字,i和j是形式参数,简称形参,void表示函数没有返回值
void max(int i,int j){
if(i>j)
printf("%d\n",j);
else
printf("%d\n",j);
}
int main(void)
{
int a,b,c,d;
a=1;
b=2;
c=3;
d=9;
max(a,b);//2
max(c,d);//9
return 0;
}
二、 什么叫函数
- 逻辑上:
能够完成特定功能的独立代码块 - 物理上:
能够接受数据(也可以不接受数据),
能够对接受的数据进行处理,
能够将数据处理的结果返回(也可以不返回任何值)
#include<stdio.h>
int f(void) //括号中的void表示该函数不能接受数据 int 表示函数返回值是int类型
{
return 10;
}
void g(void)//函数名前面的void表示该函数没有返回值
{
//不能加return
}
int main(void){
int j=88;
j=f();
printf("%d\n",j); //10
return 0;
}
- 总结:
函数是个工具,它是为了解决大量类似问题而设计的
函数可以当作一个黑匣子
三、 如何定义函数
- 函数定义的本质是详细描述函数之所以能够实现某个特定功能的具体方法
- return 表达式; 的含义:
return:
1->终止被调函数,向主调函数返回表达式的值
2->如果表达式为空,则只终止函数,不向主调函数返回任何值。
3->break是用来终止循环和switch的,return是用来终止函数的
void f(void){
int i;
for(i=0;i<5;i++){
printf("大家辛苦了!\n");
return;
}
printf("同志们好\n");
}
int main(void){
f();//大家辛苦了!
return 0;
}
break:终止循环
void f(void){
int i;
for(i=0;i<5;i++){
printf("大家辛苦了!\n");
break;
}
printf("同志们好\n");
}
int main(void){
f();//大家辛苦了!同志们好
return 0;
}
- 函数返回值的类型也成为函数的类型,因为如果函数名前的返回值类型和函数执行体中的return表达式; 中表达式的类型不同的话,则最终函数返回值的类型以函数名前的返回值类型为准。
int f()
{
return 10.5;//因为函数的返回值类型是int,所以最终f返回的是10而不是10.5
}
int main(void){
int i=99;
double x=6.6;
x=f();
printf("i=%d\n",i);//99
printf("i=%lf\n",i);//0.000000
printf("x=%lf\n",x);//10.000000
return 0;
}
四、 函数的分类
4.1分类
- 有参函数 和 无参函数
- 有返回值 和 无返回值
- 库函数 和 自定义函数
- 普通函数和主函数(main函数)
1->一个程序必须有且只能有一个主函数
2->主函数可以调用普通函数,普通函数不能调用主函数
3->普通函数可以相互调用
4->主函数是程序的入口,也是程序的出口 - 值传递函数 和 地址传递函数
4.2举例
有返回值 和 无返回值
void max1(int i,int j){
if(i>j)
printf("%d\n",i);
else
printf("%d\n",j);
}
int max2(int i,int j){
if(i>j)
return i;
else
return j;
}
int main(void){
int i,j,m1,m2;
i=10;
j=2;
max1(i,j);
printf("%d",max2(i,j));
return 0;
}
判断一个数是否是素数
bool IsPrime(int v){
int i;
for(i=2;i<v;i++){
if(v%i==0)
break;
}
if(i==v)
return true;
else
return false;
}
int main(void)
{
int val;
scanf("%d",&val);
if( IsPrime(val) )
printf("yes!\n");
else
printf("no!\n");
return 0;
}
五、 注意的问题
5.1函数调用和函数定义的顺序
如果函数调用写在了函数定义的前面,则必须加函数的前置声明
void f(void);//函数f的声明
void g(void){
f();//函数f的调用
}
void f(void){//函数f的定义
printf("hh");
}
int main(void){
g();
return 0;
}
5.2函数的声明
- 作用:
1-> 告诉编译器即将可能出现的若干个字母代表的是一个函数。
2->告诉编译器即将可能出现的若干个字母所代表的函数的形参的返回值和具体情况。 - 函数声明是一个语句,末尾必须加分号
- 对库函数的声明是通过#include<库函数所在的文件的名字.h>来实现的。
5.3形参和实参
形参和实参个数相同,位置一 一对应,数据类型必须相互兼容
void f(int i){//i:形参
printf("%d\n",i);
}
int main(void){
f(5);//5:实参
return 0;
}
5.4如何在软件开发中合理的设计函数来解决实际问题
- 一个函数的功能尽量独立,单一
- 多学习,多模仿牛人的代码
- 举例:
输出1到n之间的所有的素数:
bool IsPrime(int);
void TraverseVal(int val){//把1到n之间所有的素数在显示器上输出
int i;
for(i=2;i<=val;i++){
if(IsPrime(i)){
printf("%d\n",i);
}
}
}
bool IsPrime(int val){//判断是否为素数,是返回true,不是返回false
int i;
for(i=2;i<val;i++){
if(val%i==0)
break;
}
if(val==i)
return true;
else
return false;
}
int main(void){
int val;
int i;
scanf("%d",&val);
TraverseVal(val);
return 0;
}
六、 常用的系统函数
函数 | 作用 |
---|---|
double | 求x的平方根 |
int abs(int x) | 求x的绝对值 |
double fabs(double x) | 求x的绝对值 |
七、 专题:递归
八、变量的作用域和存储方式
8.1按作用域分
- 局部变量:在一个函数内部定义的变量或者函数的形参,都统称为局部变量。局部变量的使用范围:只能在本函数内部使用。
- 全局变量:在所有函数外部定义的变量叫全局变量。使用范围为从定义位置开始到整个程序结束。
int k=1000;//k:全局变量
void f(int i){//i:局部变量
int j;
printf("%d",k);//1000
}
- 全局变量和局部变量命名冲突问题:
在一个函数内部如果定义的局部变量的名字和全局变量名一样时,局部变量会屏蔽掉全局变量。
int i=100;
void f(int i){
printf("%d",i);//1
}
int main(void){
f(1);
return 0;
}
8.2按变量的存储方式
- 静态变量
- 自动变量
- 寄存器变量