文章目录
一、库函数
- 使用库函数,必须包含 #include 对应的头文件
- 学习库函数用到的文档::www.cplusplus.com
二、自定义函数
自定义函数的参数--实参&形参
自定义函数的调用--传值调用&传址调用
用下面例子来演示实参形参以及函数的调用
错误实现方式:
swap1(a, b); 使用传值调用
- 传值调用时函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
- 形参实例化之后其实相当于实参的一份临时拷贝。
- 形参,实参有不同的内存单元
c
void swap1(int x, int y)
{
int z = 0;
z = x;
x = y;
y = z;
printf("2交换后的a,b为%d %d\n", x, y);//20 10
}
int main()
{
int a = 10;
int b = 20;
printf("1交换前的a,b为%d %d\n", a, b);//10 20
//即传值调用时函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
//形参实例化之后其实相当于实参的一份临时拷贝。
swap1(a, b);//只传变量的值不行的,
printf("3交换后的a,b为%d %d\n", a, b);//10 20
return 0;
}
正确的实现方式:
swap2(&a, &b); 使用传址调用
- 传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
- 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。
- 即用px,py指针变量来操作a,b变量
c
void swap2(int *px, int *py)
{
int z = 0;
z = *px;//将px指针变量进行解引用即得到的是a变量的值10
*px = *py;
*py = z;
printf("2交换后的a,b为%d %d\n", *px, *py);//20 10
}
int main()
{
int a = 10;
int b = 20;
printf("1交换前的a,b为%d %d\n", a, b); // 10 20
// 传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
// 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。
// 即用px,py指针变量来操作a,b变量
swap2(&a, &b);
printf("3交换后的a,b为%d %d\n", a, b); // 20 10
return 0;
}
三、函数的嵌套调用
函数不可以进行嵌套定义
c
void new_line()
{
printf("hehe\n");
}
void three_line()
{
int i = 0;
for (i = 0; i < 3; i++)
{
new_line();
}
}
int main()
{
three_line(); // 主程序调用three_line(),three_line()调用new_line()
return 0;
}
四、函数的链式访问--需要函数必须要有返回值
例1:
- strcat()用于将源字符串追加到目标字符串末尾,并自动在结果末尾添加 \0 结束符
- 用strlen()和sizeof()求数组中元素个数的区别
- 对数组使用不同初始化方式会对使用sizeof()求数组中元素个数产生影响
c
int main()
{
char arr[20] = "hello";
// strcat()用于将源字符串追加到目标字符串末尾,并自动在结果末尾添加 \0 结束符
int ret = strlen(strcat(arr, "bit"));
printf("%d\n", ret); // 8,不算\0 用sizeof()求会算\0
int ret1 = sizeof(arr) / sizeof(arr[0]);
printf("%d\n", ret1); // 20,因为数组大小是20,没放数据的单元默认放值了\0
char arr1[] = "hello";
int ret2 = sizeof(arr1) / sizeof(arr1[0]);
printf("%d\n", ret2); // 6,因为数组大小是5个字母+\0 = 6
return 0;
}
例2:
- printf函数的返回值是打印在屏幕上字符的个数
c
int main()
{
//printf函数的返回值是打印在屏幕上字符的个数
printf("%d", printf("%d", printf("%d", 43)));//4321
return 0;
}
五、练习
写一个函数,实现一个整形有序数组的二分查找。
正确写法:
- 函数传参时必须将数组中元素个数做为实参传递(因为数组传参实际上传递的是数组首地址,不是整个数组所以不能在binarySearch函数内部来计算数组的元素个数)
c
int binarySearch(int arr[], int arrnum, int num)
{
int left = 0;
int right = arrnum - 1;
int i = 0;
while (left <= right)
{
int mid = left + (right - left) / 2;
if (arr[mid] > num)
{
right = mid - 1;
}
else if (arr[mid] < num)
{
left = mid + 1;
}
else
{
return mid;
}
}
if (left > right)
{
return -1;
}
}
int main()
{
int num = 0;
printf("请输入数字:\n");
scanf("%d", &num);
int arr[8] = {1, 3, 7, 9, 15, 36, 47, 58};
int arrnum = sizeof(arr) / sizeof(arr[0]);
// 注意这里必须将数组中元素的个数做为参数传递,
// 因为数组传参实际上传递的是数组首地址,不是整个数组所以不能在binarySearch函数内部来计算数组的元素个数
int index = binarySearch(arr, arrnum, num);
if (-1 != index)
{
printf("找到了,索引是%d\n", index);
}
else
{
printf("找不到\n");
}
return 0;
}
错误写法:
- 在binarySearch函数内部来计算数组的元素个数会发现得到的结果为1或者2(由机器字长决定)
c
int binarySearch(int arr[], int num)
{
int left = 0;
// 如果在binarySearch函数内部来计算数组的元素个数会发现数组传参实际上传递的是数组首地址
// 64位机器指针是8字节而int型元素的大小是4字节 所以arrnum==2
int arrnum = sizeof(arr) / sizeof(arr[0]);
printf("arrnum:%d\n", arrnum); // 2
}
int main()
{
int num = 0;
printf("请输入数字:\n");
scanf("%d", &num);
int arr[8] = {1, 3, 7, 9, 15, 36, 47, 58};
// int arrnum = sizeof(arr) / sizeof(arr[0]);
// 注意这里必须将数组中元素的个数做为参数传递,
// 因为数组传参实际上传递的是数组首地址,不是整个数组所以不能在binarySearch函数内部来计算数组的元素个数
int index = binarySearch(arr, num);
return 0;
}