函数
函数的概念
概念:C语言中的函数是一种封装了一定功能的代码块,可以在程序的任意位置调用。
返回值类型 函数名(参数列表)
{
函数体
return 返回值;
}
1.返回值类型指定了函数返回的数据类型
2.函数名是函数的名字
3.参数列表包含了函数所需的输入参数
4.函数体包含了函数实现的具体功能
5.return语句用于将计算结果传递给函数调用者。
维基百科中对函数的定义:子程序
在计算机科学中,子程序(英语:Subroutine, procedure, function, routine, method, subprogram, callable unit),是一个大型程序中的某部分代码, 由一个或多个语句块组 成。它负责完成某项特定任务,而且相较于其他代码,具备相对的独立性。 一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。这些代码通常被集成为软件库。
函数的作用
作用:将程序中的具体功能逻辑封装在一个函数中,可以大大提高程序的可读性和可维护性。在程序中,通过调用函数来实现相应的功能,避免了冗长、重复的代码出现,也方便了代码的复用。
函数的分类
1.库函数
库函数是指一些已经编写好的、经过测试和优化的程序函数集合,这些函数可以被其他程序调用。库函数通常是为了实现一些常见的功能而编写的,如scnaf函数、printf函数、strlen函数等。库函数有助于程序开发人员提高开发效率和代码质量,避免重复造轮子。在程序开发中,使用库函数可以简化代码,提高代码的可读性和可维护性。C语言并不直接去实现库函数,而是提供了C语言的标准和库函数的约定。
总结 - C语言常用的库函数都有:
IO函数:输入输出函数 scanf printf getchar putchar
字符串操作函数:strlen strcmp
字符操作函数:islower isupper
内存操作函数:menset memcmp
时间/日期函数:time
数学函数:sqrt pow
其他库函数
接下来,我们来学习两个库函数 :
(1).strcpy
但是这个函数到底有没有拷贝'\0'呢,我们还需验证一下。
(2).memset
2.自定义函数
自定义函数是指程序员自己编写的函数,可以和库函数一样被其他程序调用。和库函数不同的是,自定义函数是根据程序员的需求和特定的功能来编写的,可以根据具体的业务需求进行设计,可以实现一些复杂的算法或流程。
函数的组成:
ret_type fun_name(para1, *)
{
statement;//语句项
}
ret_type 返回类型
fun_name 函数名
para1 函数参数
写一个自定义函数可以找出两个整数中的最大值。
函数的参数
这里我们先来写一个函数实现两个整型变量的交换
这里我们就需要介绍一下函数参数。
3.1 实际参数(实参)
真实传给函数的参数,叫实参。 实参可以是:常量、变量、表达式、函数等。无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。
3.2 形式参数(形参)
形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函 中有效。
!!!!!!最终写法:
//写一个函数实现两个整型变量的交换 #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> void swap(int* x, int* y)//形式参数 - 形参 { int temp = 0; temp = *x; *x = *y; *y = temp; } int main() { int a = 0; int b = 0; scanf("%d %d", &a, &b); printf("交换前:%d %d\n", a, b); swap(&a, &b); //实际参数 - 实参 printf("交换前:%d %d\n", a, b); return 0; }
那我们什么时候需要传地址,什么时候又需要传值呢?这时我们就需要了解函数的调用
函数的调用
传值调用:
函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
传址调用:
传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操
作函数外部的变量。
总结:
写下写几个代码好好理解传址和传值的实际应用。
1. 写一个函数可以判断一个数是不是素数。
#include<stdio.h> #include<math.h> int is_prime(int n) { int i = 0; for (i = 2; i <= sqrt(n); i++) { if (n % i == 0)//不是素数 return 0; } return 1; } int main() { int i = 0; for (i = 101; i <= 200; i += 2) { //判断i是否是素数 //由于这里只是使用这个值,并不需要修改,所以传值 if (is_prime(i) == 1) printf("%d ", i); } return 0; }
2. 写一个函数判断一年是不是闰年。
#include<stdio.h> int is_leap_year(int year) { if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) return 1; return 0; } int main() { int year = 0; scanf("%d", &year); //判断闰年 //由于这里只是使用这个值,并不需要修改,所以传值 if (is_leap_year(year) == 1) printf("%d年是闰年!", year); return 0; }
3. 写一个函数,实现一个整形有序数组的二分查找。
#include<stdio.h> int binary_search(int arr[],int sz,int k) { int left = 0; int right = sz - 1; //int mid = (left + right) / 2;//容易超出int类型的范围 int mid = left + (right - left); while (left<=right) { if (arr[mid] > k) right = mid - 1; else if (arr[mid] < k) left = mid + 1; else return mid; } return -1; } int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int sz = sizeof(arr) / sizeof(arr[0]); int k = 5; //二分查找k值 //由于这里只是使用这个值,并不需要修改,所以传值 int ret = binary_search(arr, sz, k); if (ret == -1) printf("没找到!\n"); else printf("找到了,下标是:%d\n", ret); return 0; }
4. 写一个函数,每调用一次这个函数,就会将 num 的值增加1。
#include<stdio.h> void num_addtion(int* n) { *n += 1; } int main() { int num = 0; //每次调用函数num都会+1 //由于这里需要修改num的值,所以传址 num_addtion(&num); printf("%d\n", num); num_addtion(&num); printf("%d\n", num); num_addtion(&num); printf("%d\n", num); return 0; }