再识C语言 DAY12 【再识函数(上)】

news2024/11/16 19:36:38

文章目录

  • 前言
  • 一、函数是什么?
  • 二、自定义函数
    • 参数
    • 返回值
      • void修饰函数的返回值和参数
  • 函数不能嵌套定义
    • 形参和实参的区别
    • return的用法
    • 补充if……else if……else……的用法
  • 后面会讲解“函数调用,函数声明以及函数原型,块级变量,归函数”等等内容
  • 如果您发现文章有错误请与我留言,感谢


前言

本文章总结于此文章


一、函数是什么?

函数的本质是一段可以重复使用的代码,这段代码被提前编写好了,放到了指定的文件中,使用时直接调取即可。
例如,strcmp() 是一个用来比较字符串大小的函数,它的用法如下:

#include <stdio.h>
#include <string.h>
int main()
{
    char str1[] = "http://c.biancheng.net";
    char str2[] = "http://www.baidu.com";
    //比较两个字符串大小
    int result = strcmp(str1, str2);
    printf("str1  - str2 = %d\n", result);
    return 0;
}

str1 和 str2 是传递给 strcmp() 的参数,strcmp() 的处理结果赋值给了变量 result

int result = strcmp(str1, str2);

比较字符串大小是常用的功能,一个程序可能会用到很多次,如果每次都写这样一段重复的代码,不但费时费力、容易出错,而且交给别人时也很麻烦,所以C语言提供了一个功能,允许我们将常用的代码以固定的格式封装(包装)成一个独立的模块,只要知道这个模块的名字就可以重复使用它,这个模块就叫做函数(Function)

函数的本质是一段可以重复使用的代码,这段代码被提前编写好了,放到了指定的文件中,使用时直接调取即可。下面我们就来演示一下如何封装 strcmp() 这个函数。

二、自定义函数

  • 函数组成部分
int main()
{
reuturn 0;
}

int :返回值类型
main: 函数名 ==> 标识符 (只是一个名字,随便起)
()= 描述参数
return 0 函数返回值
函数定义的格式
函数返回值类型 函数名(形参)
{
函数体
return 返回值
}

参数

函数的一个明显特征就是使用时带括号( ),有必要的话,括号中还要包含数据或变量,称为参数(Parameter)。参数是函数需要处理的数据,例如:
strlen(str1)用来计算字符串的长度,str1就是参数。
puts(“C语言中文网”)用来输出字符串,"C语言中文网"就是参数。

返回值

既然函数可以处理数据,那就有必要将处理结果告诉我们,所以很多函数都有返回值(Return Value)。所谓返回值,就是函数的执行结果。例如:

char str1[] = "C Language";
int len = strlen(str1);

strlen() 的处理结果是字符串 str1 的长度,是一个整数,我们通过 len 变量来接收。

函数返回值有固定的数据类型(int、char、float等),用来接收返回值的变量类型要一致。

所以到底什么是返回值,如果你感到很懵,先别急,后面会详细讲。

先举一个例子:

#include <stdio.h>
int sum(){
    int i, sum=0;
    for(i=1; i<=100; i++)
    {
        sum+=i;
    }
    return sum;
}
int main()
{
    int a = sum();
    printf("The sum is %d\n", a);
    return 0;
}

运行结果: The sum is 5050

我们发现了一个 return sum;字面意思就是返回了 sum 的值,既然她返回了一个值,他去了哪里呢?为什么 int sum() 不和 int main() 一样是return 0;呢?

我们发现把return sum;改为 return 0; 时。运行结果: 0.
把return sum;改为 return 3; 时。运行结果: 3.

不难发现 return sum; 的确返回了 sum函数的值

我们知道函数是一段可以重复使用的代码,用来独立地完成某个功能,它可以接收用户传递的数据,也可以不接收。

上面的例子明显接收用户传递的数据 sum.

所以说,返回值返回的是变量的值

