定义和使用自己的子程序——函数的介绍

news2025/1/16 21:01:59

定义和使用自己的子程序——函数的介绍

  • 1.函数基础语法
    • 1.1.基础语法
    • 1.2.例题1——距离函数
      • 题目描述
      • 输入格式
      • 输出格式
      • 输入输出样例
        • 输入 #1
        • 输出 #1
      • 提示
  • 2.void类型
  • 3.变量作用域和参数传递
    • 3.1.局部变量和全局变量
    • 3.2.形式参数和实际参数
    • 3.3.例题2——歌唱比赛
      • 题目描述
      • 输入格式
      • 输出格式
      • 输入输出样例
        • 输入 #1
        • 输出 #1
  • 4.递归函数
    • 4.1.递归函数介绍
    • 4.2.例题3——计算阶乘
      • 题目描述
      • 输入格式
      • 输出格式
      • 输入输出样例
        • 输入 #1
        • 输出 #1
      • 提示
    • 4.3.递归函数运行详细演示和代码
    • 4.4.练习1——赦免战俘
      • 题目背景
      • 题目描述
      • 输入格式
      • 输出格式
      • 输入输出样例
        • 输入 #1
        • 输出 #1
  • 5.基础宏函数
  • 6.课后作业

1.函数基础语法

1.1.基础语法

    在编写程序时,我们可能会遇到需要大量实现同一种功能的情况。如果能把它们分装成像ceil,sqrt这样的函数该多好啊。我们接下来就会学习函数的相关知识。

函数,又叫子函数,也可以被称为子程序。函数定义的基本语法如下:

返回值类型 函数名(参数类型1 参数名1,参数类型2 参数名2,…参数类型n 参数名n)
{
    函数体
    return 返回值;
}

1.2.例题1——距离函数

距离函数 - 洛谷

题目描述

给出平面坐标上不在一条直线上三个点坐标 ( x 1 , y 1 ) , ( x 2 , y 2 ) , ( x 3 , y 3 ) (x_1,y_1),(x_2,y_2),(x_3,y_3) (x1,y1),(x2,y2),(x3,y3),坐标值是实数,且绝对值不超过 100.00,求围成的三角形周长。保留两位小数。

对于平面上的两个点 ( x 1 , y 1 ) , ( x 2 , y 2 ) (x_1,y_1),(x_2,y_2) (x1,y1),(x2,y2),则这两个点之间的距离 d i s = ( x 2 − x 1 ) 2 + ( y 2 − y 1 ) 2 dis=\sqrt{(x_2-x_1)^2+(y_2-y_1)^2} dis=(x2x1)2+(y2y1)2

输入格式

输入三行,第 i i i 行表示坐标 ( x i , y i ) (x_i,y_i) (xi,yi),以一个空格隔开。

输出格式

输出一个两位小数,表示由这三个坐标围成的三角形的周长。

输入输出样例

输入 #1
0 0
0 3
4 0
输出 #1
12.00

提示

数据保证,坐标均为实数且绝对值不超过 100 100 100,小数点后最多仅有 3 3 3 位。

题意分析
如果我们直接编写程序,回得到这样的代码:

#include<cstdio>
#include<cmath>
using namespace std;
int main(){
    double x1,y1,x2,y2,x3,y3,ans;
    scanf("%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&x3,&y3);
    ans=sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));//使用公式
    ans+=sqrt((x3-x2)*(x3-x2)+(y3-y2)*(y3-y2));
    ans+=sqrt((x3-x1)*(x3-x1)+(y3-y1)*(y3-y1));
    printf("%.2lf", ans);//保留两位小数
    return 0;
}

这样太啰嗦了,我们可以将计算两点的距离这个功能分装成一个函数。

