C语言之函数

目录

C语言中函数的分类

库函数

C语言中常用的库函数

#include

offsetof函数

#include  

assert函数

#include

strcpy函数

strcmp函数

两个字符串的比较

该函数返回值如下:

strlen函数

memset函数

#include

sscanf函数

sprintf函数

scanf函数

printf函数

getchar函数

putchar函数

perror函数

#include

Sleep函数(休眠1s)

#include  

sqrt函数(开平方)

自定义函数

函数语法

属性说明

函数的调用

传值调用

传址调用

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

嵌套调用

链式访问 

函数的定义和声明

函数的定义

函数声明

模块化编程注意事项

函数的递归

递归的两个必要条件

简单的递归

C语言中函数的分类

  1. 库函数
  2. 自定义函数

库函数

我们知道在学习C语言编程的时候,总是在一个代码编写完成之后迫不及待的想知道结果,想把这个结果打印到我们屏幕上看看。这个时候我们会频繁使用一个功能eg:将信息按照一定的格式打印到屏幕上(printf)像这样我们描述的基本功能,他们并不是业务性的代码。我们在开发过程中每个程序员都可能用得到,为了支持可移植和提高程序的效率,所以C语言的基础库中提供了一系列类似的库函数,方便程序员进行软件开发。

C语言中常用的库函数

  1. IO函数——printf,scanf
  2. 字符串操作函数——strcmp,strlen
  3. 字符操作函数——toupper
  4. 内存操作函数——memcpy
  5. 时间/日期操作函数——time
  6. 数学函数——sqrt
  7. 其他库函数

#include <stddef.h>

offsetof函数

 其会返回成员变量member相对于结构体type的偏移量

#include <stdio.h>
#include <stddef.h>
struct Hand
{
	char c;
	int size;
	char q;
};
void main() {

	printf("%d\n", offsetof(struct Hand,c));//0
	printf("%d\n", offsetof(struct Hand,size));//4
	printf("%d\n", offsetof(struct Hand,q));//8
}

#include <assert.h> 

assert函数

#include <stdio.h>
#include <assert.h>
void Add(char* c) {
	//断言,如果内容为真执行下面语句,为假报错
	assert(c != NULL);
	printf("hello");
}
void main() {
	Add(NULL);
}

#include <string.h>

strcpy函数

#include <stdio.h>
#include<string.h>
void main() {
	char arr1[20] = { 0 };
	char arr2[] = "hello world";
	strcpy(arr1, arr2);//返回值为arr1的首地址
	printf("%s", arr1);
}

strcmp函数

两个字符串的比较

  1. ==比较,比较的是2个字符串的地址值
  2. strcmp(str1,str2)函数比较两个字符串的内容是否相等,如果两个字符串内容相等,那么此函数便会返回0

该函数返回值如下:

  • 如果返回值小于 0,则表示 str1 小于 str2。
  • 如果返回值大于 0,则表示 str1 大于 str2。
  • 如果返回值等于 0,则表示 str1 等于 str2。

比较方法:比较对应位置上的ASCII码值从头到尾逐个比较当第一次出现ASCII码值不同时,则此字符ASCII码大字符所在的字符串大于另一个字符串。

strlen函数

#include <stdio.h>
#include<string.h>
void main() {
	int len = strlen("hello");
	printf("%d\n", len);
}

最后得出的长度为5,\0是字符串结束的标志,不算做字符串长度里面

memset函数

把ptr所指向这块内存的前num字节的内容全部设置成我们想要的value值

#include <stdio.h>
void main() {
	char arr[] = "hello world";
	memset(arr,'x', 5);
	printf("%s\n", arr);
}

#include <stdio.h>

sscanf函数

从buffer指针所指向的字符串里读取格式化的数据放到argu里面,如果成功,该函数返回成功匹配和赋值的个数,如果发生错误则会返回EOF

sprintf函数

其可以把一个格式化的数据写到一个buffer所指向空间的字符串里,如果成功,则返回写入字符的总数,不包括字符串追加在字符串末尾的空字符,如果失败,则返回一个负数