再来一个例子:

把一个数组中最大的值找出来

#include <stdio.h>
int FindMAX(int *array,int Count)
{
	int i;
	int max = array[0];
	for (i = 0; i <Count ; i++)//count函数可以用来统计字符串中某个字符的个数,或数组中某个元素的数量
	{
		if (array[i] > max)
		{
			max = array[i];
		}
	}
	return max;
 }
int main(void)
{
	int MAX;
	int a[] = { 12,6,9,34,21,7 };
	MAX = FindMAX(a,6);
	printf("MAX=%d\n", MAX);
   	return 0;
}

注:count函数可以用来统计字符串中某个字符的个数,或数组中某个元素的数量

这里是引用

void修饰函数的返回值和参数

1.void用来作为函数返回值

代码示例1:

#include <stdio.h>
#include <windows.h>
void show()
{
printf("no return value!\n");
}
int main()
{
show();
system("pause");
return 0;
}

输出结果:
在这里插入图片描述
示例2:
在这里插入图片描述
直接返回return 1也是可以通过编译的,且不会有警告

return 0指程序运行结束;
return 1指返回主调函数,程序继续运行。

但如果有变量去接收则会报错
在这里插入图片描述
2.void作为函数参数

如果一个函数没有参数,我们可以不写, 如test1()

代码示例:

//如果一个函数没有参数,我们可以不写, 如test1()
#include <stdio.h>
#include <windows.h>
int test1() //函数默认不需要参数
{
return 1;
}
int test2(void) //明确函数不需要参数
{
return 1;
}
int main()
{
printf("%d\n", test1(10)); //依旧传入参数,编译器不会告警或者报错
printf("%d\n", test2(10)); //依旧传入参数,编译器会告警(vs)或者报错(gcc)
system("pause");
return 0;
}

函数不能嵌套定义

强调一点,C语言不允许函数嵌套定义;也就是说,不能在一个函数中定义另外一个函数,必须在所有函数之外定义另外一个函数。main() 也是一个函数定义,也不能在 main() 函数内部定义新函数。

下面的例子是错误的:

#include <stdio.h>
void func1()
{
    printf("http://c.biancheng.net");
    void func2()
    {
        printf("C语言小白变怪兽");
    }
}
int main()
{
    func1();
    return 0;
}

有些初学者认为,在 func1() 内部定义 func2(),那么调用 func1() 时也就调用了 func2(),这是错误的。

正确的写法应该是这样的:

#include <stdio.h>
void func2() 
{
    printf("\nC语言小白变怪兽");
}
void func1() 
{
    printf("http://c.biancheng.net");
    func2();
}
int main() {
    func1();
    return 0;
}

要想达到「调用 func1() 时也调用 func2()」的目的,必须将 func2() 定义在 func1() 外面,并在 func1() 内部调用 func2()。

形参和实参的区别

形参(形式参数)

在函数定义中出现的 参数可以看做是一个占位符,它没有数据,只能等到函数被调用时接收传递进来的数据,所以称为形式参数 简称形参。

实参(实际参数)

函数被调用时给出的参数包含了实实在在的数据,会被函数内部的代码使用,所以称为实际参数, 简称实参。

形参和实参的功能是传递数据,发生函数调用时,实参的值会传递给形参。

补充
占位符就是先占住一个固定的位置,等着你再往里面添加内容的符号,广泛用于计算机中各类文档的编辑

请看下面的例子:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
//计算从m加到n的值
int sum(int m, int n)
 {
    int i;
    for (i = m+1; i <= n; ++i) 
    {
        m += i;
    }
    return m;
}
int main() 
{
    int a, b, total;
    printf("Input two numbers: ");
    scanf("%d %d", &a, &b);
    total = sum(a, b);
    printf("a=%d, b=%d\n", a, b);
    printf("total=%d\n", total);
    return 0;
}

在这里插入图片描述