#include<cstdio>
#include<cmath>
using namespace std;
double sq(double x)//每个子函数都必须定义在主函数外面
{
    return x*x;
}
double dist(double x1,double y1,double x2,double y2)//计算两点距离的函数
{
    return sqrt(sq(x1-x2)+sq(y1-y2));//调用前面定义过的函数
}
int main(){
    double x1, y1, x2, y2, x3, y3, ans;
    scanf("%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&x3,&y3);
    ans=dist(x1,y1,x2,y2);//使用前面分装好的函数
    ans+=dist(x1,y1,x3,y3);
    ans+=dist(x2,y2,x3,y3);
    printf("%.2lf",ans);
    return 0;
}

注意:函数内的每个参数都必须注明类型,不可以出现这种形式:

double f(int x1,x2)
{
    return x1+x2;
}

    我们应该根据引用的顺序,确定函数定义的顺序。比如上文sq函数应在dist函数前面定义dist函数应在main函数前面定义。

2.void类型

    在C++中有一种特殊的类型:空类型。即void。现阶段可以理解为void只能用来定义函数,不能用来定义变量。void类型的函数不能有返回值,或者返回一个“”。void类型的函数通常只用来执行一些操作。比如:

void print_data(int a,int b)
{
    cout<<a<<" "<<b<<endl;
}

void print_division(int a,int b)
{
    if(b==0)
    {
        cout<<"除数不能为0";
        return;//提前返回
    }
    double ans=a*1.0/b;
    cout<<ans<<endl;
}

3.变量作用域和参数传递

3.1.局部变量和全局变量

    在C++中,定义在函数外部的就叫做全局变量。反之,定义在函数内部的就叫做局部变量

    全局变量会自动赋值为0

#include<iostream>
using namespace std;
int n,a[110];//这两个是全局变量
int add(int x)
{
    return x+1;
}
int main(){
    int v=0;//这是局部变量
    cin>>n;
    a[n]=add(a[n]);
    cout<<a[n]<<endl;
}

3.2.形式参数和实际参数

    全局变量和局部变量统称为为实际参数,简称“实参”。定义函数时括号内的参数都叫做形式参数,简称“形参”。
    在函数运行的过程中,并不是直接引用实参。而是将实参的值拷贝一份来使用。函数返回之后,所有的形参都会被销毁。所以函数括号内的参数都叫做形式参数

#include<iostream>
using namespace std;
int Add(int x,int y)//x和y是形参
{
    return x+y;
}
int main(){
    int a,b;//a和b是实参
    cin>>a>>b;
    cout<<Add(a,b);
    return 0;
}

3.3.例题2——歌唱比赛

歌唱比赛 - 洛谷

题目描述

n ( n ≤ 100 ) n(n\le 100) n(n100) 名同学参加歌唱比赛,并接受 m ( m ≤ 20 ) m(m\le 20) m(m20) 名评委的评分,评分范围是 0 0 0 10 10 10 分。这名同学的得分就是这些评委给分中去掉一个最高分,去掉一个最低分,剩下 m − 2 m-2 m2 个评分的平均数。请问得分最高的同学分数是多少?评分保留 2 2 2 位小数。

输入格式

第一行两个整数 n , m n,m n,m
接下来 n n n 行,每行各 m m m 个整数,表示得分。

输出格式

输出分数最高的同学的分数,保留两位小数。

输入输出样例

输入 #1
7 6
4 7 2 6 10 7
0 5 0 10 3 10
2 6 8 4 3 6
6 3 6 7 5 8
5 9 3 3 8 1
5 9 9 3 2 0
5 8 0 4 1 10
输出 #1
6.00

题意分析
    我们可以使用类似于“打擂台”的方法寻找最大最小值。设置一个初始擂主。遍历数组,如果找到的数比当前擂主大/小就更新擂主。然后我们分装一个函数,用来计算每位同学的分数

程序如下:

#include<cstdio>
#include<algorithm>
using namespace std; 
int n,m,s[10010],maxsum=-1;//用maxsum存储最大的分数,注意初值要赋一个较小值
void score_stat(int a[],int m)//传入一个数组,计算分数总和
{
	int max_score=0,min_score=10,sum=0;//最大分、最小分和分数总和
	for(int i=0;i<m;i++)//遍历数组
	{
		max_score=max(max_score,a[i]);//更新最大分
		min_score=min(min_score,a[i]);//更新最小分
		sum+=a[i];//更新分数总和
	}
	maxsum=max(maxsum,sum-max_score-min_score);//更新最大分数
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)//循环n组数据
    {
    	for(int j=0;j<m;j++)//循环读入一组数据
    	    scanf("%d",&s[j]);
    	score_stat(s,m);
	}
	printf("%.2lf",double(maxsum)/(m-2));//输出答案
	return 0;
}

    注意:这里可以把数组作为参数传递进来。写法如上。当数组作为参数传递时,是直接传递进来的。比如上文的函数中的数组a就是函数外数组s的别名。改变数组a的值时数组s的值也会改变

