函数学习总结

  一、知识总结
    函数是一个命了名的代码块,我们通过调用函数执行相应的代码。
(一)函数的定义、声明和调用
1. 函数的定义
数据类型   函数名(形式参数表)
{

 函数体                   //执行语句
}
『注』ⅰ 函数从结构上可以分为三种:无参函数、有参函数和空函数,所以形式参数表可以为空。形参间用逗号隔开,且函数名后的圆括号必须有。形参必须有类型说明且要逐一说明,可以是变量名、数组名或指针名。
函数不允许嵌套定义,但是允许嵌套使用。
「例」
int max(int x,int y)
{   
return x>y?x:y;
}
2.函数的声明
和其他名字一样,函数的名字也必须在使用之前声明。函数只能定义一次,但可以声明多次。如果一个函数永远也不会被我们用到,那么它可以只有声明没有定义。
形式为  类型说明符     被调用函数名(含类型说明的形参表);
『注』如果函数原型声明在所有函数定义之前,那么该函数原型在本程序文件中任何地方都有效;如果在某个主调函数内部声明了被调用函数原型,则只在这个函数内部有效。
3.函数的调用
   声明了函数原型后就可以调用函数了,形式为  函数名 (实参列表),实参列表中应给出与函数原型形参个数相同、类型相符的实参;在主调函数中的实参一般应具有确定的值。
     在组成函数体的各类语句中,值得注意的是返回语句return,形式为  return (表达式); ,其功能是把程序流程从被调函数转向主调函数 并把表达式的值带回主调函数,实现函数的返回。
函数调用的三种方式:传值调用、引用调用、指针调用(传址调用)。
(1)传值调用
        这种调用方式是将实参的数据值传递给形参,即将实参值拷贝一个副本给被调用函数。函数对形参的所有操作都不会影响实参,参数传递方向只是从实参到形参。“只是赋值,形参操作后无关联”。一般不想改变实参值的时候使用传值调用。
「例」
 
  
#include<iostream>
using namespace std;
void swap(int,int);
int main()
{
int a=3,b=4;
cout<<"a="<<a<<",b="<<b<<endl;
swap(a,b);
   cout<<"a="<<a<<",b="<<b<<endl;
return 0;
}
void swap(int x,int y)
{
int t=x;
x=y;
y=t;
}
程序输出结果:a=3,b=4
(2) 引用调用
     函数调用时,形参不需要开辟新的存储空间,形参和实参使用同一个存储空间,即形参和实参是一回事,形参相当于实参的一个别名,对形参操作就是对实参操作。形式为  类型名 &引用名=某变量名;
int n=4;
int &r=n;
cout<<r;//输出为4;
cout<<n;//输出为4;
n=5;
cout<<r;//输出为5; 

引用只能引用变量,不能引用常量和表达式。

【例】
#include<iostream>using namespace std;void swap(int&,int&);int main(){ int a=3,b=8; swap(a,b); cout<<"a="<<a<<",b="<<b<<endl; return 0; }void swap(int &x,int &y){ int temp = x; x=y; y=temp;}
输出结果为:a=8,b=3

(3)指针调用(传址调用)
函数定义中的形参被说明为指针类型时,形参指针对应的实参是地址表达式,被调用函数可以在函数体内通过形参指针来间接访问实参地址所致的对象。对于一般传值参数实参向形参传送的是数据表达式,而指针参数对应的实参是地址表达式。形式为   类型标识符  *变量名,一个指针变量只能指向同一类型的变量。绝对不能对未赋值的指针变量作“取内容”运算。用指针变量作函数参数,在被调函数的执行过程中,应使指针变量所指向的参数值发生变化,这样,其变化值才能保留回主调函数。
【例】
 
#include<iostream>
using namespace std;
void swap(int *,int*);
int main()
{
int a=3,b=8;
swap(&a,&b);
   cout <<"a="<<a<<",b="<<b<<endl;
return 0;
}
void swap(int *x,in *y)
{
int temp = *x;
*x=*y;
*y=temp;
}
输出为:a=8,b=3

