• C语言函数章--该如何学习函数?阿斗看了都说会学习了


    前言
    👻作者龟龟不断向前
    👻简介宁愿做一只不停跑的慢乌龟,也不想当一只三分钟热度的兔子。
    👻专栏C++初阶知识点

    👻工具分享

    1. 刷题: 牛客网 leetcode
    2. 笔记软件:有道云笔记
    3. 画图软件:Xmind(思维导图) diagrams(流程图)

    在这里插入图片描述

    如果觉得文章对你有帮助的话,还请点赞,关注,收藏支持博主🙊,如有不足还请指点,博主及时改正

    函数

    🚀1.函数的概念(维基百科)

    函数–子程序

    • 在计算机科学中,子程序(英语:Subroutine, procedure, function, routine, method, subprogram, callable unit),是一个大型程序中的某部分代码, 由一个或多个语句块组 成。它负责完成某项特定任务,而且相较于其他代 码,具备相对的独立性

    • 一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。这些代码通常被集成为软件库。

     

     

    🚀2.函数的分类

    • 库函数–库里面帮我们写好的函数,我们可以直接使用
    • 自定义函数–自己写的函数

    当然啦,自定义函数是有他存在的价值的,因为库函数无法满足我们生活中的所有需求和想法

    那些库函数没有的一些功能,就要靠我们程序员自己用自定义函数来实现了

     

     

    🚀库函数

      虽然你可能不理解库函数,但你却时时在使用库函数,例如我们刚开始学习C语言时,向世界打招呼使用的printf
    它可以实现将数据打印在屏幕上的功能,实质上它就是个库函数!包括scanf ,sqrt,time等,都是库里面提供的函数。
    而且就算我们不知道他的原理,我们也可以直接使用。

     

     包含头文件的方式#include<头文件>

     

    🍉库函数的分类总结

      主要的库函数可以分为以下基类

    • IO函数 –printf,scanf……
    • 字符串操作函数 –strlen,strcpy……
    • 字符操作函数 –getchar,putcchar
    • 内存操作函数 –malloc
    • 时间/日期函数 –time
    • 数学函数 –sqrt,sin,cos
    • 其他库函数

     

    🍉库函数的学习方法

    最不现实的方法就是:死记硬背。

    最实用的方法就是:查文档

     

    这里给大家推荐一个我用的最多C语言库网站:cplusplus.com - The C++ Resources Network

    文档是英文版,大家可以结合浏览器翻译去使用

     

    下面我们就来使用这个文档来学习一下strcpy怎么使用

     

     

    🍉关于文档使用的那五板斧

    1.搜索库函数

    在这里插入图片描述

     

    2.语法,作用介绍

    在这里插入图片描述

    解释

    strcpy—拷贝source指向的C字符串,至destination所指向的C字符串当中,包含\0也会拷贝进去

     

    3.函数参数的介绍

    在这里插入图片描述

    解释

    source–需要被拷贝的字符串

    destination–需要拷贝至其中的字符串

     

    4.返回值的介绍

    在这里插入图片描述

     

    5.代码用例

    在这里插入图片描述

     

    这五板斧在文档中介绍的很清楚,而且该网站也很简洁,十分推荐

    大家也可以使用上述的步骤,来查一查strcat这个函数怎么用–五板斧

     

     


     

    🚀3.自定义函数

      如果库函数能干所有的事情,那还要程序员干什么?

    所有更加重要的是自定义函数。 自定义函数和库函数一样,有函数名返回值类型函数参数

    但是不一样的是这些都是我们自己来设计。这给程序员一个很大的发挥空间。

     

    🍉函数的组成
    ret_type fun_name(para1, * )
    {
     statement;//语句项
    }
    
    ret_type 返回类型
    fun_name 函数名
    para1    函数参数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

     

    举例–求两个数的最大值

    #include
    
    int get_max(int x, int y)
    {
     	return x>y?x:y;
    }
    
    int main()
    {
         int num1 = 10;
         int num2 = 20;
         int max = get_max(num1, num2);
         printf("max = %d\n", max);
         return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

     

    解释

    在这里插入图片描述

     

     


    🍉函数的参数

    函数的参数分为:

    1. 实际参数(简称实参)
    2. 形式参数(简称形参)

     

    🍇实际参数(实参)

    真实传给函数的参数,叫实参。

    实参可以是:常量、变量、表达式、函数等。 无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。例如上述的实参num1,num2,并且我们也可以将num1+num2这个表达式作为实参

     

    🍇形式参数

    形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效

     

    例题–写一个函数实现交换功能

    示例1:

    #include
    
    void Swap1(int x,int y)
    {
    	int tmp = x;
    	x = y;
    	y = tmp;
    }
    
    int main()
    {
    	int a = 3, b = 5;
        
    	printf("交换前\n");
    	printf("a = %d b = %d\n", a, b);
    	printf("\n");
    
    	Swap1(a, b);
    	printf("Swap1交换后\n");
    	printf("a = %d b = %d\n", a, b);
    	printf("\n");
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

      我们的交换函数就写完了,但是程序输出结果不尽人意–没有达到我们的需求

    在这里插入图片描述

    解决方法如示例2

     

     

    示例2

    #include
    
    void Swap2(int* x, int* y)
    {
    	int tmp = *x;
    	*x = *y;
    	*y = tmp;
    }
    
    int main()
    {
    	int a = 3, b = 5;
    	printf("交换前\n");
    	printf("a = %d b = %d\n", a, b);
    	printf("\n");
    
    	Swap2(&a, &b);
    	printf("Swap2交换后\n");
    	printf("a = %d b = %d\n", a, b);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

     

     

    解释如下

    🍉函数的调用–传址and传址(重要)

    示例1属于传值调用

    在这里插入图片描述

    大家看图即可发现:实参a,b与形参x,y虽然内容相同,但是地址不同,本质上没有建立任何联系

    传值调用中,形参只是实参的一份临时拷贝,对形参的改变不影响实参

     

     

    示例2属于传址调用

    在这里插入图片描述

    观察图即可发现:a,b与形参x,y地址不同,但是形参x,y的内容是a,b的地址,他们之间建立的联系

    这个时候我们对x,y进行解引用操作,即可找到a,b,然后再进行修改即可达到目的


    总结

    1. 设计函数时不需要修改外部变量的值,可以使用传值调用。例如Add函数,Max函数
    2. 若一个函数需要外部变量的值,可以使用传址调用,例如Swap函数

     

     

     

    🚀4.例题训练

    1. 写一个函数可以判断一个数是不是素数。
    2. 写一个函数判断一年是不是闰年。
    3. 写一个函数,实现一个整形有序数组的二分查找。
    4. 写一个函数,每调用一次这个函数,就会将 num 的值增加1。
    5. 设计一个函数打印9 9乘法表

     

    🍉写一个函数可以判断一个数是不是素数

    我们讲过判断一个数是否为素数可以使用试除法,即若2~num的平方根 的数都无法将num整除,那么num就是素数

    如果我们要设计一个函数来实现该功能的话,可以如下操作

    #include//布尔类型的头文件
    #include
    
    bool IsPrime(int n)
    {
    	for (int i = 2; i <= sqrt(n); ++i)
    	{
    		if (n%i == 0)
    		{
    			return false;//如果能被i整除说明不是素数,直接返回false
    		}
    	}
    	return true;//上面已经处理了不是素数的情况,那么剩下就是素数的情况了
    }
    
    int main()
    {
    	for (int i = 101; i < 200; i += 2)
    	{
    		if (IsPrime(i))
    		{
    			printf("%d ",i);
    		}
    	}
    	printf("\n");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    解释

    1. bool类型是布尔类型,布尔类型的值只能是真true(1)或者假false(0)

      而我们函数的思想是如果是素数返回真,如果不是素数返回假,所以返回类型用布尔类型刚刚好

    2. IsPrime(i)这个整体的值—i为素数为真(1),i不为素数为假(0),所以我们可以直接将这个表达式放在条件判断中

     

     

    🍉写一个函数判断一年是不是闰年

    我们之前也讲过判断闰年的方法

    1. 如果一年能被4整除,但是无法被100整除,那么是该年闰年
    2. 如果一年能被400整除,那么概念是闰年

    实现思路:如果是闰年返回真(true),不是闰年返回假(false)

    #include
    #include
    
    bool IsLeapYear(int y)
    {
    	return ((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0));
    }
    
    int main()
    {
    	for (int year = 1000; year <= 2000; year += 4)
    	{
    		if (IsLeapYear(year))
    		{
    			printf("%d ", year);
    		}
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    解释

    由于((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0))的表达式的值刚好也只有真和假,也刚好符合我们的需求,所以可以直接作为返回值

     

     

    🍉 写一个函数,实现一个整形有序数组的二分查找

    回顾二分查找逻辑:“猜数字”,一个有序数组我们每次猜中间的数字,都可以排除一半的错误数据

    函数要求:

    1. 如果找到了,返回该元素的下标
    2. 如果没有找到,返回0

    不知道有同学入坑了没?

    大家千万注意,如果没找到返回0,那么该函数实现的逻辑是错误的,因为如果要找的元素是第一个元素他的下标也是0

    所以,咱们设计成没有找到指定元素,返回EOF(-1)

    #include
    
    int BinSearch(int* arr,int n,int k)//找到了返回该元素下标,没找到返回零
    {
    	int left = 0;
    	int right = n - 1;//n--数组元素个数
    	while (left <= right)
    	{
    		int mid = (left + right) / 2;
    		if (arr[mid] > k)
    		{
    			right = mid - 1;
    		}
    		else if (arr[mid] < k)
    		{
    			left = mid + 1;
    		}
    		else
    		{
    			return mid;//是在这里找到的
    		}
    	}
    	return EOF;
    }
    
    
    int main()
    {
    	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        int sz = sizeof(arr)/sizeof(arr[0]);
    	int k = 8;
    	int ret = BinSearch(arr, sz, k);
    
    	if (ret != EOF)
    	{
    		printf("找到了,下标为%d\n", ret);
    	}
    	else
    	{
    		printf("没找到");
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    解释

    数组的空间大小 = 元素的空间大小 * 元素个数

    所以元素个数 = 数组的空间大小/元素的空间大小,这样我们就可以将元素个数直接算出来了

     

     

    🍉写一个函数,每调用一次这个函数,就会将 num 的值增加1。

    即需要在函数中修改num的值,咱们可以使用传址调用

    void Func(int* n)
    {
    	//.......--其他操作
    	++(*n);
    }
    
    int main()
    {
    	int num = 0;
    	//调用函数,使得num每次增加1
    	Func(&num);
    	printf("%d\n", num);
    	Func(&num);
    	printf("%d\n", num);
    	Func(&num);
    	printf("%d\n", num);
    	Func(&num);
    	Func(&num);
    	Func(&num);
    	printf("%d\n", num);
    	Func(&num);
    	Func(&num);
    	Func(&num);
    	printf("%d\n", num);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    该函数跟前面三个函数不一样,不需要返回值哟

     

     

    🍉设计一个函数打印9 9乘法表

    当然了我相信大部分同学都会打印九九乘法表,重点是:

    1. 你打印出来的格式是否美观
    2. 不仅仅只是打印九九乘法表,自己输入乘法表的行数
    #include
    
    void MulTable(n)
    {
    	//n行
    	for (int i = 1; i <= n; ++i)
    	{
    		//i列
    		for (int j = 1; j <= i; ++j)
    		{
    			printf("%2d*%-2d=%-4d", j, i, i*j);
    		}
    		printf("\n");
    	}
    }
    
    int main()
    {
    	int line = 0;
    	scanf("%d", &line);
    	MulTable(line);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里插入图片描述

    解释

    博主使用的是

    1. 第一个操作数是两个宽度,采取右对齐
    2. 第二个操作数是两个宽度,采取左对齐
    3. 第三个操作数是四个宽度,采取左对齐

    而且这个函数只实现打印功能,所以没有返回值

     

    文章就讲到这,咱们下期见!🐱‍👓

    点赞

  • 相关阅读:
    基于MFC的串口通信
    抖音seo账号矩阵源码系统
    Chrome 扩展教程之如何使用 React 构建 Chrome 扩展(教程含源码)
    消息中间件rabbitmq
    fail-safe 机制与 fail-fast 机制分别有什么作用
    颜值在线的 Keychron K8 实际上手体验
    A. Everyone Loves to Sleep
    计算机毕业设计springboot+vue基本微信小程序的大学生竞赛信息发布与报名小程序
    VScode中js关闭烦人的ts检查
    stm32f4xx-USART串口
  • 原文地址:https://blog.csdn.net/m0_64361907/article/details/127634501