【C语言详解】现学现用库函数,调用,声明和自定义函数

本章亮点

  • 传值调用的核心:形参实例化之后相当于实参的一份临时拷贝
  • 传址调用:实现在函数内部直接操作函数外部的变量
  • 想要成功交换两个变量的值,需要借助第三个临时变量
  • 带你学会借助学习网站使用库函数


1.计算机程序和子程序

程序来源于生活,在说官话之前咱先一起吃个栗子!
在这里插入图片描述

如下图,图中的六个步骤就构成了一个生活中的程序,该程序的功能是让人到银行取到钱。图中的六个动作执行过程可视为六个子程序。
图1

Q:类比生活中的程序和子程序,所以什么是计算机程序和子程序呢?

生活中的程序计算机程序
人类语言描述的编程语言编写的
一系列方式/动作执行过程一系列有序语句的集合
该系列动作/方式能使人完成某件事情该集合能让计算机执行某些操作或解决某个问题
生活中的子程序计算机子程序
执行该套方式/动作下的具体步骤该集合下的某些语句/某些语句块

A:计算机程序就是利用编程语言编写的一系列有序指令的集合,该集合能让计算机执行某些操作或解决某个问题 。 计算机子程序就是计算机程序中的某些语句/某些语句块。函数是一种子程序。


2.C语言中的函数

  • 在C语言中,函数就是一种子程序,结合生活中的子程序理解,子程序/函数就是计算机程序中的某些语句或某些语句块。子程序 的官话如下:

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

  • 在数学中,函数有三要素,分别是自变量x,因变量y,对应关系。已知x,根据对应关系,就能求出y。其实C语言中的函数同数学中函数是一样的。在C语言函数中,与数学中三要素一一对应的的分别是参数,返回值,函数名(功能)。已知参数,根据函数名代表函数能实现的功能或操作,输出返回值

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


看来咱和官方对函数的理解不谋而合呢,那接下来就让我们进入到今天的第一个重点:库函数。

在这里插入图片描述

3.库函数

C语言中的函数分为两大类,即库函数和自定义函数。

3.1库函数的发展

  • 在C语言发展早期,并没有库函数。
  • 随着C语言的不断发展,人们在写代码时发现:有一些基础功能或操作总被频繁的使用。比如:把数据信息按照一定格式打印到屏幕上(printf);拷贝字符串strcpy;计算k的n次方(pow)等等。
  • 因为这些基础功能或操作被程序员们广泛使用,同时它们是非业务性代码,所以C语言把这些基础功能或操作集成库,并根据C语言的标准规定了库的标准,后来统称库函数。库函数的出现大大提高了程序的效率和代码的可移植性。

3.2库函数是什么?

库函数是一系列能实现基础功能和操作的函数。

3.3库函数千千万,如何查找/学习库函数?

  • 在这里给大家推荐第一个库函数的学习网站是cplusplus。点击该网站的右上角Legacy Version(旧版本),就可以切换到该网站的旧版本中。该网站的旧版本中还保留着搜索库函数的功能。

在这里插入图片描述

  • 给大家推荐第二个库函数的学习网站是c/c++的官网。与cplusplus网站相比,它的好处是它有中文版本。

在这里插入图片描述

3.4现学现用库函数

  1. 使用库函数时,必须在程序入口前声明该库函数所属的头文件

  2. 在代码中使用库函数前,去学习网站搞清楚它的头文件参数和参数类型返回值和返回值类型库函数名库函数功能 以及 语法规则

  3. 接下来让我们吃两个栗子实操一下:
    在这里插入图片描述

  4. 栗子1:编写一段代码,要求使用库函数strcpy

    (1). 来到学习网站cplusplus学习strcpy, cplusplus中对strcpy的解释如图:

    在这里插入图片描述
    通过上图,我们知道:

    1.strcpy是Copy string即拷贝字符串的意思。
    2.库函数strcpy的功能是:Copies the C string pointed by source into the array pointed by destination, including the terminating null character (and stopping at that point)即将source指向的C字符串复制到destination指向的数组中包括结束的null字符(并在该点停止)。
    3.库函数strcpy的参数是destination和source。他们的类型非别是char * 和const char * 。
    4.库函数strcpy的返回值是destination,它的类型是char * 。
    5.库函数strcpy的语法规则是:
    strcpy( destination, source);
    6.库函数strcpy的头文件是string.h

    (2). 写代码:把数组arr1中的字符串复制到数组arr2和arr3中

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>//使用库函数前引头文件
int main()
{
	char arr1[] = "abcdef";//source参数是数组arr,参数类型const char*。
	char arr2[20] = {0};//destinatonc参数是数组arr2和数组arr3,参数类型是char*
	char arr3[20] = {0};
	//把source参数中的字符串复制到参数destination中
	strcpy(arr2,arr1);
	strcpy(arr3, "abcdef");
	printf("%s\n", arr2);
	printf("%s\n", arr3);
	return 0;
}