(二)递归算法
递归算法的本质是函数自己调用自己,用调用自己的方法去解处理问题,可以使解决问题变得简单明了。
能够用递归算法解决的问题一般满足如下要求:
①需要求解的问题可以化为子问题求解,其子问题的求解方法与原问题相同,只是规模上的增加或减少;
②递归调用的次数是有限的,必须有递归结束的条件。
递归调用的返回值是逐层返回的,递归的关键在于找出 递归定义 递归终止条件。
递归算法的解题步骤一般有三步:
分析问题,寻找递归:找出 大规模问题与小规模问题的关系, 这样通过递归使问题的规模逐渐变小。
设置 边界,控制递归: 找出停止条件, 算法可解的最小规模问题。
设计函数,确定函数:设计函数体中的操作及相关参数。
【例】用 递归方法求两个数m和n的最大公约数。
#include<iostream>
using namespace std;
int gcd(int,int);
int main()
{
  int m,n;
  cin>>m>>n;
  cout<<"gcd="<<gcd(m,n)<<endl;
  return 0;
}
int gcd(int m,int n)
{
   return n==0?m:gcd(n,m%n);
 }
二、 题型总结
(1)函数题型

    验证“歌德巴赫猜想”,即:任意一个大于2的偶数均可表示成两个素数之和。

#include<iostream>
#include<cmath>
using namespace std;
bool prime(int);
int main()
{
    int n,x,y;
    cin>>n;
    for(int x=2;x<=n/2;x++)
    if(prime(x)==true)
    {
        y=n-x;
        if(prime(y)==true)
        cout<<n<<" "<<"="<<" "<<x<<" "<<"+"<<" "<<y<<endl;
    }
    return 0;
}
bool prime(int s)
{
   int i=2,k;
   k=int(sqrt(s));
   while (s%i&&i<=k)
   i++;
   if (i>k) return true;
   else return false;
 }
②因子:输入1个整数n。从小到大依次输出n的所有因子。
#include<iostream>
using namespace std;
int yin(int);
int main()
{
    int n;
    cin>>n;
    yin(n);
    return 0;
}
int yin(int x)
{
    int i,sum=0;
    for (i=2;i<=(x/2);i++)
        if (x%i==0)
        {cout<<i<<" ";sum++;}
        cout<<sum<<endl;
}
放苹果:把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。
#include<iostream>
using namespace std;
int fpg(int m,int n)
{
    if (m<0) return 0;
    if (m==1 || n==1) return 1;
    else return fpg(m,n-1) + fpg(m-n,n);
}
int main()
{
  int M,N,t,k;
  cin>>t;
  for (int i=0;i<t;i++)
{  cin>>M>>N;
  k=fpg(M,N); 
  cout<<k<<endl;}
  return 0;
  }
④分解因数:给出一个正整数a,要求分解成若干个正整数的乘积,即a = a1 * a2 * a3 * ... * an,并且1 < a1 <= a2 <= a3 <= ... <= an,问这样的分解的种数有多少。注意到a = a也是一种分解。
#include<iostream>
using namespace std;
int j,k,n;
void fj(int s,int m)
{
    if (s==1)
    {
        k++;return;
    }
    else for (int i=m;i<=s;i++)
        if (s%i==0)
    {
        fj(s/i,i);
    }
}
int main()
{
    cin>>n;
    for (j=1;j<=n;j++)
    {
        k=0;int t;
        cin>>t;
        fj(t,2);
        cout<<k<<endl;
    }
    return 0;
}
⑤采药:辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。” 如果你是辰辰,你能完成这个任务吗?
#include<iostream>
using namespace std;
int T,M;
int t[1005],p[105];
int f[1005][105];
int max(int x,int y)
{
    if(x<y) return y;
    else return x;
}
int main()
{
    cin>>T>>M;
    for (int i=1;i<=M;i++) cin>>t[i]>>p[i];
    for (int i=1;i<=M;i++)
     for (int j=T;j>0;j--)
     if (t[i]<=j) f[i][j]=max(f[i-1][j],f[i-1][j-t[i]]+p[i]);
     else f[i][j]=f[i-1][j];
     cout<<f[M][T]<<endl;
     return 0;
}
三、学习心得
C++对我来说还是有点难度的,但是”为之,则难者亦易矣“。C++的基础知识还是要认真研究一下,基础知识的掌握对于做题时的分析和理解的效率还是有提高作用的。上学期的C语言学习时,对于知识点没有认真理解掌握,以至于做题时总会在一个题上滞留不前,导致在多个“WrongAnswer”之后就没有耐心自己编写而选择复制粘贴了,那样就会错过许多练习和积累的机会。这样的学习方法不提倡,C++的学习是要先理解再实践,就像是这章的递归,对于做题步骤已是明白,只是对于递归公式的寻找还欠缺训练,总是不能准确的将大规模问题分解为求解方法与之相同的小规模问题,还是需要积累题型与解题方法。也要与人多交流,多学习理解别人的思路。总之,C++是要下一番功夫的,认真学吧!



          

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值