一.基础内容
1.函数的定义
(1)定义的语法形式:
数据类型 函数名(形式参数表)
{
函数体 //执行语句
}
注释说明:
*数据类型是返回值类型(void无返回值)
*函数名按照标识符的取名规则可以任取
*形式参数:可有可无,且可以是变量名、数组名或指针名,作用是实现主调函数和被调函数的关系
*函数不允许嵌套定义
函数定义的例子:
定义一个函数,返回两数中的较大数
int max(int x,int y)
{
return x>y? x:y;
}
该函数返回值是整型,有两个整型的形参,用来接受实参传递的两个数据,函数体内的语句是求两个数中的较大并将其返回主调函数。
特殊的函数形式:
空函数(实例)
#include<iostream>
using namespace std;
int js(int); //函数的声明
int main()
{
int sum=0;
for(int i=0;i<=10;i++)
sum+=js(i); //函数的调用
ocut<<"sum+"<<sum<<endl;
return 0;
}
int js(int n) //定义的函数体
{
int s=1;
for(int i=1;i<=n;i++)
s*=i;
return s; //函数的返回值
}
空函数不完成什么工作,只占据一个位置,在大型函数设计中,空函数只用于扩充函数内容。
2.函数的声明和调用
1.(1)函数的声明:
类型说明符 被调函数名(含类型说明的形参表);
int js(int n);
或者是
int js(int);
(2)函数的调用:
函数名(实参列表)
sum+=js(i);
(3)函数的返回值:
return(表达式)
return s;
2.函数的传值调用:
(1)传值调用
这种调用方式是将实参的数据值传递给形参,即将实参拷贝一个副本存放在被调用的函数的栈区中。在被调用函数中,形参值可以改变,但不影响主函数的实参值。参数传递方向只是从实参到形参,简称单项值传递。
#include<iostream>
using namespace std;
void swap(int a,int b)
{
int tmp=a;a=b;b=tmp;
}
int main()
{
int c=1,d=2;
swap(c,d);
cout<<c<<''<<d<<endl;
return 0;
} //程序输出为:1 2
(2)传址调用
这种调用方式是将实参变量的地址值传递给形参,这时形参是指针,即让形参的指针指向实参地址,这里不再是将实参拷贝一个副本给形参,而是让形参直接指向实参,这就提供了一种可以改变实参变量的值的方法。现在用传址调用来实现swap:
#include<iostream>
using namespace std;
void swap(int &a,int &b)
{
int tmp=a;a=b;b=tmp;
}
int main()
{
int c=1,d=2;
swap(c,d);
cout<<c<<''<<d<<endl;
return 0;
} //程序输出为:2 1
3.函数指针:
(1)定义与应用
指针变量:其内容为地址(存储位置)的变量,简称指针。它所指向的地址上存放的变量称为目标变量。
指针变量也同样可以赋值:
(2)指针变量作为函数参数
函数的参数可以是指针类型,它的作用是将一个变量的地址传送的另一个函数中。
指针变量作为函数参数与变量本身作函数参数不同,变量作函数参数传递的是具体值,而指针作函数参数传递的是内存的地址。
用指针变量作函数参数,在被调函数的执行过程中,应使指针变量所指向的函数值发生变化,这样,函数在调用结束后,其变化值才能保留回主调函数。
函数调用不能改变实参指针变量的值,但可以改变实参指针变量所指向变量的值。
用指针变量作函数参数,可以得到多个变化了的值。
(3)指向数组元素的指针
例子如下
int a[10],*p;
p=&a[0]; //数组第一个元素的地址
p=a; //直接用数组名赋值;p为变量,a为常量
4.递归算法
简单的说,递归算法的本质就是自己调用自己,用调用自己的方法去处理问题,可以使问题变得简洁。
步骤如下:
保存调用前的变量和程序的返回地址——执行被调用的函数——满足条件退出递归,否则从变量值继续沿着返回地址向下执行程序
二.典型例题
1.函数的简单定义去解决问题:
(例1)
输入一个整数
输出奇数字个数
偶数字个数
#include<iostream>
using namespace std;
int oushu(int n);
int main()
{
long t,x;
int i=0,j=0;
cin>>x;
do
{
t=x%10;
if(oushu(t)==1)
i++;
if(oushu(t)==0)
j++;
x=x/10;
}
while(x!=0);
cout<<j;
cout<<endl;
cout<<i;
return 0;
}
int oushu(int n)
{
if(n%2==0)
return 1;
else
return 0;
}
(例2)
描述 给定一个整数,请将该数各个位上数字反转得到一个新数。新数也应满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数的最高位数字不应为零
输入输入共 1 行,一个整数N。
输出输出共 1 行,一个整数,表示反转后的新数。
#include<bits/stdc++.h>
using namespace std;
int fz(int n);
int main()
{
int x;
cin>>x;
cout<<fz(x);
return 0;
}
int fz(int n)
{
int s=0;
while(n)
{
s=n%10+s*10;
n=floor(n/10);
}
return s;
}
(例3)
描述 求从1加到n的阶乘的和,输入n的值,按要求输出。输入 输入一个数n输出 输出从1加到n的和#include<bits/stdc++.h>
using namespace std;
int jiecheng(int n);
int main()
{
int x,sum=0;
int j;
cin>>x;
for(j=1;j<=x;j++)
sum+=jiecheng(j);
cout<<sum;
return 0;
}
int jiecheng(int n)
{
int s=1;
int i;
for(i=1;i<=n;i++)
s=s*i;
return s;
}
2.函数的递归算法解决复杂问题:
(例4)
描述 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。输入 第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10。输出对输入的每组数据M和N,用一行输出相应的K。
#include<iostream>
using namespace std;
int t,m,n;
int up(int ,int);
int main()
{
cin>>t;
while(t--)
{
cin>>m>>n;
cout<<up(m,n)<<endl;
}
return 0;
}
int up(int m,int n)
{
if(m==0||n==1)
return 1;
else if(m<n)
return up(m,m);
else return up(m-n,n)+up(m,n-1);
}
三.学习心得
总结函数本章以及初入递归算法的内容学习,我发现函数的基础不是很难但是十分重要,就像是一门语言中的语法一样,函数的应用极大的扩充了C++的应用范围以及提高了其普遍性与可应用性,所以应该好好掌握。而接下来的递归,我个人感觉比较难掌握,尤其是各类循环的辨识与循环的跳出,恐怕是个需要深入研究的知识。