4.递归函数

4.1.递归函数介绍

    函数可以被主函数和其他函数调用,也可以被自己调用。像这种自己调用自己的函数就叫做递归函数

4.2.例题3——计算阶乘

计算阶乘 - 洛谷

题目描述

n ! n! n!,也就是 1 × 2 × 3 ⋯ × n 1\times2\times3\dots\times n 1×2×3×n

挑战:尝试不使用循环语句(for、while)完成这个任务。

输入格式

第一行输入一个正整数 n n n

输出格式

输出一个正整数,表示 n ! n! n!

输入输出样例

输入 #1
3
输出 #1
6

提示

数据保证, 1 ≤ n ≤ 12 1 \leq n\le12 1n12

4.3.递归函数运行详细演示和代码

题意分析
    对于递归的题目,我们可以将这个问题拆分成多个子问题,并逐个解决。比如这个问题,我们可以把这个问题拆解成f(n)=n*f(n-1)其中f(n)代表n的阶乘。我们就可以得出程序:

#include<iostream>
using namespace std;
long long f(int n)//阶乘的数据较大,所以使用long long类型返回
{
    return n*f(n-1);
}
int main(){
    int n;
    cin>>n;
    cout<<f(n);
    return 0;
}

    但运行这个程序,我们会发现它结束不了。这是因为,当n=1时,f(n)应该返回1。但我们却没有加特殊判断。加上就可以通过这道题了。

#include<iostream>
using namespace std;
long long f(int n)//阶乘的数据较大,所以使用long long类型返回
{
    if(n==1)return 1;//递归边界
    return n*f(n-1);
}
int main(){
    int n;
    cin>>n;
    cout<<f(n);
    return 0;
}

像这种递归函数中递归终止的条件,就叫做递归边界

n=5时,递归函数f(n)的运行过程如下。
在这里插入图片描述
    如果看完这张图也不理解也没关系。随着学习的深入,你可能会在某一瞬间领悟。我就是这样子的。所以不用气馁,将一切都交给时间。

4.4.练习1——赦免战俘

赦免战俘 - 洛谷

题目背景

借助反作弊系统,一些在月赛有抄袭作弊行为的选手被抓出来了!

题目描述

现有 2 n × 2 n ( n ≤ 10 ) 2^n\times 2^n (n\le10) 2n×2n(n10) 名作弊者站成一个正方形方阵等候 kkksc03 的发落。kkksc03 决定赦免一些作弊者。他将正方形矩阵均分为 4 个更小的正方形矩阵,每个更小的矩阵的边长是原矩阵的一半。其中左上角那一个矩阵的所有作弊者都将得到赦免,剩下 3 个小矩阵中,每一个矩阵继续分为 4 个更小的矩阵,然后通过同样的方式赦免作弊者……直到矩阵无法再分下去为止。所有没有被赦免的作弊者都将被处以棕名处罚。

给出 n n n,请输出每名作弊者的命运,其中 0 代表被赦免,1 代表不被赦免。

输入格式

一个整数 n n n

输出格式

