函数(1)
  mfv4jpsXLy5V 2023年11月02日 38 0

1.函数是什么?

函数的定义:子程序;

在计算机科学中,子程序是一个大型程序中的某部分代码,由一个或多个语句块组成。

它负责完成某项特定任务,而且相较于其他代码,具备相对的独立性。

一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。

这些代码通常被集成为软件库。

C语言中的函数分类:

①库函数;

②自定义函数。


2.Strcpy() - 字符串拷贝

语法:

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

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<string.h>

int main()
{
	char arr1[] = "PZY";
	char arr2[20] = "######";
	strcpy(arr2, arr1);
	printf("%s\n", arr2);
	return 0;
//strcpy - string copy - 字符串拷贝
//strlen - string length - 字符串长度有关
}

注意:strcpy会把数组中的“\0”也一同复制。


3.memset() - 内存设置

语法:

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

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<string.h>

//memset()的使用
int main()
{
	char arr1[] = "hello world";
	memset(arr1, '*', 5);
	//memset - memory 内存 set 设置
	printf("%s\n", arr1);
	return 0;
}

如上代码最终执行结果,屏幕上会打印出“***** world”


4.自定义函数:

函数的组成:

函数(1)_数组

函数(1)_数组_02

举例:

①找出两个数的最大值:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

//定义函数
int get_max(int x, int y)
{
	return (x > y) ? (x) : (y);
}

int main()
{
	int max;
	int a = 10;
	int b = 20;
	//函数的使用
	max = get_max(a, b);
	printf("较大值为:%d\n", max);
	
	return 0;
}


②交换两个数:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

void swap(int x, int y)
{
	int tmp;
	tmp = x;
	x = y;
	y = tmp;
}

int main()
{
	int a, b;
	a = 10;
	b = 20;
	printf("%d %d\n", a, b);
	swap(a, b);
	printf("%d %d\n", a, b);
	return 0;
}

当代码运行后会发现a , b 两个数并未交换,问题出在哪里呢?

函数(1)_函数调用_03

如图,a, b, x, y四个变量的地址都不一样,a,b的数值传给x,y后,

swap()函数最终的输出结果只是x, y的数值交换了,

a, b变量中存放的数值仍然是10, 20,并不会发生交换。

那如果我们不传数值而是远程调用a, b变量的地址呢?这时候我们就想到了指针变量。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

void swap(int*pa, int*pb)
{
	int tmp;
	tmp = *pa;
	*pa = *pb;
	*pb = tmp;
}

int main()
{
	int a, b;
	a = 10;
	b = 20;
  printf("%d %d", a, b);
	swap(&a, &b);
	printf("%d %d", a, b);
	return 0;
}

函数(1)_函数调用_04

最终,a, b的数值成功交换了。


5.函数的参数:

实际参数(实参):

真实传给函数的参数,叫实参。实参可以是:常量、变量、表达式、函数等。

无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,

以便把这些值传给形参。

形式参数(形参):

形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中

才实例化(分配内存单元),所以叫形式参数。形式参数当函数调用完成之后

就自动销毁了。因此形式参数只在函数中有效。


总结:

当实参传给形参的时候,形参只是实参的一份临时拷贝。

对形参的修改是不会改变实参的。


6.函数的调用:

传值调用:

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

传址调用:

把函数外部创建变量的内存地址传递给函数参数

→函数内部可以直接操作函数外部的变量。

7.练习:

①打印100~200之间的素数:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>

int is_prime(int a)
{
	for (int j = 2; j <= sqrt(a); j++)
	{
		if (a % j == 0)
			return 0;
	}
	return 1;
}

int main()
{
	int i;
	for (i = 100; i <= 200; i++)
	{
		if (is_prime(i) == 1)
			printf("%d ", i);
	}
	return 0;
}


②判断闰年:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int is_leap_year(int x)
{
	if (x % 4 == 0 && x % 100 != 0 || x % 400 == 0)
		return 1;
	else
		return 0;
}

