件库。
2.函数的分类 2.1库函数 2.1.1 为什么会有库函数? 1. 我们知道在我们学习 C 语言编程的时候,总是在一个代码编写完成之后迫不及待的想知道结果,想把这个结果打印到我们的屏幕上看看。这个时候我们会频繁的使用一个功能:将信息按照一定的格式打印到屏幕上(printf ) 2. 在编程的过程中我们会频繁的做一些字符串的拷贝工作( strcpy ) 3. 在编程是我们也计算,总是会计算 n 的 k 次方这样的运算( pow ) 像上面我们描述的基础功能,它们不是业务性的代码。我们在开发的过程中每个程序员都可能用的到, 为了支持可移植性和提高程序的效率,所以C 语言的基础库中提供了一系列类似的库函数,方便程序员进行软件开发。 2.2.2 C 语言常用的库函数都有: IO 函数 字符串操作函数 字符操作函数 内存操作函数时间/日期函数 数学函数 其他库函数
2.2.3 库函数的组成 2.2自定义函数 2.2.1 函数的组成2.2.2 举例
例1:写一个函数可以找出两个整数中的最大值。
int get_max(int x, int y)//函数的定义
{
int z = 0;
if (x > y)
z = x;
else
z = y;
return z;
}
int main()
{
int a = 10;
int b = 20;
int max=get_max(a, b);//函数的调用
printf("%d", max);
return 0;
}
⭐ 例2:写一个函数可以交换两个整形变量的内容。
错误示范:传值调用
void Swap(int x,int y)//void表示这个函数不返回任何值,也不需要返回
{
int z = 0;
z = x;
x = y;
y = z;
}
int main()
{
int a= 10;
int b = 20;
printf("交换前:a=%d b=%dn", a, b);
Swap(a, b);
printf("交换后:a=%d b=%dn", a, b);
return 0;
}
输出:
交换前:a=10 b=20
交换后:a = 10 b = 20
这是因为主函数中的a,b与Swap函数中的x,y并不是一块空间,在创建x,y时也为x,y创建了单独的空间
因此,Swap函数在进行交换时,只是单纯的交换了x,y的值,并没有对主函数a,b的值进行改变,二者都不在一块空间里,所以没有达到交换的效果
正确代码:传址调用
void Swap(int* pa, int* pb)
{
int z = 0;
z = *pa;
*pa = *pb;
*pb = z;
}
int main()
{
int a= 10;
int* pa = &a;
int b = 20;
int* pb = &b;
printf("交换前:a=%d b=%dn", a, b);
Swap(pa, pb);
printf("交换后:a=%d b=%dn", a, b);
return 0;
}
输出:
交换前:a=10 b=20
交换后:a=20 b=10 此时,pa存的是a的地址,pa存的是b的地址,通过*pa,*pa表示a,b的值,以改变a,b的值 3.函数的参数 3.1 实际参数(实参) 真实传给函数的参数,叫实参。 实参可以是:常量、变量、表达式、函数等。 无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。 3.2 形式参数(形参) 形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内 存单 元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。 ⭐:实参和形参并不存放在同一空间,形参实例化之后其实相当于实参的一份临时拷贝 4.函数的调用 4.1 传值调用
--仅传值使用
函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
4.2 传址调用--函数内部需要改变函数外部
传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。 4.3 练习练习1:写一个函数打印100-200之间的素数
int is_prime(int n)
{
//2-n-1之间的数字试出n
int j = 0;
for (j = 2; j < n; j++)
{
if (n % j == 0)
return 0;
}
return 1;
}
int main()
{
int i = 0;
int count = 0;
for (i = 100; i <= 200; i++)
{
//判断i是否为素数
if (is_prime(i) == 1)
{
printf("%d ", i);
count++;
}
}
printf("n100-200之间的素数一共有%d个",count);
return 0;
}
练习2:写一个函数打印1000年-2000年的闰年
int is_leap_year(int n)
{
return ((n % 4 == 0 && n % 100 != 0) || n % 400 == 0);
}
int main()
{
int y = 0;
int count = 0;
for (y = 1000; y <= 2000; y++)
{
if (is_leap_year(y) == 1)
{
printf("%d ", y);
count++;
}
}
printf("n1000-2000年内一共有%d个闰年", count);
return 0;
}
练习3:写一个函数,实现一个整形有序数组的二分查找。
int binary_search(int a[], int k, int s)
{
int left = 0;
int right = s - 1;
while (left <= right)
{
int mid = (left + right) / 2;
if (k > a[mid])
{
left = mid + 1;
}
else if (k < a[mid])
{
right = mid - 1;
}
else
{
return mid;
}
}
return -1;
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int key = 7;
int sz = sizeof(arr) / sizeof(arr[0]);
//找到就返回位置的下标,找不到就返回-1
int ret=binary_search(arr,key,sz);
if (ret == -1)
{
printf("找不到");
}
else
{
printf("找到了,下标是:%d",ret);
}
return 0;
}
:数组传参,实际传递的不是数组本身,仅仅传递了数组首元素的地址
练习4:写一个函数,每调用一次这个函数,就会将 num 的值增加1。
int main()
{
int num = 0;
//调用函数,使得num每次增加1
return 0;
}
void Add(int* p)
{
(*p)++;
}
int main()
{
int num = 0;
Add(&num);
printf("%d", num);
return 0;
}
5.函数的嵌套调用和链式访问
5.1 嵌套调用
void test3()
{
printf("hehen");
}
void test2()
{
test3();
}
int main()
{
test2();
return 0;
}
函数可以嵌套调用,但是不可以嵌套定义
5.2 链式访问把一个函数的返回值作为另外一个函数的参数
int main()
{
int len = strlen("abc");
printf("%d", len);
printf("%d", strlen("abc"));
return 0;
}
int main()
{
printf("%d", printf("%d", printf("%d", 43)));
//结果是啥?
//注:printf函数的返回值是打印在屏幕上字符的个数
return 0;
}
输出:4321
6.函数的声明和定义