2 n × 2 n 2^n \times 2^n 2n×2n 的 01 矩阵,代表每个人是否被赦免。数字之间有一个空格。

输入输出样例

输入 #1
3
输出 #1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 1 1
0 0 0 0 0 1 0 1
0 0 0 0 1 1 1 1
0 0 0 1 0 0 0 1
0 0 1 1 0 0 1 1
0 1 0 1 0 1 0 1
1 1 1 1 1 1 1 1

题意分析
    我们可以将这个方阵分成四个小方阵处理,我们先将这个方阵全部初始化为0。分别处理剩下的三个方阵递归边界为,处理到最后规模为1的方阵后就直接赋值为1。代码如下:

#include<iostream>
#include<cmath>
using namespace std;
#define MAXN 1030//2^10等于1024
int a[MAXN][MAXN],n,i,j;
/*cal是处理方阵的函数。x和y代表这个方阵的第一个人的坐标,n代表规模
  即代表这个方阵的大小是n*n的。*/
void cal(int x,int y,int n)
{
	if(n==0)//如果规模为0,即不可分割
	{
		a[x][y]=1;//赋值
		return;//返回
	}
	cal(x+pow(2,n-1),y,n-1);//处理右上角的方阵
	cal(x,y+pow(2,n-1),n-1);//处理左下角的方阵 
	cal(x+pow(2,n-1),y+pow(2,n-1),n-1);//处理右下角的方阵 
}
int main()
{
    cin>>n;
    cal(1,1,n);//从规模为n的方阵开始处理 
    for(i=1;i<=pow(2,n);i++)//打印方阵 
    {
    	for(j=1;j<=pow(2,n);j++)
            cout<<a[i][j]<<' ';
        cout<<endl;
	}
	return 0;
}

5.基础宏函数

    还记得我们之前了解过的宏定义吗?既然它是简单粗暴的替换,那可不可以替换函数呢?当然可以。一个最基础的宏函数定义如下:

#define Add(a,b)return (a)+(b);

当然,我们也可以使用\宏定义转接符,这样就可以定义多行宏函数了。具体使用如下:

#define multiplication(a,b)cout<<a<<'*'<<b<<'='<<(a)*(b);\
return (a)*(b);

注意:在宏定义时一定要勤加括号,因为宏定义是直接简单粗暴的替换。可能会出现这种情况:

multiplication(1+2,3)

不加括号宏编译后就会变成这样。

1+2*3

不符合预期效果。所以要宏定义时要勤加括号。

6.课后作业

函数与结构体 - 洛谷 中函数部分

喜欢就订阅此专辑吧!

【蓝胖子编程教育简介】
蓝胖子编程教育,是一家面向青少年的编程教育平台。平台为全国青少年提供最专业的编程教育服务,包括提供最新最详细的编程相关资讯、最专业的竞赛指导、最合理的课程规划等。本平台利用趣味性和互动性强的教学方式,旨在激发孩子们对编程的兴趣,培养他们的逻辑思维能力和创造力,让孩子们在轻松愉快的氛围中掌握编程知识,为未来科技人才的培养奠定坚实基础。

欢迎扫码关注蓝胖子编程教育
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1967969.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ADSL常见故障及维护

ADSL常见故障及维护 ADSL的最简单故障判断方法&#xff1f; 解答&#xff1a;可根据ADSL Modem面板上的信号灯的显示情况进行问题的初步判断&#xff0c;如下&#xff1a; “ADSL”等&#xff1a;用于显示Modem的同步情况&#xff0c;常亮绿灯表示Modem与局端能够正常同步&…

JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程,JDK、JRE、JVM关系;程序计数器,堆,虚拟机栈,堆栈的区别是什么,方法区,直接内存

文章目录 一、JVM基本介绍——概念、组成、重点1.1 JVM是什么1.2 JVM由哪些部分组成&#xff0c;运行流程是什么&#xff1f;1.3 JDK、JRE、JVM 关系1.4 学习什么 二、JVM组成2.1 什么是程序计数器2.2 你能详细地介绍堆吗2.3 什么是虚拟机栈2.4 垃圾回收是否涉及栈内存2.5 栈内…