++i先自增1再赋值。 i++先赋值再自增1 在这里用两个都可以。

在这段代码中,函数定义处m、n 是形参 , 函数调用处a、b 是实参。通过 scanf() 可以读取用户输入的数据,并赋值给 a、b,在调用 sum() 函数时这份数据会传递给形参 m、n。

从运行情况看,输入 a 值为 1,即实参 a 的值为 1,把这个值传递给函数 sum() 后,形参 m 的初始值也为 1,在函数执行过程中,形参 m 的值变为 5050。函数运行结束后,输出实参 a 的值仍为 1,可见实参的值不会随形参的变化而变化。

以上调用 sum() 时是将变量作为函数实参,除此以外,你也可以将常量、表达式、函数返回值作为实参,如下所示:

total = sum(10, 98);  //将常量作为实参
total = sum(a+10, b-3);  //将表达式作为实参
total = sum( pow(2,2), abs(-100) );  //将函数返回值作为实参

形参和实参可以同名,因为他们相互独立,互不影响。因为实参在函数外有效,形参在函数内有效。

请看下面的例子:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
//计算从m加到n的值
int yuo(int a, int b)
{
	int i;
	for (i=1+a ;i<=b;i++)
	{
		a += i ;
		  }
	return a ;
}
 int main()
{
	int a, b,sum;
	printf("请输入两个数字:\n");
	scanf("%d %d", &a, &b);
	printf("%d  %d", a, b);
	sum = yuo(a, b);
	printf("\ntotal: %d", sum);
		return 0;
}

运行:
在这里插入图片描述
调用 yuo() 函数后,函数内部的形参 m 的值已经发生了变化,而函数外部的实参 m 的值依然保持不变,可见它们是相互独立的两个变量,除了传递参数的一瞬间,其它时候是没有瓜葛的。

错误示范:

这种情况下,a<=b表达的意思就和我们的想法有误了(a的值并不是每次加一),所以要引进变量 i ,让 i 的值做到每次加一

	for (a ;a<=b;a++)
	{
		a += a + 1;
		  }
	return a ;
}

return的用法

函数的返回值是指函数被调用之后,执行函数体中的代码所得到的结果,这个结果通过 return 语句返回。

对C语言返回值的说明:

  1. 没有返回值的函数为空类型,用void表示。例如:
void func()
{
    printf("http://c.biancheng.net\n");
}

一旦函数的返回值类型被定义为 void,就不能再接收它的值了。例如,下面的语句是错误的:

int a = func();

但我们可以这样用:

#include <stdio.h>
void func()
{
    printf("http://c.biancheng.net\n");
}
int main ()
{
func();
return 0;
}

是可以输出的:

在这里插入图片描述

函数一旦遇到 return 语句就立即返回,后面的所有语句都不会被执行到了。从这个角度看,return语句还有强制结束函数执行的作用

下面我们举个例子,还是以判断素数为题,并且要使用函数和 void,return:

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>
void PUA(int a)
{
	int i;
	bool flog = 1;
	if (a < 0)
	{
		printf("%d其不是素数",a);
		return;
		  }
	for (i = 2;i < a;i++)
	{
		if (a % i == 0)
		{
			flog = 0;
			break;
		}
	}
	   if(flog)
	   {
		   printf("\n%d其是素数",a);
		  }
	   else
	   {
		   printf("\n%d其不是素数",a);
	   }
	 }
  int main()
{
	int num;
	printf("输入一个数字:");
	scanf("%d", &num);
	PUA(num);
    return 0;
}

运行没问题:

在这里插入图片描述
注:if(x) 当x = 0时 表达式为假,不输出,x 不为0时,表达式为真,可以输出。

补充if……else if……else……的用法

格式:

            if(1)

                    A;        // 如果1成立,执行A

            else if(2)

                    B;        //  如果1不成立,2成立,执行B

            else if(3)

                    C;        // 如果1、2不成立,3成立,执行C

            ……

            else

                    D;        // 如果1、2、3均不成立,执行D

