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

文章目录

  • 前言
  • 一、函数是什么?
  • 二、自定义函数
    • 参数
    • 返回值
      • 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 语句是提前结束函数的唯一办法

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

响应式Web开发项目教程(HTML5+CSS3+Bootstrap)第2版 例4-11 HTML5 表单验证

代码 <!doctype html> <html> <head> <meta charset"utf-8"> <title>HTML5 表单验证</title> </head><body> <form action"#" method"get" novalidate>请输入您的邮箱:<input type&q…

CNN卷积理解

1 卷积的步骤 1 过滤器&#xff08;卷积核&#xff09;&#xff08;Filter或Kernel&#xff09;&#xff1a; 卷积层使用一组可学习的过滤器来扫描输入数据&#xff08;通常是图像&#xff09;。每个过滤器都是一个小的窗口&#xff0c;包含一些权重&#xff0c;这些权重通过训…

DAY11_(简易版)VUEElement综合案例

目录 1 VUE1.1 概述1.1.1 Vue js文件下载 1.2 快速入门1.3 Vue 指令1.3.1 v-bind & v-model 指令1.3.2 v-on 指令1.3.3 条件判断指令1.3.4 v-for 指令 1.4 生命周期1.5 案例1.5.1 需求1.5.2 查询所有功能1.5.3 添加功能 2 Element2.0 element-ui js和css和字体图标下载2.1 …

简析:老隋分享的temu项目怎么做?是蓝海项目吗?

在跨境电商的热潮中&#xff0c;老隋分享的temu项目引起了广泛关注。这个项目究竟有何魅力?它是一个蓝海项目吗?本文将为你揭开temu项目的神秘面纱&#xff0c;并探讨其前景和潜在机会。 首先&#xff0c;我们来了解一下temu项目的基本情况 Temu是拼多多旗下的跨境电商平台&a…

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

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

希尔排序-排序算法

前言 希尔排序固然很好&#xff0c;但是某些情况下&#xff0c;有很多缺点。例如下面这种情况&#xff1a; 9 之前的元素都已经有序&#xff0c;只有元素 1 和 2 的位置不对&#xff0c;使用插入排序几乎要移动整个数组的元素&#xff0c;效率很低。 这时候希尔排序横空出世&…

MySQL和Redis的事务有什么异同?

MySQL和Redis是两种不同类型的数据库管理系统&#xff0c;它们在事务处理方面有一些重要的异同点。 MySQL事务&#xff1a; ACID属性&#xff1a; MySQL是一个关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;支持ACID属性&#xff0c;即原子性&#xff08;Ato…

全球 IPv4 耗尽,下个月开始收费!

哈喽大家好&#xff0c;我是咸鱼 IPv4&#xff08;Internet Protocol version 4&#xff09;是互联网上使用最广泛的网络层协议之一&#xff0c;于1981年在 RFC 791 中发布&#xff0c;它定义了 32 位的IP地址结构和基本的协议操作。 由于 IPv4 使用 32 位的地址&#xff0c;…

深入了解Figure的结构与层次

深入了解Figure的结构与层次 一 Matplotlib中的Figure1.1 Figure的概念和作用:1.2.创建Figure对象:1.3 Figure的属性和方法: 二 子图&#xff08;Axes&#xff09;的角色与创建2.1 子图&#xff08;Axes&#xff09;的概念&#xff1a;2.2 创建子图的方法&#xff1a;2.3 Axes的…

灰度图像的自动阈值分割

第一种&#xff1a;Otsu &#xff08;大津法&#xff09; 一、基于cv2的API调用 1、代码实现 直接给出相关代码&#xff1a; import cv2 import matplotlib.pylab as pltpath r"D:\Desktop\00aa\1.png" img cv2.imread(path, 0)def main2():ret, thresh1 cv2.…

软件产品研发过程 - 三、详细设计

软件产品研发过程 - 三、详细设计 详细设计是在软件开发过程中&#xff0c;基于概要设计&#xff08;将功能按子功能进行拆分&#xff0c;画面跳转关系、UI原型、画面上所有功能点及每个功能点对应的业务流程&#xff09;&#xff0c;以程序开发的角度来设计概要设计中每个功能…

GRE实验

一&#xff1a;实验要求 1、本实验采用静态路由部署&#xff1b;ISP上不配置任何静态路由条目&#xff1b; 2、在R1、R3上部署GRE隧道&#xff0c;使得私网能够互通。 二&#xff1a;实验配置 r1 配置 ISP配置 r3配置 配置静态路由 建立GRE隧道 三&#xff1a;实验结果

微信会议活动微展示在线活动报名源码系统 带完整的搭建教程

随着微信的普及&#xff0c;微信会议活动已成为企业、团体和个人进行信息交流、业务推广和品牌宣传的重要平台。然而&#xff0c;如何高效地管理、展示和报名参加这些会议活动&#xff0c;一直是许多组织者面临的难题。下面&#xff0c;小编给大家分享一款微信会议活动微展示在…

android camera系列(Camera1、Camera2、CameraX)的使用以及输出的图像格式

一、Camera 1.1、结合SurfaceView实现预览 1.1.1、布局 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.android.com/apk/res-au…

cartographer离线建图报错:data_.trajectory_nodes.SizeOfTrajectoryOrZero

cartographer离线建图报错: data_.trajectory_nodes.SizeOfTrajectoryOrZero [FATAL] [1706177325.876019302, 1706015603.398505596]: F0125 18:08:45.000000 17607 pose_graph_2d.cc:1314] Check failed: data_.trajectory_nodes.SizeOfTrajectoryOrZero(trajectory_id) &…

git用法总结

以gitee为例&#xff0c;GitHub也可参考本文 创建远程仓库 在自己的gitee主页 创建本地仓库 在文件夹下&#xff0c;右键→git bash here git init添加gitignore vi .gitignoregitignore里的内容根据自己实际情况设置&#xff0c;这里举个例子 # #开头的是注释 # Prer…

DevSecOps 参考模型介绍

目录 一、参考模型概述 1.1 概述 二、参考模型分类 2.1 DevOps 组织型模型 2.1.1 DevOps 关键特性 2.1.1.1 模型特性图 2.1.1.2 特性讲解 2.1.1.2.1 自动化 2.1.1.2.2 多边协作 2.1.1.2.3 持续集成 2.1.1.2.4 配置管理 2.1.2 DevOps 生命周期 2.1.2.1 研发过程划分…

查看php-fpm占用内存情况

1、查看每个php-fpm占用的内存大小 ps -ylC php-fpm --sort:rss 2 查看单个php-fpm进程消耗内存的明细 pmap $(pgrep php-fpm) | less pmap pmap命令用于显示一个或多个进程的内存状态 pmap [ -x | -d ] [ -q ] pids 参数&#xff1a; -x extended Show the extended f…

对于小微企业而言,数字化转型的重要性是什么?

数字化转型对于小微企业至关重要&#xff0c;原因如下&#xff1a; 1.效率和生产力&#xff1a;采用数字工具和技术可以简化业务流程、自动化重复性任务并提高整体效率。这使得小型企业能够用更少的资源完成更多的工作&#xff0c;最终提高生产力。 2.节省成本&#xff1a;数…

DevSecOps 发展历史概述

目录 一、发展概述 1.1概述说明 二、DevSecOps 发展关键里程碑 2.1 2012年Gartner首次提出DevSecOps概念 2.2 2016年Gartner发布DevSecOps议题报告 2.3 2017年美国RSAC大会开辟DevSecOps专题 2.4 2018年美国RSAC大会提出黄金管道概念 2.5 2019年Gartner 发布了DevSecOps…