c++的函数

本文深入探讨C++函数的使用,包括函数的定义、调用、分类、递归调用以及函数在程序设计中的重要性。通过实例解析了如何找到两个数中的最大值、输出素数、绘制图形,还介绍了函数声明、形参与实参的关系、数组和二维数组作为函数参数的应用,并提供了多种递归调用的示例和练习。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数

重难点

  • 用函数实现模块化程序设计
  • 函数的递归调用

函数是什么?c语言中的函数与数学函数一样吗?为什么用函数?

  • 函数是实现某一功能的模块,有的函数完成某一操作;有的函数计算出某个值;有的函数既能完成某一特定操作,又能计算数值。
  • c语言的函数可以看成是对数学函数的一种抽象(y=x+1)
  • 1、避免重复的编程。
    2、便于实现模块化的程序设计,使得便于思考、阅读、修改、多人协作等。

c++的程序是由函数构成的

  • 一个源程序文件由一个或多个函数组成。
  • 一个程序必须有且只有一个main( )函数,C++从main( )函数开始执行。

c++函数的分类

  • 从使用角度来说,分标准函数和用户自定义函数;
  • 从形式来说,分无参函数和有参函数。

标准函数实例

  • 标准函数是系统为了使用者方便而事先编好的一些函数,存储在一些库文件里边,如下面这两个库文件:
 - #include<cmath>
 - #include<cstdio>
  • 例:求两个数中的较大数的函数 max
cin>>a>>b;
c=max(a,b); 
  • 例:求某个数的绝对值
cin>>a;
b=abs(a);
  • 例:输入输出函数
scanf(“%d”,&a);
printf(“%d”,a);

函数的定义

  • 函数返回值类型 函数名(参数1类型 参数1名称, 参数2类型 参数2名称…)
    {
    函数体;
    }
  • 如果函数不需要返回值,则 “返回值类型” 为“void”

函数的调用

调用函数:

函数名(参数1, 参数2,…); //函数调用表达式
  • 在函数体内部通过 return语句结束函数运行并返回函数调用表达式的值 return 返回值; //返回值可以是变量、常量、表达式
  • 一个函数体中可能有多条return语句,根据不同情况返回不同值。
  • 不返回值的时候,直接写 return ;

函数的调用实例1

例:求两个整数的较大数。

  • 一般函数的调用可以先定义后使用
  • 函数调用语句导致程序进入函数执行,return语句导致程序回到函数调用语句的后面执行
int Max(int x, int y){// x,y称为形式参数,简称形参
  if(x>y) return x;
  return y;
}
int main(){
  int a,b,c;
  cin>>a>>b;
  c=Max(a,b); // a,b称为实际参数,简称实参
  cout<<c;
  return 0;
}
  • 注意:实参和形参的类型要兼容,形参是实参数值的复制,形参值的改变不影响实参(如上例中的x,y在Max()函数中发生了改变,不会影响到main()函数中的a和b)
  • 已经定义好了上面的Max函数,怎么求三个整数的最大数?
  cin>>a>>b>>c;
  d=Max(Max(a,b),c); 
  • 函数可以方便地嵌套使用

函数的调用实例2

输出n个数中的素数

bool f(int x){
  for ( i = 2; i <= sqrt ( x ); i++)
    if(x%i==0)return false;
  return true;
}
int main(){
  int i,n,a;
  cin>>n;
  for(i=0;i<n;i++){
	cin>>a;
	if( f(a) )cout<<a<<endl;
}
  • 函数的使用使得主程序较为简洁,便于更好地理清思路

函数的调用实例3

输出如下图形

****************
  Hello, world
****************
#include <iostream>
using namespace std;
void print_message (){ 
   cout<<" Hello, world\n";
   return;
  }     
void printstar (){
    cout<<"****************\n";
    return;
   }     
int main( ){
     printstar ();
     print_message ();
     printstar();
     return 0;
}
  • 本例中函数的调用是没有参数的
  • 本例中函数没有返回值

函数练习

看程序写结果(观察find()函数的功能)

#include<iostream>//noip2001-pj-4
using namespace std;
int n,k,i,a[40];
void find(int x){
	int s,i1=0,j1;
	bool p=true;
	while(p){
		i1++;
		s=0;
		for(j1=1;j1<=n;j1++)
			if(a[j1]>a[i1])s++;
		if(s==x-1){
			cout<<a[i1]<<endl;
			p=false;
		}
	}
}
int main(){
	cin>>n>>k;
	for(i=1;i<=n;i++)cin>>a[i];
	find(k);
	find(n-k);
	return 0;
}
输入:
10 4
12 34 5 65 67 87 7 90 120 13
输出:

编程练习

  • 已知三角形的顶点位置,从小到大输出三条边边长(保留一位小数)。
    样例输入:
    0 0 1 1 2 0
    样例输出:
    1.4 1.4 2.0
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
using namespace std;
double  f(double x1,double y1,double x2, double y2){
	double a=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));//两点间距离的公式
	return a;
}
int main(){
	double x1,y1,x2,y2,x3,y3,a,b,c;
	cin>>x1>>y1>>x2>>y2>>x3>>y3;
	a=f(x1,y1,x2,y2);
	b=f(x1,y1,x3,y3);
	c=f(x2,y2,x3,y3);
	if(a>b)swap(a,b);
	if(a>c)swap(a,c);
	if(b>c)swap(b,c);
	printf("%.1lf %.1lf %.1lf",a,b,c);
	return 0;
}

