首页 > 其他分享 >函数

函数

时间:2022-12-23 17:33:38浏览次数:51  
标签:arr return 函数 int printf 库函数

前言:

在了解循环语句之后,我们开始了解函数,函数是C语言学习的重中之重,函数就相当于C语言代码的工具,可以极大的方便我们编程

前提回顾:

在了解函数之前,我们先练习一下循环的一道经典习题,打印9*9乘法口诀表,别小看这道题,百度面试考过哦

解释:本题是利用嵌套循环,利用两个for循环可以控制两个变量,从而实现乘法口诀表的实现

//打印9*9口诀表
int main()
{
int k = 0;
for (int i=1;i<=9;i++)
{
for (int j=1;j<=i;j++)
{
k = i * j;
printf("%d*%d=%-3d",j,i,k);//-3保证每组数有间隙,左对齐

}
printf("\n");
}
return 0;
}

函数_嵌套

1.函数是什么?

数学中我们常见到函数的概念。但是你了解C语言中的函数吗? 维基百科中对函数的定义:子程序

在计算机科学中,子程序(英语:Subroutine, procedure, function, routine, method,  subprogram, callable unit),是一个大型程序中的某部分代码, 由一个或多个语句块组 成。它负责完成某项特定任务,而且相较于其他代 码,具备相对的独立性。 一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。这些代码通常被集成为软 件库。

2. C语言中函数的分类:

  1. 库函数
  2. 自定义函数

2.1 库函数

为什么会有库函数?

  1. 我们知道在我们学习C语言编程的时候,总是在一个代码编写完成之后迫不及待的想知道结果,想
    把这个结果打印到我们的屏幕上看看。这个时候我们会频繁的使用一个功能:将信息按照一定的格
    式打印到屏幕上(printf)。
  2. 在编程的过程中我们会频繁的做一些字符串的拷贝工作(strcpy)。
  3. 在编程是我们也计算,总是会计算n的k次方这样的运算(pow)。
    像上面我们描述的基础功能,它们不是业务性的代码。我们在开发的过程中每个程序员都可能用的到,
    为了支持可移植性和提高程序的效率,所以C语言的基础库中提供了一系列类似的库函数,方便程序员
    进行软件开发。

那怎么学习库函数呢?

这里我们简单的看看:​​​​​​https://www.cplusplus.com​

这里是一部分C语言库函数的头文件

函数_字符串_02

简单的总结,C语言常用的库函数都有:

IO函数

字符串操作函数

字符操作函数

内存操作函数

时间/日期函数

数学函数

其他库函数

我们参照文档,简单介绍以下两个库函数,后面我们还会详细的介绍

2.1.1 strcpy字符拷贝函数

char * strcpy ( char * destination, const char * source );

专门实现字串的拷贝,格式strcpy(dest,src)

//字符拷贝函数
int main()
{
char arr1[] = "bit";
char arr2[20] = "#########";
strcpy(arr2,arr1);//字符串拷贝,拷过去的有bit还有\0
printf("%s\n",arr2);//打印只显示bit因为后面还有\0,而\0是字符串结束的标志所以后面的####不打印
return 0;
}

函数_库函数_03

2.1.2 memset内存设置数

void * memset ( void * ptr, int value, size_t num );

内存设置函数,格式memset(目标,'替换值',大小)

//内存设置函数
int main()
{
char arr[] = "hello world";
memset(arr, '*', 5);
printf("%s\n", arr);
return 0;
}

函数_字符串_04

注:

但是库函数必须知道的一个秘密就是:使用库函数,必须包含 #include 对应的头文件。 这里对照文档来学习上面几个库函数,目的是掌握库函数的使用方法。

2.1.3 如何学会使用库函数?

需要全部记住吗?No

需要学会查询工具的使用:

MSDN(Microsoft Developer Network)
​​​www.cplusplus.com​​​​http://en.cppreference.com​​​(英文版)
​http://zh.cppreference.com​​(中文版)

英文很重要。最起码得看懂文献。

2.2  自定义函数

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

所有更加重要的是自定义函数。

自定义函数和库函数一样,有函数名,返回值类型和函数参数。

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

函数的组成:

ret_type fun_name(para1, * )
{
statement;//语句项
}
ret_type 返回类型
fun_name 函数名
para1    函数参数

2.2.1 我们举一个例子:

写一个函数可以找出两个整数中的最大值。

函数最总要的就是参数的传递,实参和形参,实参是我们真实传递的数据,形参则是接收实参的变量

//写一个函数可以找出两个整数中的最大值。
//get_max函数的设计
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;
}

函数_字符串_05

2.2.2 再举个例子

交换两个数

下面的swap1代码交换不了两个数,因为此代码是传值而非传址

这个swap2代码利用指针接收参数的地址,它将两个数据的地址进行交换,进而不就是交换了两个数据的值嘛

//交换两个数
//实现成函数,但是不能完成任务
void Swap1(int x, int y)
{
int tmp = 0;
tmp = x;
x = y;
y = tmp;
}
//正确的版本
void Swap2(int* px, int* py)
{
int tmp = 0;
tmp = *px;
*px = *py;
*py = tmp;
}
int main()
{
int num1 = 1;
int num2 = 2;
Swap1(num1, num2);
printf("Swap1::num1 = %d num2 = %d\n", num1, num2);
Swap2(&num1, &num2);
printf("Swap2::num1 = %d num2 = %d\n", num1, num2);
return 0;
}