————————————————

                        版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/qq_54110690/article/details/122519943

所以 return 语句是提前结束函数的唯一办法

后面会讲解“函数调用,函数声明以及函数原型,块级变量,归函数”等等内容

如果您发现文章有错误请与我留言,感谢

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

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

相关文章

微软成立了一个新的人工智能团队,专注于小型模型开发

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

力扣题目训练(1)

2024年1月25日力扣题目训练 2024年1月25日力扣题目训练225. 用队列实现栈257. 二叉树的所有路径258. 各位相加81. 搜索旋转排序数组 II82. 删除排序链表中的重复元素 II30. 串联所有单词的子串 2024年1月25日力扣题目训练 2024年1月25日开始进行编程训练&#xff0c;今天主要是…

运费业务:

新增或修改&#xff1a; 第一步&#xff1a;查询是否有存在的模板&#xff0c;没有的话直接新增 第二步&#xff1a;模板不为空(存在经济区互寄情况)&#xff0c;判断经济区中的关联城市是否已经添加&#xff08;一条SQL数据中经济区中的关联城市可以选择多个,但其他经济区中也…

基于Kubernetes(K8s)构建企业容器云基础运行环境

cncfstack 新 文章上线&#xff1a; 书名&#xff1a;《云原生解决方案》 地址&#xff1a;https://zhaowenyu.com/cncf-solution 访问&#xff1a;文章底部“阅读原文”或访问域名 云原生计算是云计算发展新的里程碑阶段&#xff0c;是当今与未来很长一段时间中 IT 发展的技…

《从零开始制作消除游戏:基于Web技术的简单教程》

在撰写《从零开始制作消除游戏&#xff1a;基于Web技术的简单教程》这篇博客时&#xff0c;主要的目标是提供一个清晰、逐步的指南&#xff0c;帮助读者从零开始创建自己的消除游戏。 游戏逻辑实现 游戏板设计与初始化&#xff1a;描述如何创建游戏板的数据结构&#xff0c;以…

Linux/Luanne

Enumeration nmap 首先扫描目标端口对外开放情况&#xff0c;第一轮扫描发现对外开放了22,80,9001三个端口&#xff0c;端口详细信息如下 TCP/9001 9001端口挺神奇&#xff0c;nmap给出的结果是在9001端口运行着Medusa Supervisor&#xff0c;访问站点发现了一个登录框 在谷…

Google LUMIERE 一种用于生成逼真视频的时空扩散模型

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【unity实战】实现蓄力丢手榴弹、烟雾弹、燃烧弹的效果

文章目录 爆炸燃烧烟雾效果资产手榴弹丢手雷烟雾弹、燃烧弹实现手雷每次撞墙弹发出音效&#xff08;补充&#xff09;完结 爆炸燃烧烟雾效果资产 https://assetstore.unity.com/packages/vfx/particles/war-fx-5669 手榴弹 手榴弹配置好刚体&#xff0c;碰撞体 新增脚本Th…

金融OCR领域实习日志(二)——四种OCR模型效果测试(附图)

文章目录 四种模型ocr效果简单测试模型场景1.paddle框架下PP-OCRv31.1.效果如下&#xff1a;1.2.总结 2.paddle框架下ppocr_server_v22.1.效果如下2.2.总结 3.CnOCR3.1.效果如下3.2.总结 4.TesseractOCR4.1.效果如下4.2.总结 5.后续想法 四种模型ocr效果简单测试 模型 PP-OCR…

Optional lab: Linear Regression using Scikit-LearnⅠ

scikit-learn是一个开源的、可用于商业的机器学习工具包&#xff0c;此工具包包含本课程中需要使用的许多算法的实现 Goals In this lab you will utilize scikit-learn to implement linear regression using Gradient Descent Tools You will utilize functions from sci…

用大模型训练实体机器人,谷歌推出机器人代理模型