运行结果:
在这里插入图片描述
代码分析:很基础但还是在这里强调一下

  • 为什么学习网站中说参数类型是char*,而我在代码中写的是char?因为数组名就是地址。
  • 为了避免溢出,destination指向的数组的大小应该足够长,以包含与source相同的C字符串(包括结束的null字符),并且不应该在内存中与source重叠。不要犯数组越界的错误哦!
  • 我们知道字符串"abcdef"的真实面目是’a’,‘b’,‘c’,‘d’,‘e’,‘f’,‘\0’,其中’\0’是字符串的结束标志。即复制的内容中包括’\0’,且复制到’\0’停止复制。

  1. 栗子2:编写一段代码,要求使用库函数memset
    (1):来到学习网站cplusplus学习们memset, cplusplus中对memset的解释如图:
    在这里插入图片描述
    在这里插入图片描述

    通过上图,我们知道:

    1.库函数memset的头文件时string.h
    2.memset是Fill block of memory(填充内存块) 的意思。在英文中,memory是记忆的意思,但在计算机中,memory是内存的意思。
    3.库函数memset的功能是:Sets the first num bytes of the block of memory pointed by ptr to the specified value (interpreted as an unsigned char).即将ptr指向的内存块的前num个字节设置为指定的值(解释为unsigned char)。
    4.库函数memset的参数是ptr,value,num,他们的参数类型分别是void*,int,size_t。
    5.库函数memset的返回值是ptr,返回类型是void*。
    6.库函数memset的语法规则是:
    memset( ptr, value,num);

    (2).写代码:把数组arr的前4个字节,内容设置为d

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "dianzan shoucang guanzhu";
	memset(arr,'d',4);
	printf("%s\n", arr);
	return 0;
}

运行结果:
在这里插入图片描述


吃栗子时间结束!


C语言中常用的库函数包括:IO1 函数,字符串操作函数(如strcpy),字符操作函数,内存操作函数(memst),时间/日期操作函数,数学函数以及其他库函数。虽然库函数千千万,但库函数并不需要我们特别记忆。在知道了上面两个网站后,当我们在代码中需要用到库函数时,只需要仿照上面吃栗子时,查阅网站,找到所需的库函数现学现用即可。
在这里插入图片描述


不过现学现用是很爽,但是库函数只是一系列能实现基础功能和操作的函数,所以如果我们想要写代码实现我们自己心中所想,必须掌握自定义函数!
在这里插入图片描述



4.自定义函数

  • 自定义函数:根据自定义函数在main函数中的调用需求,程序员自己设计函数的参数(参数类型),返回值(返回值类型),函数名,函数功能。
  • 即库函数的资料我们可以从学习网站上获得。而自定义函数的资料需要程序员自己设计。

4.1自定义函数的基本形态:

ret_type     fun_name(par_type  paral)
//返回值类型  函数名    参数类型  (形)参数
{
statement;//语句项
}//{}里是函数体,在{}里写代码实现函数功能

注意:返回值类型如果定义为void,表示这个自定义函数不返回值。

4.2自定义函数的实现步骤(先调后定):

    1. 在main函数中根据具体需求调用自定义函数,类似于库函数的使用
    2. 在main函数之外,根据调用需求定义函数的参数(参数类型),返回值(返回值类型),函数名,函数功能。
      在这里插入图片描述
  • 代码演示:写一个自定义函数,函数的功能是找出两个整数中的最大值。(先调后定)

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//在调用GetMax时,我们得知GetMax的功能时比较int类型参数a和int类型参数b的大小,最后输出较大的参数。
//所以根据函数调用,我们设计出GetMax函数如下:
int GetMax(int x, int y)//传参
{
   //函数功能:找出两个整数中的最大值
	int z = 0;
	if (x > y)
		z = x;
	else
		z = y;
	return z;//输出返回值到main函数
}
int main()
{
	int a = 10;
	int b = 20;
	//函数的调用(类似于库函数的使用)
	int  max = GetMax(a, b);//函数名要起的有意义
//接收返回值       //传(实)参
	printf("%d\n", max);
	return 0;
}