2024.8.1(前端服务器的配置以及tomcat环境的配置)

回顾 [roottomcat ~]# cd eleme_web/public/img/ [roottomcat img]# ls 1.jpg [roottomcat public]# cd [roottomcat ~]# cd eleme_web/ [roottomcat eleme_web]# cd src [roottomcat src]# vim views/HomeView.vue [roottomcat src]# nohup npm run serve ctrlc后网页不出…

guitar pro为什么没声音 guitar pro8播放不了 Guitar Pro播放无声音或无光标解决办法

吉他是一种非常有魅力的乐器&#xff0c;用途也非常广泛&#xff0c;在吉他学习和训练过程中&#xff0c;我们会用到吉他打谱软件Guitar Pro。但有用户发现在使用Guitar Pro没有声音或无法播放的情况。下面我们看看Guitar Pro为什么没声音以及解决办法。 一、Guitar Pro为什么没…

8.1IO进程线程

笔记 进程 一.多进程引入 1.1引入目的 程序员写程序时&#xff0c;一个程序可能由多个任务组成&#xff0c;如果使用的是单进程&#xff0c;或单任务&#xff0c;那么该任务执行阻塞时&#xff0c;其他任务就无法执行&#xff0c;必须等到该任务解除阻塞后&#xff0c;才能…

【Linux】(26) 详解磁盘与文件系统:从物理结构到inode机制

目录 1.认识磁盘、 1.1 理论 1.2 磁盘的物理结构 CHS 寻址 1.3 磁盘的逻辑抽象结构 2. inode 结构 1.Boot Block 启动块 2.Super Block&#xff08;超级块&#xff09; 3.Group Descriptor Block&#xff08;块组描述符&#xff09; 4.Data Blocks (数据块) 5.Inode…

spring boot 实现 Stream 钉钉事件订阅

1: 参考链接 https://open.dingtalk.com/document/orgapp/develop-stream-mode-push-server 2&#xff1a;钉钉开放平台订阅配置 配置之后运行一下上面提供的链接 里面的main方法&#xff0c;验证通道 3&#xff1a;订阅启动方式 EventListenerThread eventListenerThrea…

玩转ComfyUI】基于函数计算一键部署AI生图平台 ComfyUI

登录阿里云 1.前往函数计算控制台。 在推荐您创建 AliyunFcDefaultRole默认角色对话框中&#xff0c;单击创建。 3.在角色快捷创建页面&#xff0c;单击同意授权。 4.在实验操作面板顶部&#xff0c;单击 图标打开新的标签页&#xff0c;然后在地址栏中输入如下地址并回车&…

会展信息服务预约小程序开展品牌管理

如舞台、漫展、商业展会等场景都需要会展服务&#xff0c;场地建设、方案提供、人员配备&#xff0c;尤其是高线城市&#xff0c;服务开展度比较高&#xff0c;客商双方为多次互需关系&#xff0c;服务方需要拓展品牌获得更多客源加以转化&#xff0c;而客户则需要找到靠谱且具…

LogonTracer图形化事件分析工具

LogonTracer这款工具是基于Python编写的&#xff0c;并使用Neo4j作为其数据库&#xff08;Neo4j多用于图形数据库&#xff09;&#xff0c;是一款用于分析Windows安全事件登录日志的可视化工具。它会将登录相关事件中的主机名&#xff08;或IP地址&#xff09;和帐户名称关联起…

vscode中运行不同语言的文件出现报错?

vscode是一个不错的语言编辑软件&#xff0c;可以利用插件运行不同的语言&#xff0c;从而大大减少了软件的下载数量。 今天在学习的时候出现了一个令人匪夷所思的报错问题&#xff1a;早些时候一直在运行Python语言的文件&#xff0c;后来想对比一下c语言与Python的不同。于是…