int main()
{
	int year;
	for (year = 1000; year <= 2000; year++)
	{
		if (1 == is_leap_year(year))
			printf("%d ", year);
	}
	return 0;
}


③整形有序数组二分查找:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
                 
           //指针才能接收地址,因此本质上arr是一个指针
int binary_search(int arr[], int k)
{
  //算法的实现
  //假设在32位系统上运作,指针大小为4个字节,arr[0]也占4个字节
  //因此sz = 1,而不为10
	int sz = sizeof(arr) / sizeof(arr[0]);
	int left = 0;
	int right = sz - 1;
	int mid = (left + right) / 2;//中间元素的下标
	while (left <= right)
	{
		if (k < mid)
			right = mid - 1;
		else if (k > mid)
			left = mid + 1;
		else
			return mid;
	}
	return -1;
}
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 7
  //          此处传递过去的是数组arr首元素的地址
	int ret = binary_search(arr, k);
	if (binary_search(arr, k) == -1)
		printf("数组中无法找到指定数字\n");
	else
		printf("找到啦!指定数字下标为>: %d\n", ret);
	return 0;
}

数组arr[]中的元素存在数字7,但为何输入后仍然查找不到对应下标呢?

函数(1)_数组_05

具体原因在上述代码块中的注已说明,由此我们能得出一个结论:

在函数的内部,想要去求参数或者数组元素的个数是无法实现的。

那怎么无法在函数内部求,那我们就在外部求就可以了,

直接把int sz = ...这行代码移到main函数中,

并且在binary_search()函数中多加一个参数修改为:

int binary_search(int arr[], int k, int sz)即可

最终我们的代码就能正常运行了。

函数(1)_函数调用_06


④每调用一次函数,num自增:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

void Add(int* p)
{
	(*p)++;
}

int main()
{
	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;
}

 

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

嵌套调用:

程序在编译或运行时,使用某个函数来完成相关功能,称之为函数调用。

在上述介绍中有体现。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	printf("%d", printf("%d", printf("%d", 43)));
	return 0;
}


链式访问:

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

例:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<string.h>
 

int main()
{
	//1
	int len;
	len = strlen("abc");
	printf("%d\n", len);
	//2
	printf("%d\n", strlen("abc"));
	return 0;
}

上述代码中//1等价于//2


例:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	printf("%d", printf("%d", printf("%d", 43)));
	return 0;
}

上述代码输出结果为:

函数(1)_链式访问_07

printf()返回值:

返回值为整型,是输出字符的个数,即格式化字符串中字符的个数。

第三个printf()先是打印43,字符个数有两个,所以返回2;

第二个printf()再打印2,字符个数只有一个,所以返回1

第三个printf()打印1收尾,因此最终打印结果为4321。


9.函数的声明和定义:

例:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

//函数的声明
int Add(int x, int y);

int main()
{
	int a = 10;
	int b = 20;
	//函数的调用
	int sum = Add(a, b);
	printf("%d\n", sum);
	return 0;
}

//函数的定义
int Add(int x, int y)
{
	int z = x + y;
	return z;
}

但在正常使用环境下,一般不这么写函数的声明和定义

正确用法如下:

按如图所示添加新建项:

函数(1)_链式访问_08

再把声明和定义部分分别放置到对应项目中:

函数(1)_函数调用_09


函数(1)_链式访问_10

最后在需要引用Add()函数的项目中添加头文件即可:

#include"add.h"

注意:引用自定义头文件时用"",使用库里的头文件时用<>

#ifndef的意思就是如果当前宏没有被定义过,则保留函数定义

后面的定义名最好跟头文件名字相同




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

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

暂无评论

推荐阅读
  gBkHYLY8jvYd   2023年12月06日   50   0   0 #includecii++
  gBkHYLY8jvYd   2023年12月10日   18   0   0 #include邻域灰度图像
  gBkHYLY8jvYd   2023年12月10日   22   0   0 #include数组i++
  gBkHYLY8jvYd   2023年12月06日   19   0   0 #includeios数据
  gBkHYLY8jvYd   2023年12月08日   21   0   0 #includecii++
mfv4jpsXLy5V