调试结果:
在这里插入图片描述
图片演示:
在这里插入图片描述

4.3函数的参数

  1. 实参
  • 在main函数中调用自定义函数时,此时真实传给函数的参数,叫实际参数,也称实参。上面GetMax函数中的参数a,b都是实参。
  • 实参可以是:常量,变量,表达式,函数等。但无论实参是何种类型的量,在进行函数调用时,实参必须是明确的值,以便把这些值传递给形参。
  1. 形参
  • 在main函数之外,我们自己设计自定义函数时,函数名后括号中的参数叫形式参数,也称形参。上面GetMax函数中的参数x,y都是形参。
  • 在函数未被调用时,形参只是个摆设。
  • 形参只有在函数被调用的过程中才实例化(分配内存单元),并且当函数调用完成后形参的内存单元自动销毁。所以形参只在自定义函数中有效(即形参的生命周期同局部变量一样)。上面GetMax函数被调用完成后,空间x,空间y,被自动销毁。

4.4函数的调用

  • 如何理解想要成功交换两个变量的值,需要借助第三个临时变量
    (1). 先吃个栗子
    在这里插入图片描述
    借助第三个空瓶,第一步把酱油倒进空瓶中,酱油瓶空了!第二步把醋倒进酱油瓶中,,醋瓶空了!第三步把酱油倒进醋瓶中,醋和酱油成功进入了对方的瓶子中!
    在这里插入图片描述

    (2). 两个变量值(酱油和醋)分别被存放在计算机内存中的两块空间(酱油瓶和空瓶)里,所以如果我们想要成功交换两个变量的值,必须向内存申请一块空白空间(空瓶),即借助第三个临时变量。

4.41. 传值调用

传值调用是指:在main函数中调用自定义函数时,在传参过程中,实参传给形参的仅仅是实参的值。形参实例化后相当于只是实参的一份临时拷贝在自定义函数内部,对形参的修改不会影响实参

代码演示:设计一个自定义函数,函数的功能是交换两个整型变量的内容

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void Swap(int x, int y)
{
//想让函数实现功能:交换两个整型变量的内容
	int z = 0;
	z = x;
	x = y;
	y = z;
}
int main()
{
	int a = 10;
	int b = 20;
	printf("交换前:a = %d,b = %d\n", a, b);
	Swap(a, b);
	printf("交换后:a = %d,b = %d", a, b);
	return 0;
}

运行结果:
在这里插入图片描述
函数设计失败原因:
自定义函数Swap在被调用的时候,传参过程中,实参a,b仅仅把各自的值10,20传给了形参x和y。也可以说形参x和y临时创立空间,仅仅拷贝了参数a和b的值(传值调用)。所以对形参的修改不会影响实参。

在这里插入图片描述

4.42.传址调用

传址调用是指:在main函数中调用自定义函数时,在传参过程中,实参传给形参的是实参的地址。此时使函数的实参和形参建立了真正的联系,即可以在自定义函数内部通过操作形参直接改变实参

代码演示:设计一个自定义函数,函数的功能是交换两个整型变量的内容

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

//函数功能:交换两个整型变量的内容
void Swap(int* pa, int* pb)
{
	int z = 0;
	z = *pa;
	*pa = *pb;
	*pb = z;
}
int main()
{
	int a = 10;
	int b = 20;
	printf("交换前:a = %d,b = %d\n", a, b);
	Swap(&a, &b);
	printf("交换后:a = %d,b = %d", a, b);
	return 0;
}

运行结果:
在这里插入图片描述
代码分析:函数Swap在被调用的时候,传参过程中,实参传给形参的是&a,&b,即pa空间和pb空间里存放的分别是空间a和空间b的地址。&a和&b相当于两个链接,它们可以直接跳转到变量a和b所处的空间。而*pa,*pb则分别代表的是链接背后,空间a和空间b中的变量。
所以代码中,z=*pa执行的操作是:把空间a中的值10赋给空间z。*pa=*pb执行的操作是:把空间b中的值20赋给空间a,*pb=z执行的操作是:把空间z的值赋给空间b。

在这里插入图片描述

4.43.嵌套调用



  1. I和O分别代表input,output。 ↩︎

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值