阿里云、华为云、腾讯云、亚马逊云与谷歌云全景推荐

探索未来&#xff0c;选择领先云服务 —— 阿里云、华为云、腾讯云、亚马逊云与谷歌云全景推荐 在这个数字化飞速发展的时代&#xff0c;云计算已成为企业和个人日常运营不可或缺的一部分。无论是小型初创公司还是全球性大企业&#xff0c;选择合适的云服务可以大幅提升业务效…

Redis——集合 SET

目录 1. 添加元素 SADD 2. 查看元素 SMEMBERS 3. 判断元素是否存在该集合 SISMEMBER 4. 删除元素 SREM 集合 SET 是一种无序集合&#xff1b;因此其与列表有以下区别&#xff1a; &#xff08;1&#xff09;列表是有序的&#xff0c;集合是无序的&#xff1b; &#xff0…

基于SpringBoot宠物店寄养管理系统 毕业设计-附源码94084

摘 要 宠物店寄养管理系统是一个基于计算机技术的应用系统&#xff0c;旨在为宠物店提供一种便捷、高效的方式来管理宠物店寄养服务。本研究通过使用现代化的软件开发技术和数据库管理方法&#xff0c;设计和实现了一个全面的宠物店寄养管理系统。该系统具有以下主要功能:宠物资…

ONLYOFFICE文档:为企业和开发者带来强大的文档编辑功能

本文给大家介绍一个开源项目&#xff1a;ONLYOFFICE文档&#xff0c;它能够为文档编辑、多人协作提供强大支持。无论你是个人使用&#xff0c;还是企业、商业开发&#xff0c;都能找到适合你的版本。 关于 ONLYOFFICE 文档 ONLYOFFICE 文档是一套功能强大的文档编辑器&#x…

DockerCompose部署示例

目录 前言 1. 初识DockerCompose 2. 安装DockerCompose 3. 部署微服务项目 1&#xff09;找一个目录&#xff0c;创建一个新的cloud-demo文件夹。 2&#xff09;在cloud-demo文件夹创建一个docker-compose.yml文件&#xff0c;然后编写下面内容&#xff1a; 3&#xff09…

手把手构建Netty

1.Netty基础 Netty是一个提供了易于使用的API的客户端、服务器框架&#xff1b; 并发高-NIO(非阻塞IO) 传输快-零拷贝: 分析&#xff1a; 使用了NIO的零拷贝&#xff1b;java中内存是分为堆和栈&#xff0c;还有字符串常量池等等&#xff1b; 如果有一些数据需要从IO中读取&am…

28、美国国家冰雪中心(NSIDC)海冰密集度月数据处理:方法二

文章目录 1. 前言2. polarstereo-lonlat-convert-py 介绍2.1 安装方法3. 代码4. 其他1. 前言 在前文中已经详细介绍了如何使用Python对NSIDC的海冰密集度数据进行处理,将其从极地投影转换成常用的经纬度投影,但是方法较为麻烦,本文将基于另一个库,使用更加简便的方法对其进…

JVM—垃圾收集算法和HotSpot算法实现细节

1、分代回收策略 分代的垃圾回收策略&#xff0c;是基于这样一个事实&#xff1a;不同的对象的生命周期是不一样的。因此&#xff0c;不同生命周期的对象可以采取不同的收集方式&#xff0c;以便提高回收效率。 分代垃圾回收采用分治的思想&#xff0c;进行代的划分&#xff0…

π 随机数计算圆周率

如下图&#xff0c;圆与正方形面积比值等于圆内的点和总点数的比值 Disatance是点到原点的距离&#xff1a;SQRT(A2xA2B2xB2) 以下是在Excel中1.5万个点计算圆周率的结果。 InCircle公式&#xff1a;IF(C2<1,1,0) π计算公式&#xff1a;4*SUM(D2:D15000)/COUNT(D2:D15000)