一本通练习

  • 1150~1157

函数声明

函数A中调用函数B,函数B中又调用了函数A,可以吗?

  • 函数的调用语句前面只要有函数的声明即可,不一定要有定义
  • 函数声明的格式:返回值类型 函数名(参数1类型 参数1名称, …);
  • int Max( int x, int y);
  • int Max( int , int); //可以省略参数名称
void A();
void B(){
    A();
}
void A(){
    B();
}
  • 这个代码就可以实现相互的调用

函数声明实例

1150:求正整数2和n之间的完全数

  • 求正整数2和n之间的完全数(一行一个数)。
    完全数:因子之和等于它本身的自然数,如6=1+2+3
    输入n,从小到大每行输出一个完全数
bool f(int i);
int main(){
  int i,n,s=0;
  cin>>n;
  for(i=2;i<=n;i++)
    if( f(i)==true ) cout<<i<<endl;
  return 0;
}
bool f(int n){
  int s=0;
  for(int i=1;i<n;i++)
    if(n%i==0)s+=i;
  if(s==n) return true;
  else return false;
}

函数的调用实例4

输出向下移动的小人(小趣味)

#include<windows.h>
void Child();
int main(){
	for(int i=0;i<20;i++){
		system(“cls”);//清屏函数,该函数包含在windows.h的库文件中
		for(int j=0;j<i;j++) cout<<endl;
		Child();
		Sleep(100);//和wait函数有些相似,100表示100ms,程序会等待100ms后再向后执行
	}
	return 0;
}
void Child(){
	cout<<“ O”<<endl;
	cout<<“<H>”<<endl;
	cout<<“I     I”<<endl;
	return;
}

拓展练习:

  • 做一个向右移动的小人动画程序。
  • 试一下斜向移动的小人。

形参在引用时要改变实参的值

void Swap(int x, int y){
  int t;
  t=x; x=y; y=t;
  return;
}
int main(){
  int a,b,c;
  cin>>a>>b;
  Swap(a,b);
  cout<<a<<‘ ‘<<b;
  return 0;
}
Swap(int &x, int &y){
	int t;
	t=x;x=y;y=t;
	return;
}
int main(){
	int a,b;
	cin>>a>>b;
	Swap(a,b);
	cout<<a<<‘ ’<<b;
	return 0;
}
  • 两段代码的区别就是一个加了引用符号,一个没加,结果是不一样的

数组作为函数的参数可以传递值

例:将输入的n个数倒序存储后输出

void f(int b[],int n){ // 数组名称+[],不需要下标的具体值,这里的b数组接收a数组地址后等同于a数组,相当于把值也传递给了a数组
	for(int i=0;i<n/2;i++)
		swap(b[i],b[n-i-1]);
	return;
}
int main(){
	int i,n,a[105];	cin>>n;
	for(i=0;i<n;i++) cin>>a[i];
	f(a,n); //一维数组只需要写一个函数名就可以了,数组名就是传递的一个地址
	for(i=0;i<n;i++) cout<<a[i]<<‘ ’;
	return 0;
}

二维数组作为函数的参数

  • 作为形参是必须写明列数,不用写明多少行
void f(int a[][25]){
  cout<<a[1][1];
  return;
}
int main(){
	int i,j,n,m,a[105][25];
	cin>>n>>m;
	for(i=0;i<n;i++)
	  for(j=0;j<m;j++)
            cin>>a[i][j];
	f(a);
	return 0;
}

全局变量、局部变量及其作用域

  • 全局变量适用于所有函数(作用域)
  • 局部变量只适用于该函数内部(作用域)
  • 全局变量能够使用的内存更大

函数的综合运用与练习