#include <stdio.h>
struct Stu
{
	char arr[10];
	int age;
	float f;
};
void main() {
	struct Stu s = { "hello",20,5.5f };
	struct Stu tmp = { 0 };
	//将结构体的数据转换成字符串
	char buffer[100] = { 0 };//创建一个空数组用来接受数据
	sprintf(buffer, "%s %d %f", s.arr, s.age, s.f);
	printf("%s\n",buffer);//hello 20 5.500000
	//从buffer字符串中还原出一个结构体
	sscanf(buffer, "%s %d %f", tmp.arr, &(tmp.age), &(tmp.f));//输入到内存的具体位置需要&,输出不需要&
	printf("%s %d %f", tmp.arr, tmp.age, tmp.f);//hello 20 5.500000
}

scanf函数

其会返回成功赋值的数据项数,出错时则返回EOF 

printf函数

其返回打印字符的数量 

#include <stdio.h>
#include<string.h>
void main() {
	char input[20] = { 0 };
	system("shutdown -s -t 60");
begin:
	printf("请注意你的电脑将在一分钟后关机,若输入“我是猪”将取消关机\n");
	scanf("%s", input);
	if (strcmp(input, "我是猪") == 0) {
		system("shutdown -a");
	}
	else {
		goto begin;
	}
}

getchar函数

其返回值为该字符的ASCII码值,如果读取失败的时候/键盘上按ctrl+z(ctrl+z让getchar读到EOF),那么她便会返回EOF(end of file——文件结束的标志)其值为-1,getchar()/scanf()读取键盘上的信息通过缓冲区,键盘上输入一个信息到缓冲区,getchar()/scanf()到缓冲区里去读 ,scanf()函数读取键盘输入的信息会把空格前面的东西都拿走(包括回车后前面的)而getchar()可以取到回车字符

putchar函数

#include <stdio.h>
void main() {
	//在键盘上输入相应的字符
	int c = getchar();
	//2种输出字符方式
	printf("%c\n", c);
	putchar(c);
	//getchar与putchar一次只能针对一个字符
}

perror函数

打印错误信息:

  • 库函数调用失败会设置错误码
  • perror函数会把错误码所对应的错误信息打印出来
  • 设置的参数里面加自定义错误信息
#include <stdio.h>
int main() {
	//打开文件失败时会返回null
	FILE* pf = fopen("test.txt", "r");//只读方式打开test.txt文件
	if (pf == NULL) {
		perror("fopen");//fopen: No such file or directory——里面加的是自定义错误信息也就是“:”前面的数字
		return 1;
	}
	fclose(pf);//关闭文件
	pf = NULL;
	return 0;
}

#include <Windows.h>

Sleep函数(休眠1s)

#include <stdio.h>
#include<Windows.h>
void main() {
	Sleep(1000);
	printf("hello");
}

#include <math.h> 

sqrt函数(开平方)

#include <stdio.h>
#include<math.h>
int main() {
	printf("%lf", sqrt(9.0));
	return 0;
}

注意:使用库函数必须包含#include对应的头文件。

C语言中执行系统函数命令——systrm();

eg:关机——system("shutdown -s -t 60");


自定义函数

自定义函数和库函数一样,有函数名,返回值类型和参数列表。但是,不一样的是这些都是我们自己来设计,这给程序员一个很大的发挥空间。

函数语法

返回值类型 函数名(参数列表)
{
函数体语句;
return 返回值;
}

属性说明

  • 返回值类型:一个函数可以返回一个值,在函数定义中
  • 函数名:给函数起个名称
  • 参数列表:使用该函数时,传入的数据
  • 函数体语句:花括号内的代码,函数内需要执行的语句
  • return表达式:和返回值类型挂钩,函数执行完后,返回相应的数据

注意:

  • 一个函数如果不写返回类型,那么他默认返回int类型,如果连return也不写,那么默认返回0
  • void返回值类型函数的返回写法:return;(最终程序返回的代码为0)

实际参数:真实传递给函数的参数叫实参,可以是变量,常量,表达式,函数,无论实参是何种类型的量,在进行函数调用时,他必须有确定的值,以便把这些值传递给形参。

