C语言函数(5)--- 扩展练习题
  uUWKQE7Avyk4 2023年11月02日 23 0

一.练习题

1.写一段代码要求实现一个整型有序数组的二分查找


有bug的代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<windows.h>
int function(int arr[], int k){
	int left = 0;
	int right = (sizeof(arr) / sizeof(arr[0])) - 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(void){
	int arr[] = {1,2,3,4,5,6,7,8,9,10};
	int k = 7;
	int ret = function(arr,k);
	if (ret == -1){
		printf("无法找到指定数字!\n\a");
	}
	else{
		printf("找到该数字,数组下标为%d\n",ret);
	}
	system("pause");
	return 0;
}

我们先看代码的main()函数部分,我们首先创建了一个arr1[]的整型有序数组,数组中存放的是1-10这10个数字,k为我们需要找的数字这里k=7,随后我们声明了变量ret用来接收自定义函数的 function()函数中的返回值,function()函数需要传入两个参数,第一个参数为数组,第二个参数为要查找的数字,当ret等于-1的时候,也就是 function()函数返回-1的时候则代表查找失败,并调用printf()函数提醒用户,否则输出目标元素的下标ret,我们再来看到自定义函数 function()中 函数的形参是 int arr[]与k 用来接收数组与目标数字,由于使用到二分查找法,我们定义最左边的下标为left 最右边的数组我们需要进行计算,我们之前讲过利用sizeof()操作符来计算元素个数,具体代码如下:

int sz = sizeof(arr)/sizeof(arr[0])

原理就是将数组占用内存的总大小计算出来,再除以单个元素的大小就可以得到数组的元素个数,我们声明了一个变量mid,用来计算数组中间下标是多少,也就是 (left+right)/2 随后使用if语句进行判断当arr[mid]的值小于 k 的时候则代表k的值处于 arr[mid] ~ right 之间大大缩小了查找的范围,随后我们将mid+1的值赋给left便于第二次进行查找,如果arr[mid]的值大于 k 则代表 k的值处于 left ~ arr[mid]-1 之间,当以上条件都不满足的时候则有两种可能 1.已经找到了具体的数字 2.目标数字不在该数组内,但是我们在二分查找的外面套了一层循环语句,只有当(left<=right)的时候才能进入循环,这样子上面的else语句对应的只能是情况1 已经找到目标数字,我们这时候只需要使用return语句对 mid 的值进行返回,如果不满足while入口条件则返回-1,代表没有找到目标数字,看似程序好像没什么问题,但是当我们运行的时候却发现,明明7在数组中,但是程序却返回了找不到的提示,如图所示:

C语言函数(5)--- 扩展练习题_数组

当程序运行出现问题或者预期之外的结果时候就是遇到bug了,我们可以按下F10进行调试(当箭头指向函数的时候按下F11才能进入函数,下文就省略了),我们监视三个变量 分别是 left right k ,从调试结果上来看left 与 k 都为我们预期的结果,但是 right 却出现了问题 ,right的值并没有和我们预期的一样计算出数组元素的个数-1 而是变成了 1 这是为什么呢?

原来代码中,这段代码:

	int ret = function(arr1,k);

第一个参数 arr1 是传送的数组中第一个元素的地址,也就是本质上传送了一个指针给函数而不是数组,这时候函数的形参

int function(int arr[], int k)

接收的也就是一个指针,我们利用sizeof()操作符去计算指针在32位平台中会得到4,在64位平台中则会得到8,这样一来 4/4=1 

了解了错误的原因我们就可以着手修复bug了,既然我们不能在自定义函数中来计算数组的元素个数,那我们为什么不把这段代码放到main()函数中去求呢?然后再将计算结果传递给自定义函数 function()

我们可以将代码改成如下所示:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<windows.h>
int function(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(void){
	int arr1[] = {1,2,3,4,5,6,7,8,9,10};
	int k = 7;
	int sz = sizeof(arr1) / sizeof(arr1[0]);
	int ret = function(arr1,k,sz);
	if (ret == -1){
		printf("无法找到指定数字!\n\a");
	}
	else{
		printf("找到该数字,数组下标为%d\n",ret);
	}
	system("pause");
	return 0;
}

我们再在function()函数中写一个形参sz,用来接收数组元素个数,然后将 sz-1 的值赋值给 right 不就可以了,我们在main()函数中也写一段计算数组元素个数的代码即可,然后将其传入function()函数中,这时候我们就可以发现程序能够正常输出结果了,如图所示:

C语言函数(5)--- 扩展练习题_数组_02


2.写一个函数,每次调用这个函数的时候,变量就会自增1


有问题的代码:

#include<stdio.h>
void add(int *p){
	*p++;
}
int main(void){

	int num = 0;
	add(&num);
	printf("num=%d\n",num);
	add(&num);
	printf("num=%d\n", num);
	add(&num);
	printf("num=%d\n", num);
	return 0;
}

我们创建了一个名为add()的自定义函数,这个函数不需要返回内容,所以我们写成void 表示空,我们将num的地址传入add()函数中,再对指针*p进行解引用操作后进行自增,看似没问题的代码,当我们运行时候却遇到了问题,如图所示:

C语言函数(5)--- 扩展练习题_二分查找_03

变量num并未按照我们预期进行自增操作,num的值一直为0,原因是 ++的运算操作符的优先级是高于*p的,所以我们应当将 *p 用()括号括起来,变成:

(*p)++;

就可以了,当我们修改代码以后运行程序,不出我们所料,程序正确的输出了num的值,如图所示:

C语言函数(5)--- 扩展练习题_算法_04

                                                                                                                                  2023/8/11

                                                                                                                                     王起舟

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  zLxnEsMLk4BL   2023年11月19日   35   0   0 数组字符串数组名
  gBkHYLY8jvYd   2023年11月19日   27   0   0 #include数组ci
  X5zJxoD00Cah   2023年11月19日   21   0   0 数组单引号字符串
  gBkHYLY8jvYd   2023年12月10日   24   0   0 #include数组i++
uUWKQE7Avyk4