一本通练习

  • 1397~1413, 有些题目有一定难度

函数的递归调用

  • 函数调用自身被称为是函数的递归调用
  • 求解的问题能够化为子问题求解且求解方法与原问题相同
  • 递归调用的次数是有限的
  • 递归的终止条件
  • 递归式

函数的递归调用实例

求n!

  • 递归的终止条件:if(n==1) return 1;
  • 递归式:f(n)=n*f(n-1);
int f(int n){
	if(n==1) return 1;
	return n*f(n-1);
}
int main(){
	int n;
	cin>>n;
	cout<<f(n);
	return 0;
}

求最大公约数

  • 递归的终止条件:if(n%m==0)return m;
  • 递归式:f(n, m)=f(m, n%m);
int Gcd(int n, int m){
	if(n%m==0)return m;
	return Gcd(m, n%m);
}
int main(){
	int n,m;
	cin>>n>>m;
	cout<<Gcd(n,m);
	return 0;
}

递归调用练习

一本通练习

  • 1158~1167

递归调用练习讲解

进制转换(注意递的过程和归的过程)

#include<iostream>
#include<cstdio>
using namespace std;
void f(int x, int m){
    if(x!=0)f(x/m,m);
    if(x!=0)
        if(x%m>9)cout<<char('A'+x%m-10);
        else cout<<x%m;
/*
x  m
11 2    1
5  2    1
2  2    0
1  2    1
0
*/
}
int main(){
    int x,m;
    cin>>x>>m;
    f(x,m);
    return 0;
}

递归的优化

菲波那切数列

#include<iostream>
#include<cstdio>
using namespace std;
long long s=0,a[205];
long long f(int n){
//    if(n==1) return 1;
//    return n+f(n-1);
    s++;
    if(n==0)return 0;
    if(n==1)return 1;
    if(a[n]) return a[n];
    return a[n]=f(n-1)+f(n-2);
}     
int main(){
    int n;
    cin>>n;    
    cout<<f(n)<<endl;
    cout<<s<<endl;
    return 0;
}
30
832040
59

30
832040
2692537

函数综合练习

  • 矩阵匹配
    04:最匹配的矩阵
    给定一个mn的矩阵A和rs的矩阵B,其中0 < r ≤ m, 0 < s ≤ n,A、B所有元素值都是小于100的正整数。 求 A 中一个大小为 r*s 的子矩阵 C,使得 B 和 C 的对应元素差值的绝对值之和最小,这时称 C 为最匹配的矩阵。如 果有多个子矩阵同时满足条件,选择子矩阵左上角元素行号小者,行号相同时,选择列号小者。
    输入
    第一行是 m 和 n,以一个空格分开。
    之后 m 行每行有 n 个整数,表示 A 矩阵中的各行,数与数之间以一个空格分开。
    第 m+2 行为 r 和 s,以一个空格分开。
    之后 r 行每行有 s 个整数,表示 B 矩阵中的各行,数与数之间以一个空格分开。
    (1 ≤ m ≤ 100,1 ≤ n ≤ 100)
    输出
    输出矩阵 C,一共 r 行,每行 s 个整数,整数之间以一个空格分开。 样例输入
    33
    34 5
    53 4
    82 4
    22
    73
    49
    样例输出
    45
    34
#include<iostream>
#include<cstdio>
#include<cmath>
#define N 105
using namespace std;
int a[N][N],b[N][N],n,m,r,s,c1,c2,S=0x7fffffff;
void Read(int c[][105],int x,int y){
    for(int i=1;i<=x;i++)
        for(int j=1;j<=y;j++)
            cin>>c[i][j];
    return;
}
int Sum(int x,int y){
    int ans=0;
    for(int i=x;i<x+r;i++)
        for(int j=y;j<y+s;j++)
            ans+=abs(a[i][j]-b[i-x+1][j-y+1]);
    return ans;
}
void Calc(){
    for(int i=1;i<=n-r+1;i++)
        for(int j=1;j<=m-s+1;j++){
            int s1=Sum(i,j);
            if(s1<S){
                S=s1;
                c1=i;
                c2=j;
            }
        }
}
Out(){
    for(int i=c1;i<c1+r;i++){
        for(int j=c2;j<c2+s;j++)
            cout<<a[i][j]<<' ';
        cout<<endl;
    }
}
int main(){
    cin>>n>>m; 
    Read(a,n,m);
    cin>>r>>s;
    Read(b,r,s); 
    Calc();
    Out();    
    return 0;
}

3 3
3 4 5
5 3 4
8 2 4
2 2
7 3
4 9
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值