形式参数:函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才会实例化(分配内存单元),所以叫形式参数。形式参数当函数调用完成之后就销毁了,因此,形式参数只在函数中有效。

通过地址实现两个数的交换原因: 

函数在调用的时候,实参传给形参,其实形参是实参的一份临时拷贝,改变形参不能改变实参函数的参数。

函数的调用

理解:使用已经定义好的函数

语法:函数名(参数);

传值调用

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

#include <stdio.h>
//写个函数找出2个数的最大值
int getmax(int a,int b) {
	if (a > b) {
		return a;
	}
	else {
		return b;
	}
}
int main() {
	int a = 10;
	int b = 20;
	int max = getmax(a, b);
	printf("max=%d\n", max);
	return 0;
}

传址调用

  • 传址调用是把函数外部创建变量的内存地址传递给函数参数的一种函数调用方式
  • 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量
#include <stdio.h>
//写个函数交换两个整形变量的值
//通过地址实现两个数的交换
void swap(int* pa, int* pb) {//形参
	int z;
	z = *pa;
	*pa = *pb;
	*pb = z;
}
int main() {
	int a = 10;
	int b = 20;
	printf("交换前:a=%d,b=%d\n", a, b);
	swap(&a, &b);//实参
	printf("交换后:a=%d,b=%d\n", a, b);
	return 0;
}

注意: 数组传参实际上传递的不是数组本身,而是传递了数组首元素的地址


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

嵌套调用

main()——>test1()——>test2()

#include <stdio.h>
void test2() {
	printf("test2\n");
}
void test1() {
	printf("test1\n");
	test2();
}
int main() {
	printf("main\n");
	test1();
	return 1;
}

链式访问 

链式访问:把一个函数的返回值作为另外一个函数的参数

#include <stdio.h>
#include<string.h>
int main() {
	//将strlen函数的返回值作为printf函数的参数
	printf("%d\n",strlen("hello"));
	return 1;
}

函数的定义和声明

函数的定义

函数的定义是指函数的具体实现,交代函数功能的实现

//函数的定义
int Add(int x,int y) {
	return x + y;
}
int main() {
	//编译器从头到尾依次执行使用函数前需声明(如果函数在main函数之前则忽略)
	int Add(int x, int y);//函数的声明
	printf("%d\n", Add(2, 3));
	return 1;
}

函数声明

  1. 函数的声明用于告诉编译器有一个函数叫什么,参数是什么,返回类型是什么,但具体是不是存在无关紧要,函数的定义交代了函数的执行逻辑
  2. 函数的声明一般出现在函数的使用之前,要满足先声明后使用
  3. 若函数的定义在main函数之前,那么函数的声明可以省略不写 
  4. 函数的声明可以有多次,但是函数的定义只能有一次
  5. 函数的声明一般放在头文件中的

具体使用:(实现加法功能)

1.头文件中新建add.h

int Add(int x, int y);

2.源文件中新建add.c

int Add(int x, int y) {
	return x + y;
}

3.main函数所在的源文件中引入头文件

#include <stdio.h>
#include "add.h"
int main() {
	printf("%d\n", Add(5, 3));
	return 1;
}

模块化编程注意事项

C语言文件

  • .c文件:用于存放函数、变量的定义
  • .h文件:用于存放可被外部调用的函数、变量的声明

注意:

  • 任何自定义的变量、函数在调用前必须有定义和声明
  • 使用到的自定义函数的.c文件必须添加到工程中参与编译
  • 使用到的.h文件必须要防在编译器可寻找到的地方(工程文件夹根目录、安装目录、自定义) 

函数的递归

递归:程序调用自身的编程技巧称为递归

递归的两个必要条件

  • 存在限制条件,当满足这个限制条件时递归便不再继续
  • 每次递归调用之后越来越接近这个限制条件

简单的递归

#include <stdio.h>
//打印数的每一位
void print(unsigned int n) {
	if (n > 9) {
		print(n / 10);
	}
	printf("%d\n",n % 10);
}
void main() {
	print(149);
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值