前言
前面呢,我们已经学习了数据类型、变量与常量、字符、分支语句及其循环语句相关的知识点,那么接下来我们准备学习C语言中的函数部分,想要学好函数必须得了解函数是什么、函数应该怎么用、应该注意那些细节,接下来就由小编来和大家聊聊函数。
1.函数是什么?
大家都知道数学中的函数,但是大家了解C语言中的函数吗?
维基百科中对函数的定义:子程序
在计算机科学中,子程序(英语:Subroutine, procedure, function, routine, method,
subprogram, callable unit),是一个大型程序中的某部分代码, 由一个或多个语句块组
成。它负责完成某项特定任务,而且相较于其他代 码,具备相对的独立性。
一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。这些代码通常被集成为软
件库。
2.C语言中函数的分类:
1.库函数
2.自定义函数
2.1库函数
为什么会有库函数?
printf:
当我们在学习C语言编程的时候,总是在代码编写完之后迫不及待地想知道结果,想把这个结果打印到我们的屏幕上来看看。这时候我们就会频繁的使用一个功能:将信息按照一定的格式打印在屏幕上(printf)。
strcpy:
在我们日常写程序的时候,会经常遇到将一个字符串的内容拷贝到另一个字符串中,这时候我们就会用到”strcpy“函数来完成拷贝工作。
pow:
C语言中用于计算n的k次方,就要用到”pow“函数来计算。
那我们如何学习库函数呢?
像上面我们描述的基础功能,它们不是业务性的代码。我们在开发的过程中每个程序员都可能用的到,
为了支持可移植性和提高程序的效率,所以C语言的基础库中提供了一系列类似的库函数,方便程序员
进行软件开发。
简单总结一下,C语言常用的库函数都有:
IO函数 ———比如input output、scanf、printf、getchar、putchar等等
字符串操作函数 ———strlen、strcmp等等
字符操作函数 ————大小写转化、字符分类
内存操作 ———memcpy、memmove、memset等等
时间/日期函数——time
数学函数 ——pow、sqrt等等
其他库函数
char * strcpy ( char * destination, const char * source );
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<string.h> int main() { char Str[] = "hello world"; char String[80] = {0}; printf("拷贝前>"); printf("String = %s\n", String); strcpy(String, Str); printf("拷贝后>"); printf("String = %s\n", String); //直接将字符串进行拷贝 printf("直接拷贝字符串>"); strcpy(String, "HELLO WORLD"); printf("String = %s\n", String); return 0; }
我们来一起看看代码的运行结果>
注:
但是库函数必须知道的一个秘密就是:使用库函数,必须包含 #include 对应的头文件。
这里对照文档来学习上面几个库函数,目的是掌握库函数的使用方法。
这里给大家分享一个学习库函数很好的一个软件:MSDN(可以点击下载安装)
还有一个在线网站::www.cplusplus.com
进来之后我们先点击右上角的[Legacy version]
进入旧版>
这样我们就可以学习库函数啦!
当然也可以使用MSDN
安装好MSDN之后我们来到主页面>
比如我们要查询strcpy函数,我们就可以这样做>
- 在搜索框中输入strcpy,按下回车
(当然如果你跟小编一样英语不好的话也可以使用有道词典来截图翻译)
2.2自定义函数
如果库函数能干所有的事情,那还要程序员干什么?
所有更加重要的是自定义函数。
自定义函数和库函数一样,有函数名,返回值类型和函数参数。
但是不一样的是这些都是我们自己来设计。这给程序员一个很大的发挥空间。
函数组成:
et_type fun_name(para1, *) { statement;//语句项 } ret_type 返回类型 fun_name 函数名 para1 函数参数
我们来举个例子
写一个函数可以找出两个整数中的最大值
//函数 int get_max(int x, int y) { return x > y ? x : y; } //main函数 int main() { int a = 0; int b = 0; //输入 scanf("%d %d", &a, &b); //找出a和b中的较大值 int max = get_max(a, b); printf("%d\n", max); return 0; }
我们再举一个例子
写一个函数可以交换两个整型变量的内容。
void Swap1(int x, int y) { int tmp = x; x = y; y = tmp; } int main() { int a = 0; int b = 0; //输入 scanf("%d %d", &a, &b); //交换 printf("交换前:a=%d b=%d\n", a, b); //交换函数 Swap1(a, b); printf("交换后:a=%d b=%d", a, b); }
乍一看这代码写的也没有问题啊!那为什么出来的结果不是我们想要的呢?
我们来调试看一下>
这里我们可以看到a、b的地址对应的x、y的地址并不相同,只是他们的值相同,执行Swap1函数的时候只是又创建了两个变量和a、b的值相等而已,只是交换了x和y对应的值,所以才不会修改a和b的值;当Swap1函数执行完之后x、y的内存空间就会被销毁。
我们来看一个代码>
int main() { int a = 0; a = 20; printf("a=%d\n", a); int* pa = &a; *pa = 30; printf("a=%d\n", a); }
通过这个代码我们可以观察到修改一个变量的值有两种修改方法:
- 直接修改
- 通过地址修改
知道了这个知识点那我们是不是可以尝试着去解决交换问题。
void Swap2(int* pa, int* pb) { int tmp = *pa;//相当于tmp = a; *pa = *pb; //相当于a=b; *pb = tmp; //相当于b = tmp; } int main() { int a = 0; int b = 0; //输入 scanf("%d %d", &a, &b); //交换 printf("交换前:a=%d b=%d\n", a, b); //交换函数 Swap2(&a, &b); printf("交换后:a=%d b=%d", a, b); }
这样就可以修改成功了,我们再来调试看一下他们的地址>
可以看出Swap2函数是通过a和b的地址对其进行交换。
总结:
当函数调用时,实参传递给形参,这时形参实施惨的一份临时拷贝,对形参的修改不影响实参。
3.函数的参数
函数的参数分为实参和形参
3.1实际参数(实参)
真实传递给函数的参数,叫实参。
实参可以是:常量、变量、表达式、函数等。
无论实参是何种类型的量,在进行函数调用时,他们都必须由确定的值,一边把这些之传递给形参。
3.2形式参数(形参)
形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内
存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有
效。
4.函数的调用:
4.1传值调用
函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
4.2传址调用
- 传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
- 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。
练习
- 求出100~200之间的素数(用函数实现)
int is_prime(int n ) { int j = 0; for (j = 2; j <= sqrt(n); j++) { if (n % j == 0) { return 0;//不是素数 } } return 1;//是素数 } int main() { int i = 0; for (i = 100; i <= 200; i++) { //判断是不是素数 if (is_prime(i)) { printf("%d ",i); } } return 0; }
总结
以上就是函数分类、参数、调用的全部内容!有付出才会有收获,”种一棵树的最好时间是十年前,其次是现在。“
创作不易,辛苦各位小伙伴们动动小手,三连一波~~~,本文中也有不足之处,欢迎各位随时私信点评指正!