谷歌DeepMind的研究人员推出了一款&#xff0c;通过视觉语言模型进行场景理解&#xff0c;并使用大语言模型来发出指令控制实体机器人的模型——AutoRT AutoRT可有效地推理自主权和安全性&#xff0c;并扩大实体机器人学习的数据收集规模。在实验中&#xff0c;AutoRT指导超过…

架构篇25:高可用存储架构-双机架构

文章目录 主备复制主从复制双机切换主主复制小结存储高可用方案的本质都是通过将数据复制到多个存储设备,通过数据冗余的方式来实现高可用,其复杂性主要体现在如何应对复制延迟和中断导致的数据不一致问题。因此,对任何一个高可用存储方案,我们需要从以下几个方面去进行思考…

python:socket基础操作(4)-《tcp客户端基础》

tcp就和udp不一样了&#xff0c;tcp是客户端和服务器端&#xff0c;如果想通过tcp发送数据&#xff0c;要先让tcp进行连接服务器端 tcp客户端 先让服务器端进行启动 import socketdef main():# 创建套接字tcp_client_socket socket.socket(socket.AF_INET,socket.SOCK_STREAM…

flink1.13环境搭建

1、本地启动非集群模式 最简单的启动方式&#xff0c;其实是不搭建集群&#xff0c;直接本地启动。本地部署非常简单&#xff0c;直接解压安装包就可以使用&#xff0c;不用进行任何配置&#xff1b;一般用来做一些简单的测试。 具体安装步骤如下&#xff1a; 1.1 下载安装包…

【AIGC】Diffusers:训练扩散模型

前言 无条件图像生成是扩散模型的一种流行应用&#xff0c;它生成的图像看起来像用于训练的数据集中的图像。通常&#xff0c;通过在特定数据集上微调预训练模型来获得最佳结果。你可以在HUB找到很多这样的模型&#xff0c;但如果你找不到你喜欢的模型&#xff0c;你可以随时训…

【渗透测试】借助PDF进行XSS漏洞攻击

简介 在平时工作渗透测试一个系统时&#xff0c;常常会遇到文件上传功能点&#xff0c;其中大部分会有白名单或者黑名单机制&#xff0c;很难一句话木马上传成功&#xff0c;而PDF则是被忽略的一个点&#xff0c;可以让测试报告更丰富一些。 含有XSS的PDF制作步骤 1. 编辑器…

VUE引入DataV报错记录

DataV官网&#xff08;不支持Vue3&#xff09;&#xff1a;Welcome | DataV 一、按照官网引入后报错 【1】 Failed to resolve entry for package "dataview/datav-vue3". The package may have incorrect main/module/exports specified in its package.json. 将…

【第一天】蓝桥杯备战

题 1、 门牌号2、卡片3、分数 1、 门牌号 https://www.lanqiao.cn/problems/592/learning/ 解法一&#xff1a;暴力遍历 import java.util.Scanner; // 1:无需package // 2: 类名必须Main, 不可修改public class Main {public static void main(String[] args) {Scanner sca…

MyBatis中一级缓存是什么?SqlSession一级缓存失效的原因?如何理解一级缓存?

一级缓存是SqlSession级别的&#xff0c;通过同一个SqlSession查询的数据会被缓存&#xff0c;下次查询相同的数据&#xff0c;就 会从缓存中直接获取&#xff0c;不会从数据库重新访问 使一级缓存失效的四种情况&#xff1a; 1) 不同的SqlSession对应不同的一级缓存 2) 同一…

爬虫(一)

1. HTTP协议与WEB开发 1. 什么是请求头请求体&#xff0c;响应头响应体 2. URL地址包括什么 3. get请求和post请求到底是什么 4. Content-Type是什么1.1 简介 HTTP协议是Hyper Text Transfer Protocol&#xff08;超文本传输协议&#xff09;的缩写,是用于万维网&#xff08;…