函数_自定义函数_06

3. 函数的参数

3.1 实际参数(实参):

真实传给函数的参数,叫实参。 实参可以是:常量、变量、表达式、函数等。 无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形 参。

3.2 形式参数(形参):

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

上面 Swap1 和 Swap2 函数中的参数 x,y,px,py 都是形式参数。在main函数中传给 Swap1 的 num1 , num2 和传 给 Swap2 函数的 &num1 , &num2 是实际参数。 这里我们对函数的实参和形参进行分析

函数_自定义函数_07

代码对应的内存分配如下:

函数_自定义函数_08

这里可以看到 Swap1 函数在调用的时候, x , y 拥有自己的空间,同时拥有了和实参一模一样的内容。 所以我们可以简单的认为:形参实例化之后其实相当于实参的一份临时拷贝。

​4. 函数的调用:

4.1 传值调用

函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。

4.2 传址调用

传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操 作函数外部的变量。

4.3 练习

4.3.1 写一个函数可以判断100-200素数个数。

//函数实现素数判断
int is_prime(int n)
{
int j = 0;
//还可以优化for(j = 2; j <=sqrt(n); j++)sqrt是开根号的意思用<math.h>
//因为一个数字可以写成a=b*c,b和c中至少有一个数字<=开平方a,只要能在开平方n之前找到一个数字整除n就说明n不是素数
for (j = 2; j <n; j++)
{
if (n % j == 0)
{
return 0;
}
}
//优化if(j>sqrt(n))
if (j == n)
{
return 1;
}

}
int main()
{
int i = 0;
int count = 0;
for (i = 100; i < 200; i++)
{
if (is_prime(i) == 1)//is_prime是专门判断素数的,若果为素数返回1
{
count++;//记录个数
printf("%d ",i);
}
}
printf("\ncount=%d\n", count);
return 0;
}

函数_嵌套_09

4.3.2 写一个函数判断一年是不是闰年。

代码很简单不做解释

//函数判断闰年
int is_leap_year(int a)
{
if (a % 4 == 0 && a % 100 != 0 || a % 400 == 0)
{
return 1;
}
else
{
return 0;
}
}
int main()
{
int year = 0;
scanf("%d",&year);
if (is_leap_year(year) == 1)
{
printf("%d 是闰年", year);
}
else
{
printf("%d 不是闰年", year);
}
return 0;
}

函数_自定义函数_10

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

二分查找我们在前面做过重点介绍,忘记的可以翻一下之前的博客,这里之哟一点小改变,就是将主题查找实现部分写成了一个函数调用即可

////二分查找函数实现
int binary_search(int arr[], int k,int sz)
{
int left = 0;
int right = sz-1;
while (left <= right)
{
int mid = (left + right) / 2;
if (arr[mid] < k)
{
left = mid + 1;
}
else if (arr[mid] > k)
{
right = mid - 1;
}
else
{
return mid;
}
}
return -1;
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 7;
int sz = sizeof(arr) / sizeof(arr[0]);//数组传过去的是首元素的地址,不能计算数组大小,所以只能在这里计算好在传过去
//找到了返回下标,找不到返回-1
int ret = binary_search(arr, k,sz);
if (ret == -1)
{
printf("没找到\n");
}
else
{
printf("找到啦,下标是:%d\n",ret);
}
return 0;
}

函数_嵌套_11

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

这里解释没有返回值为啥num的值还可以改变,因为实参是&num传地址,使用指针接收(*p)++即可改变num的值,因为*p和num公用同一块地址

//每执行一次number值加一
void he(int* p)
{
(*p)++;
}

int main()
{
int number = 0;
he(&number);
printf("%d\n", number);
he(&number);
printf("%d\n", number);
he(&number);
printf("%d\n", number);
return 0;
}

函数_自定义函数_12

5. 函数的嵌套调用和链式访问

函数和函数之间可以根据实际的需求进行组合的,也就是互相调用的。

5.1 嵌套调用

函数可以嵌套调用,但是不能嵌套定义。

//函数的嵌套使用,打印三遍hehe
void new_line()
{
printf("hehe\n");
}
void three_line()
{
int i = 0;
for (i = 0; i < 3; i++)
{
new_line();
}
}
int main()
{
three_line();
return 0;
}

函数_字符串_13

5.2 链式访问

把一个函数的返回值作为另外一个函数的参数。

5.2.1 例1

介绍strcat是字符串追加函数,strlen是计算字符串长度的函数

int main()
{
char arr[20] = "hello";
strcat(arr, "bit");
printf("%s\n",arr);
int ret = strlen(arr);//strcat是字符串追加函数
printf("%d\n", ret);
return 0;
}

函数_嵌套_14

5.2.2 例2

解释:printf函数的返回值是打印在屏幕上字符的个数

结果是4321,首先最里层的printf打印43,外层的printf打印个数43为两位数即2,最外层的printf也打印个数2为一位数即1,所以结果为 43 2 1

int main()
{
printf("%d",printf("%d", printf("%d", 43)));
//结果是啥?
//注:printf函数的返回值是打印在屏幕上字符的个数
return 0;
}

函数_自定义函数_15







标签:arr,return,函数,int,printf,库函数
From: https://blog.51cto.com/u_15784725/5965949

相关文章